{"id":1723,"date":"2011-02-03T08:44:52","date_gmt":"2011-02-03T13:44:52","guid":{"rendered":"http:\/\/www.andygibson.net\/blog\/?p=1723"},"modified":"2011-02-08T11:16:02","modified_gmt":"2011-02-08T16:16:02","slug":"simple-restful-web-services-with-glassfish","status":"publish","type":"post","link":"https:\/\/www.andygibson.net\/blog\/article\/simple-restful-web-services-with-glassfish\/","title":{"rendered":"Simple RESTful web services with Glassfish"},"content":{"rendered":"<p>Here&#8217;s a quick guide to creating a RESTful web service with Glassfish using JAX-RS.<br \/>\n<!--more--><br \/>\nFirst create a new maven project called <code>restwebdemo<\/code> using the jee6-sandbox-archetype so we have a model and some data to work with. To get this working with Glassfish, open the <code>persistence.xml<\/code> file and change the <code>jta-data-source<\/code> name to <code>jdbc\/__default<\/code>. Also, make sure that the javaDB is up and running by going to <code>$glassfish_dir\/bin<\/code> and typing <code>asadmin start-database<\/code>. Verify that the application is working correctly by going to <a href=\"http:\/\/localhost:8080\/restwebdemo\/\">http:\/\/localhost:8080\/restwebdemo\/<\/a> and you should get a list of courses.<\/p>\n<p>Before we start getting to the interesting stuff, we have one more boring piece of configuration to perform specific to web services. We need to add the jersey servlet container to our <code>web.xml<\/code> file:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;servlet&gt;\r\n\t&lt;servlet-name&gt;Jersey Web Application&lt;\/servlet-name&gt;\r\n\t&lt;servlet-class&gt;com.sun.jersey.spi.container.servlet.ServletContainer&lt;\/servlet-class&gt;\r\n\t&lt;load-on-startup&gt;1&lt;\/load-on-startup&gt;\r\n&lt;\/servlet&gt;\r\n&lt;servlet-mapping&gt;\r\n\t&lt;servlet-name&gt;Jersey Web Application&lt;\/servlet-name&gt;\r\n\t&lt;url-pattern&gt;\/rest\/*&lt;\/url-pattern&gt;\r\n&lt;\/servlet-mapping&gt;\r\n<\/pre>\n<p>This also tells Jersey to handle urls starting with <code>\/rest<\/code> and pass it along to our web service methods.<\/p>\n<p>Now we can dive right in an create a new server bean that will respond to requests for web services. For now we&#8217;ll just return a simple message from a POJO.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Path(&quot;sample&quot;)\r\npublic class SimpleService {\r\n\t\r\n\t@Path(&quot;greet&quot;)\r\n\t@GET\r\n\tpublic String doGreet() {\r\n\t\treturn &quot;Hello Stranger, the time is &quot;+ new Date();\r\n\t}\r\n}\r\n<\/pre>\n<p>The path annotation on the class indicates that this is a root resource class and the path value given specifies the base URI for all the web service methods contained in the class.<br \/>\nOn the <code>doGreet<\/code> method we have <code>@Path<\/code> which is used to specify the path template this method should match. The <code>@GET<\/code> annotation is used to differentiate between a sub-resource method that handles the actual web service request and a sub-resource locator method that returns an object that will instead be used to handle the request. In this case, the method has the <code>@GET<\/code> annotation which means this method handles the request and returns the result.<br \/>\nIf you navigate to <a href=\"http:\/\/localhost:8080\/restwebdemo\/rest\/sample\/greet\/\">http:\/\/localhost:8080\/restwebdemo\/rest\/sample\/greet\/<\/a> you should see a welcome message with the current date and time.<\/p>\n<p>Now we&#8217;ll look at adding parameterized web services that extracts parameters from the request URL and uses them to form the output. Add the following method to the web service class :<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Path(&quot;sayHello\/{name}&quot;)\r\n@GET\r\npublic String doSayHello(@PathParam(&quot;name&quot;) String name) {\r\n\treturn &quot;Hello there &quot;+name;\t\t\r\n}\r\n<\/pre>\n<p>Again we have the path annotation to indicate what URLs this method will match, and this time we have have <code>{name}<\/code> added to the URL. This lets us extract a part of the url and give it a name. This name is used in the <code>@PathParam<\/code> annotation in the method signature to assign the URL fragment to the name parameter . To test our new method, redeploy the application and go to the URL  <a href=\"http:\/\/localhost:8080\/restwebdemo\/rest\/sample\/sayHello\/Andy\">http:\/\/localhost:8080\/restwebdemo\/rest\/sample\/sayHello\/Andy<\/a> to get the response  <code>Hello there Andy<\/code><\/p>\n<p>We can also use request parameters to provide values to the method by using the <code>@QueryParam<\/code> annotation. We&#8217;ll create another method that is similar but uses a query parameter instead.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Path(&quot;sayHello&quot;)\r\n@GET\r\npublic String doSayHelloWithRequestParam(@QueryParam(&quot;name&quot;) String name) {\r\n\treturn &quot;Hi there &quot;+name;\r\n}\r\n<\/pre>\n<p>This time, the URL to use is <a href=\"http:\/\/localhost:8080\/restwebdemo\/rest\/sample\/sayHello?name=Andy\">http:\/\/localhost:8080\/restwebdemo\/rest\/sample\/sayHello?name=Andy<\/a> to get the same message.<\/p>\n<p>To make things more interesting, lets add a new page that lets us enter a name in a form and submit it to the web service.  Add a new page called <code>form.html<\/code> with the following content : <\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;html&gt;\r\n&lt;head&gt;\r\n&lt;title&gt;Insert title here&lt;\/title&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n&lt;form action=&quot;rest\/sample\/sayHello&quot; method=&quot;GET&quot;&gt;\r\nName &lt;input id=&quot;name&quot; name=&quot;name&quot;\/&gt; &lt;input type=&quot;submit&quot; \/&gt;\r\n&lt;\/form&gt;\r\n&lt;\/body&gt;\r\n&lt;\/html&gt;\r\n<\/pre>\n<p>Go to this page at <a href=\"http:\/\/localhost:8080\/restwebdemo\/form.html\">http:\/\/localhost:8080\/restwebdemo\/form.html<\/a>, enter your name and click submit and you should be greeted by name in the next page.<\/p>\n<p>Notice that we had to set the form method to <code>GET<\/code> because our web service is only set up to respond to GET requests. If we change the form method to POST we can get the following error message : <\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nHTTP Status 405 - Method Not Allowed\r\ntype Status report\r\nmessage Method Not Allowed\r\ndescription The specified HTTP method is not allowed for the requested resource (Method Not Allowed).<\/pre>\n<p>Remember, with REST, those actual verbs have meaning and adds meaning to the request so it is strict on how it matches the method to be called.<\/p>\n<p>To solve this problem, we can add a new method to handle form POSTs like so :<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Path(&quot;sayHello&quot;)\r\n@POST\r\npublic String doSayHelloWithFormParam(@FormParam(&quot;name&quot;) String name) {\r\n\treturn &quot;Hi there &quot; + name;\r\n}\r\n<\/pre>\n<p>Here we changed the <code>@GET<\/code> to a <code>@POST<\/code> to allow the different verb and changed the annotation on the <code>name<\/code> method parameter to <code>@FormParam<\/code>. The path remains the same because we can have service methods that match the same path, but for different request verbs. We can even have the same verb and path as long as the content type returned is different. The content type is used to specify the type of output the is returned from the method. It is set by adding a <code>@javax.ws.rs.Produces<\/code> (not to be confused with the CDI <code>Produces<\/code> annotation).  The annotation takes a string parameter that indicates the type of media returned from the method. Common media types are defined as constants in the <code>MediaType<\/code> class so you can use :<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Path(&quot;sayHello&quot;)\r\n@POST\t\r\n@Produces(MediaType.APPLICATION_XML)\r\npublic String doSayHelloWithFormParam(@FormParam(&quot;name&quot;) String name) {\r\n\treturn &quot;&lt;message&gt;Hi there &quot; + name+&quot;&lt;\/message&gt;&quot;;\r\n}\r\n<\/pre>\n<p>If you run your form again, and post it, you will get an xml response as follows : <\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;message&gt;Hi there Andy&lt;\/message&gt;\r\n<\/pre>\n<p>Depending on your browser, if you return just the text, you will get an error because the plain text isn&#8217;t valid XML and the browser expects XML because that is the response type set on the response from the web service.<\/p>\n<p>To finish up, we are going to do something a little more interesting, we will create a web service to return the name of a course from the database using the sandbox data built into the archetype. For various reasons, we will take the most direct route to getting data access which is to make the web service bean a stateless bean and inject a persistence context using the <code>@PersistenceContext<\/code> annotation.<\/p>\n<ol>\n<li>Add the <code>@Stateless<\/code> annotation to the <code>SimpleService<\/code> class and an entity manager field annotated with <code>@PersistenceContext<\/code> along with the getters and setters.<\/li>\n<li>Add a new method to return the course name for the given course id parameter. We will return it as text for the time being :\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Path(&quot;courseName\/{id}&quot;)\r\n@GET\r\npublic String getCourseNameFromId(@PathParam(&quot;id&quot;) Long id) {\r\n\tCourse c = entityManager.find(Course.class, id);\r\n\tif (c == null) {\r\n\t\treturn &quot;Not Found, try the index &lt;a href='\/restwebdemo\/'&gt;page&lt;\/a&gt; and come back&quot;;\r\n\t} else {\r\n\t\treturn c.getTitle();\r\n\t}\r\n}\r\n<\/pre>\n<p>Note that the automatic type conversion takes place and the value is converted to a <code>Long<\/code> automatically. If the course is not found, we suggest the user goes to the main page of the demo. We aren&#8217;t just being overly helpful, the test data is generated when you request one of the application pages for the first time. In the current persistence context, when you redeploy, the database is dropped and rebuilt so it will be empty. You need to go to the front page to automatically create the data and then go back to  your page to view the course. An example URL is <a href=\"http:\/\/localhost:8080\/restwebdemo\/rest\/sample\/courseName\/124\">http:\/\/localhost:8080\/restwebdemo\/rest\/sample\/courseName\/124<\/a>.\n<\/li>\n<p>Of course you could grab the course object and build your own XML or JSON response to send back to the client, or use a third party library like Jackson to build the JSON response. However, as we&#8217;ll see next time, Java EE 6 has all these goodies built in for us, and with a few annotations, we&#8217;ll be slinging objects back and forth in no time at all.<\/p>\n<p>You can download the source code for the project from <a href='http:\/\/www.andygibson.net\/blog\/wp-content\/uploads\/2011\/02\/restwebdemo_pt1.zip'>here<\/a>. Simply unzip, build with maven (<code>mvn clean package<\/code>) and deploy to Glassfish.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here&#8217;s a quick guide to creating a RESTful web service with Glassfish using JAX-RS.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[63],"tags":[52,104,103],"_links":{"self":[{"href":"https:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/posts\/1723"}],"collection":[{"href":"https:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/comments?post=1723"}],"version-history":[{"count":8,"href":"https:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/posts\/1723\/revisions"}],"predecessor-version":[{"id":1764,"href":"https:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/posts\/1723\/revisions\/1764"}],"wp:attachment":[{"href":"https:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/media?parent=1723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/categories?post=1723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.andygibson.net\/blog\/wp-json\/wp\/v2\/tags?post=1723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}