Thursday, October 9, 2008

GWT UniversalClient - "Look Mom no RPC!"

GWT has enabled a more OO style programming again within the web application world (yea there are some that will say that is bad for the web). For fans of Swing type component frameworks and other similar GUI frameworks, GWT is a great welcome.

But with this style of programming, you go back to sepearting the client from the server more clearly. This is both good and bad. The good is that you can do a lot more things with the client now (AJAX stuff) but the bad is that you have a demarcation line between where the client code ends and server side code starts which requires developers to write and stub out RPC classes and interfaces. With server side web progamming everything is sort of mixed together so developers don't worry about where the resource is because most of the time the code is running on the server to begin work.

Anyway, with GWT you got to write RPC code. Not the hardest thing in the world to do, but it can be a bit of a pain. Well here comes SOAFaces framework to the rescue with its UnverisalClient. The UniversalClient is a bit like the MuleClient you find in the Mule ESB project. It can talk to just about any servier side method or services and pass and return arguments when invoking said services. The UniveralClient allows GWT developers to write their client code and call out to remote services with out much less hassle. The UniversalClient interface can invoke just about any standard Java POJO method or Mule/ESB service and return the results without writing a line of GWT RPC code. If the ESB web service already exist then just call it and if you want to create your own simply attach an annotation to any service side POJO and now it is available to be called from your GWT client (again no RPC or marshelling to deal with). And it is your choice wether to pass and return JOSN or POJO objects back and forth.

Here is an code example of what a simple GWT client would look like that uses the UniversalClient API to invoke a very simple service on the server side. This is of course a simple example but you can also use the UniversalClient to invoke Mule endpoints as well.


public class UCDemo implements EntryPoint {

private static final String UNIVERSAL_CLIENT_SERVLET = "/mywebapp/SOAFacesRPCServlet";
private UniversalClient _oClient;

private Button button;

/**
* Simple entry point and use call to UniversalClient.
*/
public void onModuleLoad() {
button = new Button("Click To Execute Service Call");

DockPanel dockPanel = new DockPanel();
dockPanel.add(button, DockPanel.WEST);
RootPanel.get().add(dockPanel);

button.addClickListener(new ClickListener() {
public void onClick(Widget btn) {

//Format endpoint is: soafaces://<fully qualified class name>/<annotation method name>
String stEndpoint1 = "soafaces://com.acme.service.HelloWorldService/helloThereEndpoint";
if (btn.equals(button)) {

//Create the UniversalClient Async Callback
UniversalClientPOJOCallback oMulePOJOCallback = new UniversalClientPOJOCallback() {

public void onUniversalClientSuccess(Object result) {
//Serivces returns a String
String returnVal = (String) result;
Window.alert("Wow this was a success! Return value: " + returnVal);
}

public void onFailure(Throwable ex) {
Window.alert("Error during UniversalClient call: " + ex.getMessage());
}
};

//Simply use the UniversalClient send method to call the remote service
//This service endpoint takes no arguments and returns a String
getUniversalClient().send(stEndpoint1, oMuleJSONCallback);
}
}
});
}

private UniversalClient getUniversalClient() {
if(_oClient == null) {
_oClient = UniversalClientFactory.getInstance().getUniversalClient(UNIVERSAL_CLIENT_SERVLET);
}
return _oClient;
}
}

Here is what the server side code looks like. This is the service endpoint referenced by the client above. As you can see very simple. Just a POJO with an annotation marker. This allows the UnviversalClient to invoke this service and return the results.


public class HelloWorldService {

@ServiceEndpoint(name="helloThereEndpoint")
public String helloThere() {
return "You got it";
}
}


Javadocs for UniversalClient:

http://www.grandlogic.com/downloads_content/soafaces-javadoc/index.html

If you would like see more, download the sample WAR that demostrates the UniversalClient in action:

http://code.google.com/p/soafaces/wiki/Downloads

This link will give you details on building your own GWT client using the UniversalClient interface:

http://code.google.com/p/soafaces/wiki/StandaloneGwtClient

You can read more about the SOAFaces and the UniversalClient open sources project here:

http://code.google.com/p/soafaces/

4 comments:

Todd Hoff said...

Looks very useful. Would there a way to make it work with GAE and Python on the backend?

Sam Taha said...

Only java backend is supported right now. It should be possible to support python via the JSON features in UniversalClient, once GWT has standard integration python.

kjordan said...

How would the string look for accessing a mule http endpoint service? Would I just specify the http address of it? If it's on a different server/port than my tomcat server would it still work (i.e. I won't get a cross-domain error)? Does it go through a servlet since I see that there are jar files I need to use in my GWT application that deal specifically with mule since there are -nomule jars. All the examples seem to deal with soafaces and only mention that you can use it with mule.

Sam Taha said...

The actual mule request gets executed using MuleClient API and gets executed on the servlet tier so you can call any mule services running on any other accessible host.

There is an example that uses mule directly using the mule VM transport. You can use any mule support protocol such as JMS or AXIS....etc.