Project

General

Profile

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

chin-yeh, 12/02/2011 04:28 PM

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
> download this sample project, attachment:sample_restful_project.zip to view all code snippets
48
49
h2. Project Dependencies
50
51
* com.springsource.org.aopalliance-1.0.0.jar
52
* jackson-core-asl-1.9.0.jar
53
* jackson-jaxrs-1.9.0.jar
54
* jackson-mapper-asl-1.9.0.jar
55
* jcl-over-slf4j-1.6.1.jar
56
* org.springframework.aop-3.0.5.RELEASE.jar
57
* org.springframework.asm-3.0.5.RELEASE.jar
58
* org.springframework.beans-3.0.5.RELEASE.jar
59
* org.springframework.context.support-3.0.5.RELEASE.jar
60
* org.springframework.context-3.0.5.RELEASE.jar
61
* org.springframework.core-3.0.5.RELEASE.jar
62
* org.springframework.expression-3.0.5.RELEASE.jar
63
* org.springframework.jdbc-3.0.5.RELEASE.jar
64
* org.springframework.transaction-3.0.5.RELEASE.jar
65
* org.springframework.web.servlet-3.0.5.RELEASE.jar
66
* org.springframework.web-3.0.5.RELEASE.jar
67
* slf4j-api-1.6.1.jar
68
* slf4j-log4j12-1.6.1.jar
69
* spring-security-config-3.0.5.RELEASE.jar
70
* spring-security-core-3.0.5.RELEASE.jar
71
* spring-security-web-3.0.5.RELEASE.jar
72
73
These dependencies can be found in:
74
* [[General Info:SearchBrowse_artifact|Nexus]]
75
* download attachment:web_inf_lib.zip and extract it to <code>WEB-INF/lib</code> folder
76
77
h1. Coding Guidelines
78
79
This guidelines will be revised anytime to accommodate requirement changes.
80
81
h2. Controller Layer
82
83
* the controller class must be *thread safe* as there's only *one instance* will be created to serve all web request
84
85
* every controller *must annotated* with <code>@Controller</code> at the class level
86
<pre>
87
<code class="JAVA">
88
@Controller
89
public class RegistrationController {
90
  ...
91
}
92
</code>
93
</pre>
94
95
* use the <code>@RequestMapping</code> to map the web request to the *handler class* or *handler method*, e.g.:
96
<pre>
97
<code class="JAVA">
98
@Controller
99
@RequestMapping(value = "/reg-services")
100
public class RegistrationController {
101
102
  @RequestMapping(value = "/shopper", method = RequestMethod.POST)
103
  @ResponseBody
104
  public boolean registerMember(@RequestBody MemberRegistrationRequest request) {
105
		return registrationServices.registerMember(request);
106
  }
107
}
108
</code>
109
</pre>
110
** for this example, the following web request will be mapped to the *registerMember* method:
111
*** *request URL* - http://.../.../reg-services/shopper
112
*** *request method* - POST
113
114
* 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*
115
116
* every *method handler* should be annotated with <code>@ResposeBody</code> at the method level and return a value _(do not return <code>void</code>)_
117
<pre>
118
<code class="JAVA">
119
@ResponseBody
120
public boolean registerMember(@RequestBody MemberRegistrationRequest request) {
121
   return registrationServices.registerMember(request);
122
}
123
</code>
124
</pre>
125
126
* if an argument is annotated with <code>@RequestBody</code>, the body of the web request will be automatically parsed.
127
<pre>
128
<code class="JAVA">
129
public boolean registerMember(@RequestBody MemberRegistrationRequest request) {
130
</code>
131
</pre>
132
133
* to bound the value of a *URI template variable*, just annotate, <code>@PathVariable</code> to the *desired argument*
134
<pre>
135
<code class="JAVA">
136
@RequestMapping(value = "/shopper/{shopperRefNo}", method = RequestMethod.GET)	
137
@ResponseBody
138
public MemberInfo retrieveMemberInfo(@PathVariable int refNo) {
139
...
140
</code>
141
</pre>
142
** for this example, the value of the URI template variable, *shopperRefNo* will be bound to the argument, *refNo*.
143
144
* use <code>@RequestParam</code> to access the specific *Servlet request paramater*. Parameter values will be converted to the declared argument type.
145
<pre>
146
<code class="JAVA">
147
public String setupForm(@RequestParam("petId") int petId)
148
</code>
149
</pre>
150
** *note:* By default, the parameter is required. To make the parameter as optional, set the *required* attribute to *false*, e.g.:
151
*** <code>@RequestParam(value="id", required=false)</code>
152
153
h2. Services Layer
154
155
* the service class is just a *POJO* (plain-old-java-object)
156
157
* the service class must be *thread safe* if, and only if it is one of the *field members* of the *controller*
158
159
* the service class should contains the *business logics only*. Try to delegate the un-relevant codes to other appropriate layers.