DTU 
 

 

02162: Course on Software Engineering 2 (e14)

In this tutorial, you will learn how to implement RESTful web services using on Jersey. They will be deployed to the GlassFish server that we installed in the first tutorial (see assignment 1). In addition, you will learn how to generate a Java client and how to invoke the web service from a Java application (which later can be used to invoke the service from an App).

 

In this assignment, a web service for reporting events from a sensor to the server and for retrieving all events of some specific sensor should be implemented.

 

Tasks

Here are the tasks for the second assignment with step by step instructions.

 

  1. First, you need to create another Dynamic Web Project (see assignment 1). Make sure that you create the project with the web.xml deployment descriptor (tick the corresponding checbox in the last dialog of the wizard).

     

  2. In order to prepare your newly created project, you need to add some information for configuring Jersey properly in the web.xml deployment descriptor. You will find the information that you need to add in the following snippet. The only thing that you probably need to change is the param-value for the packages parameter for the Jersey web services (line 7 of the snippet). This should be the fully qualified name of the Java package to which you will add the code of your web services (see below). Create this package in the src folder in the project's Java Resources.

     

  3. Now, create a first "Hello World" web service, which just returns some string with some greeting and the current date. To this end, you need to add a Java class with some annotations to the package that you named in step 2. You will find an example in HelloWorldService.java.

     

    Note that, except for some additional annotations, this is a normal Java class. The additional annotations indicate that it is a web service. The @Path annotation tells the web server the additional path fragment that is added to the URL to invoke this web service (note that you can add this annotation to the class as well as to the individual methods, where both parts will be added to the URL). The @GET annotation indicates that this service is to be invoked with a HTTP GET method (you can also choose @PUT, @POST, and @DELETE).

     

    The @Produces annotation indicates the return type of the web service (MIME type), which, in this example, is plain text. Later, we will use types that actually return objects. There is one other annotation that is @Consumes, which indicates in which form the parameters to the web service are provided (we do not need this here, since there are no parameters in this service).

     

    Before you continue implementing some more relevant web services, try out whether your simple HelloWorld service works by running this project on the server (Run As-> Run on Server; see assignment 1 for more details, if you need them). For invoking the service from a web browser, enter a URL like http://localhost:8080/dk.dtu.compute.se2.web.second/rest/helloworld/. The browser should just show the greeting and the date as text now.

     

  4. Next, you should implement two webservices (if you want you can implement these as two methods in the same class; just make sure to provide a different path fragement for both). Before you can do that, you need to implement two classes that can represent an Event and a list of events. The Event should have two attributes, a sensor id and a value (the id could be an int the value could be a float); the EventList should have an attribute for a list of events. If you properly annotate these classes with @XmlRootElement, the mechanisms behind Jersey will be able to serialise the Events and the conatainer with the list of events to XML. Make sure that these two classes have a standard constructor and setters and getters for all the attributes. For more details see Vogella's tutorial on RESTful web services.

     

    Now implement the web service that has a static reference or uses a singleton for representing all the registered events. Then you should implement one service, which has and id and a value as a parameter (if you use the GET method, for these methods, you can easily submit parameters by adding them to the URL). The service for registering an event, should create an Event object with the resp. value and id and add it to the singleton for storing the events. And the event object should also be returned as a result. To this end, the annotations and method head should look like:
    @GET
    @PATH{"/addevent"}
    @Consumes({MediaType.APPLICATION_FORM_URLENCODED})
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public Event addEvent(@QueryParam("value") float value, @QueryParam("id") int id)

     

    Note that normally new events should rather be added by using the PUT method. The @Consumes annotation indicates that the values of the parameter will be provided in the URL; the @Produces indicates that the result should be a XML representation of some Java objects (which a client can convert back to objects; see below).

     

    The other service should have an id parameter, and should return all events that are registered for the sensor with the provided id; it should return an object of type EventList, which in turn consists of all the events.

     

    Test your web services by starting your web project on the web server. Enter the resepctive URLs of the web services in your browser and add the respective values of the parameter to the URL (e.g. .../addevent?id=5&value=3.4. First add some events; then retrieve the events for some sensor. All the web services should now return some XML representing the events or the list of events respectively.

     

  5. The main purpose of a web service is not to invoke it from a browser but from other applications. In the last step, you lear how to implement such a client of a web application. Note that major parts of that can be automatically generated by some "REST Web service client" wizard. Below, the steps for that will be explained.

     

    1. First, you need to install an extension to Eclipse, which implements this wizard. To this end, start the Plugin installation dialog (Help->Install New Software), select the Oracle OEPE update site (see assignment 1) and select the "Oracle WebLogic Server Tools", follow through the installation process, and restart Eclipse.

       

    2. After you restarted Eclipse, also make sure that you restart the above web project. Then create a new Java project in your workspace. To this Java project add a folder "lib" and add the three jar files from jersey-web-client-libs.zip to this folder, and add these files to the build path of the Java Project (select "Properties" on the project, and go to "Java Build Path"; in the tab "Libraries", you can add the above jar files to the project).

       

    3. Now, you can right-click on the Java project, and select the "REST Web service client" wizard (New->Other->Web Services->REST Web Service Client". In the opended dialog, you will be asked for an URL of a WADL. To this end, enter the URL of your web application appended with /rest/application.wadl (where rest is the part of path you registered Jersey with). Also enter a qualified name of a Java package within your newly created Java project to which the client should be generated.

       

    4. This wizard generates several classes, some for the model for events, and one which represents a client to all services. Its name is a capitalized and stripped version of the URL of the web application (e.g. Localhost_DkDtuComputeSe2WebSecondRest). This class has a static method to access the services (over different levels, if the service extend the path, which will be discussed in more detail in the tutorial session on Sept. 12). You can access the service, and invoke it by methods like getAsEventJson(1.0f, 1) for the add event service or getAsEventListJson(5) for the event list of a sensor. Note that the returned result will be objects again (the wizard has generated classes that reflect the classes for events and event lists on the server side).

       

    5. Create a new class with a static main method that invokes the services via the above client; this method should first add some events for some sensors, and then obtain the registered values for the different sensors again.

       

  6. Some things are done a bit crude up to now. This tutorial is mainly meant to get going with web services. Read a bit up on more details (see links below). We will learn some more details on how to properly deal with data in RESTful services and how to store them permanantly later. This will in particular require a unqiue identifier for objects.

     

Useful links

Here are some links that might be helpful:

 

 

Ekkart Kindler (), Sept 10, 2014