BookStore 1.0 Enterprise Application, GitExt, Gradle, JBoss, Log4j Óbudai Egyetem, Java Enterprise Edition Műszaki Informatika szak Labor 2 Bedők Dávid 2016.09.30. v1.1
Struktúra I 2
Struktúra II 3
Egyszerűsített könyvesbolt Feladat: hozzunk létre egy alkalmazást, mely egy könyvesbolt könyveinek kezelésére alkalmas (CRUD műveletek). Alkalmazandó technikák: Java Enterprise Edition 6 Servlet API 3.0.1 Java EE 6 3.0.x Java EE 7 3.1 JBoss 6.4 4
Ismeretszerzés Gradle projekt hierarchia létrehozása Git folytatás Enterprise JavaBean (ejb) alapok mint business layer Egyszerű servlet mint weblayer Mockolt adatok mint persistence layer 5
Enterprise Gradle project Több projekt, hierarchiába szervezve Weblayer gradle java és war plugin war EAR web module-ja EJBService gradle java plugin jar EAR ejb module-ja Root project gradle ear plugin ear 6
WAR - Web application ARchive META-INF/ MANIFEST.MF WEB-INF/ classes/ hu/ qwaevisz/ demo/ Lorem.class Ipsum.class lib/ dummy.jar web.xml index.html public resources logo.jpg base.css <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/java ee" xmlns:xsi="http://www.w3.org/2001/xmls chema-instance" xsi:schemalocation="http://java.sun.co m/xml/ns/javaee http://java.sun.com/xml/ns/javaee/webapp_3_0.xsd">... </web-app> web.xml web application deployment descriptor 7
EAR - Enterprise ARchive META-INF/ MANIFEST.MF application.xml lib/ dummy.jar xzy.jar abc.war (3rd party) library ejb module web module <?xml version="1.0"?> <application xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" version="6"> <display-name> sample</display-name> <module> <ejb>xzy.jar</ejb> </module> <module> <web> <web-uri> abc.war</web-uri> <context-root> abcwebapp</context-root> </web> </module> <library-directory> lib</library-directory> </application> application.xml 8
Könyvtárak és build file-ok bookstore/ bs-ejbservice/ src/ main/ java/ build.gradle bs-weblayer/ src/ main/ java/ build.gradle build.gradle settings.gradle 9
Root EAR project apply plugin: 'eclipse' apply plugin: 'ear' bookstore\build.gradle dependency configuration (ear plugin): deploy és earlib dependencies { deploy project('bs-ejbservice') deploy project(path: 'bs-weblayer', configuration: 'archives') project( [NAME] ) include 'bs-ejbservice' include 'bs-weblayer' bookstore\settings.gradle >gradle ear 10
EJB Service subproject apply plugin: 'eclipse' apply plugin: 'java' bookstore\bs-ejbservice\build.gradle repositories { mavencentral() jar { archivename 'bs-ejbservice.jar' pontosan ez az alapértelmezés is, így elhagyható dependencies { compile group: 'javax', name:'javaee-api', version:'6.0' 11
Web Layer subproject apply plugin: 'eclipse' apply plugin: 'java' apply plugin: 'war' repositories { mavencentral() war { archivename 'bs-weblayer.war' dependencies { providedcompile project(':bs-ejbservice') providedcompile group: 'javax.servlet', name:'javax.servlet-api', version:'3.0.1' providedcompile group: 'javax', name:'javaee-api', version:'6.0' bookstore\bs-weblayer\build.gradle dependency configuration (war plugin): providedcompile (kell a fordításhoz, de adja a container) és providedruntime (adja a container) Használható a java plugin compile dc-je is: kell a fordításhoz, és nem adja a container, ezért belekerül a WEB-INF/lib -be. >gradle war A : jelentése egy project neve előtt azt jelzi, hogy a project-el a root project-től kiindulva kell keresni (absolute elérés lesz, nem pedig relative). 12
Repository BookStore with Gradle GIT \jboss\bookstore-light >gradle clean build DE! Vannak lokális változásaink, miközben az origin/master (branch) szintén változott! Megjegyzés: a gradle build-je ear plugin esetén ear-t, war plugin esetén war-t, java plugin esetén compile-t fog futtatni 13
Git alapok Working copy kiválasztása (root könyvtárban) >git checkout. Lokális módosítások eldobása >git reset --hard Új állományok/könyvtárak eldobása >git clean -fd Változások leszedése a master-ről >git pull 14
GitExtensions http://gitextensions.github.io/ https://github.com/gitextensions Grafikus felületet biztosít a Git parancsok végrehajtásához A Git használat nem lineáris, és ugyanaz a feladat többféleképpen is megoldható. Minden külső eszköz használata e végett magában foglal némi kockázatot (nem biztos hogy a tool azt hajtja végre, amit mi szeretnénk). Alapfunkciók esetén szinte kockázatmentes. 15
Enterprise JavaBeans Szerveroldali üzleti komponensek (back-end services) JSR19, JSR152, JSR220, JSR318, JSR345 IBM (1997), majd Sun Microsystems (1999) Egyfajta best-practice annak érdekében, hogy az üzleti értéket kelljen csak fejleszteni, ne a tipikus keret dolgokat Tranzakciókezelés Konkurenciakezelés Aszinkron metódushívás Eseménykezelés Java Message Service integráció (Message Driven Beans) Perzisztencia integráció támogatása (de már nem része a persistence az EJB specifikációnak) EJB1: minden remote EJB2: nagyon kényelmetlen, túlbonyolított EJB3: a Spring framework és a Hibernate tapasztalai alapján újraalkotott elképzelés (POJO-kat dolgozik mint Spring FW, és szakít az entity bean-ekkel, és inkább csak támogatja a perzisztens réteget, nem megvalósítja. 16
EJB Típusok Session Beans Stateless SB (állapotmentes) SLSB Stateful SB (állapottartó) SFSB Aktiválás/Passziválás (szerializálhatóság fontos) N kliens K db bean probléma esetére, ha N > K Singleton SB ( egyke ) SSB Message Driven Beans (üzenetvezérelt) MDB Elsősorban aszinkron feldolgozás Nincs kliens interface Entity Beans Deprecated, EJB 3.X-től a JPA helyettesíti 17
Business Layer Definiáljunk néhány üzleti metódust! BookStub getbook ( String isbn ) List<BookStub> getbooks ( BookCriteria criteria ) Definiáljuk a hozzájuk szükséges DTO-kat BookStub isbn (String), author (String), title (String), category (BookCategoryStub), price (double), numberofpages (int) BookCriteria author (String), title (String), minprice (int), maxprice (int) ISBN: International Standard Book Number 18
Domain osztályok létrehozása I package hu.qwaevisz.bookstrore.ejbservice.domain; public enum BookCategoryStub { SCIFI, LITERATURE, HISTORICAL; package hu.qwaevisz.bookstore.ejbservice.domain; public class BookStub { private String isbn; private String author; private String title; private BookCategoryStub category; private double price; private int numberofpages;... BookCategoryStub BookStub 19
Domain osztályok létrehozása II BookCriteria package hu.qwaevisz.bookstore.ejbservice.domain; public class BookCriteria { private String author; private String title; private BookCategoryStub category; private int minimumprice; private int maximumprice;... 20
Stateless Session Bean Local interface BookFacade package hu.qwaevisz.bookstore.ejbservice.facade; import java.util.list; import javax.ejb.local; import hu.qwaevisz.bookstore.ejbservice.domain.bookcriteriastub; import hu.qwaevisz.bookstore.ejbservice.domain.bookstub; @Local public interface BookFacade { @Remote: költséges és lassú (hálózati hívás, serializáció), RMI, eredeti koncepció csak ezt támogatta, különböző JVM-ek között használjuk @Local: olcsó és gyors, azonos JVM-en belül BookStub getbook(string isbn); List<BookStub> getbooks(bookcriteria criteria); 21
Stateless Session Bean Implementation import hu.qwaevisz.bookstore.ejbservice.domain.bookstub; BookFacadeImpl @Stateless(mappedName = "ejb/bookfacade") public class BookFacadeImpl implements BookFacade { @Override public BookStub getbook(string isbn) { return new BookStub(...); @Stateless: Stateless Session Bean name: ejb neve, def: unqualified név mappedname: global JNDI név description: leírás @Override public List<BookStub> getbooks(bookcriteria criteria) { List<BookStub> stubs = new ArrayList<>(); stubs.add(new BookStub(...)); return stubs; 22
Servlet Tesztelési célból package hu.qwaevisz.bookstore.weblayer.servlet;.. @WebServlet("/BookPing") public class BookPingServlet extends HttpServlet { @EJB private BookFacade facade; @Override protected void doget(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { BookStub book = this.facade.getbook("978-0441172719"); BookPingServlet response.setcharacterencoding("utf-8"); PrintWriter out = response.getwriter(); out.println(book.tostring()); out.close(); 23
Red Hat JBoss Middleware Enterprise Application Platform http://www.jboss.org/ Install (unzip) v7.0.0 (latest, 2016.05.10.) JEE 7 compliant v6.4.0 (latest, 2015.04.15.) JEE 6 compliant Commercial (!) Standalone/Domain mode Free: http://wildfly.org/ Content (https://access.redhat.com/articles/112673) RESTEasy - 2.3.10.Final Hibernate Core - 4.2.18.Final Hibernate JPA 2.0 API - 1.0.1.Final JSF2-2.1.28.Final HornetQ - 2.3.25.Final (EAP 7.x JBoss A-MQ) JBoss Logging - 3.1.4.GA JAXB - 2.2.5-redhat-9 Apache Web Server - 2.2.26... 24
JBoss - Standalone mode Start standalone (standalone.xml) >[JBOSSHOME]/bin/standalone.bat Start standalone (custom.xml mint standalone.xml) >[JBOSSHOME]/bin/standalone.bat custom.xml Stop standalone >[JBOSSHOME]/bin/jboss-cli.sh --connect command=:shutdown Standalone ([JBOSSHOME]/standalone) /configuration/standalone.xml /deployments /logs/server.log 25
Deploy [GIT]\oejee\jboss\bookstore\build\libs\bookstore.ear copy to: [JBOSS-HOME]\standalone\deployments\ server.log 13:07:06,946 INFO [org.jboss.as.ejb3.deployment.processors.ejbjndibindingsdeploymentunitprocessor] (MSC service thread 1-3) JNDI bindings for session bean named BookFacadeImpl in deployment unit subdeployment "bs-ejbservice.jar" of deployment "bookstore.ear" are as follows: java:global/bookstore/bs-ejbservice/bookfacadeimpl!hu.qwaevisz.ejbservice.facade.bookfacade java:app/bs-ejbservice/bookfacadeimpl!hu.qwaevisz.ejbservice.facade.bookfacade java:module/bookfacadeimpl!hu.qwaevisz.ejbservice.facade.bookfacade java:global/bookstore/bs-ejbservice/bookfacadeimpl java:app/bs-ejbservice/bookfacadeimpl java:module/bookfacadeimpl 13:07:06,975 INFO [org.jboss.web] (ServerService Thread Pool -- 196) JBAS018210: Register web context: /bs-weblayer 13:07:07,047 INFO [org.jboss.as.server] (DeploymentScanner-threads - 2) JBAS015859: Deployed "bookstore.ear" (runtime-name : "bookstore.ear") 26
Teszt http://localhost:8080/bs-weblayer/bookping BookStub [isbn=978-0441172719, author=frank Herbert, title=dune, category=scifi, price=3500.0, numberofpages=896] 27
Gradle Refactor (root project) Módosítás ext { testngversion = '6.9.+' jeeversion = '6.0' servletapiversion = '3.0.1' subprojects { apply plugin: 'eclipse' apply plugin: 'java' sourcecompatibility = 1.7 targetcompatibility = 1.7 repositories { mavencentral() dependencies { compile group: 'javax', name: 'javaee-api', version: jeeversion testcompile group: 'org.testng', name: 'testng', version: testngversion bookstore\build.gradle A subprojects{ blokk minden gyermek build script-re érvényes (merge), és létezik egy allprojects { blokk is, mely mind az aktuális (ez esetben a root), mind a gyermek scriptekre érvényes. 28
Gradle Refactor (ejbservice project) Csere bookstore\bs-ejbservice\build.gradle jar { archivename 'bs-ejbservice.jar' Mivel ez az alapértelmezés, akár üres is lehetne ez a build file. 29
Gradle Refactor (weblayer project) Csere apply plugin: 'war' bookstore\bs-weblayer\build.gradle war { archivename 'bs-weblayer.war' dependencies { providedcompile project(':bs-ejbservice') providedcompile group: 'javax.servlet', name: 'javax.servlet-api', version: servletapiversion 30
Log4j http://logging.apache.org/log4j/2.x/ http://logging.apache.org/log4j/1.2/ Latest 2.x: Apache Log4j 2.3 (Log4j2) Latest 1.2: Apache Log4j 1.2.17 JBoss 6.4 egyelőre a Log4j 1.2-őt támogatja. 31
Log4J Loggers Összerendeli a Java csomagot, a log level-t és az appendereket (1 logger N appender) Egy ún. Root Logger mindig létezik. Appenders Definiálja a log üzenet pattern -jét, a logolás típusát (pl. file, rolling file, e-mail, jms message, stb.) Standalone alkalmazás esetében log4j(2).xml vagy log4j(2).properties állományban konfiguráljuk Jboss esetében a Logging subsystem wrappeli, és 32
Log Levels TRACE DEBUG INFO WARN ERROR FATAL Nagyon részletes adatok, csak kivételes esetben érdemes bekapcsolni (pl. ciklusmagok belsejének logjai) Hibakeresési/fejlesztési szint. Végigkövetik a log üzenetek az üzleti folyamatokat komponens szinten. A Debug logok segítségével reprodukálható pl. a felhasználó tevékenysége. Azok az üzenetek, melyek minden esetben jelenjenek meg a logban. Külünösen fontos és semmiképpen sem gyakori események írhatóak ki ezen a szinten. Az Info szintű üzenetek kb. a hahó, itt vagyok típusúak, belőlük pl. hibát keresni, reprodukálni nem lehet. Figyelmeztetés. Általában olyan esemény, mely azért nem hiba, mert az alkalmazás lekezeli valamilyen módon, vagy pl. a tranzakció végrehajtódik, de bizonyos korlátozásokkal. Hiba. Olyan részletes leírást tartalmazzon, amennyire lehetséges. Ez lesz az az információ, amit a hibajegy javításakor birtokolni fogunk. Ez alapján kérni kell tudni a reprodukciót (mely során már kérhetünk debug logokat is). Ritkán alkalmazzuk. Végzetes hiba. Az ügyfelek már az Error esetén is üvöltenek, nem érdemes fatális hibákkal ijesztgetni őket. 33
Log4j és Gradle (root project) Módosítás ext {... log4jversion = '1.2.17' bookstore\build.gradle subprojects {... dependencies { compile group: 'log4j', name: 'log4j', version: log4jversion... 34
Ping Servlet - INFO logolás Módosítás public class BookPingServlet extends HttpServlet {... private static final Logger LOGGER = Logger.getLogger(BookPingServlet. class);... @Override protected void doget(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { LOGGER.info("Get Book by user");... BookPingServlet.java 35
BookFacade - DEBUG logolás Módosítás public class BookFacadeImpl implements BookFacade { BookFacadeImpl.java private static final Logger LOGGER = Logger.getLogger(BookFacadeImpl.class); @Override public BookStub getbook(string isbn) { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Get Book (isbn: " + isbn + ")");... alternatív megoldás (kevesebb kódsor): LOGGER.debug(String.format("Get Book (isbn: %s)", isbn); Fontos: production kódban a DEBUG üzenetek se a teljesítményt, se a memóriát ne terheljék, mivel valós futás közben általában a DEBUG szintet nem naplózzuk. A bemutatott megoldás egy logikai ellenőrzés költségű, míg az alternatív megoldás egy String literált elhelyez a permspace-en. A String összefűzés futását mindenképpen kerüljük el ilyen esetekben (ebből StringBuilder-t készt a fordító, de feleslegesen optimalizál ha nem naplózzuk). 36
JBoss Logging Subsystem standalone.xml áttekintés <server xmlns="urn:jboss:domain:1.7"> <extensions> <extension module="org.jboss.as.logging"/>... </extensions> <management>...</management> <profile> <subsystem xmlns="urn:jboss:domain:logging:1.5"> [APPENDERS DETAILS] [LOGGER DETAILS] </subsystem>... </profile> <interfaces>...</interfaces> <socket-binding-group>...</socket-binding-group> </server> standalone.xml 37
JBoss Logging Subsystem standalone.xml módosítás <console-handler name="console">...</console-handler> <periodic-rotating-file-handler name="file">...</periodic-rotating-file-handler> <logger category="hu.qwaevisz"> <level name="debug"/> </logger> <root-logger> <level name="info"/> <handlers> <handler name="console"/> <handler name="file"/> </handlers> </root-logger> <formatter name="pattern">...</formatter> standalone.xml 38
Git - Commit, Push Állapot lekérdezése >git status Stage >git add [FILENAME] Commit (-a/--all, -m/--message) >git commit -a -m [COMMIT_MESSAGE] Változások felküldése a master-re (authentication) >git push 39