Server (Spring Web)
I use standard Spring Web Dispatcher Servlet with some controller on server side, which I register by using a component scan. Hence, this is all I need except a scan entry in the applicationContext.xml:
BoardController.java (class header) |
To get into action I need a simple Method which is configured by the standard Spring Request Mapping and Request Path Parameter:
BoardController.java (POST method) |
There is nothing special about "@RequestMapping" and "@PathVariable". In combination with the class header mapping annotation it means:
Listen to all HTTP-POST requests that address the rescource:
/service/board/[0-n]/activity/add
take the Parameter[0-n]
out of the Uri and put it into a variable calledparentBoardId
.
A little bit more magic comes into play when you watch that method returning a DTO-Object serialized as a JSON String. And that's what SmartGWT or any other requesting client that is calling this method gets. There is no need to configure JSON at any application context. Spring itself checks the classpath and if it finds a JSON serializer, @ResponseBody will return JSON.
I do not use Spring Security in openKanban. To keep it small and simple I decided to use the "JSR-299 CDI Interceptors for Spring Bean"-Implementation and run a self-made @SecurityInterception on any controller method to check if the user is authenticated. I will provide more information about this interceptor in a further posting. For now it's enough to know, that every controller method will be checked for authentication.
In order to demonstrate SmartGWT DataBinding integration I add another HTTP-GET method example:
BoardController.java (GET method) |
Summary
There are two available rescources:
/service/board/[0-n]/activity/add (on POST)
/service/board/[0-n]/contact/get (on GET)
Client (SmartGWT)
SmartGWT provides a very versatile communication. The following example will show you what worked really great in the scope of my project. In this context I preferred using two different kinds of request usage:
- Configurated DataBinding on SmartGWT
- Using standard GWT RequestBuilder
Configurated DataBinding on SmartGWT
Any SmartGWT widget that implements the interface DataBoundComponent provides a databinding mechanism. In this case it is necessary to define a DataSource, corresponding DataSourceFields and wire it together:
BoardContactTileGrid.java (constructor) |
TileGrid is a DataBoundComponent. That's why it is possible to add a DataSource. As usual SmartGWT offers you some configurations. This widget will automatically fetch data when the object of the widget is rendered at the client. That means that it is necessary to have a correct DataSource configured at object creation time.
Let's see what the DataSource looks like:
BoardContactDS.java (constructor) |
This is a simple DataSource configuration. After rendering the corresponding widget, an autofetch will trigger a HTTP-GET request to the configured URL. The server response has to be serialized as JSON. We discussed that already in the server section of this posting. It is possible to change the required response to REST, XML or some other custom format. Because I did not need a wsdl contract I decided to use a simple JSON format.
Using standard GWT RequestBuilder
The com.google.gwt.http.client.RequestBuilder seems powerful but some lines of code are necesarry to get data serialized and send to the server. A request is built in four steps:
- Creation of RequestBuilder object and passing the HTTP-Method and URL
- Configure HTTP-Header
- Configure HTTP-Parameters
- Send Requests and add a Callback
Two lines of Code for a request |
This leads us to the following request:
- uri: service/user/remove/
- parameters: contactMail=stop@hammertime.de&id=42
This works for self defined content as well as for whole objects.
Two lines of code for a request |
As you can see I used two ways to wrap all the HTTP stuff. It is either possible to pass static URL parameters or to pass complete Data Transfer Objects (DTO's) to the PreparedRequest to get things done. This has been enabled by using generic typedef, varargs and polymorphism:
PreparedRequest conctructor for static parameters |
Java 5 varargs provides flexibility to add as much parameter as I like. The generic DTO to string serialization looks like:
PreparedRequest conctructor for DTO's |
The PreparedRequest parameter needs to be typed as a subclass of RequestParameterMap. This relationship enables a polymorphic call to the method "valuesToMap()" which has to be implemented by every DTO.
RequestParameterMap |
For a better understanding find below a simple example of an implementation:
ActivityDTO valuesToMap implementation |
Although I implemented some level of abstraction, some weak points still remain. If there is a new DTO attribute, it must be added to the valuesAsMap method and there is no "compiletime safety" to make sure it has not been forgotten. Because I could not use Java Reflection API on client side code (remember I am talking about code that is converted to JavaScript), things may get a little bit harsh. Anyway I am still positive about an easy, robust and practicable integration between Spring Web and SmartGWT over HTTP.
i would be very pleased if You could explain how do You check if user is authenticated
ReplyDeleteHi Frank thanks for your tutorial
ReplyDeleteI was wondering if there is a source code for this tutorial or is there any other tutorials for SmartGWT and RESt webservices.
good luck
Hello Mohammad, its an open source project, you can see the whole source code on: http://code.google.com/p/openkanban/
ReplyDeletePawel,
ReplyDeleteI just use session cookies and a server side user credentials DB. By using spring intercepter, I check every REST resource for accessibility.