Информациони системи 1/JPA и REST
На другој лабораторијској вежби ради се JPA (Java Persistence API) и REST (Representational State Transfer). Водич испод служи за успешно постављање алата на вашем рачунару и као помоћ при најчешћим грешкама на које можете наићи при вежбању и изради лабораторијске вежбе и написан је тако да се најчешће грешке могу лако потражити.
Виртуелна машина
Пошто поставке ових алата тако да раде могу да буду компликоване, дуге и са грешкама, можете да преузмете незваничну ИС1 виртуелну машину са свим алатима већ постављеним. Ово значи да на страницама са водичима нећете морати да испратите Поставка одељке, јер су алати већ постављени за вас, као и да су неке од честих грешки већ исправљене.
Поставка
Следећи поступак би требало да вас доведе до успешне поставке како бисте били спремни за покретање неког REST пројекта са странице предмета. Инструкције за прву лабораторијску вежбу су и даље потребне.
- Инсталирајте MySQL Workbench. Алтернативно, покретање било каквог MySQL (или MariaDB) сервера на рачунару ће радити. На пример, можете инсталирати XAMPP, покренути MySQL сервер на њему и користити phpMyAdmin као интерфејс.
- При инсталацији MySQL Workbench, изаберите Developer Default опцију, од које ће вам релевантне компоненте бити MySQL Server и MySQL Workbench, па уколико инсталација пријави да се нека друга компонента не може инсталирати можете је прескочити.
- Обавезно поставите лозинку за root корисника при инсталацији. Уколико је заборавите, можете покушати да је поново поставите помоћу овог упутства. Уколико ни то не ради, најбоље инсталирајте MySQL Server изнова.
- Да бисте покренули MySQL сервер на Windows оперативном систему, можете отворити Command Prompt као администратор и покренути следеће команде: затим потражити Services опцију у Старт менију, и укључити сервис са префиксом MySQL.
cd "C:\Program Files\MySQL\MySQL Server 8.0\bin" mysqld --install mysqld --initialize
- Стефан Тубић је на вежбама мењао
my.iniфајл како би подесио подразумевани storage engine на InnoDB. Ово није потребно, јер је након нове инсталације storage engine већ постављен на InnoDB. - Уколико вас нервира што сваког дана у поноћ искаче конзола за ажурирање MySQL, можете је угасити тако што отворите Task Scheduler програм и из Task Scheduler Library → MySQL → Installer искључите ManifestUpdate задатак.
- Преузмите Connector/J. Када вас пита за верзију, изаберите Platform Independent, и требало би да добијете један JAR фајл. Након тога, тај фајл можете убацити у директоријум са вашом инсталацијом GlassFish сервера, у директоријум
glassfish/lib. - Покрените NetBeans и GlassFish сервер. Уколико је био покренут пре него што сте убацили Connector/J, зауставите га и поново покрените.
- Направите нови JDBC Connection Pool. Параметри су следећи:
- Resource Type:
javax.sql.DataSource - Database Driver Vendor: MySql
- Уколико сте на GlassFish 5.0 и пређете преко текстуалног поља након Database Driver Vendor, вредност ће бити избрисана.
- Datasource Classname:
com.mysql.cj.jdbc.MysqlDataSource - У додатним својствима конекције подесити:
password: Лозинка вашег MySQL корисника, не сме да буде празна и можете је променити из MySQL Workbench → Admnistration → Users And Privileges (или користећиALTER USER)databaseName: Назив ваше MySQL базеserverName:localhostuser: Назив вашег MySQL корисника, подразумевано постоји корисник са називомroot.portNumber: Подразумевано 3306, али понекад MySQL Workbench може да постави на 3308.
- Resource Type:
- Тестирати Connection Pool користећи Ping дугме.
- Уколико добијате грешку у вези са
com.mysql.cj.jdbc.MysqlDataSourceили неким keystore фајлом (Keystore was tampered with...), пробајте да преко дугмета Add Property у Additional Properties табу додате својствоuseSSLса вредношћуfalse.- Уколико након овога добијате грешку у вези са public key retrieval, додајте својство
allowPublicKeyRetrievalи поставите га наtrue.
- Уколико након овога добијате грешку у вези са public key retrieval, додајте својство
- Уколико и након корака изнад добијате грешку у вези са драјверском класом, проверите да ли сте на добро место убацили JAR фајл од Connector/J. Уколико имате више GlassFish сервера на рачунару, проверите да ли сте у добар сервер убацили. Пробајте да поред
glassfish/libубаците JAR фајл и уglassfish/binиdomains/domain1/lib. - Уколико као грешка изађе "Communications link failure", проверите да ли вам је укључен MySQL сервер, односно да ли можете да се на њега повежете из неког другог програма, попут MySQL Workbench. Такође проверите да ли гађате добар порт, пошто је подразумевани порт 3306, а не 3308 како је показано на вежбама.
- Уколико у било ком тренутку поставке GlassFish сервер избаци грешку у вези са
getOutputStream(), само покушајте поново.
- Уколико добијате грешку у вези са
- Направити JDBC Resource са новонаправљеним Connection Pool као конекцијом.
- Унутар NetBeans у Services → Databases кликните десним кликом на Drivers и изаберите New Driver.
- Код Driver File(s) изаберите Add и онда изаберите Connector/J JAR фајл који сте убацили у
glassfish/libдиректоријум, па додајте драјвер. - Требало би да вам постане доступна опција Register MySQL server при десном клику на Services → Databases. Када то изаберете, можете додати параметре вашег MySQL сервера сличне онима које сте додавали за JDBC Connection Pool.
- Овај корак вам омогућава да изаберете ову конекцију када радите New → Entity Classes from Database.
- У вашем
persistence.xmlфајлу, у Source табу, сада можете заменити садржај<jta-data-source>тага са називом вашег JDBC ресурса. - Као додатан алат за тестирање ваше REST апликације можете преузети Postman.
Уколико покрећете нови REST пројекат, изаберите Java with Maven → Web Application. Обавезно гледајте GlassFish Server таб како бисте уочили грешке које се јављају током извршавања.
Проблеми са окружењем
- Уколико сте направили нови празан пројекат и он не може да вам се покрене због грешке попут "Unable to load the mojo 'war' in the plugin 'org.apache.maven.plugins:maven-war-plugin:2.3' due to an API incompatibility", могуће је да имате више верзија JDK (Java Development Kit) инсталираних на рачунару, и да подразумевани JDK није подешен на 1.8. Покушајте да обришете остале JDK са рачунара, и да поставите подразумевани на 1.8. Подразумевани JDK може да се мења додавањем путање до JDK 1.8 у
netbeans_jdkhomeопцију уnetbeans.confфајл, или једноставно реинсталацијом NetBeans. (Овај проблем је решен на ИС1 виртуелној машини.) - Уколико имате проблема са генерисањем ентитетских класа, попут тога да се генеришу празне класе, инсталирајте NetBeans верзију 12.0. (Овај проблем је решен на ИС1 виртуелној машини.)
- Уколико вам се ентитетске класе генеришу без JAXB анотација и немате опцију да то изаберете приликом генерисања, проверите да ли вам је верзија JDK добро подешена за пројекат, а онда урадите Clean and Rebuild.
- Уколико добијате грешку <entitet> cannot be added because it is already mapped to the <klasa> entity class and the entity is not in current project source приликом генерисања ентитетских класа, потребно је да очистите NetBeans кеш из
%LOCALAPPDATA/NetBeans/Cacheдиректоријума (можете му приступити тако што ту путању куцате у прозор који се појави када притиснете Windows дугме + R).
Грешке у коду
- Уколико вам се деси HTTP грешка 404 (Not Found):
- Прво проверите да ли сте добро уписали путању endpoint-а. Endpoint-ови су генерално на путањи
localhost:8080/ProjectName/ApplicationPath/ResourcePath/EndpointPath, где:ProjectNameје име вашег пројекта, на примерrestapi,ApplicationPathје одређено анотацијом@ApplicationPathизнад главне класе вашег пројекта, односно класе изведене изApplication(подразумевано постављено наresources),ResourcePathје одређено анотацијом@Pathизнад класе ресурса којем приступа, на примерpopravke, иEndpointPathје одређено анотацијом@Pathизнад методе за тај endpoint.
- Уколико је endpoint сигурно добар, могуће је да је апликација undeploy-ована због неке грешке у тренутном пројекту или некој од претходних итерација. Можете покушати да рестартујете GlassFish сервер и пратити сервер лог (GlassFish Server таб у Output прозору) да видите уколико се појављује нека грешка.
- Прво проверите да ли сте добро уписали путању endpoint-а. Endpoint-ови су генерално на путањи
- Уколико вам се дешава HTTP грешка 500 (Internal Server Error), требало би да део грешке видите на страници, али целу грешку можете пронаћи у сервер логу.
- Уколико вам се у endpoint методи нађе аргумент без анотације поред себе, такав аргумент се шаље кроз тело (body) захтева, и у Postman треба поставити body на raw опцију. На пример,
Stringаргумент се шаље са типом садржајаtext/plain(Text опција у Postman), док се тип садржаја неке друге класе шаље као XML репрезентација те класе са типом садржајаapplication/xml(XML опција у Postman). - Уколико добијате
TransactionRequiredExceptionгрешку при слању упита на неки endpoint, проверите да ли сте ставили@Statelessанотацију изнад класе ресурса. - Уколико добијате HTTP 405 (Method Not Allowed) грешку, то вероватно значи да шаљете GET захтеве на endpoint који прима захтеве само преко других метода.
- Уколико вам се приликом враћања одговора са сервера деси
StackOverflowException, вероватно вам се десила бесконачна рекурзија при серијализацији објекта због недостатка@XmlTransientанотације која спречава серијализацију неког поља. То се обично дешава када класаAима поље типаBилиList<B>, а класаBпоље типаAилиList<A>, па серијализатор ради следеће:- креће са серијализацијом објекта класе
A, - нађе његово поље типа
Bи види да нема анотацију@XmlTransient, - креће са серијализацијом објекта класе
B, - нађе његово поље типа
Aи види да нема анотацију@XmlTransient, - поново креће са серијализацијом истог објекта класе
Aи тако у круг...
- Пример овога може да буде са вежби са компанијом за превоз, где, уколико ентитет
Zaposlenне би имао@XmlTransientанотацију изнадgetMehanicar()илиgetVozac()методе, дешавала би се бесконачна серијализација тих ентитета.
- креће са серијализацијом објекта класе
Грешке на вежбама
- Стефан Тубић на вежбама за MySQL сервер користи порт 3308. Стандардни и подразумевани порт за MySQL је 3306, тако да би требало да тај порт користите осим ако га нисте мењали.
- Ако имате више од једног MySQL сервера на рачунару, можда буде потребно да једном промените порт. Могуће је да је због овога Стефану Тубићу порт био промењен на 3308.
- Стефан Тубић је пред крај једних вежби направио грешку када је писао
persistence.xmlфајл и написао<jta-data-resource>уместо<jta-data-source>, па је на следећем снимку учитао готов пројекат и грешку приписао погрешној верзији Јаве. Ово вам може правити проблем уколико вам се јавља грешка како табелаKamionне постоји. Такође, у истом томpersistence.xmlфајлу је писалоtransactionTypeуместоtransaction-type, што вам исто може правити проблем. - У готовом пројекту за компанију за превозе (
kzp, пројекатrestapi) уMehanicari.javaфајлу налази се@PersistenceContext(unitName = "my_persistence_unit"), иако се јединица перзистенције зовеZad3PU. То може проузроковати неке грешке, барем у овом ресурсу. (Овај проблем је исправљен у пројекту на ИС1 виртуелној машини.) - У том истом пројекту, на
/api/users/{datum}endpoint није могуће послати упит док се мало не промени путања, јер иначе JAX-RS не зна да ли се упит шаље ту или на/api/users/{idUsr}endpoint (иста путања, различит параметар).
Лабораторијска вежба
- На лабораторијској вежби је дата слика базе у поставци, креденцијали за базу, опис поставке JDBC ресурса, dump фајл базе који можете да увезете кроз MySQL Workbench и материјали са странице предмета у директоријуму Materijal za drugu laboratorijsku vezbu.
- Лабораторијска вежба, уколико нема аутоматских тестова, се не прегледа нарочито детаљно. Бодови се добијају на лицу места.
- Подразумевана JDK верзија на лабораторијским рачунарима је JDK 11, па је након прављења пројекта потребно да је промените на JDK 8 у Properties → Compile.