Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Enterprise Web App. Development (6): JAX-RS Training

Enterprise Web App. Development (6): JAX-RS Training

This is the sixth course of a series of courses for Enterprise Web Application development based on several Open Source products. As we finished JPA + JTA with CDI course, we are going to move on to “JAX-RS” as the third course of Jakarta EE framework specification. Later we are taking care of “Jakarta Batch” as minimum skills to develop Enterprise Web Application. In those courses, we refer to some “Application Architecture Design Patterns”. Therefore this series require the basic skills of Windows 10, CentOS, Eclipse IDE, Java SE (Oracle JDK or OpenJDK), Payara Server and PostgreSQL. Regarding the Payara Server, we can use another Web Application Server conforming to Jakarta EE specification. As for PostgreSQL, we might be able to use another RDBMS product instead. We can also make use of another Linux distribution instead of CentOS.

E7d0d73badb1cc1df2bc44f58d51aaff?s=128

Koichi NAKAGAWA

November 26, 2020
Tweet

Transcript

  1. JAKARTA RESTFUL WEB SERVICES (JAX-RS) A part of Jakarta EE™

    specification RESTful Web Service Framework 1 By Koichi NAKAGAWA
  2. JAX-RS Jakarta RESTful Web Services (JAX-RS) 2

  3. EWA development course curriculum Object Oriented Development Methodology JSF with

    CDI JPA + JTA with CDI JAX-RS Application Architecture Design Patterns Eclipse IDE™ Version Control Tool with Git™ Build Tool with Apache Maven™ Payara Server™ Administration Windows 10™ + Linux (CentOS™) Total EWA Development Exercise Jakarta Batch Java SE (Oracle JDK™/OpenJDK™) Required Skills to take courses Test Tool with JUnit5 PostgreSQL™ Administration 3
  4. Trademarks Notice • Jakarta™ EE and its logo( ) are

    trademarks of the Eclipse Foundation. • PostgreSQL™ and its logo( ) are registered trademarks of the PostgreSQL Community Association of Canada. • Apache Derby™ and its logo ( ) are trademarks of the Apache Software Foundation. • Payara™ Server and their logo( ) are trademarks of Payara Services® LTD. • EclipseLink™, EclipseLink™ logo ( ), Eclipse IDE for Enterprise Java Developer™, the Eclipse IDE for Enterprise Java Developer ™ logo( ), Eclipse M2Eclipse™, M2Eclipse™, Eclipse GitTeam Provider™, Eclipse EGit™, EGit™, Eclipse Java development tools™, Java development tools™, Eclipse JDT™, JDT™ are trademarks of the Eclipse Foundation. • Apache Maven™, Maven™ are trademarks of the Apache Software Foundation (ASF). • Git™ and the Git™ logo( ) are either registered trademarks or trademarks of Software Freedom Conservancy, Inc., corporate home of the Git Project, in the United States and/or other countries. • Java™ is trademark of Oracle Corporation. 4
  5. Assumption for this course • The trainees who take this

    course are required the following skills in advance • PostgreSQL (Version: 12) – Basic Administration Operations • Payara Server (Version: 5.2020.5) – Basic Administration Operations • Oracle JDK/OpenJDK (Version: 8) • Eclipse IDE for Enterprise Java Developers (Version: 2020-09 (4.17.0)) • Build Tool Training Course • Version Control Tool Training Course • Test Tool Training Course • JSF with CDI Training Course • JPA + JTA with CDI Training Course 5
  6. Objectives This course is aimed to obtain the following skills

    • Jakarta RESTful Web Services (JAX-RS) technology • Development of RESTful Web Services applications using JAX-RS • Integration with Transactional CDI components in business layer 6
  7. JAX-RS • Concept of Jakarta RESTful WebServices (JAX-RS) • How

    to use JAX-RS • Architecture Design with JAX-RS and CDI • First JAX-RS Application • Other JAX-RS Programming • Exercise 7
  8. Concept of Jakarta RESTful WebServices (JAX-RS) 8

  9. Concept of JAX-RS • Communications between Applications 9 Requester (Server)

    Provider (Another Server) Service Request Message Response Message Application A Application B
  10. Concept of JAX-RS • Communication Technologies between Applications with Jakarta

    EE™ 10 Requestor (Server) Provider (Another Server) Service Request Message Response Message Technology Protocol Message Dist. Object Interface Over Internet Specification REST Service HTTP Text (URL Encode, XML, JSON) No Swagger base Possible JAX-RS EJB Remote Call RMI over IIOP Binary Yes Java Interface Impossible EJB SOAP Web Service SOAP over HTTP Text (XML) Yes WSDL Possible JAX-WS
  11. Concept of JAX-RS • HTTP Message 11 HTTP Requester HTTP

    Server HTTP Response HTTP Request • HTTP Structure Start Line (Request Line) Headers Body URI  http(s)://localhost/milkProducts  GET /milkProducts HTTP 1.1  Host: localhost  Null (Mainly used by POST/PUT Methods) Start Line (Status Line) Headers Body  HTTP/1.1 200 OK  Server: Apache  Cheese, Milk, Yogurt HTTP Request HTTP Response HTTP Provider
  12. Concept of JAX-RS • What is RESTful Web Services? 12

    HTTP Usage Uniform Interface HTTP Method URI HTTP Status No matter how many time a HTTP message is sent, resource should not be changed for GET and HEAD methods All HTTP Method should be utilized (GET, POST, PUT, DELETE, PATCH, HEAD) Point out a resource by URI ex. GET /employees/1234 All HTTP Status should be utilized (Not only 200(“OK”) and 500(“Internal Server Error”) but also 201(“Created”), 204(“No Content”), etc.) Safety Rule Idempotency Rule No matter how many time a HTTP message is sent, the result should be the same for GET, HEAD, PUT and DELETE methods Providers should provide their resource operation methods based on the uniformed rules. Providers should utilize the HTTP protocol fully following its original usages.
  13. Concept of JAX-RS • Architecture of JAX-RS 13 Requester Provider

    JAX-RS Engine Request Message (JSON, XML, …) Response Message (JSON, XML, …) Web Resource Class (POJO) Decode Call Resource Method Encode Resource Method Inputs (Java Objects) Outputs (Java Object) Jakarta EE Container
  14. How to use JAX-RS 14

  15. How to configure JAX-RS Engine • Architecture of JAX-RS 15

    Requester Provider JAX-RS Engine Request Message (JSON, XML, …) Response Message (JSON, XML, …) Web Resource Class (POJO) Decode Call Resource Method Encode Resource Method Inputs (Java Objects) Outputs (Java Object) Jakarta EE Container
  16. How to configure JAX-RS Engine • What is Application Path?

    16 JAX-RS Engine Decode Call Resource Method Encode REST Service URI with JAX-RS Engine http(s)://[Host Name or IP Address]:[port]/Context Path/Application Path/Request Path Configure the Application Path in one of the two ways.
  17. How to configure JAX-RS Engine • Configuration of Application Path

    (2 Ways) 17 JAX-RS Engine Decode Call Resource Method Encode Configuration in Custom Application • Using the @ApplicationPath for a subclass of javax.ws.rs.core.Application Configuration in web.xml • Using the servlet-mapping tag within the WAR’s web.xml
  18. How to configure JAX-RS Engine • Configuration of Application Path

    (By Custom Application) 18 JAX-RS Engine Decode Call Resource Method Encode Configuration in Custom Application • Using the @ApplicationPath for a subclass of javax.ws.rs.core.Application @ApplicationPath("/webapi") public class MyApplication extends Application { ... } @Override public Set<Class<?>> getClasses() { final Set<Class<?>> classes = new HashSet<>(); // register root resource classes.add(MyResource.class); return classes; } (Option) The Custom Application can define our Web Resource Classes to be used as well. Application Path Web Resource Class Custom Application
  19. How to configure JAX-RS Engine • Configuration of Application Path

    (By web.xml) 19 JAX-RS Engine Decode Call Resource Method Encode Configuration in web.xml • Using the servlet-mapping tag within the WAR’s web.xml <servlet-mapping> <servlet-name>javax.ws.rs.core.Application</servlet-name> <url-pattern>/webapi/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>com.example.rest.MyApplication</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> (Option) Application Path in your Custom Application can be changed. Application Path Changed Application Path Custom Application
  20. How to make Web Resource Class • Architecture of JAX-RS

    20 Requestor Provider JAX-RS Engine Request Message (JSON, XML, …) Response Message (JSON, XML, …) Web Resource Class (POJO) Decode Call Resource Method Encode Resource Method Inputs (Java Objects) Outputs (Java Object) Jakarta EE Container
  21. How to make Web Resource Class • Programming for Web

    Resource Class and Resource Method 21 Web Resource Class (POJO) Resource Method @Path("/restService")  Request Line: GET /Context Path/Application Path/restService public class RestService { : @GET @Path("/hello")  Request Line: GET /Context Path/Application Path/restService/hello @Produces(MediaType.TEXT_PLAIN)  MIME Type of Response Message: “text/xml”, “application/json”, etc. public String hello() { return "Hello World! "; } : } Request Line: GET /Context Path/Application Path/restService/hello Response Message: Hello World! Check the value of the “accept” attribute of HTTP Request Header Request Path Path Parameter
  22. How to make Web Resource Class • Input Types obtained

    from HTTP Request 22 Web Resource Class (POJO) Input Types Path Query Form (URL Encoded) Objects (JSON, XML, …) Using Body (For POST, PUT Only) Start Line (Request Line) Headers Body HTTP Request Using Request Line JAX-RS Engine
  23. How to make Web Resource • How to obtain Path

    Parameters from HTTP Request 23 Web Resource Class (POJO) Resource Method @Path(“/restService”) public class RestService { : @GET @Path(“/visit1/{visitorName}”) @Produces(MediaType.TEXT_PLAIN) public String visit1(@PathParam(“visitorName”) String visitorName) {  Obtain a Path Parameter set return “Welcome to the REST World, ” + visitorName + “!”; } : } Request Line: GET /Context Path/Application Path/restService/visit1/Smith URI Template Response Message: Welcome to the REST World, Smith!
  24. How to make Web Resource • How to obtain Query

    Parameters from HTTP Request 24 Web Resource Class (POJO) Resource Method @Path(“/restService”) public class RestService { : @GET @Path(“/visit2”) @Produces(MediaType.TEXT_PLAIN) public String visit2(@QueryParam(“visitorName”) String visitorName) {  Obtain a Query Parameter set return “Welcome to the REST World, ” + visitorName + “!”; } : } Request Line: GET /Context Path/Application Path/restService/visit2?visitorName=Smith Response Message: Welcome to the REST World, Smith!
  25. How to make Web Resource • How to obtain Form

    Parameters from HTTP Request 25 Web Resource Class (POJO) Resource Method @Path(“/restService”) public class RestService { : @POST @Path(“/visit3”) @Produces(MediaType.TEXT_PLAIN) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)  MIME Type of the POST Request public String visit3(@FormParam(“visitorName”) String visitorName) {  Obtain a Form Parameter set return “Welcome to the REST World, ” + visitorName + “!”; } : } Request Line: POST /Context Path/Application Path/restService/visit3 Request Body: <form> … <input … name=“visitorName” value=“Smith” …/> … </form> Response Message: Welcome to the REST World, Smith! Check the value of the “content-type” attribute of HTTP Request Header
  26. How to make Web Resource • How to obtain JSON

    String as Java Object from HTTP Request 26 Web Resource Class (POJO) Resource Method @Path(“/restService”) public class RestService { : @POST @Path(“/visit4”) @Produces(MediaType.TEXT_PLAIN) @Consumes(MediaType.APPLICATION_JSON)  MIME Type of the POST Request public String visit4(Visitor visitor) {  Obtain a JSON Object as a Parameter return “Welcome to the REST World, ” + visitor.getName() + “!”; } : } Request Line: POST /Context Path/Application Path/restService/visit4 Request Body: {“name”:“Smith”}  JSON KVS(Key-Value-Store) String Response Message: Welcome to the REST World, Smith!
  27. How to make Web Resource • Output Types in HTTP

    Response 27 Output Types Status Code Objects (Plain Text, JSON, XML, …) Exceptions (Message, Root Cause) Using Status Line Using Body Web Resource Class (POJO) Start Line (Status Line) Headers Body HTTP Response JAX-RS Engine
  28. How to make Web Resource • How to return Object(s)

    in HTTP Response 28 Web Resource Class (POJO) Resource Method @GET @Produces(MediaType.APPLICATION_JSON) public List<MilkProduct> milkProducts() { List<MilkProduct> list = new ArrayList<>(); …. return list;  Return some JSON encoded Entities } Examples to set the Object(s) encoded with JSON in Response Message @GET @Produces(MediaType.APPLICATION_JSON)  Set MIME Type of Response Message public MilkProduct milkProduct(@QueryParam("id") Integer id) { MilkProduct product = new MilkProduct(); …. return product;  Return a JSON encoded Entity }
  29. How to make Web Resource • How to return Status

    Code and Object(s) in HTTP Response 29 Web Resource Class (POJO) Resource Method @GET @Produces(MediaType.APPLICATION_JSON) public Response milkProducts() { List<MilkProduct> list = new ArrayList<>(); …. return Response.status(200).entity(new GenericEntity<List<MilkProduct>>(list){}).build();  Return some JSON encoded Entities } Examples to set the HTTP Status Code Specifically and Object(s) encoded with JSON in Response Message @GET @Produces(MediaType.APPLICATION_JSON)  Set MIME Type of Response Message public Response milkProduct(@QueryParam("id") Integer id) { MilkProduct product = new MilkProduct(); …. return Response.status(Response.Status.OK).entity(product).build();  Return a JSON encoded Entity }
  30. How to make Web Resource • How to return Exception

    in HTTP Response 30 Web Resource Class (POJO) Resource Method Example to set the Exception Message, Root Cause of with HTTP Status Code in Response Message public String hello(…) throws WebApplicationException { try { : } catch (BusinessException cause) { String message = “Your request does not have enough information”; throw new WebApplicationException(message, cause, Response.Status.NOT_ACCEPTABLE);  Set a Message and a Root Cause of Exception and 406 as HTTP Status and throw WebApplicationException } }
  31. How to make Requestor • Architecture of JAX-RS 31 Requester

    Provider JAX-RS Engine Request Message (JSON, XML, …) Response Message (JSON, XML, …) Web Resource Class (POJO) Decode Call Resource Method Encode Resource Method Inputs (Java Objects) Outputs (Java Object) Jakarta EE Container
  32. How to make Requestor • Program for Requestor (1) 32

    String response = ClientBuilder.newClient()  Create a client object .target("http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/hello")  Set target URI .request(MediaType.TEXT_PLAIN)  Set MIME type of Returned Entity .get(String.class);  Send a GET request expecting String type as a Returned Entity Requestor final String VISITOR_NAME = “Smith”; WebTarget myResource = ClientBuilder.newClient() .target("http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit1") .path("{visitorName}")  Set Path Parameter using template name .resolveTemplate("visitorName", VISITOR_NAME)  Set value for the above template name String response = myResource .request(MediaType.TEXT_PLAIN) .get(String.class); Request Line: GET /jaxrs_jsf_jpa/webapi/restService/visit1/Smith Request Line: GET /jaxrs_jsf_jpa/webapi/restService/hello
  33. How to make Requestor • Program for Requestor (2) 33

    final String VISITOR_NAME = “Smith”; WebTarget myResource = ClientBuilder.newClient() .target("http:// localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit2") .queryParam(“visitorName", VISITOR_NAME);  Specify a Query Parameter set String response = myResource.request(MediaType.TEXT_PLAIN).get(String.class); Requestor final String VISITOR_NAME = “Smith”; Form form = new Form(); form.param("visitorName", VISITOR_NAME); WebTarget myResource = ClientBuilder.newClient() .target("http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit3 "); String response = myResource.request(MediaType.TEXT_PLAIN) .post(Entity.entity(form,MediaType.APPLICATION_FORM_URLENCODED_TYPE), String.class);  set POST request including a FORM encoded order Entity expecting String Class as a Returned Entity. Request Line: POST /jaxrs_jsf_jpa/webapi/restService/visit3, Body: <form> … <input … name=“visitorName” value=“Smith” …/> … </form> Request Line: GET /jaxrs_jsf_jpa/webapi/restService/visit2?visitorName=Smith
  34. How to make Requestor • Program for Requestor (3) 34

    Requestor final String VISITOR_NAME = “Smith”; Visitor visitor = new Visitor(VISITOR_NAME); WebTarget myResource = ClientBuilder.newClient() .target("http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit4 "); String response = myResource.request(MediaType.TEXT_PLAIN) .post(Entity.entity(visitor, MediaType.APPLICATION_JSON), String.class);  set POST request including a FORM encoded order Entity expecting String Class as a Returned Entity. Request Line: POST /jaxrs_jsf_jpa/webapi/restService/visit4, Body: {“name”:”Smith”}
  35. How to make Requestor • Program for Requestor (4) 35

    Requestor final Integer ID = 1; WebTarget myResource = ClientBuilder.newClient() .target("http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/milkProduct") .queryParam(“id", ID); MilkProduct product = myResource.request(MediaType.APPLICATION_JSON) .get(MilkProduct.class);  send a GET request expecting a custom class of “MilkProduct.class” as a Single Returned Entity Request Line: GET /jaxrs_jsf_jpa/webapi/restService/milkProduct?id=1 List<MilkProduct> products = ClientBuilder.newClient() .target(" http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/milkProducts") .request(MediaType.APPLICATION_JSON) .get(new GenericType<List<MilkProduct>>() {});  Send a GET request expecting a Java Collection class of a custom class of “MilkProduct.class” as Multiple Returned Entities Request Line: GET /jaxrs_jsf_jpa/webapi/restService/milkProducts
  36. Architecture Design with JAX-RS and CDI 36

  37. Architecture Design • Architecture Design with JAX-RS and JSF in

    Presentation Layer 37 Presentation REST Req. Handler Web Resource CDI Web Req. Handler Named CDI Action Method Business Domain Service Transactional CDI Service Method Data Access O-R Mapper Entity Entity RDB Entity Entity Name: Vendor: ABC XYZ Update Update Results: Name ABC Vendor XYZ DTO DTO Jakarta EE Container Requester JSON JSON Resource Method DTO DTO
  38. JAX-RS with CDI • Program for Web Resource Class with

    CDI 38 Web Resource Class (CDI) Resource Method @RequestScoped  Make this Web Resource Class work as a RequestScoped CDI Class @Path(“/restService“) public class RestService { : @Inject EnterpriseService service;  Inject a Transactional CDI : @GET @Path(“/getProduct”) @Produces(MediaType.APPLICATION_JSON) public Response showProducts(@QueryParam(“productId”) String productId) { Product productInfo = service.getProduct(productId); return Response.status(200).entity(productInfo).build(); } : }
  39. First JAX-RS Application 39

  40. Requester Provider Example of First JAX-RS Application • Use Case

     JUnit5 makes a GET request and obtains a message from a REST Service Provider. • GET Request URI: http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/hello • Response Message: “Hello World!” in String (MIME Type: “text/plain”) 40 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/hello) REST Response Message (String: “Hello World!”) JUnit5 System Test (integration-test) Eclipse Exercise: Let’s make the First JAX-RS Application.
  41. First JAX-RS Application Development • This project of “jaxrs_jsf_jpa” is

    based on the “jsf_jpa” project and add necessary components newly created on the Eclipse IDE. 41 jsf_jpa Copy jaxrs_jsf_jpa Add • RestApplication : REST Custom App. • ResourceProvider : Web Resource Class • RestIT : System Test Class • …
  42. First JAX-RS Application Development • Procedure of the Development Edit

    pom.xml and Change package names Modify persistence.xml and Setup PostgreSQL Change the Message folder and the associated Class Create the Required Class Execute the REST System Test with Maven Test with Talend API Tester 42
  43. First JAX-RS Application Development • Modify the created Maven Object

    Model file (pom.xml) Change the artifactId to “jaxrs_jsf_jpa”. • Change the package names Refactor all the packages to rename the packages from “jsf_jpa” to “jaxrs_jsf_jpa” creating new packages of “org.example.jaxrs_jsf_jpa.rest” under “src/main/java” and “src/test/java”. <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>jaxrs_jsf_jpa</artifactId> <packaging>war</packaging> <version>0.0.1</version> 43 New pom.xml New Package Names New New
  44. First JAX-RS Application Development • Procedure of the Development Edit

    pom.xml and Change package names Modify persistence.xml and Setup PostgreSQL Change the Message folder and the associated Class Create the Required Class Execute the REST System Test with Maven Test with Talend API Tester 44
  45. JPA in Jakarta EE System Test Exercise • Modify the

    JPA configuration file (persistence.xml) for Live Modify the Persistence Unit in the persistence.xml under the folder of “src/main/resources/META- INF” like the following for Live Web Application System and Web System Test by Selenium product. <persistence-unit name="persistenceUnit" transaction-type=“JTA"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>jdbc/jaxrs_jsf_jpa</jta-data-source> <!-- shouldn't be valid for java SE per specification, but it works for EclipseLink ... --> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <!-- EclipseLink should create the database schema automatically --> <property name="eclipselink.ddl-generation" value="create-tables" /> <property name="eclipselink.ddl-generation.output-mode" value="database" /> <property name="eclipselink.logging.level" value="SEVERE"/> <property name="eclipselink.target-database" value="PostgreSQL" /> </properties> </persistence-unit> 45
  46. JPA in Jakarta EE System Test Exercise • Modify the

    JPA configuration file (persistence.xml) for CDI Unit Test Modify the Persistence Unit in the copied persistence.xml under the folder of “src/test/resources/META-INF” for CDI Unit Test like the following. <persistence-unit name="persistenceUnit4Test" transaction-type="RESOURCE_LOCAL"> <!-- To make it work on JavaSE, we have to specify all used classes like the followings --> <class>org.example.jaxrs_jsf_jpa.domain.Department</class> <class>org.example.jaxrs_jsf_jpa.domain.Employee</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/jaxrs_jsf_jpa" /> <property name="javax.persistence.jdbc.user" value=“jaxrs_jsf_jpa" /> <property name="javax.persistence.jdbc.password" value=“jaxrs_jsf_jpa" /> <!-- EclipseLink should create the database schema automatically --> <property name="eclipselink.ddl-generation" value="create-tables" /> <property name="eclipselink.ddl-generation.output-mode" value="database" /> <property name="eclipselink.logging.level" value="SEVERE"/> <property name="eclipselink.target-database" value="PostgreSQL" /> </properties> </persistence-unit> 46
  47. JPA in Jakarta EE System Test Exercise • Setup PostgreSQL

    making an account of “jaxrs_jsf_jpa” setting its password to “jaxrs_jsf_jpa” with pgAdmin 4.  For the created account, enable the account to login. 47
  48. JPA in Jakarta EE System Test Exercise • Setup PostgreSQL

    making a database of “jaxrs_jsf_jpa” with pgAdmin 4 Set the owner of the database to the “jaxrs_jsf_jpa” account. 48
  49. JPA in Jakarta EE System Test Exercise • Setup Payara

    Server to accommodate a JDBC Connection Pool of “jaxrs_jsf_jpaPool”  Set “Resource Type” to “javax.sql.DataSource”, “Database Driver Vendor” to “Postgresql” and “Introspect” to “Enable”.  Set required parameters: “DatabaseNamejaxrs_jsf_jpa”, “Userjaxrs_jsf_jpa”, “Passwordjaxrs_jsf_jpa”, “URLjdbc:postgresql://localhost/jaxrs_jsf_jpa” and “Urljdbc:postgresql://localhost/jaxrs_jsf_jpa” 49
  50. JPA in Jakarta EE System Test Exercise • Setup Payara

    Server to accommodate a JDBC Resource of “jdbc/jaxrs_jsf_jpa” Set “Pool Name” to “jaxrs_jsf_jpaPool”. 50
  51. First JAX-RS Application Development • Procedure of the Development Edit

    pom.xml and Change package names Modify persistence.xml and Setup PostgreSQL Change the Message folder and the associated Class Create the Required Class Execute the REST System Test with Maven Test with Talend API Tester 51
  52. First JAX-RS Application Development • Change the Message folder Rename

    the Message folder to “org/example/jaxrs_jsf_jpa”. • Change the Message Utility Class Modify the Message Utility Class, Messages.java, under the package of “org.example.jaxrs_jsf_jpa.util” about the new folder name. 52 New Message Folder Name Renamed Revised Messages.java (src/main/java/org.example.jaxrs_jsf_jpa.util) Renamed
  53. First JAX-RS Application Development • Procedure of the Development Edit

    pom.xml and Change package names Modify persistence.xml and Setup PostgreSQL Change the Message folder and the associated Class Create the Required Class Execute the REST System Test with Maven Test with Talend API Tester 53
  54. First JAX-RS Application Development • Create required Classes 1. Create

    a new Web Resource Class, ResourceProvider.java, of the “org.example.jaxrs_jsf_jpa.rest” package under the “src/main/java” folder, which specifies the Web Resource Class Path of “/restService” and it returns a String message of “Hello World!” whose MIME type is “text/plain” as a response to the HTTP GET request for the Resource Method Path of “/hello” by creating a Resource Method of “hello()”. 2. Create a new Custom REST Application Class, RestApplication.java, of the “org.example.jaxrs_jsf_jpa.rest” package under the “src/main/java” folder to specify an Application Path of “webapi” and the ResouceProvider.java as a Web Resource Class. 3. A new System Test Class, RestIT.java, of the “org.example.jaxrs_jsf_jpa.rest” package under the “src/test/java” folder is provided to execute a System Test for the ResourceProvider.class. 54
  55. First JAX-RS Application Development • RestIT.java (1) – Preparation for

    System Test A new System Test Class, RestIT.java, of the “org.example.jaxrs_jsf_jpa.rest” package under the “src/test/java” folder is provided to execute a System Test for the ResourceProvider.class. 55 class RestIT { private static Client client; private static String baseUri = ""; @BeforeAll public static void loadTestConfig() { final String hostname = System.getProperty("servlet.host"); final String port = System.getProperty("servlet.port"); final String context = System.getProperty("servlet.context"); final String REST_APPLICATION_PATH = "webapi"; baseUri = "http://" + hostname + ":" + port + "/" + context + "/" + REST_APPLICATION_PATH; client = ClientBuilder.newClient(); }
  56. First JAX-RS Application Development • RestIT.java (2) – Execution of

    the System Test 56 @Test public void testHello() { final String WEB_RESOURCE_PATH = "/restService"; final String RESOURCE_METHOD_PATH = "/hello"; String response = client.target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH) .request(MediaType.TEXT_PLAIN) .get(String.class); assertTrue(response.contains("Hello World!")); } }
  57. First JAX-RS Application Development • Final Java Source Folder Structure

    57 Provided New New
  58. First JAX-RS Application Development • Procedure of the Development Edit

    pom.xml and Change package names Modify persistence.xml and Setup PostgreSQL Change the Message folder and the associated Class Create the Required Class Execute the REST System Test with Maven Test with Talend API Tester 58
  59. First JAX-RS Application Development • Execute JUnit through M2Eclipse™ for

    the provided REST System Test Class (1)  Right click on the project and select “Run As”  “4 Maven build”  Specify “jaxrs_jsf_jpa – integration-test” for the “Name” field and “clean integration-test” for the “Goals” field. 59
  60. First JAX-RS Application Development • Execute JUnit through M2Eclipse™ for

    the provided REST System Test Class (2)  Click “Run” button. Confirm that test completes successfully in “Console” 60
  61. First JAX-RS Application Development • Procedure of the Development Edit

    pom.xml and Change package names Modify persistence.xml and Setup PostgreSQL Change the Message folder and the associated Class Create the Required Class Execute the REST System Test with Maven Test with Talend API Tester 61
  62. First JAX-RS Application Development • Install “Talend API Tester –

    Free Edition”  With Chrome browser, access to https://chrome.google.com/webstore/detail/talend-api-tester-free- ed/aejoelaoggembcahagimdiliamlcdmfm?hl=en to install “Talend API Tester – Free Edition”.  Click “Add to Chrome” button 62
  63. First JAX-RS Application Development • Execute “Talend API Tester –

    Free Edition” (1) – Request REST Service  Click the icon of on the Chrome browser.  Select “Get” Method and specify “http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/hello” as the URI and click the “Send” button. 63
  64. First JAX-RS Application Development • Execute “Talend API Tester –

    Free Edition” – Response for the REST Service Request  Confirm that the expected HEADERS and BODY were responded. 64
  65. Other JAX-RS Programming 65

  66. Requester Provider Other JAX-RS Programming • Use Case (1) 

    JUnit5 makes a GET request with a PATH Parameter of a user name and obtains a message including the user name from a REST Service Provider. • GET Request URI: http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit1/Smith • Response Message: “Welcome to the REST World, Smith” in String (MIME Type: “text/plain”) 66 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit1/Smith) REST Response Message (String: “Welcome to the REST World, Smith!”) JUnit5 System Test (integration-test) Eclipse
  67. Requester Provider Other JAX-RS Programming • Use Case (2) 

    JUnit5 makes a GET request with a Query Parameter of a user name and obtains a message including the user name from a REST Service Provider. • GET Request URI: http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit2?visitorName=“Smith” • Response Message: “Welcome to the REST World, Smith” in String (MIME Type: “text/plain”) 67 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit2? visitorName=Smith) REST Response Message (String: “Welcome to the REST World, Smith!”) JUnit5 System Test (integration-test) Eclipse
  68. Requester Provider Other JAX-RS Programming • Use Case (3) 

    JUnit5 makes a POST request with a Form Parameter of a user name and obtains a message including the user name from a REST Service Provider. • POST Request URI: http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit3 • POST Request Body: <form> … <input … name=“visitorName” value=“Smith” …/> … </form> • Response Message: “Welcome to the REST World, Smith” in String (MIME Type: “text/plain”) 68 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit3, Body:<form> … <input … name=“visitorName” value=“Smith” …/> … </form> REST Response Message (String: “Welcome to the REST World, Smith!”) JUnit5 System Test (integration-test) Eclipse
  69. Requester Provider Other JAX-RS Programming • Use Case (4) 

    JUnit5 makes a POST request with a JSON Object including a user name and obtains a message including the user name from a REST Service Provider. • POST Request URI: http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit4 • POST Request Body: {“name”:“Smith”} • Response Message: “Welcome to the REST World, Smith” in String (MIME Type: “text/plain”) 69 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/visit4, Body: {“name”:“Smith”}) REST Response Message (String: “Welcome to the REST World, Smith!”) JUnit5 System Test (integration-test) Eclipse
  70. Requester Provider Other JAX-RS Programming • Use Case (5) 

    JUnit5 makes a GET request with a Query Parameter of the ID and obtains a JSON message including the product name based on the ID from a REST Service Provider. • GET Request URI: http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/milkProduct?id=1 • Response Message: “{"product": "Cheese"}” in JSON (MIME Type: “application/json”) 70 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/milkProduct? id=1) REST Response Message (JSON: {"product": "Cheese"}) JUnit5 System Test (integration-test) Eclipse id product 1 Cheese 2 Milk 3 Yogurt
  71. Requester Provider Other JAX-RS Programming • Use Case (6) 

    JUnit5 makes a GET request and obtains a JSON message including the list of product names from a REST Service Provider. • GET Request URI: http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/milkProducts • Response Message: “[{"product": "Cheese"}, {"product": “Milk"}, {"product": “Yogurt"}]” in JSON (MIME Type: “application/json”) 71 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jaxrs_jsf_jpa/webapi/restService/milkProducts) REST Response Message (JSON: [{"product": "Cheese"},{"product": “Milk"},{"product": “Yogurt"}]) JUnit5 System Test (integration-test) Eclipse product Cheese Milk Yogurt
  72. Other JAX-RS Programming • Development Procedure on Eclipse™ 1. Create

    a new “Visitor.java” of the “org.example.jaxrs_jsf_jpa.rest” package in the “src/main/java” folder for the additional Resource Methods for Use Case (4). This class has a String of “name” as its property which accommodates a user name. The class also has the default constructor, a constructor which accepts the name as a parameter, accessors like a getter and a setter for the property. 2. Create a new “MilkProduct.java” of the “org.example.jaxrs_jsf_jpa.rest” package in the “src/main/java” folder for the additional Resource Methods for Use Case (5) and (6). This class has a String of “product” as its property which accommodates a product name. The class also has the default constructor, a constructor which accepts the product as a parameter, accessors like a getter and a setter for the property. 3. Modify the Web Resource Class of “ResourceProvider.java” to implement Resource Methods for all the Use Cases. 4. Modified “RestIT.java” is provided to test the Web Resource Class you developed. 5. Execute the above System Test and confirm all the Tests are passed with M2Eclipse. 6. Send several requests to the new Provider with Talend API Tester and confirm every Use Case is OK. 72
  73. Other JAX-RS Programming • RestIT.java – System Test for Use

    Case (1) 73 @Test public void testVisit1() { final String WEB_RESOURCE_PATH = "/restService"; final String RESOURCE_METHOD_PATH = "/visit1"; final String VISITOR_NAME = "Smith"; WebTarget myResource = client.target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH).path("{visitorName}") .resolveTemplate("visitorName", VISITOR_NAME); String response = myResource.request(MediaType.TEXT_PLAIN).get(String.class); assertTrue(response.contains(VISITOR_NAME)); }
  74. Other JAX-RS Programming • RestIT.java – System Test for Use

    Case (2) 74 @Test public void testVisit2() { final String WEB_RESOURCE_PATH = "/restService"; final String RESOURCE_METHOD_PATH = "/visit2"; final String VISITOR_NAME = "Smith"; WebTarget myResource = client.target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH) .queryParam("visitorName", VISITOR_NAME); String response = myResource.request(MediaType.TEXT_PLAIN).get(String.class); assertTrue(response.contains(VISITOR_NAME)); }
  75. Other JAX-RS Programming • RestIT.java – System Test for Use

    Case (3) 75 @Test public void testVisit3() { final String WEB_RESOURCE_PATH = "/restService"; final String RESOURCE_METHOD_PATH = "/visit3"; final String VISITOR_NAME = "Smith"; Form form = new Form(); form.param("visitorName", VISITOR_NAME); WebTarget myResource = ClientBuilder.newClient().target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH); String response = myResource.request(MediaType.TEXT_PLAIN) .post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE), String.class); assertTrue(response.contains(VISITOR_NAME)); }
  76. Other JAX-RS Programming • RestIT.java – System Test for Use

    Case (4) 76 @Test public void testVisit4() { final String WEB_RESOURCE_PATH = "/restService"; final String RESOURCE_METHOD_PATH = "/visit4"; final String VISITOR_NAME = "Smith"; Visitor visitor = new Visitor(VISITOR_NAME); WebTarget myResource = ClientBuilder.newClient().target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH); String response = myResource.request(MediaType.TEXT_PLAIN) .post(Entity.entity(visitor, MediaType.APPLICATION_JSON), String.class); assertTrue(response.contains(VISITOR_NAME)); }
  77. Other JAX-RS Programming • RestIT.java – System Test for Use

    Case (5) 77 @Test public void testMilkProduct() { final String WEB_RESOURCE_PATH = "/restService"; final String RESOURCE_METHOD_PATH = "/milkProduct"; final String PRODUCT_NAME = "Cheese"; final Integer ID = 1; WebTarget myResource = ClientBuilder.newClient().target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH) .queryParam("id", ID); MilkProduct product = myResource.request(MediaType.APPLICATION_JSON) .get(MilkProduct.class); assertTrue(product.getProduct().contains(PRODUCT_NAME)); }
  78. Other JAX-RS Programming • RestIT.java – System Test for Use

    Case (6) 78 @Test public void testMilkProducts() { final String WEB_RESOURCE_PATH = "/restService"; final String RESOURCE_METHOD_PATH = "/milkProducts"; final Integer SIZE = 3; WebTarget myResource = ClientBuilder.newClient().target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH); List<MilkProduct> products = myResource.request(MediaType.APPLICATION_JSON) .get(new GenericType<List<MilkProduct>>() {}); assertEquals(products.size(), SIZE); }
  79. Other JAX-RS Programming • Final Java Source Folder Structure 79

    Provided Modify New New
  80. Exercise 80

  81. Exercise for Managing Departments with REST • Required features 

    Create a new Web Resource Class which provides the Personnel Service managing “Department” Entities with CRUD operations.  The Web Resource Class is implemented as a Request Scoped CDI component and its Web Resource Class path is “/personnelService”.  Create several Resource Methods to query Entities (path:/getAllDepartments) and create an Entity (path:/newDepartment), update (path:/updateDepartment) and remove (path:/deleteDepartment) an Entity. 81 Requestor Presentation Jakarta EE Container Web Resource CDI (Request Scoped) Resource Methods REST Request Message (URI:http://localhost:8080/jaxrs_jsf_jpa/w ebapi/personelService/newDepartment Body(JSON): {.., “name”:“Marketing”, …}) REST Response Message (JSON: {“id": “123“, “version”: “1”, …}) JUnit5 System Test (integration-test) Eclipse Business Data Access Transactional CDI O-R Mapper Provider Domain Service Business Methods RDB
  82. Exercise for Managing Departments with REST • PersonnelServiceIT.java – System

    Test for Managing Departments (Initialize DB) 82 @Test public void testManageDepartment() { final String WEB_RESOURCE_PATH = "/personnelService"; // Initialize DB deleting all the data in DB String RESOURCE_METHOD_PATH = "/initializeDB"; WebTarget myResource = client.target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH); Integer result = myResource.request(MediaType.TEXT_PLAIN).get(Integer.class); assertEquals(result, new Integer(Response.Status.OK.getStatusCode())); :
  83. Exercise for Managing Departments with REST • PersonnelServiceIT.java – System

    Test for Managing Departments (Create a new Entity) 83 : // Create a New Department Entity whose “name” property is “Marketing” RESOURCE_METHOD_PATH = "/newDepartment"; Department department = new Department("Marketing"); myResource = client.target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH); department = myResource.request(MediaType. APPLICATION_JSON) . post(Entity.entity(department, MediaType.APPLICATION_JSON), Department.class); assertNotNull(department); assertEquals(department.getName(), "Marketing"); :
  84. Exercise for Managing Departments with REST • PersonnelServiceIT.java – System

    Test for Managing Departments (Update the Entity) 84 : // Update the Department Entity to have the new “name” property of “R&D” RESOURCE_METHOD_PATH = "/updateDepartment"; department .setName("R&D"); myResource = client.target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH); department = myResource.request(MediaType. APPLICATION_JSON) . put(Entity.entity(department, MediaType.APPLICATION_JSON), Department.class); assertNotNull(department); assertEquals(department.getName(), "R&D"); :
  85. Exercise for Managing Departments with REST • PersonnelServiceIT.java – System

    Test for Managing Departments (Obtain all the Entities) 85 : // Obtain all the Department Entities RESOURCE_METHOD_PATH = "/getAllDepartments"; myResource = client.target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH); List<Department> departments = myResource.request(MediaType.APPLICATION_JSON) .get(new GenericType<List<Department>>() {}); assertNotNull(departments); assertEquals(departments.size(), 1); assertEquals(departments.get(0).getName(), "R&D"); :
  86. Exercise for Managing Departments with REST • PersonnelServiceIT.java – System

    Test for Managing Departments (Delete the Entity) 86 : // Delete the Department Entity which was created and updated RESOURCE_METHOD_PATH = "/deleteDepartment"; myResource = client.target(baseUri + WEB_RESOURCE_PATH + RESOURCE_METHOD_PATH); result = myResource.queryParam("id", department.getId()).queryParam("version", department.getVersion()) .request(MediaType.TEXT_PLAIN) .delete(Integer.class); assertEquals(result, new Integer(Response.Status.OK.getStatusCode())); }
  87. Exercise for Managing Departments with REST • Final Java Source

    Folder Structure 87 Provided Modify New