|
|
Want to know more about Packt's Article Network? Interested in contributing your article ideas? Please visit our FAQ for more information. See More BROWSE
All Titles WordPress Web Services SOA BPEL Web Graphics & Video Web Development RAW Portugues, Espanol, Italiano, French PHP/MySQL Oracle Open Source Networking & Telephony Moodle Microsoft & .NET Linux Servers jQuery Joomla! JBoss Java e-Learning e-Commerce Dynamics Drupal CRM Cookbook Content Management Beginner Guides Architecture and Analysis AJAX Future Titles Recently Published Titles In this article by Jose Sandoval, we implement the web service requirements we outlined in the previous article on RESTful Web Services Design, with the RESTEasy framework. RESTEasy is not only a RESTful framework, but is also JBoss's umbrella project that provides other frameworks to build RESTful web services. As part of the REST facilities, RESTEasy fully implements the JAX-RS specification. Subsequently, we only look at how we use RESTEasy to implement RESTful web services. At the time of this writing, the released version is 1.1GA. See More |
RESTful Java Web Services Design
We'll leave the RESTful implementation for a later article. Our sample application is a micro-blogging web service (similar to Twitter), where users create accounts and then post entries. Finally, while designing our application, we'll define a set of steps that can be applied to designing any software system that needs to be deployed as a RESTful web service. Designing a RESTful web serviceDesigning RESTful web services is not different from designing traditional web applications. We still have business requirements, we still have users who want to do things with data, and we still have hardware constraints and software architectures to deal with. The main difference, however, is that we look at the requirements to tease out resources and forget about specific actions to be taken on these resources. We can think of RESTful web service design as being similar to Object Oriented Design (OOD). In OOD, we try to identify objects from the data we want to represent together with the actions that an object can have. But the similarities end at the data structure definition, because with RESTful web services we already have specific calls that are part of the protocol itself. The underlying RESTful web service design principles can be summarized in the following four steps:
This design process is not static. These are iterative steps that gravitate around resources. Let's say that during the URI definition step we discover that one of the URI's responses is not covered in one of the resources we have identified. Then we go back to define a suitable resource. In most cases, however, we find that the resources that we already have cover most of our needs, and we just have to combine existing resources into a meta-resource to take care of the new requirement. Requirements of sample web serviceThe RESTful web service we design in this article is a social networking web application similar to Twitter. We follow an OOD process mixed with an agile philosophy for designing and coding our applications. This means that we create just enough documentation to be useful, but not so much that we spend an inordinate amount of time deciphering it during our implementation phase. As with any application, we begin by listing the main business requirements, for which we have the following use cases (these are the main functions of our application):
However simple this example may be, social networking sites work on these same principles: users sign up for accounts to post personal updates or information. Our intention here, though, is not to fully replicate Twitter or to fully create a social networking application. What we are trying to outline is a set of requirements that will test our understanding of RESTful web services design and implementation. The core value of social networking sites lies in the ability to connect to multiple users who connect with us, and the value is derived from what the connections mean within the community, because of the tendency of users following people with similar interests. For example, the connections between users create targeted distribution networks. Resource identificationOut of the use cases listed above, we now need to define the service's resources. From reading the requirements we see that we need users and messages. Users appear in two ways: a single user and a list of users. Additionally, users have the ability to post blog entries in the form of messages of no more than 140 characters. This means that we need resources for a single message and a list of messages. In sum, we identify the following resources:
RESTful Java Web Services
Representation definitionIn RESTful web services, a representation is a temporal mapping of a resource at the time of a request. Furthermore, a representation is transmitted between clients and servers over HTTP. Because of HTTP's flexibility, any binary stream can be transferred. Nevertheless, we don't recommend choosing just any type of binary representation that requires special code or libraries to consume. We recommend using primarily XML and JSON structures, remembering, of course, that the requirements of the problem we're solving dictate what representation types we must provide. A well-designed RESTful web service needs to provide multiple resource representations. We can't assume that only web browsers will be accessing our public APIs or that only the one type of client we identified in our requirement gathering process will use our services. What are the options available, then? Again, arriving at the ideal representation format is a matter of the design process. We need to take into account what the service is doing and what clients will be using the resources for. The safest representation format is therefore XML. This is what web services are known for: transferring XML streams over web transport protocols. More important, most programming languages already have libraries available to parse XML streams. Finally, we need to account for linkability of representations. Linkability of representation means that the web services provide for resource discoverability, such that resources link to other resources (what's currently being referred to as HATEOS or Hypermedia As The Engine Of State transfer). For example, our URI for a list of users returns a structure of users with each element in the list having a direct URI to each element in the service (a link to a user). XML representationsFrom our analysis, we identified two types of resources: users and messages. As part of the heuristics we outlined earlier, we need to define what our representation will look like. The following representations are the structures that we will have to implement when we actually code the web service. UsersWe first define a user representation as follows: <user> As part of a user resource, we store only a username and a password. The username is unique in the context of our system and is used to uniquely identify each user. The link element, which points back to the web service, is either assigned when the resource is created or a representation is built for transport (for our sample service, we let the backend create the link). We now define a list of users as follows: <users> This XML structure declares a list of users stored in an XML element <users>. We use ellipses or ... to show that we can have more than one user in the list. We can see here the linkability concept at play: with a list of users we can drill down to individual users using the link element's value. MessagesWe first define a single blog entry or message as follows: <message> A message needs a message id, the body of the message (the content element), and the user who posted the message. Note that depending on what we are doing with the message, we don't pass all the resource's information back and forth. For example, when we are creating a message at the client layer, we don't know what the value for messageID is. Therefore, we still need to pass the message structure to the service, but our web service will know that any messageID value needs to be ignored, because, in our case, it will be created by the storage layer. Finally, we define a list of messages as follows: <messages> This XML structure holds a collection of messages, and each message holds the user who posted the message. We use the XML representation type for input and output. Input in this case means that we send a resource representation to create and update the resources at the web service layer in the form of an XML object. Output means that a client requests an XML representation of a resource. JSON representationsWe use the same key names for our JSON representation, and we still have only two types of resources: users and messages. Again, these structures are our specification of what we need to return for each request. UsersWe define a user representation as follows: {"user":{"username":"john", "password":"password",And we define a list of users as follows (we use the ... characters to show that there is more than one user in the array): {"users-result":{"count":"6", "users":[{"username":"john",The array for all users as a JSON structure, looks as follows: "users":[{"username":"john", "password":"password",Once the JSON response has been evaluated with the JavaScript eval() function, we can then access any of the values in the structure. For example, if we need the user name of the first element on the array, we use users-result.users[0].username. We now define a message representation as follows: {"message":{"messageID":"some-id", "content":"some content",And a list of messages as follows: {"messages-result":{"count":"6", "link":"/messages",Each message element in the array has a user structure embedded as follows: {"messageID":"some-id", "content":"some content",Once the JSON response has been evaluated with the JavaScript eval() function, we can then access the first element on the list with messages-result.messages[0].content; if we want to get the user name of the user who posted the message, we access the value with messages-result.messages[0].user.username. Note that during implementation we'll use JSON representations only as response streams. This means that we won't use JSON structures to create or update resources at the web service layer. Although we could use XML and JSON to update resources at the service layer, we'll omit JSON for the sake of brevity. URI definitionThe next step involves the definition of URIs. This is a crucial step, as the URIs define our API and it's likely that we want to make our web service public. We strive to make our APIs logical, hierarchical, and as permanent as we can. We must emphasize these three tenets, as we may have many developers depending on the services we make available. Therefore, a good API is one that doesn't change too often and is unambiguous to use. Furthermore, the idea of RESTful APIs is that we maintain URI uniqueness and reliability of service. (For a complete discussion about this topic, see http://www.w3.org/Provider/Style/URI.) The first thing we need is a web address. In our case, we assume that we're using our development machine running on http://localhost:8080/. It's important to distinguish between a web service and a web application: we use web services to implement web applications, and web services can be, and are recommended to be, independent of web applications. What's more, web applications are meant to be consumed by humans, as opposed to web services that are intended for machine consumption. The nomenclature of RESTful URIs falls under the topic of URI templates and the following conventions are widely used. First, for items or identifiers that don't change, we find the keyword to be part of the actual URI—for instance, we use users to be the URI for a list of all users. Second, we use keys or dynamic keywords to be enclosed in { and }. Applying these conventions, our URI list for users looks as follows:
And for messages, our URI list looks as follows:
At the time of this writing, the URI Template specification is still under review. For more information, see http://tools.ietf.org/html/draft-gregorio-uritemplate-03. Executing logic with RESTful URIsA question arises when designing RESTful web services that has to do with executing code at the server level. Specifically, how do we execute logic if we limit our client/server interactions to only four CRUD-like calls (POST, GET, PUT, and DELETE)? For this we need to introduce URIs that execute logic on the server, remembering that responses must be in the form of resource representations. In other words, we avoid any RPC style calls and concentrate on the resources only. For our web service, we only offer the ability of searching for a term or a phrase in the blog entries. For example, any user can search for the term "programming" or "software development" using the following URI (note that the URI pattern is arbitrary and you can choose whatever makes sense for the service you are developing): http://localhost:8080/messages/search/{search_item}This URI returns a list of messages that contain the word or words search_item—this is strictly a GET method call and no POST, PUT, or DELETE method is supported Using URIs to request representation typesA RESTful web service is one that adheres to all the constraints outlined in RESTful Architectures. However, we have encountered APIs that don't strictly adhere to every constraint. For example, requesting representation types via URIs is something we saw with Twitter's API. We requested three different types of representations with the URI http://twitter.com/statuses/public_timeline.{xml, json, rss}. We said that this is not technically a RESTful web service request, because we don't use the communication protocol—HTTP headers—to tell the service what kind of representation to get. Even though this is not a RESTful web service, it still works. Nevertheless, the API may be open to interpretation. For example, what does it mean to send an HTTP GET request to the URI http://twitter.com/statuses/public_timeline.json with an HTTP Accept header value of application/xml? Do we get a JSON representation or an XML representation? A properly designed RESTful web service has to adhere to all REST constraints, and using the protocol to negotiate representations is part of being RESTful. Creating a properly defined RESTful web service, however, ensures that there are no misunderstandings on how to use such services. For example, setting the HTTP method type to GET with an appropriate Accept header value makes it clear that we are requesting a resource of a specific type. In the end, you, as a developer or software architect, need to make a decision as to which style will benefit your users the most. Using this representation request style is a design decision that facilitates—it can be argued—the writing of clients. For instance, the majority of public APIs are read only, so using a straight HTTP GET request with the type of representation embedded in the URI is easier than instantiating a full HTTP request and modifying the HTTP header Accept each time. Note that neither is hard to implement; however, with the former, we save a couple of lines of code at the client layer. Again, it's a matter of choice. Our sample web service is a canonical application, thus we don't deviate from any of the constraints. This means that we use the HTTP protocol to request a preferred resource representation and not the URI style described in this section. SummaryAs we've seen, the RESTful design process is resource centric. In addition, we have no arbitrary actions executing on the data—we have HTTP method calls that exchange representations using clearly defined URIs. The steps to arrive at a web service that adheres to all REST constraints are similar to traditional web application design. So we can still use all our traditional requirement gathering techniques, but tweak the process to account for proper design of usable URIs and consumable representations. Now that we have our social networking web service specification defined together with a set of RESTful design principles, the next step is implementation which we will cover in the next article on RESTEasy: JAX-RS. If you have read this article you may be interested to view : RESTful Java Web Services
About the AuthorJose Sandoval is a software developer based in Canada. He's played and worked with web technologies since the Mosaic web browser was released into the wild, and for the last eight years he's consulted for various financial institutions and software companies in Canada and the US, concentrating in large-scale Java web applications. He holds a Bachelor of Mathematics degree from the University of Waterloo and an MBA from Wilfrid Laurier University. Aside from coding and writing, he enjoys watching a good soccer match and coaching his son's soccer team. You can learn more about his interests at his personal web site http://www.josesandoval.com or his consulting firm's web site http://www.sandoval.ca. Books from Packt |
REST (REpresentational State Transfer) is an architecture for distributed hypermedia systems. The World Wide Web is possibly the best known implementation of this architecture style. The term "REST" was coined and described by a dissertation written by Roy Fielding in 2000. This article by Nicholas Floyd covers the architecture which contains four basic constructs that address common concerns such as: scalability, generalized interfaces and resources, and patternized approaches for manipulation of resources. See More |
| ||||||||