CS 639 Class 22

Handout: firstRest2 on front, orderService on back

 

Last class notes: see cleaned up explanation of JAXB annotations for orderService.

 

Recall last time that we have ant targets to use JAXB for conversion of XSD to/from POJOs.  The additional JAXB tool support code is in basedir/lib, not deployed to tomcat.   This is using JAXB outside of Jersey.  We are of course also using JAXB when we use Jersey with POJOs.

 

Let’s look at the slick setup generated by JAXB from our schema, OrderService.xsd, located in the gen-src directory of the orderService project.

 

They are all in one package (specified in the XJC command in build.xml) with package-info to set the NS for all classes, and elementFormDefault. So OrderRepresentation (POJO name from XSD type name) gets the advantage of this setup, and has no NS markup itself.  OrderRepresentation.java has

 

@XmlAccessorType(XmlAccessType.FIELD)

 

So that fields will be one-one with child elements.  Then only the fields for the required child elements are given @XmlElement  markup:

 

@XmlElement(required = true)

 

We see a new annotation of the class:

@XmlType(name = "orderRepresentation", propOrder = {                

    "id",

    "item",

    "location",

    "cost",

    "status"

})

 

This tells JAXB what order to generate child elements in.  At runtime, JAXB only has .class files to look at for serialization, and it turns out that reflection does not reliably report on the order of the fields, so this annotation is needed to bridge that gap.  This also explains the “laxness” we discussed last time, that JAXB will accept XML with out of order child elements.  So this annotation is important, and really should be in our orderService POJOs.

 

Mysteriously, there is no @XMLRootElement in gen-src’s OrderRepresentation or Item, although order and item are global elements in the OrderService.xsd. This is explained by reading the spec and finding there are two ways to specify root elements, the @XMLRootElement we used before and by having an ObjectFactory.java with class annotation @XmlRegistry and a createOrder method with @XmlElementDecl annotation, and this more obscure way is used here. We can easily convert to @XMLRootElement.

 

 

Back to Vogel’s JAX-RS tutorial, Sec. 5. nicely set up, example of GET to collection URI

(re design problem in pa3) Available in firstRest2, linked to class web page under Resources.

 

Packages

resources: ToDoResource, ToDosResource

dao: TodoDao: uses HashMap<String, Todo> to store Todos

model: Todo, with minimal JAXB markup, just @XmlRootElement on the class.

 

These packages can be corresponded to the three well-known web app layers:

·         Presentation: top layer, where new requests come in: resources

·         Service: heart of app, where business code resides: pretty trivial here, also in resources

·         Data access: dao

 

This leaves model, with the POJO, separate from the layers, and this is right. The Todo POJO carries data across the layers.

 

More on these layers when we analyze orderService later in this class.

 

Note: no namespace in use here, simplifying the JAXB needs. If we want to add a namespace, we can annotate the child elements as in OrderRepresentation, or set up package annotations.

 

His Todo service looks like this:

GET /todos    ßGET to collection URI

GET /todos/count

POST /todos

GET /todos/{id]

PUT /todos/{id}

DELETE /todos/{id}

Using GET to Collection URI (relevant to pa3’s “Designing a better orderService”)

 

Vogel’s GET /todos returns List<Todo> to JAX-RS. Here’s the XML:

This is printed in the tutorial, from a browser:

 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<todoes>

  <todo><id>3</id><summary>Blabla</summary>

  </todo>

  <todo><description>Read complete http://www.vogella.de</description>

    <id>2</id><summary>Do something</summary>

  </todo>

  <todo><description>Read
          http://www.vogella.de/articles/REST/article.html</description>

     <id>1</id><summary>Learn REST</summary>

  </todo>

</todoes>

 

Interestingly, it spells the plural of todo with an e, different from the URI segment. It has some pluralization algorithm of its own to go from “todo” to its plural. There is no JAXB markup to guide it here.

 

Note that in the big table of class 18, we saw in GET for collection URI:

     List the URIs and perhaps other details of the collection's members

 

So another option would be List<URI>, but JAXB won’t serialize this type, or List<String> without additional work (providing message handlers.)

 

JAXB will serialize List<POJO> for any JAXB POJO, so we could set up a POJO for a URI and send that List off.

 

But for our purposes, sending List<Todo> for the collection-URI GET fits with our URI-free responses.

 

        // Return the list of todos to the user in the browser

        @GET

        @Produces(MediaType.TEXT_XML)

        public List<Todo> getTodosBrowser() {

                List<Todo> todos = new ArrayList<Todo>();

                todos.addAll( TodoDao.instance.getModel().values() );

                return todos;

        }

 

So List<POJO> gets serialized, using funny plural of todo to contain the list, because there is no markup to specify that element name.

 

On the client side: set up a service object of type WebResource, as before, and, for above display

// Get the Todos                  System.out.println(service.path("rest").path("todos").accept(

                                MediaType.TEXT_XML).get(String.class));

 

The implementation of the whole REST API could be all in TodosResource, but instead it’s split up into two source files to show the power of subresources to handle hierarchy in URIs.

 

/todos/{id}

<----> <--->

TodosResource: main resource for handling collection of Todos

                TodoResource: a subresource handling a single Todo

 

For now, just accept this as an explanation for why there are two java files in resources.  This service could easily be implemented all in TodosResource, as follows:

 

TodosResource has

@Path(“/todos”) on the class: the root resource, starts with / (not allowed in subresources)

sets first part of URI for the class

 

@GET on a method, to handle GET /todos

 

@GET

@Path(“count”)  on a method, to handle GET /todos /count

 

@POST on a method, to handlle POST /todos

 

Following orderService, we could handle GET /todos/1234 here too:

@GET

@Path(“{todo}”) 

To handle GET /todos/1234

 

And similarly for the others.

 

Instead, there’s a handoff from here into the subresource---look at later

 

Another trick in this firstRest2 example: Form handling

REST services are so simple we can use them from HTML

 

Consider a HTML form in the top-level directory of the web app called “todo_form.html” and make it (simplified and corrected) as follows:

...

<form action="rest/todos" method="POST"> 

       <input name="id" /><br/>

       <input name="summary" /><br/>

       Description:

       <TEXTAREA NAME="description" COLS=40 ROWS=6></TEXTAREA><br/>

       <input type="submit" value="Submit" />

</form>

 

The resulting POST to the local URL rest/todos with params id=6, summary=new+entry, description=new+idea, brings it to the following in TodosResource.java:

 

@POST

       @Produces(MediaType.TEXT_HTML)

       @Consumes(MediaType.APPLICATION_FORM_URLENCODED)  <--form data coming in

       public void newTodo(

              @FormParam("id") String id,   <--and particular params

              @FormParam("summary") String summary,

              @FormParam("description") String description,

              @Context HttpServletResponse servletResponse  <-- for redirect

       ) throws IOException {

              Todo todo = new Todo(id,summary);

              if (description!=null){

                     todo.setDescription(description);

              }

              TodoDao.instance.getModel().put(id, todo);

             

              URI uri = uriInfo.getAbsolutePathBuilder().path(id).build();

              Response.created(uri).build();

             

              servletResponse.sendRedirect("../create_todo.html");

       }

      

Then Jersey can give us the params with @FormParam(“id”) annotation of a method parameter as we process the POST, and also the servlet response object for a redirect. The create_todo.html is in the top-level directory, .. to /rest.

 

To check your addition, browse to /firstRest/rest/todos and get a new list.

 

See the new project posting at the end of the class web page, with links for the project and for the form and the list of Todos, from the deployed project at sf08.cs.umb.edu:11600/firstRest2/.

 

Headers, Cookies can be picked up similarly—see Javadocs

 

orderService Software Architecture, Pull technology vs. notifications

 

So far we have been concentrating on orderServices REST services, since that’s what is important to clients, and also JAXB, which is more generally useful than just this one app.

 

Now look at it as a decent REST service implemention, and get ready for pa4, which expands it to handle payment and flexible options.

 

 

C:\CS\CS639\ORDERSERVICE\SRC

├───functionaltest

              ...

├───main

   └───java

       └───com

           └───restbucks

               └───ordering

                   ├───activities

                   ├───domain

                   ├───repositories

                   ├───representations

                   └───resources

└───test

... unit tests

 

orderService packages

resources: where the @GET, @POST, etc.,  handlers are for each resource. Minimal REST-related code is here.  The methods call into the main app code to do whatever the app is meant to do.

representations: where OrderRepresentation is, and any other POJO needed just for external communication.

domain: where Order is, also Item, used by both Order and OrderRepresentation, and the enums for all the options.  These are the POJOs used by the app internals in activities and repositories.

activities: the heart of the app. Implementations of the actions this app wants to do for each incoming request.  Also known as the “business layer” or “service layer”

repositories: code for accessing database tables or similar holders of long-term state for the app. Also known as the Data Access layer, or DAO layer, for data access objects.

 

Web apps (including orderService) generally have three layers:

·         Presentation layer: here resources: interacting with a user or external agents

·         Business/Service layer: here activities: the heart of the app, doing what it knows how to do

·         Data Access layer, here repositories: arranging long-term storage for app data

 

What is a layer here?

In a layered system, the code in a higher layer calls methods in the next layer down, or in its own layer, but never calls up to the layer above it.  Here resources methods call activities methods, and activities methods call repositories methods, which just do their thing saving or retrieving data and return.  Then the activities method returns to the resources method. 

 

That leaves domain as not being a layer.  That is correct: domain objects circulate in the system, carrying data.  After all, the data needs to flow from the network down into the long-term storage when an order is created, and back up when order status is asked for.

 

Note that the calls go down the layers even in the case that the data is coming up the layers.  Consider a GET for order status.

1.       It first shows up as a call into resources at the @GET method in OrderResource.

2.       This resources method calls into activities to get status by id.

3.       This activities method calls into repositories to get the data from long-term storage

4.       The data is returned from repositories to activities in an Order object.

5.       Then it is converted into an OrderRepresentation object and returned from activities  to resources

6.       Then in resources, the GET method of OrderResource sends it off as XML.

 

 

 

Pull Web Interactions

Note that the user has to ask over and over for status to be sure to find out immediately if their order is ready.  It would be nice if the system contacted the user when the order became ready.  But HTTP is client-request driven, otherwise known as Pull technology. Although the server’s web address is known to the client, and the server accepts new requests any time, the client does not have the same capability. The server gets to send to the client at the end of each client request, but once it closes that connection, it has lost contact.

 

In the case that the server must get back to the user at some “random” time, email is one option. That’s because the user has a relationship with another server, and checks it now and then, or has an email agent that periodically checks and signals new email. It is strightforward to add email capability to web apps, something like adding database access (covered in CS636).

 

Of course HTTP is not the only protocol on the network. It is possible to have a TCP connection open for longer times, say hours, and keep a conversation going between two ends. But in practice, it’s hard to engineer this approach, because the network has interruptions, and then you have to resynchronize the conversation. It’s better to live within the restrictions of HTTP.

 

Having only Pull Requests makes call-down layering possible

The fact that REST follows HTTP Pull protocols makes the layering possible and practical.  If the system had to notify the client when the coffee order was ready, that would be an up-call: the change of state would happen in the repository level, and then the repository would have to call up to the user-communications level.  But that doesn’t happen.

 

The orderService package structure is reusable, “natural” for web services apps, even web apps

So we see that this layered software organization is not just for this particular app, but can be used for any REST server.  Or any web services server, for that matter, SOAP or REST.  Or a web app using JDBC.

 

Even though JDBC can use a long-term TCP connection, it still does only Pull actions from the client. You might think you could hook up database triggers to JDBC, but in fact you can’t do server-to-client notifications via JDBC.

 

(not covered in class--)

The network technology to do notifications is called a publish-subscribe service, or “pub-sub” for short. It can be done with JMS, Java Messaging Service, another technology of Java EE, with the help of longer-term TCP connections to a database.  It’s not an easy thing to work with.

 

Event Handling the REST way: using feeds

The closest thing in the REST world to notification is an event “feed”, using the Atom protocol (Chap. 7 in Webber et al.), or the older RSS protocol.  A feed doesn’t deliver events, but it organizes them to make it easy for clients to pick them up now and then at their own convenience.

 

The example in Chap. 7: Restbucks has occasional price changes, special drinks to put on the menu, etc. These changes to its basic catalog are “events” that get put in a “feed”.  The individual coffee shops “poll” the feed to pick up these changes and apply them to their local menus.  That’s the REST way to handle events.

 

The APIs between the layers

OK 3 layers. That means 2 APIs between layers:

Call into business layer:  the Service API, tells what the service can do

 

Look at Software Layers handout

 

In pa4, you will extend these APIs to cover payment and receipts and options.

 

We want to go on to Chapter 5 to look at the hypermedia version of orderService, which comes with an Jersey implementation I’ll post as orderDap, after converting it to tomcat.  It is useful for pa4 because it has support for payments and receipts.

 

Q: What’s hypermedia?  The idea that a response from one URI should present the all the next-URIs that follow from that state, to guide the user around the service.  We are not returning URIs, just information relevant to the resource of the URI.  In Chapter 5, the responses contain URIs too.

 

But first, we should look at other “plain” REST services, i.e., not hypermedia.  There’s more we can do with just URI templates and XML messages.

 

 

The Jersey REST Samples.

Jersey comes with a whole distribution of samples, available in a zip file for example at http://download.java.net/maven/2/com/sun/jersey/samples/jersey-samples/1.0.3/

 

One of the samples is a bookmark app that  has users with bookmarks like the example we just looked at, with URI template  /users/{userId}/bookmarks/{bookmarkId}.

 

However it serves JSON and uses JPA, so it’s not directly in our ballpark.

 

Another Jersey sample is a bookstore REST service: items are CDs or books, CDs have tracks.  It shows how we can use inheritance in the representational POJOs.

 

Bookstore 

GET 

/count 

Bookstore 

GET 

/time 

Bookstore 

GET 

/items/{itemid} 

Book, CD 

GET 

/items/{itemid}/tracks/{num} 

Track 

GET 

 

The Bookstore resource returns a list of items, either CDs or books. The resource dynamically references a Book or CD resource using the getItem method that is annotated with @Path. Both the Book and CD resources inherit from the Item class, therefore, the item can be managed as an Item whether it’s really a Book or CD.

 

This shows an example where subresources could more reasonably be used than the simple firstRest2 case, that is, hand off to a subresource to handle the individual track requests.