{"id":164,"date":"2015-05-25T09:28:12","date_gmt":"2015-05-25T09:28:12","guid":{"rendered":"http:\/\/h2916922.stratoserver.net:8084\/?p=164"},"modified":"2015-05-26T20:25:24","modified_gmt":"2015-05-26T20:25:24","slug":"jax-rs-ejb-and-jpa-eclipselink-mysql-using-annotations","status":"publish","type":"post","link":"https:\/\/www.ivojonker.nl\/?p=164","title":{"rendered":"Java EE: JAX-RS, EJB en JPA (EclipseLink \/ Mysql)  mbv annotaties."},"content":{"rendered":"<p>In de meeste gevallen kom ik als javaan ergens binnen om aan bestaande functionaliteit te werken. Maar, het leukste blijft toch om alles &#8216;from scratch&#8217; bouwen.<\/p>\n<p>In dit artikel niet zozeer een verhaal over nieuwe technieken, of mijn &#8216;from scratch&#8217; aanpak, maar simpelweg een stuk voorbeeld code + uitleg om te laten zien hoe gemakkelijk de technieken uit de titel zijn in te zetten.<\/p>\n<h3>Als eerste wat context<\/h3>\n<p>Om het geheugen op te frissen, of om wat gaten in te vullen, van links naar rechts:<\/p>\n<p><b>JAX-RS <\/b>is een api waarmee REST webservices gemaakt kunnen worden. Deze vorm van webservices is met name populair omdat het gebouwd is op de HTTP\/1.1 specificatie waardoor het super gemakkelijk te begrijpen is, of aan te sluiten aan je frontend. (Zie <a title=\"JAX-RS specificatie\" href=\"https:\/\/jax-rs-spec.java.net\/\" target=\"_blank\">@Specificatie<\/a>, <a title=\"JAX rs @ Wikipedia\" href=\"http:\/\/en.wikipedia.org\/wiki\/Java_API_for_RESTful_Web_Services\" target=\"_blank\">@Wikipedia<\/a>). (Sinds EE5)<\/p>\n<p><strong>EJB<\/strong> of&#8221;Enterpsie JavaBeans&#8217; zijn bedoeld voor\u00a0je applicatie logica en draaien binnen een EJB container op je applicatieserver. De EJB\u00a0schrijft o.a.\u00a0voor hoe omgegaan dient te worden met zaken als trancties, concurrency en security. Het schrijven van EJB&#8217;s is pas echt een feest sinds EJB 3.0 waar annotaties de\u00a0warboel van deployment descriptors en interfaces hebben vervangen. (<a title=\"EJB @ Wikipedia\" href=\"http:\/\/en.wikipedia.org\/wiki\/Enterprise_JavaBeans\" target=\"_blank\">@Wikipedia<\/a>)<\/p>\n<p><strong>JPA\u00a0<\/strong>of &#8216;Java Persistence API&#8217; is een een specificatie die beschrijft hoe van uit Java\u00a0met (relationele) data omgegaan dient te worden. Met JPA breng je een object-relational-mapping tot stand o.b.v. annotaties. \u00a0JPA kent een aantal implementaties waarvan de bekendste wellicht Hibernate is.<\/p>\n<p><strong>EclipseLink\u00a0<\/strong>is de &#8216;referentie implementatie&#8217; voor JPA en is (net zoals overigens Hibernate) volledig JPA 2.0 complient. \u00a0(<a title=\"EclipseLink FAQ\" href=\"https:\/\/wiki.eclipse.org\/EclipseLink\/FAQ\/JPA\" target=\"_blank\">@EclipseLink FAQ<\/a>, <a title=\"EclipseLink @ Wikipedia\" href=\"http:\/\/en.wikipedia.org\/wiki\/EclipseLink\" target=\"_blank\">@Wikipedia<\/a>)<\/p>\n<p><strong>MySQL\u00a0<\/strong>is\u00a0&#8216;s werelds meest gebruikte opensource RDBMS. En vergt volgens mij geen verdere toelichting.<\/p>\n<h3>De implementatie<\/h3>\n<p>Welnu, de voorbeeld implementatie betreft een denkbeeldig onderdeel van een beheerplatform. Het stukje &#8216;UserManagement&#8217; is bedoeld om informatie van gebruikers van &#8216;het systeem&#8217; aan te maken, of te raadplegen.<\/p>\n<p>De demo bestaat uit een Stateless Session Bean (SSB) &#8216;UserManagement&#8217; die met zijn twee methoden (t.b.v create\/retreive) beschikbaar wordt gesteld via JAX-RS. De User objecten worden gemanaged, opgehaald en opgeslagen in MySQL d.m.v. EclipseLink.<\/p>\n<p><b>1. Structuur \/ overzicht<\/b><\/p>\n<p>Om te beginnen hieronder een overzicht van\u00a0het project. In dit project zit geen web.xml, alle configuratie gebeurt o.b.v. annotaties.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-178\" src=\"http:\/\/h2916922.stratoserver.net:8084\/wp-content\/uploads\/2015\/05\/Java-EE-JAX-RS-EJB-and-JPA-EclipseLink-Mysql-mbv-annotaties..png\" alt=\"Java EE JAX-RS, EJB and JPA (EclipseLink Mysql)  mbv annotaties.\" width=\"317\" height=\"226\" srcset=\"https:\/\/www.ivojonker.nl\/wp-content\/uploads\/2015\/05\/Java-EE-JAX-RS-EJB-and-JPA-EclipseLink-Mysql-mbv-annotaties..png 317w, https:\/\/www.ivojonker.nl\/wp-content\/uploads\/2015\/05\/Java-EE-JAX-RS-EJB-and-JPA-EclipseLink-Mysql-mbv-annotaties.-300x214.png 300w, https:\/\/www.ivojonker.nl\/wp-content\/uploads\/2015\/05\/Java-EE-JAX-RS-EJB-and-JPA-EclipseLink-Mysql-mbv-annotaties.-150x107.png 150w, https:\/\/www.ivojonker.nl\/wp-content\/uploads\/2015\/05\/Java-EE-JAX-RS-EJB-and-JPA-EclipseLink-Mysql-mbv-annotaties.-100x71.png 100w\" sizes=\"auto, (max-width: 317px) 100vw, 317px\" \/><\/p>\n<p><strong>2. EclipseLink &amp; Mysql configuratie<\/strong><\/p>\n<p>De basisconfiguratie van JPA wordt gevormd door persistence.xml. Hierin configureer je &#8216;Persistence Units&#8217;. Een persistent unit is een groep van &#8216;persistable classes&#8217; met bijbehorende configuratie.<\/p>\n<pre class=\"lang:xhtml decode:true\" title=\"persistence.xml\">&lt;persistence-unit name=\"default\" transaction-type=\"JTA\"&gt;\r\n\t&lt;provider&gt;org.eclipse.persistence.jpa.PersistenceProvider&lt;\/provider&gt;\r\n\r\n\t&lt;jta-data-source&gt;java:app\/ee6sample\/SampleDS&lt;\/jta-data-source&gt;\r\n\r\n\t&lt;exclude-unlisted-classes&gt;false&lt;\/exclude-unlisted-classes&gt;\r\n\r\n\t&lt;properties&gt;\r\n\t\t&lt;property name=\"eclipselink.ddl-generation\" value=\"create-tables\" \/&gt;\r\n\t\t&lt;property name=\"eclipselink.ddl-generation.output-mode\"\tvalue=\"database\" \/&gt;\r\n\t&lt;\/properties&gt;\r\n&lt;\/persistence-unit&gt;<\/pre>\n<p>In bovenstaand voorbeeld configureren we een persisten-unit met de naam &#8216;default&#8217;. Het &#8216;transaction-type&#8217; JTA (<a title=\"JTA @ Wikipedia\" href=\"http:\/\/en.wikipedia.org\/wiki\/Java_Transaction_API\" target=\"_blank\">@wiki<\/a>) wordt afgedwongen doordat we JPA binnen de EJB managed context gebruiken.<\/p>\n<p>We gebruiken EclipseLink (&lt;provider\/&gt;) en maken gebruik van de &#8216;java:app\/ee6sample\/SampleDS&#8217; datasource (zie volgend onderdeel).<\/p>\n<p>Waar je normaal gesproken met &lt;class\/&gt; configureert welke klassen bij deze persistence-unit horen, geven we in dit voorbeeld aan dat niet geconfigureerde klassen opgenomen kunnen worden in deze PU. Met slechts \u00e9\u00e9n PU laten we alle klassen dus managen door default. (exclude-unlisted-classes = false).<\/p>\n<p>Aanvullend specificeren we dat de DDL voor de tabellen direct op de databases uit laten voeren. Anders verwoord, JPA gaat de tabellen aanmaken voor onze applicatie.<\/p>\n<p><strong>3. Datasources.java &#8211; Datasource registratie m.b.v. annotaties<\/strong><\/p>\n<p>Sinds\u00a0JSR-250 is er de mogleijkheid om datasources te regiteren met behulp van de annotaties @DataSourceDefinition en @DataSourceDefinitions. Voorheen was het altijd nodig om deze configuratie in de applicatie server uit te voeren, maar nu wordt deze configuratie dus portable.<\/p>\n<p>Onderstaand codevoorbeeld registreert een datasource in de applicatie scope.<\/p>\n<pre class=\"lang:java decode:true\" title=\"Datasources.java\">package nl.ivojonker.ee6sample.configuration;\r\n\r\nimport javax.annotation.sql.DataSourceDefinition;\r\n\r\n\r\n\/**\r\n * Registers the following datasources: \r\n * \t\tjava:app\/ee6sample\/SampleDS\r\n * \r\n * web.xml allow's to override the defaults.\r\n * @author ivo.jonker\r\n *\/\r\n\r\n@DataSourceDefinition(\r\n\t\tname = \"java:app\/ee6sample\/SampleDS\",\r\n\t\tclassName = \"com.mysql.jdbc.jdbc2.optional.MysqlXADataSource\",\r\n\t\turl = \"jdbc:mysql:\/\/localhost:3306\/ivo\",\r\n\t\tuser = \"root\",\r\n\t\tpassword = \"\") \r\n\r\npublic class Datasources {\r\n\r\n}<\/pre>\n<p>Deze configuratie valt uiteraard onder de noemer &#8216;hard-coded&#8217;, maar kan eventueel worden overriden in de web.xml<\/p>\n<p><strong>4. User.java &#8211; een JPA managed entiteit<\/strong><\/p>\n<p>De klasse User is een POJO geannoteerd met @Entity waarmee we zeggen dat dit een door &#8216;JPA gemanagde entiteit&#8217; is.\u00a0Met de aangebrachte annotatie zal deze entiteit corresponderen met de\u00a0<span class=\"lang:default decode:true  crayon-inline \"> tabel User (ID int(11) primary key, NAME varchar(255))<\/span>\u00a0.<\/p>\n<p>De tabel &#8211; indien hij niet bestaat &#8211; zal automatisch worden aangemaakt door EclipseLink. Waarden voor ID zullen automatisch worden gegenereerd (@Id).<\/p>\n<pre class=\"lang:default decode:true\">package nl.ivojonker.ee6sample.model;\r\n\r\nimport javax.persistence.Entity;\r\nimport javax.persistence.GeneratedValue;\r\nimport javax.persistence.Id;\r\n\r\n@Entity\r\npublic class User {\r\n\r\n\t@Id\r\n\t@GeneratedValue\r\n\tprivate int id;\r\n\t\r\n\tprivate String name;\r\n\r\n\tpublic int getId() {\r\n\t\treturn id;\r\n\t}\r\n\r\n\tpublic void setId(int id) {\r\n\t\tthis.id = id;\r\n\t}\r\n\r\n\tpublic String getName() {\r\n\t\treturn name;\r\n\t}\r\n\r\n\tpublic void setName(String name) {\r\n\t\tthis.name = name;\r\n\t}\r\n}\r\n<\/pre>\n<p>Uiteraard zijn er veel meer annotaties en instellingen, een mooi overzicht vondt ik op de website van de <a title=\"JPA annotations\" href=\"http:\/\/www.objectdb.com\/api\/java\/jpa\/annotations\" target=\"_blank\">ObjectDB JPA implementatie<\/a>.<\/p>\n<p><strong>\u00a05. UserManagement.java &#8211; een JAX-RS exposed SSB met een EntityManager<\/strong><\/p>\n<p>De klasse UserManagement\u00a0bevat de business logica voor het managen\u00a0van users. In dit geval een Stateless Session Bean (@Stateless) met twee methoden. Een om een user mee aan te maken, een andere om user-gegevens op te vragen a.d.h.v. een user id. Beide methoden worden aangeboden\u00a0via JAX-RS webservices. De\u00a0annotaties spreken voor zich wanneer je beseft dat ze het volgende mogelijk maken:<\/p>\n<p style=\"padding-left: 30px;\"><em>HTTP PUT http:\/\/localhost:8080\/Demo\/rest\/users?name=Ivo<\/em><br \/>\nOm een nieuwe gebruiker aan te maken<\/p>\n<p style=\"padding-left: 30px;\"><em>HTTP GET http:\/\/localhost:8080\/Demo\/rest\/users?id=1<\/em><br \/>\nOm een gebruikergegevens met id 1 op te halen uit de database.<\/p>\n<p>Met @PersistenceContext injecteren we een container-managed entity manager. Deze gebruiken we vervolgens om nieuwe Users aan te maken of terug te halen uit de database.<\/p>\n<p><em>Naast de @QueryParam kun je ook nog annotaties als \u00a0@MatrixParam, @HeaderParam, @CookieParam, @FormParam gebruiken om b.v. headers of cookiers te benaderen.<\/em><\/p>\n<pre class=\"lang:java decode:true\" title=\"UserManagement.java\">package nl.ivojonker.ee6sample.logic;\r\n\r\nimport javax.ejb.Stateless;\r\nimport javax.persistence.EntityManager;\r\nimport javax.persistence.PersistenceContext;\r\nimport javax.ws.rs.GET;\r\nimport javax.ws.rs.PUT;\r\nimport javax.ws.rs.Path;\r\nimport javax.ws.rs.Produces;\r\nimport javax.ws.rs.QueryParam;\r\n\r\nimport nl.ivojonker.ee6sample.model.User;\r\n\r\n@Stateless\r\n@Path(\"\/users\")\r\n@Produces(\"text\/plain\")\r\npublic class UserManagement {\r\n\t\r\n\t@PersistenceContext\r\n\tEntityManager em;\r\n\r\n\t@GET\r\n\tpublic String getUser(@QueryParam(\"id\") int id){\r\n\t\tUser user = em.find(User.class, id);\r\n\t\treturn \"username: \"+user.getName();\r\n\t}\r\n\t\r\n\t@PUT\r\n\tpublic String createUser(@QueryParam(\"name\") String name){\r\n\t\tUser newUser = new User();\r\n\t\tnewUser.setName(name);\r\n\t\t\r\n\t\tem.persist(newUser);\r\n\t\t\r\n\t\treturn \"New user created with id: \"+newUser.getId();\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>\u00a06.\u00a0JerseyConfig.java<\/strong><\/p>\n<p><a href=\"https:\/\/jersey.java.net\/\">Jersey <\/a>is JAX-RS implementatie die zich erg gemakkelijk laat configureren. \u00a0In het voorbeeld doen we dit met een annotatie waarmee we alle classes in de nl.ivojonker.ee6sample.logic package exposen binnen het rest path.<\/p>\n<p>Alternatief laat Jersey zich ook prima in de <a href=\"https:\/\/jersey.java.net\/documentation\/latest\/deployment.html#deployment.servlet\">web.xm<\/a>l file configuren.<\/p>\n<pre class=\"lang:java decode:true\" title=\"JerseyConfig.java\">package nl.ivojonker.ee6sample.configuration;\r\n\r\nimport javax.ws.rs.ApplicationPath;\r\n\r\nimport org.glassfish.jersey.server.ResourceConfig;\r\n\r\n\/**\r\n * Registers the JAX-rs path rest for classes within the nl.ivojonker.* package.\r\n * @author ivo.jonker\r\n *\r\n *\/\r\n@ApplicationPath(\"rest\")\r\npublic class JerseyConfig extends ResourceConfig {\r\n\r\n    public JerseyConfig() {\r\n        packages(\"nl.ivojonker.ee6sample.logic\");\r\n    }\r\n}<\/pre>\n<p>Makkelijk toch?<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In de meeste gevallen kom ik als javaan ergens binnen om aan bestaande functionaliteit te werken. Maar, het leukste blijft toch om alles &#8216;from scratch&#8217; bouwen. In dit artikel niet [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-164","post","type-post","status-publish","format-standard","hentry","category-geen-categorie"],"_links":{"self":[{"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/posts\/164","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=164"}],"version-history":[{"count":37,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/posts\/164\/revisions"}],"predecessor-version":[{"id":202,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=\/wp\/v2\/posts\/164\/revisions\/202"}],"wp:attachment":[{"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=164"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=164"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ivojonker.nl\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=164"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}