blob: 79660d9b9ec75400d4a447872eb0700e7528c04c [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Apache Wink : JAX-RS Resources, HTTP Methods, and Paths</title>
<link rel="stylesheet" href="styles/site.css" type="text/css" />
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
<tr>
<td valign="top" class="pagebody">
<div class="pageheader">
<span class="pagetitle">
Apache Wink : JAX-RS Resources, HTTP Methods, and Paths
</span>
</div>
<div class="pagesubheading">
This page last changed on Sep 07, 2009 by <font color="#0050B2">michael</font>.
</div>
<h1><a name="JAX-RSResources%2CHTTPMethods%2CandPaths-Resources"></a>Resources</h1>
<p>Resources are one of the fundamental concepts in REST. REST emphasizes the manipulation of resources rather than issuing function calls. Resources have unique identifiers. In HTTP terms, this means associating every resource with at least one URL.</p>
<p>In order to manipulate a resource, requests are made with a specific HTTP method. For instance, in order to retrieve a representation of a resource, an HTTP GET request to the resource's URL is issued. In order to create a new item in a collection, an HTTP POST can be used with the collection URL.</p>
<p>Application developers define resources and the HTTP methods in order to quickly manipulate them by using regular plain old Java objects and JAX-RS annotations.</p>
<p><a name="JAX-RSResources%2CHTTPMethods%2CandPaths-RootResource"></a></p>
<h3><a name="JAX-RSResources%2CHTTPMethods%2CandPaths-DefiningaRootResource%28@PathonJavaclass%29"></a>Defining a Root Resource (@Path on Java class)</h3>
<p>Developers can use POJOs to define a resource. Root resources have a <b>@Path</b> annotation at the class declaration level. JAX-RS matches an incoming request's URL with the <b>@Path</b> annotation on all of an application's root resources in order to determine which initial Java class will handle the request.</p>
<p>Root resources Java class instances are created per request by default.</p>
<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="images/icons/emoticons/information.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>Reference</b><br />Refer to the JAX-RS Application configuration topic for more information.</td></tr></table></div>
<p>Resource classes have methods that are invoked when specific HTTP method requests are made, referred to as resource methods. In order to create Java methods that will be invoked with specific HTTP methods, a regular Java method must be implemented and annotated with one of the JAX-RS @HttpMethod annotated annotations (namely, @GET, @POST, @PUT, and @DELETE).</p>
<p>For example, if a resource is located at a "/welcome" URL, the following root resource is defined.</p>
<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><b>WelcomeMessage.java</b></div><div class="codeContent panelContent">
<pre class="code-java">@Path(<span class="code-quote">"/welcome"</span>)
<span class="code-keyword">public</span> class WelcomeMessage {
<span class="code-keyword">private</span> <span class="code-object">String</span> welcomeMessage = <span class="code-quote">"Hello world!"</span>;
@GET
<span class="code-keyword">public</span> <span class="code-object">String</span> returnWelcomeMessage() {
<span class="code-keyword">return</span> welcomeMessage;
}
}
</pre>
</div></div>
<p>Any incoming GET request that has the URL of "/welcome" is handled by WelcomeMessage class's <b>returnWelcomeMessage()</b> method. A string is returned that represents the response body and is sent as the response payload in a HTTP 200 status response.</p>
<h3><a name="JAX-RSResources%2CHTTPMethods%2CandPaths-Usingajavax.ws.rs.core.Response"></a>Using a javax.ws.rs.core.Response</h3>
<p>In the previous GET resource method example, the response body is returned as a String. If a more complex response is requiredfor example, additional HTTP response headers or a different status code, a <b>javax.ws.rs.core.Response</b> should be used as the Java method's return type. By building a Response object, additional information can be returned to the client.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">@Path(<span class="code-quote">"/welcome"</span>)
<span class="code-keyword">public</span> class WelcomeMessage {
<span class="code-keyword">private</span> <span class="code-object">String</span> welcomeMessage = <span class="code-quote">"Hello world!"</span>;
@GET
<span class="code-keyword">public</span> Response returnWelcomeMessage() {
<span class="code-object">String</span> responseEntity = welcomeMessage;
<span class="code-keyword">return</span> Response.status(299).entity(responseEntity).header(<span class="code-quote">"CustomHeader"</span>, <span class="code-quote">"CustomValue"</span>).build();
}
}
</pre>
</div></div>
<p>The previous example uses 299 as the status code, standard HTTP status codes should be used in order to help clients understand responses.When using Strings as the response entity, different Java types may be used for complex responses.</p>
<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="images/icons/emoticons/information.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>Reference</b><br />Refer to the Request/Response entities page for more details on how request/response entities are handled.</td></tr></table></div>
<p><a name="JAX-RSResources%2CHTTPMethods%2CandPaths-HTTPMethods"></a></p>
<h3><a name="JAX-RSResources%2CHTTPMethods%2CandPaths-UsingCommonHTTPMethods%28@GET%2C@POST%2C@PUT%2C@DELETE%29"></a>Using Common HTTP Methods (@GET, @POST, @PUT, @DELETE)</h3>
<p>The four most common HTTP methods are GET, POST, PUT, and DELETE.</p>
<p>As shown in the previous example, an HTTP GET response to "/welcome" invokes the returnWelcomeMessage() Java method.In order&nbsp; to add a Java method that would be invoked when a HTTP PUT request is made to "/welcome", the following code should be added:</p>
<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><b>WelcomeMessageWithPut</b></div><div class="codeContent panelContent">
<pre class="code-java">@Path(<span class="code-quote">"/welcome"</span>)
<span class="code-keyword">public</span> class WelcomeMessage {
<span class="code-keyword">private</span> <span class="code-object">String</span> welcomeMessage = <span class="code-quote">"Hello world!"</span>;
@GET
<span class="code-keyword">public</span> <span class="code-object">String</span> returnWelcomeMessage() {
<span class="code-keyword">return</span> welcomeMessage;
}
@PUT
<span class="code-keyword">public</span> <span class="code-object">String</span> updateWelcomeMessage(<span class="code-object">String</span> aNewMessage) {
welcomeMessage = aNewMessage;
}
}
</pre>
</div></div>
<p>Notice that the updateWelcomeMessage has an unannotated parameter which represents an incoming request's body.</p>
<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="images/icons/emoticons/information.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>Reference</b><br />Refer to the Request/Response entities page for more details on how request/response entities are handled.</td></tr></table></div>
<p><a name="JAX-RSResources%2CHTTPMethods%2CandPaths-SubresourceMethod"></a></p>
<h3><a name="JAX-RSResources%2CHTTPMethods%2CandPaths-SubresourceMethods%28@Pathand@GET%2C@POST%2C@PUT%2C@DELETEonaJavamethod%29"></a>Subresource Methods (@Path and @GET, @POST, @PUT, @DELETE on a Java method)</h3>
<p>Sometimes it is easier having a root resource resolve a generic URL path and to have <b>@Path</b> annotated methods further resolve the request. For instance, suppose that a HTTP GET to "/administrator" returned generic information about an administrator. However, sometimes it is better to return smaller bits or more detailed information about the resource using a slightly different URL identifier. Suppose that a HTTP GET to "/administrator/name" should return the name. Instead of creating many root resource classes for each URL, you can have the root resource initially resolve the beginning of the URL request and then further resolve the request against subresource methods.</p>
<p>Subresource methods are Java methods with a <b>@Path</b> annotation and a @HttpMethod annotated annotation (@GET, @POST, @PUT, @DELETE).</p>
<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><b>AdministratorResourceWithSubresourceMethod</b></div><div class="codeContent panelContent">
<pre class="code-java">@Path(<span class="code-quote">"/administrator"</span>)
<span class="code-keyword">public</span> class Administrator{
@GET
<span class="code-keyword">public</span> <span class="code-object">String</span> findUserInfo() {
<span class="code-object">String</span> userInfo = <span class="code-keyword">null</span>;
/* build user info */
<span class="code-keyword">return</span> userInfo;
}
@GET
@Path(<span class="code-quote">"/name"</span>)
<span class="code-keyword">public</span> <span class="code-object">String</span> getJustUserName() {
<span class="code-object">String</span> userName = "";
/* get the user name */
<span class="code-keyword">return</span> userName;
}
@GET
@Path(<span class="code-quote">"/id"</span>)
<span class="code-keyword">public</span> <span class="code-object">String</span> getUserId() {
<span class="code-object">String</span> userId = "";
/* get the user id */
<span class="code-keyword">return</span> userId;
}
}
</pre>
</div></div>
<p>An HTTP URL request to the <b>"/administrator"</b> would resolve to Administrator#findUserInfo(). A HTTP URL request to "/administrator/name" would invoke the Administrator#getJustUserName() method. Finally a HTTP URL request to "/administrator/id" would resolve to Administrator#getUserId().</p>
<p><a name="JAX-RSResources%2CHTTPMethods%2CandPaths-SubresourceLocator"></a></p>
<h3><a name="JAX-RSResources%2CHTTPMethods%2CandPaths-UsingSubresourceLocators%28@PathonJavamethod%29"></a>Using Subresource Locators (@Path on Java method)</h3>
<p>In more complicated scenarios, subresource locators are needed. Subresource locators are particularly useful when requests must be further resolved by other objects. Subresource locators are Java methods which have only an <b>@Path</b> annotation. They are different than subresource methods because they do <b>not</b> have any HTTP method annotation on them.</p>
<p>A subresource locator returns an object that has JAX-RS annotations on its methods (or inherits them). The object is used to further resolve the incoming requests by dynamically inspecting the object for JAX-RS annotations.</p>
<p>This scenario uses @PathParams which are discussed on the parameters page.</p>
<div class="code panel" style="border-style: solid;border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><b>UsersResourcesWithSubresourceLocators</b></div><div class="codeContent panelContent">
<pre class="code-java">@Path(<span class="code-quote">"/users"</span>)
<span class="code-keyword">public</span> class UsersCollection {
@Path(<span class="code-quote">"{userid}"</span>)
<span class="code-keyword">public</span> <span class="code-object">Object</span> findUserInfo(@PathParam(<span class="code-quote">"userid"</span>) <span class="code-object">String</span> userId) {
<span class="code-keyword">if</span>(userId.equals(<span class="code-quote">"superuser"</span>)) {
<span class="code-keyword">return</span> <span class="code-keyword">new</span> SuperUser();
}
<span class="code-keyword">return</span> User.findUserInDatabase(userId);
}
}
<span class="code-keyword">public</span> class Superuser {
@GET
<span class="code-keyword">public</span> <span class="code-object">String</span> getUserInfo() {
<span class="code-object">String</span> userInfo = /* get the user info */;
<span class="code-keyword">return</span> userInfo;
}
@GET
@Path(<span class="code-quote">"/contactinfo"</span>)
<span class="code-keyword">public</span> <span class="code-object">String</span> getContactInfo() {
<span class="code-object">String</span> contactInfo = /* get the user contact info */;
<span class="code-keyword">return</span> contactInfo;
}
}
<span class="code-keyword">public</span> class User {
<span class="code-keyword">protected</span> <span class="code-object">String</span> name;
<span class="code-keyword">protected</span> User() {
/* subresource locator object lifecycles are controlled by the developer */
}
<span class="code-keyword">public</span> <span class="code-keyword">static</span> User findUserInDatabase(<span class="code-object">String</span> userName) {
User u = /* get user from database with assigned field values */
<span class="code-keyword">return</span> u;
}
@GET
<span class="code-keyword">public</span> <span class="code-object">String</span> getInfo() {
<span class="code-object">String</span> info = /* get the user info */;
<span class="code-keyword">return</span> info;
}
@GET
@Path(<span class="code-quote">"/name"</span>)
<span class="code-keyword">public</span> <span class="code-object">String</span> getMyUserName() {
<span class="code-keyword">return</span> name;
}
}
</pre>
</div></div>
<p>A HTTP GET to "/users/superuser" would result in User#findUserInfo() being invoked first. The method inspects the "userId" path parameter (which resolves to "superuser" for this request) so a Superuser object is returned. The request is then further resolved against the Superuser object. In the simple "/users/superuser" case, the request invokes Superuser#getUserInfo();</p>
<p>If a HTTP GET to "/users/superuser/contactinfo" was made, then User#findUserInfo() is invoked and again returns a Superuser object. The Superuser object is then used to resolve the "/contactinfo" portion of the request which invokes Superuser#getContactInfo.</p>
<p>If a HTTP GET to "/users/user1/name" was made, then User#findUserInfo() is again invoked but it would go and look up the user from the database and return a User object. The User object is then used to resolve the "/name" portion and results in the User#getMyUserName() method being invoked on the User object returned.</p>
</td>
</tr>
</table>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td height="12" background="http://cwiki.apache.org/confluence/images/border/border_bottom.gif"><img src="images/border/spacer.gif" width="1" height="1" border="0"/></td>
</tr>
<tr>
<td align="center"><font color="grey">Document generated by Confluence on Nov 11, 2009 06:57</font></td>
</tr>
</table>
</body>
</html>