More JAX-RS Annotations
Having a REST service greet you is nice, but it’s hardly a very useful service. Next you’ll implement a simple service that ties directly to our Banking example. Remember from the description of the sample in Chapter 1 that often a development team wants to mock up services so that the UI and Java development teams can test independently. The rest of this chapter walks you through the implementation of such a set of services—in Chapter 7, “Introduction to IBM Worklight,” we show you a complete example that is much more like the production code that would be used to implement these services. Table 4.2 shows a set of services you need to implement as part of the example online and mobile banking solution.
Table 4.2 Services for Online Banking
URI |
Description |
/banking/accounts |
List of accounts |
/banking/accounts/{id} |
Detail of given account ID |
/banking/accounts/{id}/transactions |
List of transactions for a given account |
/banking/accounts/{id}/transactions/{id} |
Detail of given account ID/transaction ID |
We begin by looking at the Accounts resource. You can see two interesting resource references here: one service to return a list of accounts and another service to return the detail for a specific account. From this point on in the chapter, we assume that you know how to create new resource classes, so we just look at the code for each new class. Let’s start by creating a new class in com.ibm.mwdbook.restexamples named SimpleAccountResource, with the code shown in Listing 4.3. We begin with this class in the listing and use it to learn some more features of JAX-RS; then we replace it with a more complete implementation in Listing 4.4. Remember that this class, as with all resource classes, has no special base class.
Listing 4.3 SimpleAccountResource Class
package com.ibm.mwdbook.restexamples; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @Path("/simple/accounts") public class SimpleAccountResource { @GET @Produces("application/xml") public String getAccounts() { return "<accounts><account>123</account>"+ "<account>234</account></accounts>"; } @Path("{id}") @GET @Produces("application/xml") public String getAccount(@PathParam(value="id") int accountId){ if (accountId==123) return "<account><id>123</id>" + "<description>Savings</description>" + "<balance>110.00</balance></account>"; else return "<error>No account having that id</error>"; } }
In this example, the code implementing the functionality of the service isn’t the interesting part; it’s the annotations that surround the functionality. The first @Path annotation simply sets up the basic URI of this example—remember that you’re initially building a throwaway example that you will replace, so you don’t use the actual URI in Table 4.2 for this example. Instead, to differentiate this example from others later, you prefix the end of this test URI with simple instead of just accounts, as the table shows.
As in the previous example, you begin with the method named getAccounts(), which returns an XML string representing a collection of two different accounts. The first point to notice is a new tag, @Produces, which states what type of content the method returns. In the case of both our new methods, this is application/xml. At this point, you might be wondering why we didn’t need this for our previous example. The answer is simple—if you don’t add the @Produces annotation to a resource method, the JAX-RS provider assumes that the content type is text/html.
As useful as that is, you can see a much more interesting new feature in the second @Path annotation added to the bottom method. Here we’re adding the mechanism to handle a second part of the URI that comes after the /accounts portion handled by getAccounts(). In the example, we want to provide access to a specific account that is identified by an integer account number placed after the /accounts portion of the URI. The @Path({id}) annotation identifies that specific account number. But then the question becomes, how do we manage to map the account number information from the URI to the getAccount(int) method? That’s the role of the @PathParam(value="id") annotation.
@PathParam is probably the single most useful source of parameter information for resource methods, but it’s not the only source. Table 4.3 shows some other common sources of information that you can use as parameters in your resource classes.
Table 4.3 Sources of Parameter Information in Resource Classes
Source |
Description |
@QueryParam |
Individual query string parameter attached to the URI in the form ?name=value |
@PathParam |
Parameter from URI template |
@CookieParam |
Http cookies value |
@HeaderParam |
Http header value |
@FormParam |
HTML form elements |
@Context |
Limited set of context objects |
Testing the New Example
Entering that little bit of code is all you need to do for this new example. At this point, you should be able to test your new examples in your browser. You don’t even need to restart the server—when you change the classes, Eclipse and Liberty automatically update the files on the server (using the dropins directory on the Liberty server that we mentioned in Chapter 2), so your changes take effect immediately.
Enter the following URLs into your browser to view the results. First, to see the list type, use this:
http://localhost:9080/RestServicesSamples/banking/simple/accounts
Then to see the individual account, type this:
http://localhost:9080/RestServicesSamples/banking/simple/accounts/123
Finally, to see the error path, type this:
http://localhost:9080/RestServicesSamples/banking/simple/accounts/234