Friday, March 11, 2011
Thursday, February 24, 2011
Saturday, February 12, 2011
Integrating Atmosphere (WebSockets) and Appfuse (struts2, spring, hibernate etc)
For my latest project, i needed to play with Web Sockets - A way to push notifications/events to the browser without a pull. So while researching for toolkits and various frameworks out there i came across Atmosphere ((http://bit.ly/9CzDtq). This is a really cool framework that lets you code without worrying about browser support etc. Basically under the hoods it uses WebSockets if the browser supports it and Comet if it doesnt.
Atmosphere on its own was very easy to setup and run. The challenge was to get Atmosphere to play nicely with my Appfuse app that basically had Spring, Struts 2, Hibernate, CXF and what not.
Versions:
Spring - 3.0.5.RELEASE
Struts 2 - 2.18
Hibernate - 3.3.2.GA
CXF - 2.2.4
I had to go through many jar conflicts before i was even able to get the web app up and running. So my approach was a process of elimination - one error at a time.
Here's what i did:
1. Pom file edits
Firstly, i needed to load the Atmosphere related jars.
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-runtime</artifactId>
<version>0.6.4</version>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-annotations</artifactId>
<version>0.6.4</version>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-jersey</artifactId>
<version>0.6.4</version>
</dependency>
Then, I needed Atmosphere to work nicely with Spring. For this I needed to load jersey-spring into my application. Note that i have excluded a bunch of spring libraries. If i didnt do that, it would load its dependent spring libraries and then i would get a whole load of jar conflicts.
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-spring</artifactId>
<version>1.5</version>
<exclusions>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-context</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-web</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-aop</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-test</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-jdbc</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-orm</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-aspects</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-context-support</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-webmvc</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-security-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-security-config</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-support</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
Now to the errors. Once i started up my Jetty container the first error i got was,
java.lang.NoSuchMethodError: org.objectweb.asm.ClassReader.accept(Lorg/objectweb/asm/ClassVisitor;I)V
at com.sun.jersey.spi.scanning.AnnotationScannerListener.onProcess(AnnotationScannerListener.java:133)
This was because hibernate was loading its dependent version of asm. To overcome this i had to explicitly load the asm version i needed - which was 3.1.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
<exclusions>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.1</version>
</dependency>
<dependency>
The next error i got was,
java.lang.RuntimeException: The scope of the component class org.codehaus.jackson.jaxrs.JacksonJsonProvider must be a singleton
at com.sun.jersey.core.spi.component.ioc.IoCProviderFactory.wrap(IoCProviderFactory.java:102)
This was because the bean definition of JacksonJsonProvider was not explicity given as singleton. The change was straightforward.
<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" scope="singleton"/>
The next error was,
Class javax.ws.rs.core.Response$Status does not implement the requested interface javax.ws.rs.core.Response$StatusType
For this i had to ensure the cxf-rt-frontend-jaxrs didnt load the dependent jsr311-api jar and instead explicitly load the version i needed.
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${cxf.version}</version>
<exclusions>
...
<exclusion>
<artifactId>jsr311-api</artifactId>
<groupId>javax.ws.rs</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
Getting closer now. The next error i got was,
com.sun.jersey.api.container.ContainerException: The ResourceConfig instance does not contain any root resource classes.
This is Jersey related and so what i had to do to overcome this was to provide the following in the web.xml
<servlet>
<description>AtmosphereServlet</description>
<servlet-name>AtmosphereServlet</servlet-name>
<servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
...
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.howzat.util;org.codehaus.jackson.jaxrs</param-value>
</init-param>
...
I also had to add the following to the atmosphere.xml file located in the META-INF folder
<?xml version="1.0" encoding="UTF-8"?>
<atmosphere-handlers>
<atmosphere-handler context-root="/*"
class-name="org.atmosphere.handler.ReflectorServletProcessor">
<property name="servletClass" value="com.sun.jersey.spi.spring.container.servlet.SpringServlet"/>
</atmosphere-handler>
</atmosphere-handlers>
With these changes Jetty started up without any errors. The Classes i was using was from the Sample (atmosphere-jquery-pubsub-0.6.4-sources; JQueryPubSub.java, FileResource.java, EventsLogger.java).
However, everything was not quite right yet.
I had to make sure the atmosphere was not hikacking all my requests, so i gave it its own path,
<servlet-mapping>
<servlet-name>AtmosphereServlet</servlet-name>
<url-pattern>/atmosphere/*</url-pattern>
</servlet-mapping>
Then i modified the html (index.html that came with the sample) to send app pub sub requests to the context i just provided for Atmosphere.
With that it worked! At least the basic app. Now to tweak it more...
Atmosphere on its own was very easy to setup and run. The challenge was to get Atmosphere to play nicely with my Appfuse app that basically had Spring, Struts 2, Hibernate, CXF and what not.
Versions:
Spring - 3.0.5.RELEASE
Struts 2 - 2.18
Hibernate - 3.3.2.GA
CXF - 2.2.4
I had to go through many jar conflicts before i was even able to get the web app up and running. So my approach was a process of elimination - one error at a time.
Here's what i did:
1. Pom file edits
Firstly, i needed to load the Atmosphere related jars.
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-runtime</artifactId>
<version>0.6.4</version>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-annotations</artifactId>
<version>0.6.4</version>
</dependency>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-jersey</artifactId>
<version>0.6.4</version>
</dependency>
Then, I needed Atmosphere to work nicely with Spring. For this I needed to load jersey-spring into my application. Note that i have excluded a bunch of spring libraries. If i didnt do that, it would load its dependent spring libraries and then i would get a whole load of jar conflicts.
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-spring</artifactId>
<version>1.5</version>
<exclusions>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-context</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-web</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-aop</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-test</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-jdbc</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-orm</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-aspects</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-context-support</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-webmvc</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-security-core</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-security-config</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-support</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>
Now to the errors. Once i started up my Jetty container the first error i got was,
java.lang.NoSuchMethodError: org.objectweb.asm.ClassReader.accept(Lorg/objectweb/asm/ClassVisitor;I)V
at com.sun.jersey.spi.scanning.AnnotationScannerListener.onProcess(AnnotationScannerListener.java:133)
This was because hibernate was loading its dependent version of asm. To overcome this i had to explicitly load the asm version i needed - which was 3.1.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
<exclusions>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.1</version>
</dependency>
<dependency>
The next error i got was,
java.lang.RuntimeException: The scope of the component class org.codehaus.jackson.jaxrs.JacksonJsonProvider must be a singleton
at com.sun.jersey.core.spi.component.ioc.IoCProviderFactory.wrap(IoCProviderFactory.java:102)
This was because the bean definition of JacksonJsonProvider was not explicity given as singleton. The change was straightforward.
<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" scope="singleton"/>
The next error was,
Class javax.ws.rs.core.Response$Status does not implement the requested interface javax.ws.rs.core.Response$StatusType
For this i had to ensure the cxf-rt-frontend-jaxrs didnt load the dependent jsr311-api jar and instead explicitly load the version i needed.
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>${cxf.version}</version>
<exclusions>
...
<exclusion>
<artifactId>jsr311-api</artifactId>
<groupId>javax.ws.rs</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
Getting closer now. The next error i got was,
com.sun.jersey.api.container.ContainerException: The ResourceConfig instance does not contain any root resource classes.
This is Jersey related and so what i had to do to overcome this was to provide the following in the web.xml
<servlet>
<description>AtmosphereServlet</description>
<servlet-name>AtmosphereServlet</servlet-name>
<servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
...
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.howzat.util;org.codehaus.jackson.jaxrs</param-value>
</init-param>
...
I also had to add the following to the atmosphere.xml file located in the META-INF folder
<?xml version="1.0" encoding="UTF-8"?>
<atmosphere-handlers>
<atmosphere-handler context-root="/*"
class-name="org.atmosphere.handler.ReflectorServletProcessor">
<property name="servletClass" value="com.sun.jersey.spi.spring.container.servlet.SpringServlet"/>
</atmosphere-handler>
</atmosphere-handlers>
With these changes Jetty started up without any errors. The Classes i was using was from the Sample (atmosphere-jquery-pubsub-0.6.4-sources; JQueryPubSub.java, FileResource.java, EventsLogger.java).
However, everything was not quite right yet.
I had to make sure the atmosphere was not hikacking all my requests, so i gave it its own path,
<servlet-mapping>
<servlet-name>AtmosphereServlet</servlet-name>
<url-pattern>/atmosphere/*</url-pattern>
</servlet-mapping>
Then i modified the html (index.html that came with the sample) to send app pub sub requests to the context i just provided for Atmosphere.
With that it worked! At least the basic app. Now to tweak it more...
Wednesday, December 29, 2010
Hibernate - Reading a datasource from a jndi
I was writing this utility that read the data produced by the main application, but presented it in a different way - basically sliced and diced the information such that it was more meaningful to the user.
My goal for this utility was simple - provide as little configurations as possible - make it work more like a plug-and-play utility.
To achieve this, the first goal was to read the same jndi’s the main application was reading to fetch data. I didnt want the user to have to re-enter the connection params. Fairly simple request right?
Here’s what i had to do to achieve this:
Step1 - The JNDI was already defined - in the tomcat server.xml in this case. So make a note of the jndi name
auth=”Container”
type=”javax.sql.DataSource”
….
Step2 - Update your Spring application context to include the datasource bean as follows,
class=”org.springframework.jndi.JndiObjectFactoryBean”>
/jdbc/unity”/>
Step2 - Last step - update your Context.xml (if you dont have one, create one under META-INF)
jdbc/unity”
type=”javax.sql.DataSource”
global=”jdbc/unity”/>
Thats it!
My goal for this utility was simple - provide as little configurations as possible - make it work more like a plug-and-play utility.
To achieve this, the first goal was to read the same jndi’s the main application was reading to fetch data. I didnt want the user to have to re-enter the connection params. Fairly simple request right?
Here’s what i had to do to achieve this:
Step1 - The JNDI was already defined - in the tomcat server.xml in this case. So make a note of the jndi name
type=”javax.sql.DataSource”
….
Step2 - Update your Spring application context to include the datasource bean as follows,
Step2 - Last step - update your Context.xml (if you dont have one, create one under META-INF)
type=”javax.sql.DataSource”
global=”jdbc/unity”/>
Thats it!
Tuesday, December 28, 2010
Formatting Struts 2 s:checkboxlist tag
I recently had the need to format the struts 2 tag. By default it appears as a horizontal formatted list (checkBox1[] checkBox2[] checkBox3[] etc) but since the number of checkboxes were large, i wanted them to appear in a tabular format.
Here's what i did:
- After doing a quick Google search i figured that i needed to overwrite the default Freemarker template.
- All the templates are located in the struts-core.jar
1. Create a new directory structure at the root of my application called template/myapp and template/myapp_simple
2. The template we're looking for is checkboxlist.ftl. This is located in the struts-core.jar under templates/xhtml folder. We want to override that, so lets create our own version of it. To start with lets copy the existing freemarker templates (located in struts-core.jar templates/xhtml) into your new template/myapp folder.
3. Now edit the filer checkboxlist.ftl. As you can see its referring to the template stored under the simple folder.
<#include "/${parameters.templateDir}/simple/checkboxlist.ftl" />
Lets change that so that it points to your directory structure
<#include "/${parameters.templateDir}/myapp_simple/checkboxlist.ftl" />
4. Now lets copy the checkboxlist.ftl located in the template/simple folder (from the struts-core.jar) into your template/myapp_simple folder.
5. Lets override this file now. What i want to do is make all the checkboxes appear in a 4 column table. So here's what my checkboxlist.ftl looks like.
Thats it
Here's what i did:
- After doing a quick Google search i figured that i needed to overwrite the default Freemarker template.
- All the templates are located in the struts-core.jar
1. Create a new directory structure at the root of my application called template/myapp and template/myapp_simple
2. The template we're looking for is checkboxlist.ftl. This is located in the struts-core.jar under templates/xhtml folder. We want to override that, so lets create our own version of it. To start with lets copy the existing freemarker templates (located in struts-core.jar templates/xhtml) into your new template/myapp folder.
3. Now edit the filer checkboxlist.ftl. As you can see its referring to the template stored under the simple folder.
<#include "/${parameters.templateDir}/simple/checkboxlist.ftl" />
Lets change that so that it points to your directory structure
<#include "/${parameters.templateDir}/myapp_simple/checkboxlist.ftl" />
4. Now lets copy the checkboxlist.ftl located in the template/simple folder (from the struts-core.jar) into your template/myapp_simple folder.
5. Lets override this file now. What i want to do is make all the checkboxes appear in a 4 column table. So here's what my checkboxlist.ftl looks like.
<#assign itemCount = 0/> <#if parameters.list?exists> <@s.iterator value="parameters.list"> <#assign itemCount = itemCount + 1/> <#if parameters.listKey?exists> <#assign itemKey = stack.findValue(parameters.listKey)/> <#else> <#assign itemKey = stack.findValue('top')/> <#if parameters.listValue?exists> <#assign itemValue = stack.findString(parameters.listValue)/> <#else> <#assign itemValue = stack.findString('top')/> <#assign itemKeyStr=itemKey.toString() /> <#if itemCount%4=0> <#elseif itemCount%4=2> <#elseif itemCount%4=3> <#else> <#rt/> <#if tag.contains(parameters.nameValue, itemKey)> checked="checked"<#rt/> <#if parameters.disabled?default(false)> disabled="disabled"<#rt/> <#if parameters.title?exists> title="${parameters.title?html}"<#rt/> <#include "/${parameters.templateDir}/simple/scripting-events.ftl" /> <#include "/${parameters.templateDir}/simple/common-attributes.ftl" /> /> <#if itemCount%4=0> <#else> <#rt/> <#else>
Thats it
Monday, July 12, 2010
I love my Grill!
Its the 4th of July weekend and so i thought its about time i got myself a Grill.
My budget was limited, and so even tho the webers looked very appealing i had to stick within my $200 limit (self imposed ofcourse).
I ended up going for the Nexgrill (http://www.homedepot.com/h_d1/N-5yc1vZ1xg1Zbwo59/R-202326969/h_d2/ProductDisplay?langId=-1&storeId=10051&catalogId=10053)
My first BBQ turned out to be pretty good. Here are few recipes that went down well with the peeps.
1. Pork Chops (http://www.foodnetwork.com/recipes/paulas-home-cooking/grilled-pork-chops-recipe/index.html)
2. Chicken Tikka Masala (http://allrecipes.com//Recipe/chicken-tikka-masala/Detail.aspx)
3. Grilled Shrimp (http://www.foodnetwork.com/recipes/ina-garten/grilled-herb-shrimp-recipe/index.html)
My budget was limited, and so even tho the webers looked very appealing i had to stick within my $200 limit (self imposed ofcourse).
I ended up going for the Nexgrill (http://www.homedepot.com/h_d1/N-5yc1vZ1xg1Zbwo59/R-202326969/h_d2/ProductDisplay?langId=-1&storeId=10051&catalogId=10053)

1. Pork Chops (http://www.foodnetwork.com/recipes/paulas-home-cooking/grilled-pork-chops-recipe/index.html)
2. Chicken Tikka Masala (http://allrecipes.com//Recipe/chicken-tikka-masala/Detail.aspx)
3. Grilled Shrimp (http://www.foodnetwork.com/recipes/ina-garten/grilled-herb-shrimp-recipe/index.html)
Installing GWT on Ubuntu 10.04
When trying to run GWT in hosted mode i got the following,
** Unable to find a usable Mozilla install **
You may specify one in mozilla-hosted-browser.conf, see comments in the file for details.
To overcome this i downloaded mozilla-1.7.13 from the following location,
http://google-web-toolkit.googlecode.com/svn/tools/redist/mozilla/mozilla-1.7.13.tar.gz
I then updated the mozilla-hosted-browser.conf to point to my newly unziped mozilla dist.
When i retried to launch the GWT hosted browser i now got the following,
** Unable to load Mozilla for hosted mode **
java.lang.UnsatisfiedLinkError: /
/mozilla-1.7.13/libxpcom.so: libstdc++.so.5:
cannot open shared object file: No such file or directory
source: http://whatwouldnickdo.com/wordpress/99/unable-to-load-mozilla-for-hosted-mode-gwt-ubuntu-810-linux/
The key to troubleshooting the problem is in the second line, libstdc++.so.5 to be exact. It can’t find this C++ library. Turns out the hosted browser needs libstdc++5, but the version currently installed on my 8.10 system is libstdc++6. So you can either:
I had trouble installing the libstdc++5 using sudo apt-get install libstdc++5
So instead i did the following,
# wget http://ftp.egr.msu.edu/debian/pool/main/g/gcc-3.3/libstdc%2b%2b5_3.3.6-20_i386.deb
# dpkg-deb -x libstdc++5_3.3.6-20_i386.deb libstdc++5
# cp -p libstdc++5/usr/lib/libstdc++.so.5.0.7 /usr/lib
# cp -p libstdc++5/usr/lib/libstdc++.so.5 /usr/lib
This solved the problem!
** Unable to find a usable Mozilla install **
You may specify one in mozilla-hosted-browser.conf, see comments in the file for details.
To overcome this i downloaded mozilla-1.7.13 from the following location,
http://google-web-toolkit.googlecode.com/svn/tools/redist/mozilla/mozilla-1.7.13.tar.gz
I then updated the mozilla-hosted-browser.conf to point to my newly unziped mozilla dist.
When i retried to launch the GWT hosted browser i now got the following,
** Unable to load Mozilla for hosted mode **
java.lang.UnsatisfiedLinkError: /
/mozilla-1.7.13/libxpcom.so: libstdc++.so.5:
cannot open shared object file: No such file or directory
source: http://whatwouldnickdo.com/wordpress/99/unable-to-load-mozilla-for-hosted-mode-gwt-ubuntu-810-linux/
The key to troubleshooting the problem is in the second line, libstdc++.so.5 to be exact. It can’t find this C++ library. Turns out the hosted browser needs libstdc++5, but the version currently installed on my 8.10 system is libstdc++6. So you can either:
I had trouble installing the libstdc++5 using sudo apt-get install libstdc++5
So instead i did the following,
# wget http://ftp.egr.msu.edu/debian/pool/main/g/gcc-3.3/libstdc%2b%2b5_3.3.6-20_i386.deb
# dpkg-deb -x libstdc++5_3.3.6-20_i386.deb libstdc++5
# cp -p libstdc++5/usr/lib/libstdc++.so.5.0.7 /usr/lib
# cp -p libstdc++5/usr/lib/libstdc++.so.5 /usr/lib
This solved the problem!
Subscribe to:
Posts (Atom)