Friday, September 24, 2010

GWT+Restlet CRUD application

A client the following requirements

"Build a web based client entry tracking application with API support on Google App Engine"
I followed the usual route of doing a preliminary use case analysis and out came the top level idea of the project. The use case were:
- CRUD Client entry
- Auth using google UserService
- REST based API to expose "Client Entry" as a resource.

The technology platform/libraries choosen to implement the above system:
- Eclipse with Google Plugin
- Google App Engine SDK 1.3.7
- GWT 2.1M3 for client application
- Restlet 2.0.x for REST implementation
- MVP4G for MVP implementation in GWT.

Current application can be browsed here http://cloudresidentapi.appspot.com/

The first thing i did was to put a class diagram which reflects the entire application domain model. See a snapshot below.

I am using StartUML diagraming tool to do the UML diagram above.

I divided the project into 2 major parts. 
- The API part, which will allow any user with proper credentials to access the entries and its details in XML or JSON. 
The urls should be of the form http://someserver/myapp/api/entries to get all the entries
For getting individual entry http://someserver/myapp/api/entries/{clientname}
where, {clientname} is variable to identify the client by just his/her name.

- The client part, that  uses the api for various  operations on the entities


First I proceeded on to build the REST api that will be used by the client app. Using Google plugin, build a google web application, making sure of the various framework versions. Add the Restlet jars in WEB-INF/lib dir of the web application.

To do all the CRUD operations i made 2 Resources (as per the Restlet API).
EntitiesResource and EntityResource. Below is the relevant code.

The Restlet application class to manage the resource and its URL mappings

MyApplication.java


@Override
public Restlet createInboundRoot() {
System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");

Router r=new Router(getContext());
//r.attachDefault(HelloResource.class);

r.attach("/hello", HelloResource.class);
r.attach("/entries",EntriesResource.class);
r.attach("/entries/{entry}",EntryResource.class);


MapVerifier mv=new MapVerifier();
mv.getLocalSecrets().put("scott", "tiger".toCharArray());

ChallengeAuthenticator ca=new ChallengeAuthenticator(getContext(), ChallengeScheme.HTTP_BASIC, "Hello resource gaurd");
ca.setVerifier(mv);
ca.setNext(r);


return ca;

}


The web.xml servlet mappings pointing to the MyApplication class.


<servlet>
  <servlet-name>RestletServlet</servlet-name>
  <servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class>
  <init-param>
      <param-name>org.restlet.application</param-name>
      <param-value>com.anansu.api.MyApplication</param-value>
  </init-param>
  </servlet>
  <servlet-mapping>
      <servlet-name>RestletServlet</servlet-name>
      <url-pattern>/api/*</url-pattern>
  </servlet-mapping>



The implementation of EntitiesResource.java,
This is to respond to url like
http://someserver/myapp/api/entries

@Get("xml")
public Representation toXml(){

DomRepresentation dr=null;
try {
dr = new DomRepresentation(MediaType.TEXT_XML);
Document d=dr.getDocument();

Element r = d.createElement("items");
d.appendChild(r);
for (Entry item : getItems().values()) {
Element eltItem = d.createElement("item");

Element eltId=d.createElement("id");
eltId.appendChild(d.createTextNode(String.valueOf(item.getId())));
eltItem.appendChild(eltId);

Element eltName = d.createElement("name");
eltName.appendChild(d.createTextNode(item.getName()));
eltItem.appendChild(eltName);

Element eltEmail = d.createElement("email");
eltEmail.appendChild(d.createTextNode(item.getEmail()));
eltItem.appendChild(eltEmail);

Element eltMsg=d.createElement("msg");
eltMsg.appendChild(d.createTextNode(item.getMessage()));
eltItem.appendChild(eltMsg);

r.appendChild(eltItem);
}
d.normalizeDocument();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return dr;
}


EntityResource.java
Responds to url like http://someserver/myapp/api/entries/jack


@Get
public Representation toJson(){
JsonRepresentation jr=new JsonRepresentation(this.entry);

return jr;
}

Notice that one this output is in JSON and not in XML.

Before implementing the POST, i needed to make a web form to actually POST the client info to the API. So i then proceeded to make the GWT client.
First i selected a design template and then proceeded on make the UiBinder version of the design template.



2 comments:

  1. Wow Super like ! would you be able to share more info on this. i want to develop a similar application that actually maps to another application.
    Much Appreciated.

    ReplyDelete
  2. If you would be able to share some "sources" it'b great. No commercial benefits for me. Just for educational purpose.
    Much Appreciated.

    ReplyDelete