Showing posts with label ajax. Show all posts
Showing posts with label ajax. Show all posts

Reverse Ajax with Spring and DWR


Ajax is used heavily for web 2.0 applications to provide enhance user experience, which allows a web page to be updated without the need of full refresh. Normally this updated information is pulled from client side.
Javascript call is used to make an Ajax call to the server and received information is updated.
But there are scenarios when server decides to update information on client side e.g. Chat applications, server side processing status, user presence etc.


In these situations server side "PUSH" is required instead of Client side "PULL". There are three techniques used for this purpose:
  • Polling (the browser sends requests at regular interval)
  • Comet (long lived HTTP connection connection is kept open and server keeps replying)
  • Piggyback (server waits for client to make request and sends update with that request data)
Configuration:
1. Enable Reverse Ajax in DWR configuration
There are two ways of going this:

You can enable in DWR.xml
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>activeReverseAjaxEnabled</param-name>
<param-value>true</param-value>
</init-param>

or if you are using DWR name spaces then you can provide entry in [Servlet Name]-servelt.xml
<dwr:controller id="dwrController" debug="true">
<dwr:config-param name="activeReverseAjaxEnabled" value="true" />
</dwr:controller>

2. Enable Reverse Ajax in JSP
dwr.engine.setActiveReverseAjax(true);

3. Now we need to get Browser sessions from server side and push content there:

WebContext wctx = WebContextFactory.get();
String currentPage = wctx.getCurrentPage();

Get current page from webContext

Collection sessions = wctx.getScriptSessionsByPage(currentPage);
Get all other clients session

After getting these sessions you can push data from here using proxy interface
Util utilAll = new Util(sessions);
utilAll.addOptions("chatlog", messages, "text");

Above lines will add messages collection to all the browsers under "chatlog" element

Similarly you can execute scripts on browsers from server side.

ScriptBuffer script = new ScriptBuffer();
script.appendScript("receiveMessages(")
.appendData(messages)
.appendScript(");");

Above snippet will execute receiveMessages() javascript function on client side.

This way you can have full control on client side from server side. Chat application, Stock Ticker control applications, mail client can use this feature effectively.

AJAXing with Spring using DWR

Recently I have an opportunity to work with Spring Framework. With Spring I have used following technologies:

1. Spring MVC
2. Ajax - DWR
3. Hibernate
4. Tiles
5. Acegi Security

It was really a nice experience working with Spring and other supporting technologies.

I found a littlet bit problem in getting DWR 2.0 working with Spring 2.0.

Approach that worked for me as follows:

1. Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app schemalocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4">
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
<!-- Listner Config-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
<!-- Ajax DWR config ends -->
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>
index.jsp
</welcome-file>
</welcome-file-list>
<servlet>

2. Application-Context.xml

<!-- DWR Configurations -->
<dwr:controller id="dwrController" debug="true"/>
<!-- Configure DWR handlers -->

<bean id="dwrUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="alwaysUseFullPath" value="true"/>
<property name="mappings">
<props>
<prop key="/dwr/**/*">dwrController</prop> </props> </property>
</bean>
<!-- Configure Convertor -->

<dwr:configuration>
<dwr:convert type="bean" class="com.app.domain.User" />
</dwr:configuration>

<!-- Configure Ajax controller -->

<bean id="ajaxController" class="com.app.controller.dwr.AjaxController">
<dwr:remote javascript="UserList">
<dwr:include method="getUser"/>
<dwr:include method="updateUser"/>
</dwr:remote>
<property name="userDao" ref="userDao"/>
</bean>

3. JSP Page

Add following lines to jsp page:
<script type='text/javascript' src='/spring/dwr/interface/UserList.js'></script>
<script type='text/javascript' src='/spring/dwr/engine.js'></script>
<script type='text/javascript' src='/spring/dwr/util.js'></script>

Define call back javascript function and attach that to some event

<script type="text/javascript">
function editUser(id) {
UserList.getUser(id,function(array){DWRUtil.setValue(fname,array.fname); });
}
</script>

Finally deploy the application and restart the server and here is your DWR wroking...

To test it you can use: http://localhost:8080/spring/dwr/index.html

Resources: