Wednesday, May 30, 2012

Moved!!

As much as i loved Posterous, with the Twitter aquisition, i dont foresee them improving the platform going forward. Because of that, i have decided to move my blog to wordpress. (yea yea, i'm trying out all the different blogging platforms -> started with Blogger, then Posterous and now Wordpress).

The new url is - http://roshanpaiva.wordpress.com/

Thanks Posterous for a good run.

Sunday, April 3, 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...

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!

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.


<#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

Search This Blog