Informacioni sistemi 1/JPA i REST

Izvor: SI Wiki
< Информациони системи 1
Datum izmene: 30. oktobar 2023. u 03:00; autor: KockaAdmiralac (razgovor | doprinosi) (Ispravka linka do NetBeans 12.0)
(razl) ← Starija izmena | Trenutna verzija (razl) | Novija izmena → (razl)
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.

Virtuelna mašina

Pošto postavke ovih alata tako da rade mogu da budu komplikovane, duge i sa greškama, možete da preuzmete nezvaničnu IS1 virtuelnu mašinu sa svim alatima već postavljenim. Ovo znači da na stranicama sa vodičima nećete morati da ispratite Postavka odeljke, jer su alati već postavljeni za vas, kao i da su neke od čestih greški već ispravljene.

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.
    • Ukoliko vas nervira što svakog dana u ponoć iskače konzola za ažuriranje MySQL, možete je ugasiti tako što otvorite Task Scheduler program i iz Task Scheduler LibraryMySQLInstaller isključite ManifestUpdate zadatak.
  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.

Problemi sa okruženjem

  • 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. (Ovaj problem je rešen na IS1 virtuelnoj mašini.)
  • Ukoliko imate problema sa generisanjem entitetskih klasa, poput toga da se generišu prazne klase, instalirajte NetBeans verziju 12.0. (Ovaj problem je rešen na IS1 virtuelnoj mašini.)
    • 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 dobijate grešku <entitet> cannot be added because it is already mapped to the <klasa> entity class and the entity is not in current project source prilikom generisanja entitetskih klasa, potrebno je da očistite NetBeans keš iz %LOCALAPPDATA/NetBeans/Cache direktorijuma (možete mu pristupiti tako što tu putanju kucate u prozor koji se pojavi kada pritisnete Windows dugme + R).

Greške u kodu

  • 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.
  • 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.

Greške na vežbama

  • 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. (Ovaj problem je ispravljen u projektu na IS1 virtuelnoj mašini.)
  • U tom istom projektu, na /api/users/{datum} endpoint nije moguće poslati upit dok se malo ne promeni putanja, jer inače JAX-RS ne zna da li se upit šalje tu ili na /api/users/{idUsr} endpoint (ista putanja, različit parametar).

Laboratorijska vežba

  • Na laboratorijskoj vežbi je data slika baze u postavci, kredencijali za bazu, opis postavke JDBC resursa, dump fajl baze koji možete da uvezete kroz MySQL Workbench i materijali sa stranice predmeta u direktorijumu Materijal za drugu laboratorijsku vezbu.
  • Laboratorijska vežba, ukoliko nema automatskih testova, se ne pregleda naročito detaljno. Bodovi se dobijaju na licu mesta.
  • Podrazumevana JDK verzija na laboratorijskim računarima je JDK 11, pa je nakon pravljenja projekta potrebno da je promenite na JDK 8 u PropertiesCompile.