October 21, 2010
We have been seeing this issue in DWR/Spring integrations. It looks like the Spring guys changed (changed since Spring 3.x?) their schema and now require an id attribute on top-level annotation-config elements. DWR uses a Spring class to parse the XML and it throws the following error:
“Configuration problem: Id is required for element ‘annotation-config’ when used as a top-level tag”
It appears for now adding an id attribute resolves the issue. I will continue to look into this.
This post applies to DWR 3.x and Spring 3.x. Configuring DWR to work with annotations and Spring isn’t difficult, but there are a lot of moving parts and many users struggle with it. There are a few elements that DWR has available and understanding them is key (these elements can be viewed in the DWR Spring schema – http://directwebremoting.org/schema/spring-dwr-3.0.xsd):
annotation-scan – This element enables DWR to scan the classpath, detect beans annotated with @RemoteProxy, @RemoteMethod, @DataTransferObject and register the beans (@DataTransferObject) and Creator proxies (@RemoteProxy & @RemoteMethod) for them.
annotation-config – This element enables DWR to scan the Spring context, detect beans annotated with @RemoteProxy and @RemoteMethod and registers Creator proxies for them. Note this element will only search the Spring context and will only create the Creator proxies. You will need to manually register converters for the types the proxy methods will return or accepts as parameters.
For now I have completed two sample applications that you can use to get started. I don’t have time to discuss the code right now but it is pretty straightforward.
January 17, 2010
For Jetty 7 a lot of re-factoring has been done on the Continuations API. I recently took a look at the changes and modified DWR’s code to reflect the latest API. If you are using the latest version of DWR 3.x (currently unreleased) and you are still using a Jetty version < 7.x you will need to follow these directions to get Continuations working.
First you will need to download the Jetty continuation 7 jar and place it in WEB-INF/lib. You can read more about why this works here.
Next you will need to add the JettyContinuationFilter to your web.xml:
<filter>
<filter-name>JettyContinuationFilter</filter-name>
<filter-class>org.eclipse.jetty.continuation.ContinuationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>JettyContinuationFilter</filter-name>
<url-pattern>/dwr/*</url-pattern>
</filter-mapping>
You should now be up and running.
December 6, 2009
If you want to integrate DWR 3.x with Spring you can follow my previous posts (note – I have included a working sample application and updated source at the bottom of this page):
- I am using DWR 2.0.x, Spring 2.x, and Spring MVC
- I am using DWR 2.0.x, Spring 2.x, but I am not using Spring MVC
However, you will need to make the following changes.
Spring 2.5 or greater is Required
You must upgrade to Spring 2.5 or higher (I am using Spring 3.0.4).
Update you Spring Application Context
Update your Spring Application Context:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
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-.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd">
I have added two working examples (~10 mb in size), both of these zip files contain all source as well as a working web-app that you can drop into your container:
December 24, 2008
Recently there have been some questions on DWR’s user mailing list about integration with Hibernate. Most of the questions stem from a misunderstanding of how DWR works and I thought it would be helpful to write a post to give new users some information on what to expect from DWR.
DWR provides two main integration points with Hibernate:
- A converter (hibernate3) that attempts to avoid reading from un-initialized (lazy) properties.
- A filter (H3SessionAjaxFilter) which provides a Hibernate Session to the hibernate3 converter if un-initialized properties need to be read.
What converter should I use and how do I configure it?
You should use the hibernate3 converter if:
- The returned object has lazy properties which have not been excluded in your DWR configuration and you do not want DWR to attempt to serialize these properties.
- Add a converter to your dwr.xml:
<allow>
....
<convert converter="hibernate3" match="yourpackage.yourClass" />
....
</allow>
- The returned object has lazy properties and you want DWR to attempt to serialize these properties.
- Add a converter to your dwr.xml with the assumeSession parameter set to true. This will tell DWR it should attempt to access the Hibernate session to read un-initialized properties:
<allow>
....
<convert converter="hibernate3" match="yourpackage.yourClass">
<param name="assumeSession" value="true"/>
</convert>
....
</allow>
- Add the H3SessionAjaxFilter filter to your dwr.xml, this filter provides the Hibernate session needed by the hibernate3 converter to read the un-initialized properties.
<allow>
....
<filter class=" org.directwebremoting.hibernate.H3SessionAjaxFilter"/>
....
</allow>
You should use the standard bean converter if:
- The returned object does not have lazy properties and you want DWR to blindly serialize all properties on the object (or properties based on the exclusions, inclusions set in your DWR configuration).
Where the confusion lies:
So what was the problem that the users on the list were having? Both users thought it was possible for DWR to make a call to the server to retrieve a lazy property when an attempt was made to access that property in JavaScript. Here is a code sample to illustrate this point:
function dwrCallBack(beanFromServer) {
alert(beanFromServer.lazyProperty);
}
DWR does a lot of magical things but it DOES NOT access the server when reading JavaScript properties. All serialization of the object DWR will return to the browser is performed one-time – in the converter. The converters job is to serialize the bean into a complete JavaScript object.
In short the conversion of Hibernate beans is an all or nothing process. The developer needs to understand what properties he needs to display in the view and prepare his converter configuration with this in mind. Please note that the hibernate converter is very similar to the bean converter and thus you may specify include and exclude parameters (to exclude or include properties in serialization). For more information on the bean and hibernate converters please see the DWR docs:
- http://directwebremoting.org/dwr/server/hibernate
- http://directwebremoting.org/dwr/server/dwrxml/converters/bean
If you have any questions feel free to post them in the comments area.
August 5, 2008
JAWR is an open source tool written in Java that compresses and organizes an applications JavaScript/CSS source. I found out about JAWR through the DWR mailing list. It took me awhile to check it out, but I finally got around to it. I have been working on a DWR application with an ExtJS front-end and I thought this would be a perfect place to try JAWR.
First Impressions:
Setting up JAWR is simple! The project is well documented and by following the quick start I was able to get up and running in no time. JAWR does a lot more than JavaScript/CSS compression — here are some of the features:
- Allows you to componentize and organize your JavaScript sources. Not only does this improve your code it also makes maintenance a lot easier.
- Debug mode allows you to debug your JS source with the modification of one property — Great for development.
- DWR 3.x plugin that compresses interface files generated by DWR as well as static DWR scripts.
- Gzips the response.
JAWR does a lot more. All developers working on Java web apps should check it out — sooner rather than later!
February 20, 2008
DWR and Spring is a great combination. The Spring integration in DWR can support many configurations but many times this can lead to confusion. The goal of this article is to provide developers with a working skeleton for several common environments (using Spring MVC, not using Spring MVC, using the DWR Namespace, etc.).
References
Before we get started you may want to take a quick look at the official DWR documentation.
The DWR Namespace Handler:
Spring 2.x introduced an “XML Namespace Handlers” feature. DWR 2.x allows you to leverage this feature through a custom namespace — eliminating the need for the DWR configuration file (dwr.xml). If you are using DWR > 2.0.x and Spring > 2.x this is the recommended approach if you want seamless integration (almost) between DWR and Spring.
There are a myriad of configurations to consider. I have included what I feel or the more popular choices. Please select a link for a detailed description of each configuration and to download a fully functioning basic example:
- I am using DWR 3.x, and Spring 3.x …
- I am using DWR 3.x and Spring 3.x and I would like to use Annotations without Spring MVC.
- I am using DWR 3.x and Spring 3.x and I would like to use Annotations with Spring MVC.
- I am using DWR 2.0.x, Spring 2.x, and Spring MVC
- I am using DWR 2.0.x, Spring 2.x, but I am not using Spring MVC
dwr.xml:
If you are using an older version (pre 2.x) of DWR or Spring, DWR still provides integration with Spring through the Spring Creator. This configuration requires a dwr.xml configuration. Information on this set-up is covered in the DWR manual.
If you are using DWR 2.0.x, Spring 2.x dwr.xml is not required. You can use the new DWR namespace feature in your Spring xml even if you are not using Spring MVC.
You can download the files from this article here. This includes all the source, configuration, and a ready to run web-app.
Step 1: Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:dwrSampleApp2.xml
</param-value>
</context-param>
<servlet>
<servlet-name>dwr</servlet-name>
<servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>
Since we are not using Spring MVC there are two things that we need to take care of in the web.xml:
- We need a way for our application to find and load our Spring configuration. There is more than one way to do this but I recommend using a Spring ContextLoadListener.
- The DwrSpringServlet needs to be specified and all DWR requests need to be mapped to it.
Step 2: Spring xml/Application Context (for this example, dwrSampleApp2.xml)
-
Add the DWR namespace declarations to dwrSampleApp2.xml:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd">
-
Configure DWR with the configuration tag.
For this example we are returning an Address POJO from our DWR service. We need to tell DWR to convert the Address POJO with DWR’s “bean” converter. The configuration tag’s children elements mimic the behavior of dwr.xml elements. If you are familiar with the options available in dwr.xml — setting up this tag should be second nature.
Add the dwr:configuration tag to dwrSampleApp2.xml:
<dwr:configuration>
<dwr:convert type="bean" class="org.uk.ltd.dwr.dev.model.Address" />
</dwr:configuration>
- Expose your Beans to DWR with the remote tag.
Add the following bean to dwrSampleApp2.xml:
<bean id="dwrService" class="org.uk.ltd.dwr.dev.service.DWRService">
<dwr:remote javascript="dwrService">
<dwr:include method="getAddress" />
</dwr:remote>
</bean>
You can download the files from this article here. This includes all the source, configuration, and a ready to run web-app.
If you are using DWR 2.0.x, Spring 2.x, with Spring MVC, dwr.xml is not required. You can use the new DWR namespace feature in your Spring xml.
This page assumes you know how to use Spring MVC, you have a Spring Dispatcher Servlet mapped (dwrSampleApp), and you are ready to integrate Spring with DWR. I strongly encourage you to have a working configuration before attempting to integrate DWR.
You can download the files from this article here. This includes all the source, configuration, and a ready to run web-app.
Step 1: Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">
<servlet>
<servlet-name>dwrSampleApp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value> classpath:dwrSampleApp.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dwrSampleApp</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dwrSampleApp</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
</web-app>
We have added two mappings to the Dispatcher Servlet (*.html and /dwr/*). The problem with the “*.html” mapping alone is that it will not handle all of the DWR requests (described in the next section ‘Spring Application Context’). So, depending on how you have your mappings configured the /dwr/* mapping will or will not be necessary. The key thing to remember is that DWR requests need to be mapped to the configured DispatcherServlet.
Step 2: Spring xml/Application Context (for this example, dwrSampleApp.xml)
- Add the DWR namespace declarations to dwrSampleApp.xml:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd">
- Create a DWR Controller and a way for Spring (SimpleUrlHandlerMapping) to map DWR requests to this controller. The DWR Controller needs to handle the following requests:
- /dwr/engine.js
- /dwr/util.js
- /dwr/interface/**
- /dwr/call/**
Add the DWR Controller to dwrSampleApp.xml:
<dwr:controller id="dwrController" debug="true" />
- Create the mapping from DWR requests to the DWR controller. There are several ways to create this mapping but I feel the following is the easiest to comprehend and the least verbose option:
Add the SimpleUrlHandlerMapping to dwrSampleApp.xml:
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property value="true" name="alwaysUseFullPath"></property>
<property name="mappings">
<props>
<prop key="/dwr/**/*">dwrController</prop>
</props>
</property>
</bean>
Please note the use of the alwaysUseFullPath property. If this is not set to true (by default it is false) we will have to map all of the required DWR requests:
<prop key="/interface/**">dwrController</prop>
etc., etc.
Why? Because we have mapped /dwr/* to the DispatcherServlet in web.xml, what gets passed into the SimpleUrlHandlerMapping is everything after the /dwr/ (We are not matching on the entire path, because alwaysUseFullPath is false by default). I think not understanding how the SimpleUrlHandlerMapping works is one of the most common problems with this configuration. This has nothing to do with DWR directly, but the DWR mailing list pays the price!
Another important note about Handler Mappings:
It is important to note that the creation of the SimpleUrlHandlerMapping may cause your existing mappings to fail if you have not explicitly created a Handler Mapping in your Spring configuration. By default Spring creates a BeanNameUrlHandlerMapping if you have not explicitly created a Handler Mapping. So when the SimpleUrlHandlerMapping is created for DWR, Spring will no longer create the default BeanNameUrlHandlerMapping and existing mappings will not work. Spring allows you to have multiple Handler Mappings, so to fix this you need to create a BeanNameUrlHandlerMapping explicitly in your spring.xml (in addition to the SimpleUrlHandlerMapping). See the Spring documentation section 13.4.1 for more information.
- Configure DWR with the configuration tag.
For this example we are returning an Address POJO from our DWR service. We need to tell DWR to convert the Address POJO with DWR’s “bean” converter. The configuration tag’s children elements mimic the behavior of dwr.xml elements. If you are familiar with the options available in dwr.xml — setting up this tag should be second nature.
Add the dwr:configuration tag to dwrSampleApp.xml:
<dwr:configuration>
<dwr:convert class="org.uk.ltd.dwr.dev.model.Address" type="bean" />
</dwr:configuration>
- Expose your Beans to DWR with the remote tag.
Add the following bean to dwrSampleApp.xml:
<bean class="org.uk.ltd.dwr.dev.service.DWRService" id="dwrService">
<dwr:remote javascript="dwrService">
<dwr:include method="getAddress"/>
</dwr:remote>
</bean>
You can download the files from this article here. This includes all the source, configuration, and a ready to run web-app.