Project

General

Profile

Programming Guide - Web Services (RESTful) » History » Version 4

chin-yeh, 02/13/2012 09:38 AM

1 1 chin-yeh
{{toc}}
2
3
h1. Programming Guide - Web Services (RESTful)
4
5
This guide describes how to develop the _RESTful_ based web services.
6
7
In general, the web services should contains the following layers:
8
* *Web Services Layer* _(a.k.a controller)_ - this is the only place where the client will talk to
9
* *Services Layer* - contains the business logic on how to handle the client's request
10
* *DAO layer* - contains the logic on how to retrieve & persist data
11
12
!web_services_layers.png!
13
14
h2. Step-By-Step
15
16
> Assume that you have setup the [[General Info:Setup Development Environment|Eclipse environment]] 
17
18
# launch *Eclipse*
19
# create a new *Dynamic Web Project*:
20
** _Dynamic web module version_ should set to _2.4_ or above
21
** _JDK_ compiler compliance version should set to _5.0_ or above
22
# and then *configure* the project:
23
## obtain the [[Programming Guide - Web Services (RESTful)#Project-Dependencies|project dependencies]] and then place it in the <code>WEB-INF/lib</code> folder
24
## replace the *web.xml* with this attachment:"web.xml"
25
## create the following folder:
26
*** <code>src/META-INF/spring</code>
27
## copy attachment:"applicationContext.xml" to <code>src/META-INF/spring</code> folder
28
*** edit the following line to put in the *root package* of the project
29
<pre>
30
<code class="XML">
31
<context:component-scan base-package="my.root.package"/>
32
</code>
33
</pre>
34
## copy attachment:"restful-servlet.xml" to <code>src/META-INF/spring</code> folder
35
*** edit the following line to put in the *package name* which contains all of the *controller* classes
36
<pre>
37
<code class="XML">
38
<context:component-scan base-package="my.package.controller"/>
39
</code>
40
</pre>
41
# after configured the project, let's start coding the following layers:
42
** *Web Services/Controller* - _see_ [[Programming_Guide_-_Web_Services_(RESTful)#Controller-Layer|Coding Guidelines]]
43
** *Services* - _see_ [[Programming_Guide_-_Web_Services_(RESTful)#Services-Layer|Coding Guidelines]]
44
** *DAO* - _optional but it's highly recommended to implement it_
45
# done
46
47 4 chin-yeh
*[resources]*:
48 1 chin-yeh
> download this sample project, attachment:sample_restful_project.zip to view all code snippets
49
50
h2. Project Dependencies
51
52
* com.springsource.org.aopalliance-1.0.0.jar
53
* jackson-core-asl-1.9.0.jar
54
* jackson-jaxrs-1.9.0.jar
55
* jackson-mapper-asl-1.9.0.jar
56
* jcl-over-slf4j-1.6.1.jar
57
* org.springframework.aop-3.0.5.RELEASE.jar
58
* org.springframework.asm-3.0.5.RELEASE.jar
59
* org.springframework.beans-3.0.5.RELEASE.jar
60
* org.springframework.context.support-3.0.5.RELEASE.jar
61
* org.springframework.context-3.0.5.RELEASE.jar
62
* org.springframework.core-3.0.5.RELEASE.jar
63
* org.springframework.expression-3.0.5.RELEASE.jar
64
* org.springframework.jdbc-3.0.5.RELEASE.jar
65
* org.springframework.transaction-3.0.5.RELEASE.jar
66
* org.springframework.web.servlet-3.0.5.RELEASE.jar
67
* org.springframework.web-3.0.5.RELEASE.jar
68
* slf4j-api-1.6.1.jar
69
* slf4j-log4j12-1.6.1.jar
70
* spring-security-config-3.0.5.RELEASE.jar
71
* spring-security-core-3.0.5.RELEASE.jar
72
* spring-security-web-3.0.5.RELEASE.jar
73
74
These dependencies can be found in:
75
* [[General Info:SearchBrowse_artifact|Nexus]]
76
* download attachment:web_inf_lib.zip and extract it to <code>WEB-INF/lib</code> folder
77
78
h1. Coding Guidelines
79
80
This guidelines will be revised anytime to accommodate requirement changes.
81
82
h2. Controller Layer
83
84
* the controller class must be *thread safe* as there's only *one instance* will be created to serve all web request
85
86
* every controller *must annotated* with <code>@Controller</code> at the class level
87
<pre>
88
<code class="JAVA">
89
@Controller
90
public class RegistrationController {
91
  ...
92
}
93
</code>
94
</pre>
95
96
* use the <code>@RequestMapping</code> to map the web request to the *handler class* or *handler method*, e.g.:
97
<pre>
98
<code class="JAVA">
99
@Controller
100
@RequestMapping(value = "/reg-services")
101
public class RegistrationController {
102
103
  @RequestMapping(value = "/shopper", method = RequestMethod.POST)
104
  @ResponseBody
105
  public boolean registerMember(@RequestBody MemberRegistrationRequest request) {
106
		return registrationServices.registerMember(request);
107
  }
108
}
109
</code>
110
</pre>
111
** for this example, the following web request will be mapped to the *registerMember* method:
112
*** *request URL* - http://.../.../reg-services/shopper
113
*** *request method* - POST
114
115
* 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*
116
117
* every *method handler* should be annotated with <code>@ResposeBody</code> at the method level and return a value _(do not return <code>void</code>)_
118
<pre>
119
<code class="JAVA">
120
@ResponseBody
121
public boolean registerMember(@RequestBody MemberRegistrationRequest request) {
122
   return registrationServices.registerMember(request);
123
}
124
</code>
125
</pre>
126
127
* if an argument is annotated with <code>@RequestBody</code>, the body of the web request will be automatically parsed.
128
<pre>
129
<code class="JAVA">
130
public boolean registerMember(@RequestBody MemberRegistrationRequest request) {
131
</code>
132
</pre>
133
134 2 chin-yeh
* to bound the value of a *URI template variable*, just annotate, <code>@PathVariable</code> to the *target argument*
135 1 chin-yeh
<pre>
136
<code class="JAVA">
137
@RequestMapping(value = "/shopper/{shopperRefNo}", method = RequestMethod.GET)	
138
@ResponseBody
139
public MemberInfo retrieveMemberInfo(@PathVariable int refNo) {
140
...
141
</code>
142
</pre>
143
** for this example, the value of the URI template variable, *shopperRefNo* will be bound to the argument, *refNo*.
144
145
* use <code>@RequestParam</code> to access the specific *Servlet request paramater*. Parameter values will be converted to the declared argument type.
146
<pre>
147
<code class="JAVA">
148
public String setupForm(@RequestParam("petId") int petId)
149
</code>
150
</pre>
151 3 chin-yeh
** *note:* By default, the parameter is required. To make the parameter optional, set the *required* attribute to *false*, e.g.:
152 1 chin-yeh
*** <code>@RequestParam(value="id", required=false)</code>
153
154
h2. Services Layer
155
156
* the service class is just a *POJO* (plain-old-java-object)
157
158
* the service class must be *thread safe* if, and only if it is one of the *field members* of the *controller*
159
160
* the service class should contains the *business logics only*. Try to delegate the un-relevant codes to other appropriate layers.