Tuesday, July 06, 2010

Integration of GWT With Spring

GWTWithSpring example gives you the in depth of using using Spring IOC(Inversion of Control) and DI (Dependency Injection) Concept along with GWT.

IOC(Inversion of Control) also referred as DI (Dependency Injection) Concept: Per Spring core Concept it has two main Package (1) org.springframework.Bean and (2) Context , Spring Frame work emphasis on creation of the object i.e. Bean object containing business logic at run time with the use of some configuration file and that creation is done with the help of Factory pattern i.e. XmlBeanFactory also known as Spring Bean Container, keeping in turn the dependencies required while creating the respective object.

Web.xml:

xml version="1.0" encoding="UTF-8"?>

DOCTYPE web-app

PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"

"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<servlet>

<servlet-name>dispatcherservlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>

<load-on-startup>1load-on-startup>

servlet>

<servlet>

<servlet-name>myServiceservlet-name>

<servlet-class>gwtWithSpring.server.GreetingServiceImplservlet-class>

servlet>

<servlet-mapping>

<servlet-name>dispatcherservlet-name>

<url-pattern>/services/*url-pattern>

servlet-mapping>

<servlet>

<servlet-name>greetServletservlet-name>

<servlet-class>gwtWithSpring.server.GreetingServiceImplservlet-class>

servlet>

<welcome-file-list>

<welcome-file>GWTWithSpring.htmlwelcome-file>

welcome-file-list>

<servlet-mapping>

<servlet-name>greetServletservlet-name>

<url-pattern>/gwtwithspring/services/myServiceurl-pattern>

servlet-mapping>

web-app>

Dispatcher.servlet.xml:

xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="urlMapping"

class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<property name="urlMap">

<map>

<entry key="myService">

<ref bean="ServiceController">ref>

entry>

map>

property>

bean>

<bean id="ServiceController" class="gwtWithSpring.server.ServletWrappingController">

<property name="servletName" value="myService">

property>

<property name="servletInstance">

<ref bean="myService">ref>

property>

bean>

<bean id="myService" class="gwtWithSpring.server.GreetingServiceImpl" />

beans>

GWTWithSpring.html:

doctype html>

<html>

<head>

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

<link type="text/css" rel="stylesheet" href="GWTWithSpring.css">

<title>Web Application Starter Projecttitle>

<script type="text/javascript" language="javascript" src="gwtwithspring/gwtwithspring.nocache.js">script>

head>

<body>

<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0">iframe>

<noscript>

<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">

Your web browser must have JavaScript enabled

in order for this application to display correctly.

div>

noscript>

<h1>Web Application Starter Projecth1>

<table align="center">

<tr>

tr>

<tr>

<td id="value1LabelContainer">td>

<td id="value1FieldContainer">td>

<td id="value2LabelContainer">td>

<td id="value2FieldContainer">td>

<td id="ansLabelContainer">td>

<td id="ansFieldContainer">td>

<td id="addButtonContainer">td>

tr>

<tr>

<td colspan="2" style="color:red;" id="errorLabelContainer">td>

tr>

table>

body>

html>

GWTWithSpring.gwt.xml:

xml version="1.0" encoding="UTF-8"?>

<module rename-to='gwtwithspring'>

<inherits name='com.google.gwt.user.User'/>

<inherits name='com.google.gwt.user.theme.standard.Standard'/>

<entry-point class='gwtWithSpring.client.GWTWithSpring'/>

<servlet path="/services/myService" class="gwtWithSpring.server.GreetingServiceImpl"/>

<source path='client'/>

<source path='shared'/>

module>

GreetingService:

package gwtWithSpring.client;

import com.google.gwt.user.client.rpc.RemoteService;

import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

/**

* The client side stub for the RPC service.

*/

@RemoteServiceRelativePath("services/myService")

public interface GreetingService extends RemoteService {

public String greetServer(String name) throws IllegalArgumentException;

//by Siddhu [

public String addValue(String value1, String value2) throws IllegalArgumentException;

//by Siddhu ]

}

GreetingServiceAsync:

package gwtWithSpring.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

/**

* The async counterpart of GreetingService.

*/

public interface GreetingServiceAsync {

void greetServer(String input, AsyncCallback callback)

throws IllegalArgumentException;

//by siddhu[

void addValue(String value1,String value2, AsyncCallback callback)

throws IllegalArgumentException;

//by siddhu]

}

GWTWithSpring:

package gwtWithSpring.client;

import gwtWithSpring.shared.FieldVerifier;

import com.google.gwt.core.client.EntryPoint;

import com.google.gwt.core.client.GWT;

import com.google.gwt.event.dom.client.ClickEvent;

import com.google.gwt.event.dom.client.ClickHandler;

import com.google.gwt.event.dom.client.KeyCodes;

import com.google.gwt.event.dom.client.KeyUpEvent;

import com.google.gwt.event.dom.client.KeyUpHandler;

import com.google.gwt.user.client.rpc.AsyncCallback;

import com.google.gwt.user.client.ui.Button;

import com.google.gwt.user.client.ui.DialogBox;

import com.google.gwt.user.client.ui.HTML;

import com.google.gwt.user.client.ui.Label;

import com.google.gwt.user.client.ui.RootPanel;

import com.google.gwt.user.client.ui.TextBox;

import com.google.gwt.user.client.ui.VerticalPanel;

/**

* Entry point classes define onModuleLoad().

*/

public class GWTWithSpring implements EntryPoint {

/**

* The message displayed to the user when the server cannot be reached or

* returns an error.

*/

private static final String SERVER_ERROR = "An error occurred while "

+ "attempting to contact the server. Please check your network "

+ "connection and try again.";

/**

* Create a remote service proxy to talk to the server-side Greeting service.

*/

private final GreetingServiceAsync greetingService = GWT

.create(GreetingService.class);

/**

* This is the entry point method.

*/

public void onModuleLoad() {

final Button addButton = new Button("Add");

final Label value1Label = new Label();

value1Label.setText("Value1:");

RootPanel.get("value1LabelContainer").add(value1Label);

final TextBox value1Field = new TextBox();

RootPanel.get("value1FieldContainer").add(value1Field);

final Label value2Label = new Label();

value2Label.setText("Value2:");

RootPanel.get("value2LabelContainer").add(value2Label);

final TextBox value2Field = new TextBox();

RootPanel.get("value2FieldContainer").add(value2Field);

addButton.addStyleName("Insert");

final Label ansLabel = new Label();

ansLabel.setText("Answer:");

RootPanel.get("ansLabelContainer").add(ansLabel);

final TextBox ansField = new TextBox();

RootPanel.get("ansFieldContainer").add(ansField);

final Label errorLabel = new Label();

RootPanel.get("addButtonContainer").add(addButton);

RootPanel.get("errorLabelContainer").add(errorLabel);

// Create a handler for the sendButton and nameField

class MyHandler implements ClickHandler {

/**

* Fired when the user clicks on the sendButton.

*/

public void onClick(ClickEvent event) {

if(event.getSource().equals(addButton))

{

addValue();

}

}

/**

* Send the name from the nameField to the server and wait for a response.

*/

private void addValue() {

String value1Text = value1Field.getText();

String value2Text = value2Field.getText();

greetingService.addValue(value1Text,value2Text,

new AsyncCallback() {

public void onFailure(Throwable caught) {

// Show the RPC error message to the user

RootPanel.get().add(new HTML("RPC call failed. :-("));

}

public void onSuccess(String result) {

ansField.setText(result);

RootPanel.get().add(new HTML("RPC call Success:"));

}

});

}

}

// Add a handler to send the name to the server

MyHandler handler = new MyHandler();

addButton.addClickHandler(handler);

//nameField.addKeyUpHandler(handler);

}

}

GreetingServiceImpl:

package gwtWithSpring.server;

import gwtWithSpring.client.GreetingService;

import gwtWithSpring.shared.FieldVerifier;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**

* The server side implementation of the RPC service.

*/

@SuppressWarnings("serial")

public class GreetingServiceImpl extends RemoteServiceServlet implements

GreetingService {

public String greetServer(String input) throws IllegalArgumentException {

// Verify that the input is valid.

if (!FieldVerifier.isValidName(input)) {

// If the input is not valid, throw an IllegalArgumentException back to

// the client.

throw new IllegalArgumentException(

"Name must be at least 4 characters long");

}

String serverInfo = getServletContext().getServerInfo();

String userAgent = getThreadLocalRequest().getHeader("User-Agent");

return "Hello, " + input + "!

I am running " + serverInfo

+ ".

It looks like you are using:
" + userAgent;

}

//by siddhu[

public String addValue(String value1,String value2) throws IllegalArgumentException {

int addValue = Integer.parseInt(value1) + Integer.parseInt(value2);

Integer i = new Integer(addValue);

return i.toString();

}

//by siddhu]

}

ServletWrappingController:

package gwtWithSpring.server;

import java.util.Enumeration;

import java.util.Properties;

import javax.servlet.Servlet;

import javax.servlet.ServletConfig;

import javax.servlet.ServletContext;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.BeanNameAware;

import org.springframework.beans.factory.DisposableBean;

import org.springframework.beans.factory.InitializingBean;

import org.springframework.web.servlet.ModelAndView;

import org.springframework.web.servlet.mvc.AbstractController;

/**

* Spring Controller implementation that mimics standard ServletWrappingController behaviour

* (see its documentation), but with the important difference that it doesn't instantiate the

* Servlet instance directly but delegate for this the BeanContext, so that we can also use IoC.*

*/

public class ServletWrappingController extends AbstractController

implements BeanNameAware, InitializingBean, DisposableBean {

private Class servletClass;

private String servletName;

private Properties initParameters = new Properties();

private String beanName;

private Servlet servletInstance;

public void setServletClass(Class servletClass) {

System.out.print("setServletClass : "+servletClass);

this.servletClass = servletClass;

}

public void setServletName(String servletName) {

System.out.print("setServletName : "+servletName);

this.servletName = servletName;

}

public void setInitParameters(Properties initParameters) {

System.out.print("setInitParameters : "+initParameters);

this.initParameters = initParameters;

}

public void setBeanName(String name) {

System.out.print("setBeanName : "+name);

this.beanName = name;

}

public void setServletInstance(Servlet servletInstance) {

System.out.print("setServletInstance : "+servletInstance);

this.servletInstance = servletInstance;

}

public void afterPropertiesSet() throws Exception {

System.out.print("afterPropertiesSet");

if (this.servletInstance == null) {

throw new IllegalArgumentException("servletInstance is required");

}

if (!Servlet.class.isAssignableFrom(servletInstance.getClass())) {

throw new IllegalArgumentException("servletInstance [" + this.servletClass.getName() +

"] needs to implement interface [javax.servlet.Servlet]");

}

if (this.servletName == null) {

this.servletName = this.beanName;

}

this.servletInstance.init(new DelegatingServletConfig());

}

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)

throws Exception {

System.out.print("handleRequestInternal");

this.servletInstance.service(request, response);

return null;

}

public void destroy() {

System.out.print("destroy");

this.servletInstance.destroy();

}

private class DelegatingServletConfig implements ServletConfig {

public String getServletName() {

return servletName;

}

public ServletContext getServletContext() {

return getWebApplicationContext().getServletContext();

}

public String getInitParameter(String paramName) {

return initParameters.getProperty(paramName);

}

public Enumeration getInitParameterNames() {

return initParameters.keys();

}

}

}

FieldVerifier:

package gwtWithSpring.shared;

/**

*

* FieldVerifier validates that the name the user enters is valid.

*

*

* This class is in the shared packing because we use it in both

* the client code and on the server. On the client, we verify that the name is

* valid before sending an RPC request so the user doesn't have to wait for a

* network round trip to get feedback. On the server, we verify that the name is

* correct to ensure that the input is correct regardless of where the RPC

* originates.

*

*

* When creating a class that is used on both the client and the server, be sure

* that all code is translatable and does not use native JavaScript. Code that

* is note translatable (such as code that interacts with a database or the file

* system) cannot be compiled into client side JavaScript. Code that uses native

* JavaScript (such as Widgets) cannot be run on the server.

*

*/

public class FieldVerifier {

/**

* Verifies that the specified name is valid for our service.

*

* In this example, we only require that the name is at least four

* characters. In your application, you can use more complex checks to ensure

* that usernames, passwords, email addresses, URLs, and other fields have the

* proper syntax.

*

* @param name the name to validate

* @return true if valid, false if invalid

*/

public static boolean isValidName(String name) {

if (name == null) {

return false;

}

return name.length() > 3;

}

}


No comments: