Informacioni sistemi 1/Projekat

Izvor: SI Wiki
Pređi na navigaciju Pređi na pretragu

Projekat na predmetu nosi 20 bodova i brani se u prva dva ispitna roka. Može da se radi samo jednom i bodovi sa ispita mogu da se prenesu u naredni rok ukoliko se tada brani projekat. Obuhvata celo gradivo rađeno na vežbama, ali takođe može da dođe gradivo koje je pomenuto ali ne i rađeno na vežbama, pa je ponekad potrebno snalaziti se po resursima na internetu. Na odbrani projekta mogu da dođu modifikacije, ali se to od početka 2022. godine nije još uvek desilo.

Projekat se menja svake godine, ali obično se radi o centralnom serveru (Web Application projekat kao na drugoj laboratorijskoj vežbi) koji komunicira sa podsistemima (Enterprise Application Client projekat kao na prvoj laboratorijskoj vežbi) preko JMS, samo podsistemi imaju pristup svojim bazama podataka (koriste JPA) i postoji klijentska aplikacija (klijentski deo se obično ne radi na vežbama) koja sa centralnim serverom komunicira preko HTTP protokola (pozivajući njegov REST API). Vodič ispod služi kako bi napomenuo neke česte greške u izradi projekta.

Preporučuje se da pre izrade projekta uradite laboratorijske vežbe i pročitate vodiče za JMS, JPA i REST. Ukoliko ste radili laboratorijske vežbe, za projekat je obično potrebno od 3 do 7 dana.

Klijent

Klijentski deo projekta treba da komunicira sa REST serverom preko HTTP protokola, ali se korišćenje HTTP klijenata obično ne radi na vežbama. Na konsultacijama za projekat 2022. godine (11:12) Stefan Tubić je pokazao kako se pravi Java with AntJava Application projekat i u njega ubacuje JAX-RS 2.0 biblioteka, a primeri upotrebe su dati na prezentaciji na stranici predmeta, poslednja tri slajda. Na konsultacijama nije pokrenuo nijedan HTTP zahtev koristeći kod sa prezentacija, i zato su se studentima dešavale greške kada bi pokušavali da rade na taj način. Nije poznato da li je ijedan predati projekat dosad koristio tu metodu.

Jedan pristup pisanju HTTP klijentske aplikacije jeste korišćenje HttpURLConnection iz Java standardne biblioteke, ali ona nudi interfejs koji može biti previše niskog nivoa za potrebe projekta (kao što je i normalno u standardnim bibliotekama programskih jezika). Zbog toga se preporučuje korišćenje biblioteka poput Retrofit, koje neke detalje HTTP komunikacije sakrivaju od korisnika, dajući jednostavniji interfejs.

Ukoliko koristite Retrofit
  • Umesto Ant projekta, preporučuje se Maven projekat u kome za uvoženje biblioteke možete da dodate sledeće u pom.xml fajl, unutar <dependencies>:
        <dependencies>
            <dependency>
                <groupId>com.squareup.retrofit2</groupId>
                <artifactId>retrofit</artifactId>
                <version>2.8.1</version>
            </dependency>
            <dependency>
                <groupId>com.squareup.retrofit2</groupId>
                <artifactId>converter-gson</artifactId>
                <version>2.8.1</version>
            </dependency>
        </dependencies>
    
    • Ako su izašle nove verzije možete da ažurirate na njih, a ako ne koristite Gson konverter (za JSON) već neki drugi, možete da zamenite sa konverterom koji koristite.
  • Preporučuje se da na svojim klasama resursa imate @Produces(MediaType.APPLICATION_JSON) anotaciju kako bi vraćali podatke u JSON formatu umesto XML. U ovom slučaju mogu da se dese greške ciklične serijalizacije jer nema anotacija koje bi sprečile to (postoji anotacija @JsonbTransient koja bi trebalo da bude slična @XmlTransient anotaciji za JSON, ali ponekad može da ne radi) pa u tom slučaju pre vraćanja resursa morate da prođete kroz njegova inverzna polja i postavite ih na null, ili u potpunosti izbacite inverzna polja.
  • Najbitnija dokumentacija se nalazi na stranici projekta, a možete pogledati i jedan od primera upotrebe sa GitHub repozitorijuma.

Česte greške

  • Ukoliko za projekat dodajete JMS komunikaciju u REST projekat, ne zaboravite da se JMS Connection Factory, Topic ili Queue može ubaciti preko Resource Injection (koristeći @Resource anotaciju) samo ukoliko je polje u koje se ubacuju označeno kao nestatičko. Greška koja se pojavljuje zbog ovoga glasi Illegal use of static field on class that only supports instance-based injection.
  • Ukoliko morate da u jednoj metodi pošaljete a zatim čekate na odgovor u toj istoj metodi i dešava vam se da se poruka ne pošalje pre nego što se čeka na zahtev, problem je u tome što se nalazite u EJB (Enterprise Java Bean) kontekstu i pokrenuta je transakcija pa se tek na kraju te transakcije pošalje tražena poruka. Ovo se može rešiti na dva načina:
    • Sa svake klase resursa ukoniti @Stateless anotaciju. Ovo ima efekat da se vaše metode više ne izvršavaju u EJB kontekstu, pa se transakcije ne dešavaju i poruke se šalju odmah.
      • Ukoliko ste kojim slučajem koristili @Singleton anotaciju kao način reupotrebe koda pređite sa EJB Singleton (javax.ejb.Singleton) na CDI Singleton (javax.inject.Singleton) i ubacujte ga koristeći @Inject umesto @EJB anotacije u resurse.
    • (ili) Na svaki metod resursa postavite @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) anotaciju. Ovo ima efekat da te metode ne budu obuhvaćene transakcijama, pa se problem slično rešava.
  • Može da vam se desi greška koja prijavljuje da entitetske klase možda nisu označene sa @Entity. To se obično dešava u slučaju da vam je transaction-type postavljen na RESOURCE_LOCAL ali nemate sve klase izlistane u persistence.xml pod <class> tagovima.
  • Ukoliko je transaction-type postavljen na RESOURCE_LOCAL i dobijate grešku java.lang.NoClassDefFoundError: sun/security/ssl/HelloExtension ili java.lang.NoSuchMethodError: sun.security.ssl.SSLSessionImpl, u persistence.xml dodajte:
          <property name="eclipselink.jdbc.property.useSSL" value="false"/>
          <property name="eclipselink.jdbc.property.requireSSL" value="false"/>
    
  • Ukoliko vam se desi greška sa opisom: An attempt was made to traverse a relationship using indirection that had a null Session. This often occurs when an entity with an uninstantiated LAZY relationship is serialized and that relationship is traversed after serialization. To avoid this issue, instantiate the LAZY relationship prior to serialization. moguće je da ste poslali entitetski objekat preko JMS u neki drugi adresni prostor gde taj objekat više nije u istom JPA kontekstu, a neka polja su ostala neinicijalizovana zbog FetchType.LAZY na toj asocijaciji, pa je neuspešno pokušana inicijalizacija tih polja dok je serijalizator obilazio objekat kako bi serijalizovao njegova polja (dešava se bez obzira na to da li su polja označena sa @XmlTransient ili ne). Ovo možete rešiti tako što ta polja postavite na null pre serijalizacije.
  • Ukoliko dobijate org.omg.CORBA.COMM_FAILURE greške, najlakše rešenje je da restartujete računar. Drugo rešenje je da nasilno pogasite sve Java, NetBeans i GlassFish procese na koje možete da naiđete. Ova greška se obično dešava zbog toga što je više GlassFish instanci pokrenuto.
  • Ukoliko pravite nove kontekste i JMS consumer pri svakom zahtevu, trebalo bi da pozovete close() nad njima, ili da ih postavite u try-with-resources kako bi se automatski zatvorili. Ovo može da bude potencijalno rešenje za grešku iznad.

Napomene

  • Kada se od vas traže dump fajlovi baze za predaju, možete ih naći u MySQL Workbench pod ServerData Export/Import.
  • Preporučuje se da u projektima podsistema (projektima koji nisu Web Application) koristite transaction-type="RESOURCE_LOCAL" jer postavljanje JTA da radi u tim projektima može da bude teško. U tom slučaju nije potrebno stvaranje nikakvih JDBC resursa na GlassFish serveru, jer se kredencijali čitaju iz persistence.xml, ali je potrebno ručno pokretanje i završavanje transakcija kako bi se uspešno unele promene u bazu.
  • UML dijagrame koji se traže u projektu možete da generišete koristeći neki alat poput StarUML sa Java dodatkom instaliranim kroz ToolsExtension Manager (pretražiti Java). Koristeći taj dodatak možete generisati dijagram iz koda opcijom ToolsJavaReverse Code. Možda je potrebno malo ulepšati dijagrame nakon generisanja.

Pokretanje na odbrani

Pošto je ovo prvi put da studenti donose svoje projekte na laboratorijske računare, mogu naići na nekoliko greški na koje pri izradi laboratorijskih vežbi nisu nailazili.

  1. Napravite bazu podataka na MySQL serveru koristeći opciju sličnu onoj za pravljenje dump fajlova. Alternativno, napravite ručno bazu a zatim sadržaj svog fajla izvršite kao regularnu SQL skriptu koja će napraviti tabele i popuniti ih podacima.
  2. U ServicesServers dodati GlassFish koji se nalazi na direktorijumu C:\Program1\glassfish5, osim ako već nije dodat sa te putanje. Pokrenuti i dodati neophodne resurse za bazu podataka ili JMS.
    • Ukoliko niste koristili transaction-type="JTA" ni u jednom persistence.xml, nisu vam potrebni resursi za bazu podataka na GlassFish i ukoliko imate <jta-data-source> u bilo kom persistence.xml možete ga ukloniti.
  3. Pri kreiranju/otvaranju projekata promenite JDK na JDK 1.8 (podrazumevano je JDK 11) na svim projektima. U Ant projektima ova opcija se nalazi na PropertiesLibraries, dok se u Maven projektima nalazi na Compile.
  4. U svim Ant projektima moraju da se dodaju biblioteke kojima GlassFish ne može da pristupi jer je NetBeans instaliran u direktorijumu čija putanja sadrži razmak. Biblioteke sa spiska kopirati u folder čija putanja nema razmak i u jednom projektu pod PropertiesLibraries izabrati opciju Edit nad bibliotekama EclipseLink (JPA 2.1) i Java EE 8 API, ukloniti sve JAR fajlove učitane od strane biblioteke i zameniti ih JAR fajlovima iskopiranim na putanju bez razmaka.
    • Putanje JAR fajlova tih biblioteka su na sledećih mestima:
      • EclipseLink (JPA 2.1)C:\Program Files\NetBeans\netbeans\java\modules\ext\eclipselink
      • Java EE 8 APIC:\Program Files\NetBeans\netbeans\enterprise\modules\ext\javaee-api-8.0.jar
    • Takođe je potrebno dodati i konektor za MySQL sa C:\Program1\glassfish5\glassfish\lib\mysql-connector-java-8.0.20.jar.
    • Idealno je spakovati sve ove fajlove zajedno sa projektom, povezane relativnim putanjama.
  5. U svim persistence.xml podesiti da se na bazu povezuje sa nalogom admin, čija je šifra 123.
    • Ili bolje, u SQL skripti za generisanje baze napraviti novog korisnika i dati mu sve privilegije i onda njega koristiti u persistence.xml.
      CREATE USER 'is1'@'localhost' IDENTIFIED BY 'sifra';
      GRANT ALL PRIVILEGES ON * . * TO 'is1'@'localhost';
      
    • Ukoliko niste koristili transaction-type="RESOURCE_LOCAL" ni u jednom persistence.xml, kredencijali za bazu se čitaju sa JDBC resursa na GlassFish serveru i oni iz datoteke nisu relevantni.