Informacioni sistemi 1/JPA i REST

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

Na drugoj laboratorijskoj vežbi radi se JPA (Java Persistence API) i REST (Representational State Transfer). Vodič ispod služi za uspešno postavljanje alata na vašem računaru i kao pomoć pri najčešćim greškama na koje možete naići pri vežbanju i izradi laboratorijske vežbe i napisan je tako da se najčešće greške mogu lako potražiti.

Postavka

Sledeći postupak bi trebalo da vas dovede do uspešne postavke kako biste bili spremni za pokretanje nekog REST projekta sa stranice predmeta. Instrukcije za prvu laboratorijsku vežbu su i dalje potrebne.

  1. Instalirajte MySQL Workbench. Alternativno, pokretanje bilo kakvog MySQL (ili MariaDB) servera na računaru će raditi. Na primer, možete instalirati XAMPP, pokrenuti MySQL server na njemu i koristiti phpMyAdmin kao interfejs.
    • Pri instalaciji MySQL Workbench, izaberite Developer Default opciju, od koje će vam relevantne komponente biti MySQL Server i MySQL Workbench, pa ukoliko instalacija prijavi da se neka druga komponenta ne može instalirati možete je preskočiti.
    • Obavezno postavite lozinku za root korisnika pri instalaciji. Ukoliko je zaboravite, možete pokušati da je ponovo postavite pomoću ovog uputstva. Ukoliko ni to ne radi, najbolje instalirajte MySQL Server iznova.
    • Da biste pokrenuli MySQL server na Windows operativnom sistemu, možete otvoriti Command Prompt kao administrator i pokrenuti sledeće komande:
      cd "C:\Program Files\MySQL\MySQL Server 8.0\bin"
      mysqld --install
      mysqld --initialize
      
      zatim potražiti Services opciju u Start meniju, i uključiti servis sa prefiksom MySQL.
    • Stefan Tubić je na vežbama menjao my.ini fajl kako bi podesio podrazumevani storage engine na InnoDB. Ovo nije potrebno, jer je nakon nove instalacije storage engine već postavljen na InnoDB.
  2. Preuzmite Connector/J. Kada vas pita za verziju, izaberite Platform Independent, i trebalo bi da dobijete jedan JAR fajl. Nakon toga, taj fajl možete ubaciti u direktorijum sa vašom instalacijom GlassFish servera, u direktorijum glassfish/lib.
  3. Pokrenite NetBeans i GlassFish server. Ukoliko je bio pokrenut pre nego što ste ubacili Connector/J, zaustavite ga i ponovo pokrenite.
  4. Napravite novi JDBC Connection Pool. Parametri su sledeći:
    • Resource Type: javax.sql.DataSource
    • Database Driver Vendor: MySql
      • Ukoliko ste na GlassFish 5.0 i pređete preko tekstualnog polja nakon Database Driver Vendor, vrednost će biti izbrisana.
    • Datasource Classname: com.mysql.cj.jdbc.MysqlDataSource
    • U dodatnim svojstvima konekcije podesiti:
      • password: Lozinka vašeg MySQL korisnika, ne sme da bude prazna i možete je promeniti iz MySQL WorkbenchAdmnistrationUsers And Privileges (ili koristeći ALTER USER)
      • databaseName: Naziv vaše MySQL baze
      • serverName: localhost
      • user: Naziv vašeg MySQL korisnika, podrazumevano postoji korisnik sa nazivom root.
      • portNumber: Podrazumevano 3306, ali ponekad MySQL Workbench može da postavi na 3308.
  5. Testirati Connection Pool koristeći Ping dugme.
    • Ukoliko dobijate grešku u vezi sa com.mysql.cj.jdbc.MysqlDataSource ili nekim keystore fajlom (Keystore was tampered with...), probajte da preko dugmeta Add Property u Additional Properties tabu dodate svojstvo useSSL sa vrednošću false.
      • Ukoliko nakon ovoga dobijate grešku u vezi sa public key retrieval, dodajte svojstvo allowPublicKeyRetrieval i postavite ga na true.
    • Ukoliko i nakon koraka iznad dobijate grešku u vezi sa drajverskom klasom, proverite da li ste na dobro mesto ubacili JAR fajl od Connector/J. Ukoliko imate više GlassFish servera na računaru, proverite da li ste u dobar server ubacili. Probajte da pored glassfish/lib ubacite JAR fajl i u glassfish/bin i domains/domain1/lib.
    • Ukoliko kao greška izađe "Communications link failure", proverite da li vam je uključen MySQL server, odnosno da li možete da se na njega povežete iz nekog drugog programa, poput MySQL Workbench. Takođe proverite da li gađate dobar port, pošto je podrazumevani port 3306, a ne 3308 kako je pokazano na vežbama.
    • Ukoliko u bilo kom trenutku postavke GlassFish server izbaci grešku u vezi sa getOutputStream(), samo pokušajte ponovo.
  6. Napraviti JDBC Resource sa novonapravljenim Connection Pool kao konekcijom.
  7. Unutar NetBeans u ServicesDatabases kliknite desnim klikom na Drivers i izaberite New Driver.
  8. Kod Driver File(s) izaberite Add i onda izaberite Connector/J JAR fajl koji ste ubacili u glassfish/lib direktorijum, pa dodajte drajver.
  9. Trebalo bi da vam postane dostupna opcija Register MySQL server pri desnom kliku na ServicesDatabases. Kada to izaberete, možete dodati parametre vašeg MySQL servera slične onima koje ste dodavali za JDBC Connection Pool.
    • Ovaj korak vam omogućava da izaberete ovu konekciju kada radite NewEntity Classes from Database.
  10. U vašem persistence.xml fajlu, u Source tabu, sada možete zameniti sadržaj <jta-data-source> taga sa nazivom vašeg JDBC resursa.
  11. Kao dodatan alat za testiranje vaše REST aplikacije možete preuzeti Postman.

Ukoliko pokrećete novi REST projekat, izaberite Java with MavenWeb Application. Obavezno gledajte GlassFish Server tab kako biste uočili greške koje se javljaju tokom izvršavanja.

Napomene

  • Ukoliko ste napravili novi prazan projekat i on ne može da vam se pokrene zbog greške poput "Unable to load the mojo 'war' in the plugin 'org.apache.maven.plugins:maven-war-plugin:2.3' due to an API incompatibility", moguće je da imate više verzija JDK (Java Development Kit) instaliranih na računaru, i da podrazumevani JDK nije podešen na 1.8. Pokušajte da obrišete ostale JDK sa računara, i da postavite podrazumevani na 1.8. Podrazumevani JDK može da se menja dodavanjem putanje do JDK 1.8 u netbeans_jdkhome opciju u netbeans.conf fajl, ili jednostavno reinstalacijom NetBeans.
  • Ukoliko imate problema sa generisanjem entitetskih klasa, poput toga da se generišu prazne klase, instalirajte NetBeans verziju 12.0.
    • Ukoliko vam se entitetske klase generišu bez JAXB anotacija i nemate opciju da to izaberete prilikom generisanja, proverite da li vam je verzija JDK dobro podešena za projekat, a onda uradite Clean and Rebuild.
  • Ukoliko vam se desi HTTP greška 404 (Not Found):
    • Prvo proverite da li ste dobro upisali putanju endpoint-a. Endpoint-ovi su generalno na putanji localhost:8080/ProjectName/ApplicationPath/ResourcePath/EndpointPath, gde:
      • ProjectName je ime vašeg projekta, na primer restapi,
      • ApplicationPath je određeno anotacijom @ApplicationPath iznad glavne klase vašeg projekta, odnosno klase izvedene iz Application (podrazumevano postavljeno na resources),
      • ResourcePath je određeno anotacijom @Path iznad klase resursa kojem pristupa, na primer popravke, i
      • EndpointPath je određeno anotacijom @Path iznad metode za taj endpoint.
    • Ukoliko je endpoint sigurno dobar, moguće je da je aplikacija undeploy-ovana zbog neke greške u trenutnom projektu ili nekoj od prethodnih iteracija. Možete pokušati da restartujete GlassFish server i pratiti server log (GlassFish Server tab u Output prozoru) da vidite ukoliko se pojavljuje neka greška.
  • Ukoliko vam se dešava HTTP greška 500 (Internal Server Error), trebalo bi da deo greške vidite na stranici, ali celu grešku možete pronaći u server logu.
  • Ukoliko vam se u endpoint metodi nađe argument bez anotacije pored sebe, takav argument se šalje kroz telo (body) zahteva, i u Postman treba postaviti body na raw opciju. Na primer, String argument se šalje sa tipom sadržaja text/plain (Text opcija u Postman), dok se tip sadržaja neke druge klase šalje kao XML reprezentacija te klase sa tipom sadržaja application/xml (XML opcija u Postman).
  • Ukoliko dobijate TransactionRequiredException grešku pri slanju upita na neki endpoint, proverite da li ste stavili @Stateless anotaciju iznad klase resursa.
  • Ukoliko dobijate HTTP 405 (Method Not Allowed) grešku, to verovatno znači da šaljete GET zahteve na endpoint koji prima zahteve samo preko drugih metoda.
  • Stefan Tubić na vežbama za MySQL server koristi port 3308. Standardni i podrazumevani port za MySQL je 3306, tako da bi trebalo da taj port koristite osim ako ga niste menjali.
    • Ako imate više od jednog MySQL servera na računaru, možda bude potrebno da jednom promenite port. Moguće je da je zbog ovoga Stefanu Tubiću port bio promenjen na 3308.
  • Stefan Tubić je pred kraj jednih vežbi napravio grešku kada je pisao persistence.xml fajl i napisao <jta-data-resource> umesto <jta-data-source>, pa je na sledećem snimku učitao gotov projekat i grešku pripisao pogrešnoj verziji Jave. Ovo vam može praviti problem ukoliko vam se javlja greška kako tabela Kamion ne postoji. Takođe, u istom tom persistence.xml fajlu je pisalo transactionType umesto transaction-type, što vam isto može praviti problem.
  • U gotovom projektu za kompaniju za prevoze (kzp, projekat restapi) u Mehanicari.java fajlu nalazi se @PersistenceContext(unitName = "my_persistence_unit"), iako se jedinica perzistencije zove Zad3PU. To može prouzrokovati neke greške, barem u ovom resursu.
  • Ukoliko vam se prilikom vraćanja odgovora sa servera desi StackOverflowException, verovatno vam se desila beskonačna rekurzija pri serijalizaciji objekta zbog nedostatka @XmlTransient anotacije koja sprečava serijalizaciju nekog polja. To se obično dešava kada klasa A ima polje tipa B ili List<B>, a klasa B polje tipa A ili List<A>, pa serijalizator radi sledeće:
    1. kreće sa serijalizacijom objekta klase A,
    2. nađe njegovo polje tipa B i vidi da nema anotaciju @XmlTransient,
    3. kreće sa serijalizacijom objekta klase B,
    4. nađe njegovo polje tipa A i vidi da nema anotaciju @XmlTransient,
    5. ponovo kreće sa serijalizacijom istog objekta klase A i tako u krug...
    • Primer ovoga može da bude sa vežbi sa kompanijom za prevoz, gde, ukoliko entitet Zaposlen ne bi imao @XmlTransient anotaciju iznad getMehanicar() ili getVozac() metode, dešavala bi se beskonačna serijalizacija tih entiteta.
  • Za projekat 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.
  • Ukoliko je transaction-type postavljen na RESOURCE_LOCAL i dobijate grešku java.lang.NoClassDefFoundError: sun/security/ssl/HelloExtension, u persistence.xml dodajte:
          <property name="eclipselink.jdbc.property.useSSL" value="false"/>
          <property name="eclipselink.jdbc.property.requireSSL" value="false"/>
    

Vodič za uspešno pokretanje projekata na laboratorijskim računarima

  1. 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.
  2. 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.
  3. 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.
  4. 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.