Module CSC5002—ASR6: Middleware and software architecture for distributed applications

Portail informatique

Learn about REST with JAX-RS

Understand and test all the JAX-RS examples in the CodeForLearning/Learn-REST-JAX-RS directory. This is Maven module csc5002.learn.rest.jax-rs.

The writing of REST services in JAVA follows the JAX-RS (Jakarta RESTful Web Services) specifications and is achieved with the Eclipse Jersey and Eclipse Grizzly frameworks.

For this lab, we use the JSON and optionally XML representations (for XML serialisation, please have a look to the Addendum REST slides).

Read the source files in your favorite development environment. We favor using Eclipse. Before importing the project into Eclipse, build it by executing command mvn install. Then, import the Maven project using the menu File / import, then select Maven / Existing Maven Projects, and use the Browse button to select directory Learn-REST-JAX-RS.

Follow the instructions in the readme.md file in order to test the server:

  • With the Junit tests.
  • With some GET commands in a browser.
  • With JAVA clients.

When you have understood the examples (especially the one with the skiers), you are ready to write your own RESTFul client and server.

Verify first that you are able to answer the following questions:

  1. You do need to start the server before starting any client. How do you start the server?
    mvn exec:java@server
    You first have to compile the code with
    mvn clean install
  2. On which TCP port is the server listening?
    The TCP port is defined when you start the server. In our example the server reads in the file src/main/resources/rest.properties the address and the TCP port of the server:
    rest.serveraddress=localhost:8083
    Then, it defines its baseURI (http://localhost:8083/MyServer/) and creates the REST server that will be listening for requests.
    baseURI = "http://" + properties.getProperty("rest.serveraddress") + "/MyServer/"; GrizzlyHttpServerFactory.createHttpServer(URI.create(baseURI), rc)
  3. What does that mean if I have the Address already in use error when I start the server?
    It means that another process is already listening to this port. You can use the following command to find out which process is using this port:
    lsof -i:8083
    If the answer is not empty, it gives you the details of the process listening on that port. If necessary, you can stop and remove it with the following command:
    kill -9 PID
    (PID is the process number you have found with command lsof.)
  4. What is the URL you can use in the navigator to see the API of the server?
    http://localhost:8083/MyServer/application.wadl
    It displays this kind of information. In this display, we have unfolded only resource calc resource, endpoint add.
    — <application> <doc jersey:generatedBy="Jersey: 3.1.8 2024-08-02 14:29:24"/> <doc jersey:hint="This is simplified WADL with user and core resources only. To get full WADL with extended resources use the query parameter detail. Link: http://localhost:8083/MyServer/application.wadl?detail=true"/> — <grammars> — <include href="application.wadl/xsd0.xsd"> <doc title="Generated" xml:lang="en"/> </include> </grammars> — <resources base="http://localhost:8083/MyServer/"> — <resource path="/calc"> — <resource path="/add"> — <method id="addPlainText" name="GET"> — <request> <param name="a" style="query" type="xs:double"/> <param name="b" style="query" type="xs:double"/> </request> — <response> <representation mediaType="text/plain"/> </response> — </method> ...
  5. In which JAVA class the skiers API is defined?
    mw.learn.rest.jaxrs.b.serverSkiersInterface.
  6. In which JAVA class the server class is defined?
    mw.learn.rest.jaxrs.b.server.Main.
  7. How do you specify the resources that will be handled by the HTTP server?
    With the following line of code, you define the name of the packages that contain the REST resources.
    final ResourceConfig rc = new ResourceConfig().packages(Skiers.class.getPackageName());

    In this package, all the resources that have a @Path annotation are REST resources handled by the HTTP server.
  8. How the marshalling in JSON or in XML is realized?
    The marshalling is handled automatically according to the returned class and the format provided by the resource and required by the client. In the following example, the returned value is of type Skier.
    @GET @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) @Path("/searchByName") public Skier searchName(@QueryParam("name") final String name) throws JAXBException, IOException { Skier skier; getSkiersFromFile(fileName); skier = skiers.lookupName(name); if (skier == null) { throw new WebApplicationException(Response.Status.NOT_FOUND); } else { return skier; } }
    The format provided by the method are JSON and XML. If the client requires JSON, the Jersey and JSON libraries will manage the marshalling in JSON.
    If the client requires XML, the Jersey and JAXB library will manage the marshalling in XML. In JAXB, some annotations are necessary in the returned class (Skier) to manage correctly the marshalling.
    N.B.: The client needs also a Skier class for the unmarshalling of the returned value: See class mw.learn.rest.jaxrs.b.Skier in directory src/test/java.
  9. Are the server-side and client-side objects (Person, Skier, Skiers) of the same class?
    No: on the server side, classes of package mw.learn.rest.jaxrs.b.server; on the client side, e.g. in the test class, classes of package mw.learn.rest.jaxrs.b.
    In a way, this demonstrates that the example doesn't use JAVA serialisation.
  10. (Warning: you can give it a go, but our latest tests have revealed a problem with a lot of extra display output).
    Use the logging facility to trace the interactions between the client and the server. For this purpose, provide a configuration file for the logging library through a JAVA variable.
    $ # in a terminal, start the server $ mvn exec:java@server $ # in another terminal, execute the client $ mvn exec:java@client-skier -Djava.util.logging.config.file=src/main/resources/logging.properties
    This option may be very usefull for debugging your REST clients in the future labs. Here is an exerpt of the output with logging.
    ... --------------------------------------------------- skiers of 41 years old removed : FINE [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@25071a125 pairs: {DELETE /MyServer/skiers/delete/41 HTTP/1.1: null}{User-Agent: Jersey/3.1.8 (HttpUrlConnection 21.0.6)}{Host: localhost:8083}{Accept: */*}{Connection: keep-alive} FINE [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@351b23671 pairs: {null: HTTP/1.1 204 No Content} FINE [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@2a9518895 pairs: {GET /MyServer/skiers/alltxt HTTP/1.1: null}{Accept: text/plain}{User-Agent: Jersey/3.1.8 (HttpUrlConnection 21.0.6)}{Host: localhost:8083}{Connection: keep-alive} FINE [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@37df40433 pairs: {null: HTTP/1.1 200 OK}{Content-Type: text/plain}{Content-Length: 32} all skiers in plain text : Jean Claude Killy 73 years old ...
Congratulations, you are now ready to build your own REST application in JAVA!