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

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

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

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 requires the basic skills of Windows 10, Rocky Linux, 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 Rocky Linux.

Koichi NAKAGAWA

November 26, 2020
Tweet

More Decks by Koichi NAKAGAWA

Other Decks in Programming

Transcript

  1. JAKARTA RESTFUL WEB SERVICES (JAX-RS) (VER. 3.1) A part of

    Jakarta EE™ specification RESTful Web Service Framework 1 By Koichi NAKAGAWA Enterprise Web Application Development Course (6)
  2. Update Information • Ver. 3: Use Rocky Linux™ instead of

    CentOS™ as a Linux platform and Payara Server 6™ certified as Jakarta EE 9.1 Platform Compatible Products. • Ver. 2 : Use JDK 11 instead of JDK 8 and Jakarta EE 9 instead of Jakarta EE 8 in all exercises. 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 (Rocky Linux™) Total EWA Development Exercise Jakarta Batch Java SE (Oracle JDK™/OpenJDK™) Required Skills to take courses Test Tool with JUnit5 PostgreSQL™ Administration 4
  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. 5
  5. Assumption for this course • The trainees who take this

    course are required the following skills in advance • PostgreSQL (Version: 13.5) – Basic Administration Operations • Payara Server (Version: 6.2021.1.Alpha1) – Basic Administration Operations • Oracle JDK/OpenJDK (Version: 11) • Eclipse IDE for Enterprise Java Developers (Version: 2021-12 (4.22.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 6
  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 7
  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 8
  8. Concept of JAX-RS • Communications between Applications 10 Requester (Server)

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

    EE™ 11 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
  10. Concept of JAX-RS • HTTP Message 12 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
  11. Concept of JAX-RS • What is RESTful Web Services? 13

    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.
  12. Concept of JAX-RS • Architecture of JAX-RS 14 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
  13. How to configure JAX-RS Engine • Architecture of JAX-RS 16

    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 configure JAX-RS Engine • What is Application Path?

    17 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.
  15. How to configure JAX-RS Engine • Configuration of Application Path

    (2 Ways) 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 Configuration in web.xml • Using the servlet-mapping tag within the WAR’s web.xml
  16. How to configure JAX-RS Engine • Configuration of Application Path

    (By Custom Application) 19 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 Web Resource Classes to be used as well. Application Path Web Resource Class Custom Application
  17. How to configure JAX-RS Engine • Configuration of Application Path

    (By web.xml) 20 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
  18. How to make Web Resource Class • Architecture of JAX-RS

    21 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
  19. How to make Web Resource Class • Programming for Web

    Resource Class and Resource Method 22 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
  20. How to make Web Resource Class • Input Types obtained

    from HTTP Request 23 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
  21. How to make Web Resource • How to obtain Path

    Parameters from HTTP Request 24 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!
  22. How to make Web Resource • How to obtain Query

    Parameters from HTTP Request 25 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!
  23. How to make Web Resource • How to obtain Form

    Parameters from HTTP Request 26 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
  24. How to make Web Resource • How to obtain JSON

    String as Java Object from HTTP Request 27 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!
  25. How to make Web Resource • Output Types in HTTP

    Response 28 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
  26. How to make Web Resource • How to return Object(s)

    in HTTP Response 29 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 }
  27. How to make Web Resource • How to return Status

    Code and Object(s) in HTTP Response 30 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 }
  28. How to make Web Resource • How to return Exception

    in HTTP Response 31 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 } }
  29. How to make Requestor • Architecture of JAX-RS 32 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
  30. How to make Requestor • Program for Requestor (1) 33

    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
  31. How to make Requestor • Program for Requestor (2) 34

    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
  32. How to make Requestor • Program for Requestor (3) 35

    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”}
  33. How to make Requestor • Program for Requestor (4) 36

    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
  34. Architecture Design • Architecture Design with JAX-RS and JSF in

    Presentation Layer 38 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
  35. JAX-RS with CDI • Program for Web Resource Class with

    CDI 39 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(); } : }
  36. Requester Provider First JAX-RS Application Development Exercise • Use Case

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

    is based on the “jsf_jpa” project and add necessary components newly created on the Eclipse IDE. 42 jsf_jpa Copy jsf_jpa_jaxrs • RestApplication : REST Custom App. • ResourceProvider : Web Resource Class • RestIT : System Test Class • … Add
  38. First JAX-RS Application Development Exercise • 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 43
  39. First JAX-RS Application Development Exercise • Modify the Maven Object

    Model file (pom.xml) Change the artifactId to “jsf_jpa_jaxrs”. Add the 2 dependency artifacts for REST Client in the the REST Interface Test : <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>jsf_jpa_jaxrs</artifactId> <packaging>war</packaging> <version>0.0.1</version> : 44 Revised pom.xml : <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-client</artifactId> <version>3.0.3</version> <scope>test</scope> </dependency> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> <version>3.0.3</version> <scope>test</scope> </dependency> :
  40. First JAX-RS Application Development Exercise • Change the package names

    Refactor all the packages to rename the packages from “jsf_jpa” to “jsf_jpa_jaxrs” creating new packages of “org.example.jsf_jpa_jaxrs.rest” under “src/main/java” and “src/test/java”. 45 New Package Names New New
  41. First JAX-RS Application Development Exercise • 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 46
  42. First JAX-RS Application Development Exercise • Modify the JPA configuration

    file (persistence.xml) for CDI Unit Test Modify the class package names of 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.jsf_jpa_jaxrs.domain.Department</class> <class>org.example.jsf_jpa_jaxrs.domain.Employee</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://[host name]/jpa_db" /> <property name="javax.persistence.jdbc.user" value=“jpa_exercise" /> <property name="javax.persistence.jdbc.password" value=“jpa_exercise" /> <!-- 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> 47
  43. First JAX-RS Application Development Exercise • 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 48
  44. First JAX-RS Application Development Exercise • Change the Message folder

    Rename the Message folder to “org/example/jsf_jpa_jaxrs”. • Change the Message Utility Class Modify “BUNDLE_NAME” in Message Utility Class, Messages.java, under the package of “org.example. jsf_jpa_jaxrs.util” because of the changed folder name. 49 New Message Folder Name Revised Messages.java (src/main/java/org.example.jsf_jpa_jaxrs.util) Renamed Renamed
  45. First JAX-RS Application Development Exercise • 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 50
  46. First JAX-RS Application Development Exercise • Create required Classes 1.

    Create a new Web Resource Class, ResourceProvider.java, of the “org.example.jsf_jpa_jaxrs.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.jsf_jpa_jaxrs.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.jsf_jpa_jaxrs.rest” package under the “src/test/java” folder is provided to execute a System Test for the ResourceProvider.class. 51
  47. First JAX-RS Application Development Exercise • RestIT.java (1) – Preparation

    for System Test A new System Test Class, RestIT.java, of the “org.example.jsf_jpa_jaxrs.rest” package under the “src/test/java” folder is provided to execute a System Test for the ResourceProvider.class. 52 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(); }
  48. First JAX-RS Application Development Exercise • RestIT.java (2) – Execution

    of the System Test 53 @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!")); } }
  49. First JAX-RS Application Development Exercise • 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 55
  50. First JAX-RS Application Development Exercise • 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 “jsf_jpa_jaxrs – integration-test (Remote)” for the “Name” field and “clean integration-test” for the “Goals” field. 56
  51. First JAX-RS Application Development Exercise • Execute JUnit through M2Eclipse™

    for the provided REST System Test Class (2)  Click “Run” button. Confirm that test completes successfully in “Console” 57
  52. First JAX-RS Application Development Exercise • 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
  53. First JAX-RS Application Development Exercise • 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 59
  54. First JAX-RS Application Development Exercise • 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/jsf_jpa_jaxrs/webapi/restService/hello” as the URI and click the “Send” button. 60
  55. First JAX-RS Application Development Exercise • Execute “Talend API Tester

    – Free Edition” – Response for the REST Service Request  Confirm that the expected HEADERS and BODY were responded. 61
  56. Requester Provider Other JAX-RS Programming Exercises • 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/jsf_jpa_jaxrs/webapi/restService/visit1/Smith • Response Message: “Welcome to the REST World, Smith” in String (MIME Type: “text/plain”) 63 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jsf_jpa_jaxrs/webapi/restService/visit1/Smith) REST Response Message (String: “Welcome to the REST World, Smith!”) JUnit5 System Test (integration-test) Eclipse
  57. Requester Provider Other JAX-RS Programming Exercises • 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/jsf_jpa_jaxrs/webapi/restService/visit2?visitorName=“Smith” • Response Message: “Welcome to the REST World, Smith” in String (MIME Type: “text/plain”) 64 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jsf_jpa_jaxrs/webapi/restService/visit2? visitorName=Smith) REST Response Message (String: “Welcome to the REST World, Smith!”) JUnit5 System Test (integration-test) Eclipse
  58. Requester Provider Other JAX-RS Programming Exercises • 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/jsf_jpa_jaxrs/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”) 65 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jsf_jpa_jaxrs/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
  59. Requester Provider Other JAX-RS Programming Exercises • 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/jsf_jpa_jaxrs/webapi/restService/visit4 • POST Request Body: {“name”:“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/jsf_jpa_jaxrs/webapi/restService/visit4, Body: {“name”:“Smith”}) REST Response Message (String: “Welcome to the REST World, Smith!”) JUnit5 System Test (integration-test) Eclipse
  60. Requester Provider Other JAX-RS Programming Exercises • 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/jsf_jpa_jaxrs/webapi/restService/milkProduct?id=1 • Response Message: “{"product": "Cheese"}” in JSON (MIME Type: “application/json”) 67 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jsf_jpa_jaxrs/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
  61. Requester Provider Other JAX-RS Programming Exercises • 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/jsf_jpa_jaxrs/webapi/restService/milkProducts • Response Message: “[{"product": "Cheese"}, {"product": “Milk"}, {"product": “Yogurt"}]” in JSON (MIME Type: “application/json”) 68 Jakarta EE Container Web Resource Class Resource Method REST Request Message (URI:http://localhost:8080/jsf_jpa_jaxrs/webapi/restService/milkProducts) REST Response Message (JSON: [{"product": "Cheese"},{"product": “Milk"},{"product": “Yogurt"}]) JUnit5 System Test (integration-test) Eclipse product Cheese Milk Yogurt
  62. Other JAX-RS Programming Exercises • Modify the Maven Object Model

    file (pom.xml) Add the 1 dependency artifacts for REST Client in the the REST Interface Test to use JSON media conversion in Use Case (5) and (6). 69 Revised pom.xml : <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>3.0.3</version> <scope>test</scope> </dependency> :
  63. Other JAX-RS Programming Exercises • Development Procedure on Eclipse™ 1.

    Create a new “Visitor.java” of the “org.example.jsf_jpa_jaxrs.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.jsf_jpa_jaxrs.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. 70
  64. Other JAX-RS Programming Exercises • RestIT.java – System Test for

    Use Case (1) 71 @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)); }
  65. Other JAX-RS Programming Exercises • RestIT.java – System Test for

    Use Case (2) 72 @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)); }
  66. Other JAX-RS Programming Exercises • RestIT.java – System Test for

    Use Case (3) 73 @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)); }
  67. Other JAX-RS Programming Exercises • RestIT.java – System Test for

    Use Case (4) 74 @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)); }
  68. Other JAX-RS Programming Exercises • RestIT.java – System Test for

    Use Case (5) 75 @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)); }
  69. Other JAX-RS Programming Exercises • RestIT.java – System Test for

    Use Case (6) 76 @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); }
  70. Managing Departments with REST Exercise • 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. 79 Requestor Presentation Jakarta EE Container Web Resource CDI (Request Scoped) Resource Methods REST Request Message (URI:http://localhost:8080/jsf_jpa_jaxrs/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
  71. Managing Departments with REST Exercise • PersonnelServiceIT.java – System Test

    for Managing Departments (Initialize DB) 80 @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())); :
  72. Managing Departments with REST Exercise • PersonnelServiceIT.java – System Test

    for Managing Departments (Create a new Entity) 81 : // 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"); :
  73. Managing Departments with REST Exercise • PersonnelServiceIT.java – System Test

    for Managing Departments (Update the Entity) 82 : // 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"); :
  74. Managing Departments with REST Exercise • PersonnelServiceIT.java – System Test

    for Managing Departments (Obtain all the Entities) 83 : // 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"); :
  75. Managing Departments with REST Exercise • PersonnelServiceIT.java – System Test

    for Managing Departments (Delete the Entity) 84 : // 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())); }