REST
REST, understand the skier example
For this lab, we use the Json and xml representations (the marshalling and unmarshalling are done with the Jakarta library), and the writing of REST services in Java with the JAX-RS specifications is achieved with the glassfish Jersey library.
Study the JAXRS examples
Understand and test all the JAX-RS examples (they are in the ExemplesREST/REST-JAXREST-01 directory of the csc-mw-examples project). Read the source files in your favorite development environment (e.g. Eclipse).
With the help of the README.md file, test the server:
- With the Junit tests
- With some get commands in the navigator
- With get and posts commands via Postman
- 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
- You do need to start the server, before starting any client. How do
you start the server ? mvn exec:java@serverYou first have to compile the code withmvn clean install
- On which TCP port is listening the server ? 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
Then it defines its baseURI (http://localhost:8083/MyServer/) and creates the REST server that will be listening for requests.rest.serveraddress=localhost:8083baseURI = "http://" + properties.getProperty("rest.serveraddress") + "/MyServer/"; GrizzlyHttpServerFactory.createHttpServer(URI.create(baseURI), rc)
-
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, to find out which process is using this port you can use the following command If the answer is not empty, it gives you the details of the process listening on that port. If necessary, you can stop it withlsof -i:8083(PID is the process number you have found with lsof). You can also use lsof to verify that your server is running.kill -9 {PID}
- What is the URL you can use in the navigator to see the server
interface ? It will show this kind of information. In this picture we have unfolded only the skiers resource. It gives a synthesis of the skiers resource API.http://localhost:8083/MyServer/application.wadl
- In which java class the skiers API is defined? package server, class SkiersRest
- In which class the java server class is defined? package server, class Main
- How do you specify the resources that will be handled by the
Grizzly HTTP server? With the following line of code, you define
the name of the packages that contain the REST resources.
In this package all the resources that have a @Path annotation are REST resources handled by the Grizzly HTTP server.final ResourceConfig rc = new ResourceConfig().packages("server");
- How the marshalling in json or in XML is realized? The
marshalling is handled automatically according to the return
class and the format provided by the resource and required by the
client. In the following example: The return is of type Skier. The format provided by the method are XML and JSON. 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 return class (Skier) to manage correctly the marshalling.@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; } }
NB: The client needs also a Skier class. This class may be generated based on an XML document or a Json String. - 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.
This option may be very usefull for debugging your REST clients in the future labs. Here is an exerpt of the output with logging.mvn exec:java@client-skier -Djava.util.logging.config.file=src/main/resources/logging.propertiesPRÉCIS [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@1739b9c97 pairs: {PUT /MyServer/skiers/addvictory/Killy HTTP/1.1: null}{Content-Type: text/plain}{User-Agent: Jersey/3.0.8 (HttpUrlConnection 17.0.3)}{Host: localhost:8083}{Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2}{Connection: keep-alive}{Content-Length: 8} PRÉCIS [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@27b21b711 pairs: {null: HTTP/1.1 204 No Content} PRÉCIS [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@7fa535375 pairs: {GET /MyServer/skiers/all HTTP/1.1: null}{Accept: text/xml}{User-Agent: Jersey/3.0.8 (HttpUrlConnection 17.0.3)}{Host: localhost:8083}{Connection: keep-alive} PRÉCIS [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@25d50bfd3 pairs: {null: HTTP/1.1 200 OK}{Content-Type: text/xml}{Content-Length: 358} PRÉCIS [org.glassfish.jersey.message.internal.ReaderInterceptorExecutor] Message body reader (class org.glassfish.jersey.jaxb.internal.XmlRootElementJaxbProvider$Text) is trying to close the entity input stream. Not closing. PRÉCIS [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@2cf7defc5 pairs: {GET /MyServer/skiers/searchByName?name=Killo HTTP/1.1: null}{Accept: application/xml}{User-Agent: Jersey/3.0.8 (HttpUrlConnection 17.0.3)}{Host: localhost:8083}{Connection: keep-alive} PRÉCIS [sun.net.www.protocol.http.HttpURLConnection] sun.net.www.MessageHeader@534df2fc2 pairs: {null: HTTP/1.1 404 Not Found}{Content-Length: 0} jakarta.ws.rs.NotFoundException: HTTP 404 Not Found
$Date: 2020-10-06 00:31:01 +0200 (mar. 06 oct. 2020) $