|
| Home > Apache Geronimo v3.0 > Documentation > Reference > Samples > Java EE sample applications > restfulorder-javaee6 - Simple Web Service with JAX-RS |
This sample application demonstrates a simple order system which can get, delete, and edit ordering data using RESTful Web services. This RESTful Web services application works at XML message level. It uses the Asynchronous JavaScript and XML (Ajax) technique to combine Java technologies, XML, and JavaScript for the web service applications to uses client-side scripting to exchange data with the server. When a user creates a new order or edits an existing one, the resource data is converted into XML schema for processing. This web service is exposed as a Servlet in the Geronimo application server. See RESTful Web Services for more information on the concept.
The restfulorder-javaee6 application is deployed as a WAR to the application server. The overview of the structural content of this WAR file is given as follows.
|-restfulorder-javaee6.war
+-index.html
+-rest
+- restfulorder
+- Support.js
+- showAll.html
+-WEB-INF
+- web.xml
+- classes
+- org.apache.geronimo.samples.javaee6.restfulorder
+- META-INF
+-META-INF
The org.apache.geronimo.samples.javaee6.restfulorder package consists of the following files.
+- org.apache.geronimo.samples.javaee6.restfulorder +-service +- RestfulordersResource.class +- RestfulorderResource.class +-config +- ApplicationConfig.class +-converter +- RestfulorderConverter.class +- RestfulordersConverter.class +-entities +- Restfulorder.class +-JPASessionBeans
where,
When running the restfulorder-javaee6 application, index.html is launched as the welcome-file as specified in web.xml. From index.html, showAll.html is called. By clicking the Add a new order link on showAll.html, you are linked to addOrder.html. On this page, you can create a new order by inputting data into the fields. The order data is received by a Restfulorder JavaScript object which provides methods to record and configure the order resource into String type. Then, an addItem method provided by Restfulorders.js is called to add the new order resource into the database. The working process is as follows:
The postJson method, called to send a XMLHttpRequest to the servlet class, uses the Ajax technique provided in the following JavaScript support.js.
var rjsSupport = { proxy : "", getHttpProxy: function() { return this.proxy; }, setHttpProxy: function(proxy_) { this.proxy = proxy_; }, isSetHttpProxy: function() { return this.getHttpProxy().length > 0; }, getHttpRequest: function() { var xmlHttpReq; try { // Firefox, Opera 8.0+, Safari, IE7.0+ xmlHttpReq=new XMLHttpRequest(); } catch (e) { // Internet Explorer 6.0+, 5.0+ try { xmlHttpReq=new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlHttpReq=new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { this.debug("Your browser does not support AJAX!"); } } } return xmlHttpReq; }, findUrl : function(url, method) { var url2 = url; if(this.isSetHttpProxy()) url2 = this.getHttpProxy()+"?method="+method+"&url="+url2; return url2; }, findMethod : function(method) { var method2 = method; if(method != "GET" && this.isSetHttpProxy()) method2 = "POST"; return method2; }, open : function(method2, url2, mimeType, paramLen, async) { //Change url and method if using http proxy var url = this.findUrl(url2, method2); var method = this.findMethod(method2); //add timestamp to make url unique in case of IE7 var timestamp = new Date().getTime(); if(url.indexOf("?") != -1) url = url+"×tamp="+timestamp; else url = url+"?timestamp="+timestamp; var xmlHttpReq = this.getHttpRequest(); if(xmlHttpReq == null) { this.debug('Error: Cannot create XMLHttpRequest'); return null; } try { netscape.security.PrivilegeManager.enablePrivilege ("UniversalBrowserRead"); } catch (e) { //this.debug("Permission UniversalBrowserRead denied."); } try { xmlHttpReq.open(method, url, async); } catch( e ) { this.debug('Error: XMLHttpRequest.open failed for: '+url+' Error name: '+e.name+' Error message: '+e.message); return null; } if (mimeType != null) { if(method == 'GET') { //this.debug("setting GET accept: "+mimeType); xmlHttpReq.setRequestHeader('Accept', mimeType); } else if(method == 'POST' || method == 'PUT'){ //this.debug("setting content-type: "+mimeType); //Send the proper header information along with the request xmlHttpReq.setRequestHeader("Content-Type", mimeType); xmlHttpReq.setRequestHeader("Content-Length", paramLen); xmlHttpReq.setRequestHeader("Connection", "close"); } } //For cache control on IE7 xmlHttpReq.setRequestHeader("Cache-Control", "no-cache"); xmlHttpReq.setRequestHeader("Pragma", "no-cache"); xmlHttpReq.setRequestHeader("Expires", "-1"); return xmlHttpReq; }, loadXml : function(xmlStr) { var doc2; // code for IE if (window.ActiveXObject) { doc2=new ActiveXObject("Microsoft.XMLDOM"); doc2.async="false"; doc2.loadXML(xmlStr); } // code for Mozilla, Firefox, Opera, etc. else { var parser=new DOMParser(); doc2=parser.parseFromString(xmlStr,getDefaultMime()); } return doc2; }, findIdFromUrl : function(u) { var li = u.lastIndexOf('/'); if(li != -1) { var u2 = u.substring(0, li); var li2 = u2.lastIndexOf('/'); u2 = u.substring(0, li2); return u.substring(li2+1, li); } return -1; }, get : function(url, mime) { var xmlHttpReq = this.open('GET', url, mime, 0, false); try { xmlHttpReq.send(null); if (xmlHttpReq.readyState == 4) { var rtext = xmlHttpReq.responseText; if(rtext == undefined || rtext == '' || rtext.indexOf('HTTP Status') != -1) { if(rtext != undefined) this.debug('Failed XHR(GET, '+url+'): Server returned --> ' + rtext); return '-1'; } return rtext; } } catch( e ) { this.debug('Caught Exception; name: [' + e.name + '] message: [' + e.message+']'); } return '-1'; }, post : function(url, mime, content) { var xmlHttpReq = this.open('POST', url, mime, content.length, false); try { xmlHttpReq.send(content); if (xmlHttpReq.readyState == 4) { var status = xmlHttpReq.status; if(status == 201) { return true; } else { this.debug('Failed XHR(POST, '+url+'): Server returned --> ' + status); } } } catch( e ) { this.debug('Caught Exception; name: [' + e.name + '] message: [' + e.message+']'); } return false; }, put : function(url, mime, content) { var xmlHttpReq = this.open('PUT', url, mime, content.length, false); try { xmlHttpReq.send(content); if (xmlHttpReq.readyState == 4) { var status = xmlHttpReq.status; if(status == 204) { return true; } else { this.debug('Failed XHR(PUT, '+url+'): Server returned --> ' + status); } } } catch( e ) { this.debug('Caught Exception; name: [' + e.name + '] message: [' + e.message+']'); } return false; }, delete_ : function(url) { var xmlHttpReq = this.open('DELETE', url, 'application/xml', 0, false); try { xmlHttpReq.send(null); if (xmlHttpReq.readyState == 4) { var status = xmlHttpReq.status; if(status == 204) { return true; } else { this.debug('Failed XHR(DELETE, '+url+'): Server returned --> ' + status); } } } catch( e ) { this.debug('Caught Exception; name: [' + e.name + '] message: [' + e.message+']'); } return false; }, debug : function(message) { var dbgComp = document.getElementById("dbgComp"); if(dbgComp == null) { dbgComp = document.createElement("div"); dbgComp.setAttribute("id", "dbgComp"); dbgComp.style.border = "#2574B7 1px solid"; dbgComp.style.font = "12pt/14pt sans-serif"; var br = document.createElement("div"); document.getElementsByTagName("body")[0].appendChild(br); br.innerHTML = '<br/><br/><br/>'; document.getElementsByTagName("body")[0].appendChild(dbgComp); if((typeof rjsConfig!="undefined") && rjsConfig.isDebug) { dbgComp.style.display = ""; } else { dbgComp.style.display = "none"; } var tab = 'width: 20px; border-right: #2574B7 1px solid; border-top: #2574B7 1px solid; border-left: #2574B7 1px solid; border-bottom: #2574B7 1px solid; color: #000000; text-align: center;'; var addActionStr = '<div style="'+tab+'"><a style="text-decoration: none" href="javascript:rjsSupport.closeDebug()"><span style="color: red">X</span></a></div>'; dbgComp.innerHTML = '<table><tr><td><span style="color: blue">Rest Debug Window</span></td><td>'+addActionStr + '</td></tr></table><br/>'; } var s = dbgComp.innerHTML; var now = new Date(); var dateStr = now.getHours()+':'+now.getMinutes()+':'+now.getSeconds(); dbgComp.innerHTML = s + '<span style="color: red">rest debug('+dateStr+'): </span>' + message + "<br/>"; }, closeDebug : function() { var dbgComp = document.getElementById("dbgComp"); if(dbgComp != null) { dbgComp.style.display = "none"; dbgComp.innerHTML = ''; } } }
where,
ApplicationConfig is a servlet that extends the javax.ws.rs.core.Application class to configure the application classes within a JAX-RS runtime.
package org.apache.geronimo.samples.javaee6.restfulorder.config; @javax.ws.rs.ApplicationPath("resources") public class ApplicationConfig extends javax.ws.rs.core.Application { }
where,
RestfulordersResource is a resource class that uses JAX-RS annotations to implement the corresponding Web resource. The request methods defined in this class are called when the server receives the corresponding HTTP requests.
package org.apache.geronimo.samples.javaee6.restfulorder.service; import java.util.Collection; import javax.ws.rs.Path; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Produces; import javax.ws.rs.Consumes; import javax.ws.rs.PathParam; import javax.ws.rs.QueryParam; import javax.ws.rs.DefaultValue; import javax.ws.rs.core.Response; import javax.ws.rs.core.Context; import javax.ws.rs.core.UriInfo; import javax.persistence.EntityManager; import org.apache.geronimo.samples.javaee6.restfulorder.converter.RestfulordersConverter; import org.apache.geronimo.samples.javaee6.restfulorder.converter.RestfulorderConverter; import javax.persistence.PersistenceContext; import javax.ejb.Stateless; import org.apache.geronimo.samples.javaee6.restfulorder.entities.Restfulorder; @Path("/restfulorders/") @Stateless public class RestfulordersResource { @javax.ejb.EJB private RestfulorderResource restfulorderResource; @Context protected UriInfo uriInfo; @PersistenceContext(unitName = "RestfulProduct2PU") protected EntityManager em; /** Creates a new instance of RestfulordersResource */ public RestfulordersResource() { } /** * Get method for retrieving a collection of Restfulorder instance in XML format. * * @return an instance of RestfulordersConverter */ @GET @Produces({"application/xml", "application/json"}) public RestfulordersConverter get(@QueryParam("start") @DefaultValue("0") int start, @QueryParam("max") @DefaultValue("10") int max, @QueryParam("expandLevel") @DefaultValue("1") int expandLevel, @QueryParam("query") @DefaultValue("SELECT e FROM Restfulorder e") String query) { return new RestfulordersConverter(getEntities(start, max, query), uriInfo.getAbsolutePath(), expandLevel); } /** * Post method for creating an instance of Restfulorder using XML as the input format. * * @param data an RestfulorderConverter entity that is deserialized from an XML stream * @return an instance of RestfulorderConverter */ @POST @Consumes({"application/xml", "application/json"}) public Response post(RestfulorderConverter data) { System.out.println("before resolve,in post"); Restfulorder entity = data.resolveEntity(em); createEntity(data.resolveEntity(em)); return Response.created(uriInfo.getAbsolutePath().resolve(entity.getId() + "/")).build(); } /** * Returns a dynamic instance of RestfulorderResource used for entity navigation. * * @return an instance of RestfulorderResource */ @Path("{id}/") public RestfulorderResource getRestfulorderResource(@PathParam("id") Integer id) { restfulorderResource.setId(id); restfulorderResource.setEm(em); return restfulorderResource; } /** * Returns all the entities associated with this resource. * * @return a collection of Restfulorder instances */ protected Collection<Restfulorder> getEntities(int start, int max, String query) { return em.createQuery(query).setFirstResult(start).setMaxResults(max).getResultList(); } /** * Persist the given entity. * * @param entity the entity to persist */ protected void createEntity(Restfulorder entity) { em.persist(entity); } }
where,
RestfulordersConverter is a Java Architecture for XML Binding (JAXB) annotated class that support the processing of XML in requests and responses.
package org.apache.geronimo.samples.javaee6.restfulorder.converter; import java.net.URI; import java.util.Collection; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.XmlAttribute; import java.util.ArrayList; import org.apache.geronimo.samples.javaee6.restfulorder.entities.Restfulorder; @XmlRootElement(name = "restfulorders") public class RestfulordersConverter { private Collection<Restfulorder> entities; private Collection<RestfulorderConverter> items; private URI uri; private int expandLevel; /** Creates a new instance of RestfulordersConverter */ public RestfulordersConverter() { } /** * Creates a new instance of RestfulordersConverter. * * @param entities associated entities * @param uri associated uri * @param expandLevel indicates the number of levels the entity graph should be expanded */ public RestfulordersConverter(Collection<Restfulorder> entities, URI uri, int expandLevel) { this.entities = entities; this.uri = uri; this.expandLevel = expandLevel; getRestfulorder(); } ......
where,
Please refer to Samples General Information for informations on obtaining and building the source for this and other samples.
Once all the sources get checked out the next step is to build restfulorder-javaee6 sample. It requires Maven 2 or above for building the binaries.
From the <restfulorder-javaee6_home> directory run the following command.
mvn clean install
This process will take a couple of minutes. The binaries will be generated in the corresponding target directory .
Deploying sample application is pretty straight forward as we are going to use the Geronimo Console.
The application is visible at http://localhost:8080/restfulorder-javaee6.
Click the Add a new order link to create a new order.
Unable to render embedded object: File (restfulorder1.jpg) not found.
Click Save after inputting all the data for your order. You will see the added order on the next page.
Unable to render embedded object: File (restfulorder2.jpg) not found.
You can also see the order resource at http://localhost:8080/restfulorder-javaee6/resources/restfulorders/id in XML format, where id is the unique id value you defined for your order.
|
|
Privacy Policy - Copyright © 2003-2013, The Apache Software Foundation, Licensed under ASL 2.0. |