Programming Guide - Web Services (RESTful) » History » Revision 2
Revision 1 (chin-yeh, 12/02/2011 04:28 PM) → Revision 2/4 (chin-yeh, 12/27/2011 12:00 PM)
{{toc}} h1. Programming Guide - Web Services (RESTful) This guide describes how to develop the _RESTful_ based web services. In general, the web services should contains the following layers: * *Web Services Layer* _(a.k.a controller)_ - this is the only place where the client will talk to * *Services Layer* - contains the business logic on how to handle the client's request * *DAO layer* - contains the logic on how to retrieve & persist data !web_services_layers.png! h2. Step-By-Step > Assume that you have setup the [[General Info:Setup Development Environment|Eclipse environment]] # launch *Eclipse* # create a new *Dynamic Web Project*: ** _Dynamic web module version_ should set to _2.4_ or above ** _JDK_ compiler compliance version should set to _5.0_ or above # and then *configure* the project: ## obtain the [[Programming Guide - Web Services (RESTful)#Project-Dependencies|project dependencies]] and then place it in the <code>WEB-INF/lib</code> folder ## replace the *web.xml* with this attachment:"web.xml" ## create the following folder: *** <code>src/META-INF/spring</code> ## copy attachment:"applicationContext.xml" to <code>src/META-INF/spring</code> folder *** edit the following line to put in the *root package* of the project <pre> <code class="XML"> <context:component-scan base-package="my.root.package"/> </code> </pre> ## copy attachment:"restful-servlet.xml" to <code>src/META-INF/spring</code> folder *** edit the following line to put in the *package name* which contains all of the *controller* classes <pre> <code class="XML"> <context:component-scan base-package="my.package.controller"/> </code> </pre> # after configured the project, let's start coding the following layers: ** *Web Services/Controller* - _see_ [[Programming_Guide_-_Web_Services_(RESTful)#Controller-Layer|Coding Guidelines]] ** *Services* - _see_ [[Programming_Guide_-_Web_Services_(RESTful)#Services-Layer|Coding Guidelines]] ** *DAO* - _optional but it's highly recommended to implement it_ # done > download this sample project, attachment:sample_restful_project.zip to view all code snippets h2. Project Dependencies * com.springsource.org.aopalliance-1.0.0.jar * jackson-core-asl-1.9.0.jar * jackson-jaxrs-1.9.0.jar * jackson-mapper-asl-1.9.0.jar * jcl-over-slf4j-1.6.1.jar * org.springframework.aop-3.0.5.RELEASE.jar * org.springframework.asm-3.0.5.RELEASE.jar * org.springframework.beans-3.0.5.RELEASE.jar * org.springframework.context.support-3.0.5.RELEASE.jar * org.springframework.context-3.0.5.RELEASE.jar * org.springframework.core-3.0.5.RELEASE.jar * org.springframework.expression-3.0.5.RELEASE.jar * org.springframework.jdbc-3.0.5.RELEASE.jar * org.springframework.transaction-3.0.5.RELEASE.jar * org.springframework.web.servlet-3.0.5.RELEASE.jar * org.springframework.web-3.0.5.RELEASE.jar * slf4j-api-1.6.1.jar * slf4j-log4j12-1.6.1.jar * spring-security-config-3.0.5.RELEASE.jar * spring-security-core-3.0.5.RELEASE.jar * spring-security-web-3.0.5.RELEASE.jar These dependencies can be found in: * [[General Info:SearchBrowse_artifact|Nexus]] * download attachment:web_inf_lib.zip and extract it to <code>WEB-INF/lib</code> folder h1. Coding Guidelines This guidelines will be revised anytime to accommodate requirement changes. h2. Controller Layer * the controller class must be *thread safe* as there's only *one instance* will be created to serve all web request * every controller *must annotated* with <code>@Controller</code> at the class level <pre> <code class="JAVA"> @Controller public class RegistrationController { ... } </code> </pre> * use the <code>@RequestMapping</code> to map the web request to the *handler class* or *handler method*, e.g.: <pre> <code class="JAVA"> @Controller @RequestMapping(value = "/reg-services") public class RegistrationController { @RequestMapping(value = "/shopper", method = RequestMethod.POST) @ResponseBody public boolean registerMember(@RequestBody MemberRegistrationRequest request) { return registrationServices.registerMember(request); } } </code> </pre> ** for this example, the following web request will be mapped to the *registerMember* method: *** *request URL* - http://.../.../reg-services/shopper *** *request method* - POST * refer to this "link":http://en.wikipedia.org/wiki/Representational_state_transfer#RESTful_web_services for the guidelines about how to choose the appropriate *HTTP methods* and *request URI* * every *method handler* should be annotated with <code>@ResposeBody</code> at the method level and return a value _(do not return <code>void</code>)_ <pre> <code class="JAVA"> @ResponseBody public boolean registerMember(@RequestBody MemberRegistrationRequest request) { return registrationServices.registerMember(request); } </code> </pre> * if an argument is annotated with <code>@RequestBody</code>, the body of the web request will be automatically parsed. <pre> <code class="JAVA"> public boolean registerMember(@RequestBody MemberRegistrationRequest request) { </code> </pre> * to bound the value of a *URI template variable*, just annotate, <code>@PathVariable</code> to the *target *desired argument* <pre> <code class="JAVA"> @RequestMapping(value = "/shopper/{shopperRefNo}", method = RequestMethod.GET) @ResponseBody public MemberInfo retrieveMemberInfo(@PathVariable int refNo) { ... </code> </pre> ** for this example, the value of the URI template variable, *shopperRefNo* will be bound to the argument, *refNo*. * use <code>@RequestParam</code> to access the specific *Servlet request paramater*. Parameter values will be converted to the declared argument type. <pre> <code class="JAVA"> public String setupForm(@RequestParam("petId") int petId) </code> </pre> ** *note:* By default, the parameter is required. To make the parameter as optional, set the *required* attribute to *false*, e.g.: *** <code>@RequestParam(value="id", required=false)</code> h2. Services Layer * the service class is just a *POJO* (plain-old-java-object) * the service class must be *thread safe* if, and only if it is one of the *field members* of the *controller* * the service class should contains the *business logics only*. Try to delegate the un-relevant codes to other appropriate layers.