Tuesday, 5 January 2010

GWT client with Coldfusion CFC server

Here is an example project showing how to use a Google Web Toolkit generated JavaScript front end with server side logic implemented in Coldfusion.

The GWT RemoteServiceServlet can't be extended by Coldfusion components, so using GWT's RPC and serialization mechanisms isn't an option. For this example I will making use of a RESTful service using JSON.

Both the Java and CF code are contained in the same project and built using Maven.

The GWT entry point class below has a couple of text input boxes, a button to send a request and a text box to display some response text. The buttons click handler sends an http get request to a url backed by a Coldfusion CFC, parses the JSON formatted data returned, and updates the response text area.

Entry point class inputs:

GWTColdfusion.java

package org.adrianwalker.gwtcoldfusion.gwt.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public final class GWTColdfusion implements EntryPoint {

 private static final String CFC = "/gwtcoldfusion/Message.cfc";
 private static final String METHOD = "getMessage";

 private Label nameLabel;
 private TextBox nameBox;
 private Label ageLabel;
 private TextBox ageBox;
 private Button button;
 private Label responseLabel;
 private TextArea responseArea;

 @Override
 public void onModuleLoad() {

   VerticalPanel basePanel = new VerticalPanel();

   nameLabel = new Label("Name:");
   nameBox = new TextBox();
   ageLabel = new Label("Age:");
   ageBox = new TextBox();
   responseLabel = new Label("Response:");
   responseArea = new TextArea();
   responseArea.setReadOnly(true);
   button = new Button("Click Me");

   button.addClickHandler(new ClickHandler() {

     @Override
     public void onClick(final ClickEvent event) {

       String url = CFC + "?method=" + METHOD + "&name=" + nameBox.getText() + "&age=" + ageBox.getText();

       RequestBuilder requestBuilder = new RequestBuilder(RequestBuilder.GET, url);
       requestBuilder.setCallback(new RequestCallback() {

         @Override
         public void onResponseReceived(final Request request, final Response response) {
           JSONObject jsonObject = (JSONObject) JSONParser.parse(response.getText());
           JSONString jsonString = (JSONString) jsonObject.get("MESSAGE");

           responseArea.setText(jsonString.stringValue());
         }

         @Override
         public void onError(final Request request, final Throwable t) {
           Window.alert("Error recieving response");
         }
       });
      
       try {
         requestBuilder.send();
       } catch (RequestException re) {
         Window.alert("Error sending request");
       }
     }
   });

   basePanel.add(nameLabel);
   basePanel.add(nameBox);
   basePanel.add(ageLabel);
   basePanel.add(ageBox);
   basePanel.add(responseLabel);
   basePanel.add(responseArea);
   basePanel.add(button);

   RootPanel.get().add(basePanel);
 }
}

The Coldfusion component accepts requests via http, constructs a response structure and returns it in JSON format.

Message.cfc

<cfcomponent output="false">
  
  <cfcontent type="application/json">
  
  <cffunction access="remote" returnformat="JSON" name="getMessage" >
    <cfargument required="true" type="string" name="name">
    <cfargument required="true" type="numeric" name="age">

    <cfset var response = {
      message = "Hello #ARGUMENTS.name#, you are #ARGUMENTS.age# years old"
    }>

    <cfreturn response>
  </cffunction>
</cfcomponent>

JSON response:

Response on interface:

The Maven project is available for download below.

Build the project using 'mvn clean war:explode', then copy the target/gwtcoldfusion directory to your Coldfusion server's wwwroot directory. To view the page point your brower at http://localhost:8500/gwtcoldfusion

Source Code