<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;C0AEQ3g4eCp7ImA9WhRaFE0.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557</id><updated>2012-02-16T09:15:02.630-05:00</updated><category term="Tools" /><category term="Software" /><category term="Ubuntu" /><category term="OpenLaszlo" /><category term="Java" /><category term="Ruby" /><category term="Web Service" /><category term="Framework" /><category term="Linux" /><category term="Programming" /><category term="Web" /><title>Atif's Technology Musings</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.khanspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.khanspot.com/" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/khanspot/ERWw" /><feedburner:info uri="khanspot/erww" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CUEASXo4eyp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-8248602747929567776</id><published>2009-04-28T09:52:00.000-04:00</published><updated>2011-11-25T12:54:08.433-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T12:54:08.433-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Web" /><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><category scheme="http://www.blogger.com/atom/ns#" term="Framework" /><title>Is RIFE dead?</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LYLwyY20UVLRt-1LccmU8fTz-2s/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LYLwyY20UVLRt-1LccmU8fTz-2s/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LYLwyY20UVLRt-1LccmU8fTz-2s/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LYLwyY20UVLRt-1LccmU8fTz-2s/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;I wrote a &lt;a title="Impressions of RIFE framework" href="http://www.khanspot.com/2007/04/10/impression-of-rife-web-framework/"&gt;blog entry&lt;/a&gt; in April 2007 about RIFE. It has been 2 years since I wrote that entry. I had mentioned that RIFE was lacking in documention and the learning curve was pretty steeep. That was one of the resons why I decided not to investigate further. Geert tried to calrify some of the questions I had, but that didn't really remove all the doubts I had. I know that Geert has moved on to bigger and better things. The framework seems to be dead now as there hasn't been any new releases since 2007. This goes to show that with too much complexity, it is very difficult to build a community that can sustain the project beyond the original founders. It was a framework built on some very good concepts and I am sad to see it go. I do see some nightly snapshots, but no new releases. Is RIFE really dead?&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense#link--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-8248602747929567776?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/tpk_lR3t_-A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/8248602747929567776/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2009/04/is-rife-dead.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/8248602747929567776?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/8248602747929567776?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/tpk_lR3t_-A/is-rife-dead.html" title="Is RIFE dead?" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.khanspot.com/2009/04/is-rife-dead.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEASXo5cCp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-543797951397777966</id><published>2009-01-17T13:24:00.000-05:00</published><updated>2011-11-25T12:54:08.428-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T12:54:08.428-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu" /><title>KDE free and happy</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/61rBu3QRbp9NUOBZv-MVi6jstBo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/61rBu3QRbp9NUOBZv-MVi6jstBo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/61rBu3QRbp9NUOBZv-MVi6jstBo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/61rBu3QRbp9NUOBZv-MVi6jstBo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;I wrote in a previous post from October 20008 that I was very unhappy with the direction of KDE. The Kubuntu Intrepid was about to be released with KDE 4 as the default desktop. I got a lot of responses saying that I could still continue using KDE 3.x or I should switch to another distro like OpenSuse. Neither of those were really feasible options as I didn't want to be stuck on KDE 3.x and switching distro was even more a radical change.&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br/&gt;When Kubuntu Intrepid released, I downloaded it and gave it a try. I knew immediately that I could no longer use it as my desktop. It was sluggish and not very user friendly. I promptly switched to Ubuntu Intrepid with Gnome desktop. I must admit that Gnome implementation in Ubuntu feels a lot more tightly integrated than KDE was in Kubuntu.&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense#link--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br/&gt;I did have to adjust myself to Gnome initially. As an example, I was very fond of Superkaramba on KDE. Gnome does have comparable desklet and screenlet implememtations. But they just do not seem as seemless as Superkaramba. So, I decided to stick with regular panel applets and I must admit that I somehow like them better than full fledged Superkaramba widgets. This could be true with Gnome in general as everything seems intuitive and simple. Gnome doesn't try to emulate Windoze like KDE. I got the native drivers for the Nvidia card installed and now have Compiz enabled. So, now I have the simplicity of Gnome with added 3D effects. It's not a scientific observation, but the memory management also seems better on Gnome than KDE.&lt;br/&gt;&lt;br/&gt;The moral of the story is that I am &lt;strong&gt;KDE free and happy&lt;/strong&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-543797951397777966?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/Ybvega9pG0Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/543797951397777966/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2009/01/kde-free-and-happy.html#comment-form" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/543797951397777966?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/543797951397777966?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/Ybvega9pG0Y/kde-free-and-happy.html" title="KDE free and happy" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>5</thr:total><feedburner:origLink>http://www.khanspot.com/2009/01/kde-free-and-happy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEASXo5fyp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-3473403401049952503</id><published>2008-10-19T09:04:00.000-04:00</published><updated>2011-11-25T12:54:08.427-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T12:54:08.427-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Linux" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu" /><title>Is this the end of KDE for me?</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/iC3Ztpeq86F7Obd50xl6WLkVrbA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/iC3Ztpeq86F7Obd50xl6WLkVrbA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/iC3Ztpeq86F7Obd50xl6WLkVrbA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/iC3Ztpeq86F7Obd50xl6WLkVrbA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;I have been a linux user since early days. In fact for home use I only have Linux and Mac OSX. I have used RedHat, Fedora and Mandrake/Mandriva in the past. Then I discovered Ubuntu few years back and it’s been no looking back. I have used both Ubuntu and Kubuntu extensively. But my destop of choice for home computer has been Kubuntu as I have alwyas felt that KDE has better tooling than GNOME. I like the simplicity of GNOME, but KDE always had more applications.&lt;br/&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;br/&gt;I love how KDE evloved and matured in 3.x versions. But, then I think the focus shifted to make it look and behave more like Windows (especially Vista with Plasma L&amp;amp;;) for version 4. That’s where my frustration with KDE comes from. I have given it a try a number of times since early beta days and I have been disappointed every single time. My main frustrations have been:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;	&lt;li&gt;It’s horribly slow compared to 3.x versions.&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;It takes more memory to run. In fact it pretty much takes same memory as you would require for Windows XP.&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;The Desktop is ugly. I am pretty happy some simple icons on the desktop. I don’t need fancy effects. There is a value in simplicty and I wish KDE devleopers learnt this from Mac OSX.&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;I have been using Superkaramba for a long time and love it compared to KDE applets. In version 4, these are replaced by widgets. It just seems like a step in wrong direction as it has fewer widgets and they are horrible.&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;Every time I tried to customize the desktop and L&amp;amp;F, it ended up screwing up everything.&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;The main KDE menu is almost unusable. I don’t understand how it is more user friendly&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;Same applies to Dolphin file manager. I have Dolphin on KDE 3.x as well, but again there isn’t anything mind blowing.&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;The release of Ubuntu 8.10 is almost here and Kubuntu is going to make KDE 4 as the default desktop. I am seriously considering switching to GNOME or Xfce going forward. The purpose of a desktop is make the life easier for a user and that has not been my impression of KDE 4. May be GNOME was right all along in the philosophy of keeping things simple and usable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-3473403401049952503?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/ld2xCwbkggU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/3473403401049952503/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2008/10/is-this-end-of-kde-for-me.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/3473403401049952503?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/3473403401049952503?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/ld2xCwbkggU/is-this-end-of-kde-for-me.html" title="Is this the end of KDE for me?" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>6</thr:total><feedburner:origLink>http://www.khanspot.com/2008/10/is-this-end-of-kde-for-me.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAGSHkyfyp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-3128976146008295306</id><published>2008-01-01T15:22:00.000-05:00</published><updated>2011-11-25T13:12:09.797-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T13:12:09.797-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Web Service" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><title>POX (Plain Old XML) JAX-WS service using CXF and Spring Configuration</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/asz-5bgLhNavJBnVz4hPxIvnnZA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/asz-5bgLhNavJBnVz4hPxIvnnZA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/asz-5bgLhNavJBnVz4hPxIvnnZA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/asz-5bgLhNavJBnVz4hPxIvnnZA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
The new and upcoming &lt;a href="http://incubator.apache.org/cxf/"&gt;Apache CXF&lt;/a&gt; framework is quickly gaining steam and rightfully so. It's very intuitive, simple to use and functional. Some of it comes from the fact the its roots are in popular &lt;a href="http://xfire.codehaus.org/"&gt;XFire&lt;/a&gt; and &lt;a href="http://celtix.objectweb.org/"&gt;Celtix&lt;/a&gt; frameworks. It's still in the incubation stage at Apache but the current releases are pretty stable. The documentation is not complete right now, but it's improving as well.&lt;br /&gt;
&lt;br /&gt;
One of the cases where I found the document and example lacking is the POX (Plain Old XML) service using JAX-WS Provider model and configuring it using Spring. The examples are mainly focussed towards configuring and starting the service from Java code. So, I created this simple EchoService example that shows step by step how to do it.&lt;br /&gt;
&lt;br /&gt;
First step is to create the service Java class that will echo the incoming XML message back to the requester. We will also annotate this class using the JAX-WS annotation to mark it as a web service provider and the message type to be the payload. So, the CXF implementation knows that it should only deliver the message payload to the service class. The CXF binding layer processes any binding level wrappers and headers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;
/**
 * EchoService.java Jan 1, 2008
 */
package test.jws.provider;

import javax.xml.transform.dom.DOMSource;
import javax.xml.ws.Provider;
import javax.xml.ws.Service;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;

/**
 * &amp;lt;p&amp;gt;
 * A sample EchoService POX service using the JAX-WS Provider interface.
 * &amp;lt;/p&amp;gt;
 * @author Atif Khan
 * @since Jan 1, 2008
 */
@WebServiceProvider()
@ServiceMode(value = Service.Mode.PAYLOAD)
public class EchoService
  implements Provider&amp;lt;DOMSource&amp;gt;
{

  /**
   * &amp;lt;p&amp;gt;
   * Process the incoming DOM request and echo it back.
   * &amp;lt;/p&amp;gt;
   * @param request
   *          DOMsource representing the request source
   * @return DOMsource representing the response source
   * @see javax.xml.ws.Provider#invoke(java.lang.Object)
   */
  public DOMSource invoke( DOMSource request )
  {
    System.out.println( "EchoService received the POX request." );

    return request;
  }

}

&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
In the above class we specified that we want to receive the incoming XML message as DOM. You can change it to use any concrete subclass of the &lt;code&gt;Source &lt;/code&gt; interface (e.g. SAXSource).&lt;br /&gt;
&lt;br /&gt;
Next step is to create the Spring configuration. For simplicity sake, let's keep the name of this file to applicationContext.xml. Here is an example:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;
&amp;lt;beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:jaxws="http://cxf.apache.org/jaxws"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"&amp;gt;

  &amp;lt;import resource="classpath:META-INF/cxf/cxf.xml" /&amp;gt;
  &amp;lt;import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /&amp;gt;
  &amp;lt;import resource="classpath:META-INF/cxf/cxf-servlet.xml" /&amp;gt;
  &amp;lt;import resource="classpath:META-INF/cxf/cxf-extension-xml.xml" /&amp;gt;
  &amp;lt;import resource="classpath:META-INF/cxf/cxf-extension-http-binding.xml" /&amp;gt;

  &amp;lt;jaxws:endpoint id="echoService" implementor="test.jws.provider.EchoService"
    address="/echo" bindingUri="http://www.w3.org/2004/08/wsdl/http"&amp;gt;
    &amp;lt;jaxws:serviceFactory&amp;gt;
      &amp;lt;bean class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean"&amp;gt;
        &amp;lt;property name="wrapped" value="true" /&amp;gt;
      &amp;lt;/bean&amp;gt;
    &amp;lt;/jaxws:serviceFactory&amp;gt;
  &amp;lt;/jaxws:endpoint&amp;gt;
  
&amp;lt;/beans&amp;gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
The key things to notice in the above XML are:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
&lt;li&gt;Address of the service (/echo).&lt;/li&gt;
&lt;li&gt;Binding URI (http://www.w3.org/2004/08/wsdl/http). This is really important. This is what tells CXF that this service is going to be simple XML over HTTP.&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;Declaration of service factor where we indicate that the messages are going to be of wrapped nature&lt;/li&gt;
&lt;/ul&gt;
All that's remaining is to declare the Spring context listener in your web.xml for the web application that this service is going to be a part of. Here is an example of the web.xml:&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;
&amp;lt;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"&amp;gt;

  &amp;lt;listener&amp;gt;
    &amp;lt;listener-class&amp;gt;org.springframework.web.context.ContextLoaderListener&amp;lt;/listener-class&amp;gt;
  &amp;lt;/listener&amp;gt;

  &amp;lt;servlet&amp;gt;
    &amp;lt;display-name&amp;gt;CXF Servlet&amp;lt;/display-name&amp;gt;
    &amp;lt;servlet-name&amp;gt;CXFServlet&amp;lt;/servlet-name&amp;gt;
    &amp;lt;servlet-class&amp;gt;org.apache.cxf.transport.servlet.CXFServlet&amp;lt;/servlet-class&amp;gt;
    &amp;lt;load-on-startup&amp;gt;1&amp;lt;/load-on-startup&amp;gt;
  &amp;lt;/servlet&amp;gt;

  &amp;lt;servlet-mapping&amp;gt;
    &amp;lt;servlet-name&amp;gt;CXFServlet&amp;lt;/servlet-name&amp;gt;
    &amp;lt;url-pattern&amp;gt;/*&amp;lt;/url-pattern&amp;gt;
  &amp;lt;/servlet-mapping&amp;gt;
&amp;lt;/web-app&amp;gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
As you can see that there is nothing special here at all. It's all standard Spring configuration using the context loader listener. Also, we are declaring the CXF servlet here and mapping it to &lt;code&gt;/*&lt;/code&gt; to make all the requests to this web application go through the CXF servlet.&lt;br /&gt;
&lt;br /&gt;
Now all you have to do is to package this web application and deploy it in your favorite application server. You should be able to access the Echo Service we wrote at http://localhost:8080/AppName/echo (you will have to adjust the port and application name in the URL). Now HTTP post a XML to this URL and you should get the request echoed back to you.&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;Maven POM&lt;/strong&gt;&lt;br /&gt;
I think it's more useful to also specify the Maven POM that contains all the dependencies as well to build the run this example. Please keep in mind that some of the dependencies here may not be required anymore as I was playing around with a lot of CXF functionalities.&lt;br /&gt;
&lt;pre style="background-color: #eeeeee; border: 1px dashed #999999; color: black; font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;"&gt;&lt;code&gt;
 &amp;lt; ?xml version="1.0" encoding="UTF-8"?&amp;gt;
 &amp;lt;project&amp;gt;
   &amp;lt;modelversion&amp;gt;4.0.0&amp;lt;/modelversion&amp;gt;
   &amp;lt;groupid&amp;gt;CXFTest&amp;lt;/groupid&amp;gt;
   &amp;lt;artifactid&amp;gt;CXFTest&amp;lt;/artifactid&amp;gt;
   &amp;lt;packaging&amp;gt;war&amp;lt;/packaging&amp;gt;
   &amp;lt;version&amp;gt;0.0.1&amp;lt;/version&amp;gt;
   &amp;lt;repositories&amp;gt;
     &amp;lt;repository&amp;gt;
       &amp;lt;id&amp;gt;apache.incubating.releases&amp;lt;/id&amp;gt;
       &amp;lt;name&amp;gt;
         Apache Incubating Release Distribution Repository  
       &amp;lt;/name&amp;gt;
       &amp;lt;url&amp;gt;
         http://people.apache.org/repo/m2-incubating-repository  
       &amp;lt;/url&amp;gt;
     &amp;lt;/repository&amp;gt;
   &amp;lt;/repositories&amp;gt;
   &amp;lt;properties&amp;gt;
     &amp;lt;spring .version&amp;gt;2.0.7&amp;lt;/spring&amp;gt;
     &amp;lt;cxf .version&amp;gt;2.0.3-incubator&amp;lt;/cxf&amp;gt;
   &amp;lt;/properties&amp;gt;
   &amp;lt;dependencies&amp;gt;
     &amp;lt;!--
     Spring is directly included to override the version 2.0.4 cxf 
     brings in its own dependencies.  This is not strictly necessary but
     just being shown to let you know how this is done.
     --&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.springframework&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;spring-core&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${spring.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.springframework&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;spring-beans&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${spring.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.springframework&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;spring-context&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${spring.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.springframework&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;spring-web&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${spring.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;log4j&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;log4j&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;1.2.14&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;!-- Depending on your requirements you may need more or less modules from cxf --&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.apache.cxf&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;cxf-rt-core&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${cxf.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.apache.cxf&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;cxf-rt-frontend-simple&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${cxf.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.apache.cxf&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;cxf-rt-frontend-jaxws&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${cxf.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.apache.cxf&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;cxf-rt-databinding-aegis&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${cxf.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.apache.cxf&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;cxf-rt-transports-local&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${cxf.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.apache.cxf&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;cxf-rt-transports-http&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${cxf.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.apache.cxf&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;cxf-rt-transports-http-jetty&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${cxf.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.apache.cxf&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;cxf-rt-transports-jms&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${cxf.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.apache.cxf&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;cxf-rt-management&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${cxf.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.apache.cxf&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;cxf-common-utilities&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${cxf.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.mortbay.jetty&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;jetty&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;6.1.5&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;junit&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;junit&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;3.8.2&amp;lt;/version&amp;gt;
       &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
     &amp;lt;/dependency&amp;gt;
     &amp;lt;dependency&amp;gt;
       &amp;lt;groupid&amp;gt;org.apache.cxf&amp;lt;/groupid&amp;gt;
       &amp;lt;artifactid&amp;gt;cxf-rt-bindings-http&amp;lt;/artifactid&amp;gt;
       &amp;lt;version&amp;gt;${cxf.version}&amp;lt;/version&amp;gt;
     &amp;lt;/dependency&amp;gt;
   &amp;lt;/dependencies&amp;gt;
   &amp;lt;build&amp;gt;
     &amp;lt;plugins&amp;gt;
       &amp;lt;plugin&amp;gt;
         &amp;lt;artifactid&amp;gt;maven-compiler-plugin&amp;lt;/artifactid&amp;gt;
         &amp;lt;configuration&amp;gt;
           &amp;lt;source&amp;gt;1.6&amp;lt;/source&amp;gt;
           &amp;lt;target&amp;gt;1.6&amp;lt;/target&amp;gt;
         &amp;lt;/configuration&amp;gt;
       &amp;lt;/plugin&amp;gt;
     &amp;lt;/plugins&amp;gt;
   &amp;lt;/build&amp;gt;
 &amp;lt;/project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;
Here is a list of all the jar files that ended up being in the war file from the build using above Maven POM. Again, some of the jars here may not be needed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;ol class="dp-xml" start="1" style="background-color: white; color: #2b91af; font-family: 'Courier New', Courier, mono; font-size: 12px; line-height: 1.5em; list-style-type: none; margin-bottom: 1px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: -webkit-auto;"&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;XmlSchema-1.3.2.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jaxb-impl-2.0.5.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;aopalliance-1.0.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jaxb-xjc-2.0.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;avalon-framework-4.1.3.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jaxen-1.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;commons-lang-2.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jaxws-api-2.0.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;commons-logging-1.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jdom-1.0.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-api-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jetty-6.1.5.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-common-schemas-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jetty-util-6.1.5.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-common-utilities-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;jra-1.0-alpha-4.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-bindings-http-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;log4j-1.2.14.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-bindings-soap-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;logkit-1.0.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-bindings-xml-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;neethi-2.0.2.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-core-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;saaj-api-1.3.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-databinding-aegis-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;saaj-impl-1.3.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-databinding-jaxb-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;servlet-api-2.3.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-frontend-jaxws-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;servlet-api-2.5-6.1.5.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-frontend-simple-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;slf4j-api-1.3.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-management-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;slf4j-jdk14-1.3.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-transports-http-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;spring-beans-2.0.7.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-transports-http-jetty-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;spring-context-2.0.7.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-transports-jms-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;spring-core-2.0.7.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-rt-transports-local-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;spring-web-2.0.7.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;cxf-tools-common-2.0.3-incubator.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stax-api-1.0.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;geronimo-activation_1.1_spec-1.0-M1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;stax-utils-20060502.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;geronimo-annotation_1.0_spec-1.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;velocity-1.4.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;geronimo-javamail_1.4_spec-1.0-M1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;velocity-dep-1.4.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;geronimo-jms_1.1_spec-1.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wsdl4j-1.6.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;geronimo-servlet_2.5_spec-1.1-M1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wstx-asl-3.2.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="" style="border-bottom-width: 0px; border-color: initial; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;geronimo-ws-metadata_2.0_spec-1.1.1.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xml-apis-1.3.02.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li class="alt" style="background-color: #f8f8f8; border-bottom-width: 0px; border-color: initial; border-left-color: rgb(108, 226, 108); border-left-style: solid; border-left-width: 0px; border-right-width: 0px; border-style: initial; border-top-width: 0px; line-height: 14px; padding-left: 10px;"&gt;&lt;span style="color: black;"&gt;jaxb-api-2.0.jar&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xml-resolver-1.2.jar&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-3128976146008295306?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/7tWNdf1mwHE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/3128976146008295306/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2008/01/pox-plain-old-xml-jax-ws-service-using.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/3128976146008295306?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/3128976146008295306?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/7tWNdf1mwHE/pox-plain-old-xml-jax-ws-service-using.html" title="POX (Plain Old XML) JAX-WS service using CXF and Spring Configuration" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.khanspot.com/2008/01/pox-plain-old-xml-jax-ws-service-using.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8HSX08eip7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-8174679705120174450</id><published>2007-04-16T14:46:00.000-04:00</published><updated>2011-11-25T13:13:58.372-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T13:13:58.372-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><title>Multi-valued Reversible enum in Java</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/KznjTaAScaqS_5VIcZOlQYIvmyA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/KznjTaAScaqS_5VIcZOlQYIvmyA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/KznjTaAScaqS_5VIcZOlQYIvmyA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/KznjTaAScaqS_5VIcZOlQYIvmyA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
Sometime back I proposed a reversible enum pattern in my &lt;a href="http://www.khanspot.com/2006/12/04/java-wish-a-reversible-enum/"&gt;&lt;strong&gt;post&lt;/strong&gt;&lt;/a&gt;. One thing missing from that implementation was the ability to successfully lookup the enum constants in cases where enum constants can have multiple values. To accomplish this, I utilized another feature introduced in Java 5, namely &lt;strong&gt;varargs&lt;/strong&gt; or variable argument support. This way while building the key for the map, we utilize all the values for a constant and use the varargs in the reverse() method of the enum.&lt;br /&gt;
&lt;br /&gt;
Let's look at the interface &lt;code&gt;MultiValueReversibleEnum&lt;/code&gt; that denotes an enum as reversible and that an enum should implement.&lt;br /&gt;
&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
/**
 * &amp;lt;p&amp;gt;
 * This interface defines the method that the {@link Enum} implementations
 * should implement if they want to have the reversible lookup functionality and
 * define multiple values for each enum constant. i.e. allow the lookup using
 * the codes for the {@link Enum} constants.
 * &amp;lt;/p&amp;gt;
 * @param &amp;lt;E&amp;gt;
 *          The value of Enum constant
 * @param &amp;lt;V&amp;gt;
 *          The Enum constant to return from lookup
 *          &amp;lt;/p&amp;gt;
 * @author Atif Khan
 * @since Mar 26, 2007
 */
public interface MultiValueReversibleEnum&amp;lt;E, V&amp;gt;
{
  /**
   * &amp;lt;p&amp;gt;
   * Return the values/codes of the enum constant. It should return the
   * values/codes in the same order as defined in the enum.
   * &amp;lt;/p&amp;gt;
   * @return value
   */
  public E[] getAllCodes();

  /**
   * &amp;lt;p&amp;gt;
   * Get the {@link Enum} constant by looking up the code in the reverse enum
   * map.
   * &amp;lt;/p&amp;gt;
   * @param code
   * @return V - The enum constant
   */
  public V reverse( E ... code );

}

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
The things to notice in this interface are:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
&lt;li&gt;&lt;code&gt;getAllCode()&lt;/code&gt; method - It returns an array of all the possible values for an enum constant&lt;/li&gt;
&lt;br /&gt;
&lt;li&gt;&lt;code&gt;reverse( E ... code )&lt;/code&gt; method - You can see the usage of varargs here. You basically give all the possible values for the enum constant you want to lookup in the right order&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;center&gt;&lt;pre&gt;&lt;/pre&gt;
&lt;/center&gt;&lt;br /&gt;
Next we need to look at the map &lt;code&gt;MultiValueReverseEnumMap&lt;/code&gt; that will store the enum constants and their value mappings.&lt;br /&gt;
&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
import java.util.HashMap;
import java.util.Map;

/**
 * &amp;lt;p&amp;gt;
 * A utility class that provides a reverse map of the {@link Enum} that is keyed
 * by the values of the {@link Enum} constant. &amp;lt;br/&amp;gt; This map implementation
 * should be used with the enums implementing the
 * {@link MultiValueReversibleEnum} interface.
 * &amp;lt;/p&amp;gt;
 * @author Atif Khan
 * @param &amp;lt;K&amp;gt;
 *          The class type of the values of the enum constant
 * @param &amp;lt;V&amp;gt;
 *          The Enum for which the map is being created
 * @since Mar 26, 2007
 */
public class MultiValueReverseEnumMap&amp;lt;K, V extends MultiValueReversibleEnum&amp;lt;K, V&amp;gt;&amp;gt;
{
  private final Map&amp;lt;String, V&amp;gt; mReverseMap = new HashMap&amp;lt;String, V&amp;gt;();

  /**
   * &amp;lt;p&amp;gt;
   * Create a new instance of ReverseEnumMap.
   * &amp;lt;/p&amp;gt;
   * @param valueType
   */
  public MultiValueReverseEnumMap( final Class&amp;lt;V&amp;gt; valueType )
  {
    for( final V v : valueType.getEnumConstants() ) {
      mReverseMap.put( buildKey( v.getAllCodes() ), v );
    }
  }

  /**
   * &amp;lt;p&amp;gt;
   * Perform the reverse lookup for the given enum values and return the enum
   * constant.
   * &amp;lt;/p&amp;gt;
   * @param enumValues
   * @return enum constant
   */
  public V get( final K ... enumValues )
  {
    return mReverseMap.get( buildKey( enumValues ) );
  }

  /**
   * &amp;lt;p&amp;gt;
   * Build the key for the entry in the map using the array of values supplied.
   * &amp;lt;/p&amp;gt;
   * @param values
   * @return key for the entry
   */
  private String buildKey( final K[] values )
  {
    final StringBuilder valueBuff = new StringBuilder( values.length * 5 );
    for( final K value : values ) {
      valueBuff.append( value.hashCode() );
    }

    return valueBuff.toString();
  }
}

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
As you can see, the &lt;code&gt;getAllCodes()&lt;/code&gt; defined in the interface is used to build the key for the map. Also, the &lt;code&gt;get( final K ... enumValues )&lt;/code&gt; method that looks up the value in map uses varargs.&lt;br /&gt;
&lt;br /&gt;
&lt;center&gt;&lt;pre&gt;&lt;/pre&gt;
&lt;/center&gt;&lt;br /&gt;
Now it's time to glue everything together and see how to use the interface and map to build a multi-valued reversible enum. We will write a test class &lt;code&gt;MultiValuedEnumTest&lt;/code&gt;.&lt;br /&gt;
&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
import com.ihg.dec.framework.commons.utils.enums.MultiValueReverseEnumMap;
import com.ihg.dec.framework.commons.utils.enums.MultiValueReversibleEnum;

/**
 * &amp;lt;p&amp;gt;
 * A test class for multi-values enum that implements the
 * &amp;lt;code&amp;gt;MultiValueReversibleEnum&amp;lt;/code&amp;gt; interface and uses the
 * &amp;lt;code&amp;gt;MultiValueReverseEnumMap&amp;lt;/code&amp;gt;.
 * &amp;lt;/p&amp;gt;
 * @author Atif Khan
 * @since Apr 16, 2007
 */
public class MultiValuedEnumTest
{
  enum TestEnum
    implements MultiValueReversibleEnum&amp;lt;Integer, TestEnum&amp;gt;
  {

    ONE(1, 11),
    TWO(2, 22);

    private int mCode1;
    private int mCode2;

    private static final MultiValueReverseEnumMap&amp;lt;Integer, TestEnum&amp;gt; mMap = new MultiValueReverseEnumMap&amp;lt;Integer, TestEnum&amp;gt;(
      TestEnum.class );

    /**
     * Create a new instance of TestEnum. &amp;lt;p/&amp;gt;
     * @param code1
     * @param code2
     */
    private TestEnum( final int code1, final int code2 )
    {
      mCode1 = code1;
      mCode2 = code2;
    }

    /**
     * Get the value of &amp;lt;code&amp;gt;code1&amp;lt;/code&amp;gt;. &amp;lt;p/&amp;gt;
     * @return Returns the code1.
     */
    public int getCode1()
    {
      return mCode1;
    }

    /**
     * Get the value of &amp;lt;code&amp;gt;code2&amp;lt;/code&amp;gt;. &amp;lt;p/&amp;gt;
     * @return Returns the code2.
     */
    public int getCode2()
    {
      return mCode2;
    }

    /**
     * Get an instance of TestEnum
     * @return TestEnum constant
     */
    public static TestEnum getInstance()
    {
      return TestEnum.ONE;
    }

    /**
     * @see com.ihg.dec.framework.commons.utils.enums.MultiValueReversibleEnum#getAllCodes()
     */
    public Integer[] getAllCodes()
    {
      return new Integer[] {
        getCode1(), getCode2()
      };
    }

    /**
     * @see com.ihg.dec.framework.commons.utils.enums.MultiValueReversibleEnum#reverse(E[])
     */
    public TestEnum reverse( final Integer ... code )
    {
      return mMap.get( code );
    }
  }

  /**
   * &amp;lt;p&amp;gt;
   * The main method to execute this class.
   * &amp;lt;/p&amp;gt;
   * @param args
   */
  public static void main( final String[] args )
  {
    System.out.println(&amp;quot;Reverse for [1, 11]: &amp;quot; + TestMultiValueEnum.getInstance().reverse( 1, 11 ) );
    System.out.println(&amp;quot;Reverse for [2, 22]: &amp;quot; +  TestMultiValueEnum.getInstance().reverse( 2, 22 ) );
  }

}

&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
If you run this class, you should see following getting printed:&lt;br /&gt;
&lt;pre&gt;
Reverse for [1, 11]: ONE
Reverse for [2, 22]: TWO&lt;/pre&gt;
&lt;br /&gt;
It's all very simple and straightforward. If you have any suggestions or feedback to improve this, please leave me a comment.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-8174679705120174450?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/dX6shpyIyxg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/8174679705120174450/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2007/04/multi-valued-reversible-enum-in-java.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/8174679705120174450?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/8174679705120174450?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/dX6shpyIyxg/multi-valued-reversible-enum-in-java.html" title="Multi-valued Reversible enum in Java" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.khanspot.com/2007/04/multi-valued-reversible-enum-in-java.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEASXo6cSp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-1969496658696209303</id><published>2007-04-10T11:05:00.000-04:00</published><updated>2011-11-25T12:54:08.419-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T12:54:08.419-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Web" /><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><title>Impression of RIFE Web Framework</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/yUWNRmP4Y1bhBWa_1bpB2kYgjYk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yUWNRmP4Y1bhBWa_1bpB2kYgjYk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/yUWNRmP4Y1bhBWa_1bpB2kYgjYk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yUWNRmP4Y1bhBWa_1bpB2kYgjYk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;I have been spending time on and off looking at various web frameworks available for a little more than a year. A lot of this has to do with keeping track of what's going on in the web framework arena and keep in sync with the technologies. Another focus of mine is to see how the new (at least for me) frameworks affect the productivity of a developer.&lt;br/&gt;&lt;br/&gt;I first looked at &lt;a href="http://www.rifers.org"&gt;RIFE&lt;/a&gt; last year and I have been very impressed by the concepts.The developers of RIFE, Geert Bevin and others have been very helpful when I had some questions. I was even able to get answers on the IRC channel for RIFE. It was not until recently that I tried to write an application using RIFE that I really got a feel of it.&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br/&gt;Here are some of the good and bad that I encountered:&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;	&lt;li&gt;A complete framework. It includes basic web framework, ORM, Content Management, Validations, Templates etc.&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;Good support from developers&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;A nice quick start application to get you running quickly&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;Good support for constraints for adding validations&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;Continuations - ability to pause, rewind, jump through transaction steps&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;	&lt;li&gt;Templates are really weird to work with. The syntax for the templates really did me. It is not really designer friendly like Tapestry or Wicket&lt;/li&gt;	&lt;br/&gt;        &lt;li&gt;The concept of flowlink and datalink is just too verbose and not clear&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;Using annotation didn't do me any good as well for defining the flow and data links. There isn't enough documentation for annotations&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;The only way for form validations I could find was to define the a MetaData class equivalent to the domain object representing the form and define the validations in there. This just seems like way too much of work for simple validations.&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;I could not figure out how to customize the error messages for form validations&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;In the end, I feel that it's the lack of documentation that prevented me from really exploring it. I know Geert is a very sharp guy and if he ever gets to read my blog, I welcome his comments. I think the learning curve is too much for RIFE and lack of documentation adds to it and I am not sure if the return is proportional to the effort compared to other frameworks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-1969496658696209303?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/XR2CBmsb6x0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/1969496658696209303/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2007/04/impression-of-rife-web-framework.html#comment-form" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/1969496658696209303?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/1969496658696209303?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/XR2CBmsb6x0/impression-of-rife-web-framework.html" title="Impression of RIFE Web Framework" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>7</thr:total><feedburner:origLink>http://www.khanspot.com/2007/04/impression-of-rife-web-framework.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4ER34zeCp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-8676670373094782618</id><published>2007-03-27T12:50:00.000-04:00</published><updated>2011-11-25T13:15:06.080-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T13:15:06.080-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><title>A simple file based Ruby Database - KirbyBase</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/FuRPF5eTzujhA8aUkfcM8HE50oo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FuRPF5eTzujhA8aUkfcM8HE50oo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/FuRPF5eTzujhA8aUkfcM8HE50oo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/FuRPF5eTzujhA8aUkfcM8HE50oo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Have you ever been in a situation where you wanted to write a simple application for internal use that should be portable and completely self contained (including the database)? I am pretty sure you have. I had to do this recently for one of the simple reporting applications and I didn't really want to create a dependency on external database like MySQL or PostgreSQL. This application needed only 4 tables and the data in these table is never going to be large enough to warrant an extensive database system. I thought about putting the data in flat files and write the code to access it. But, then I found this really neat gem called &lt;a href="http://www.netpromi.com/kirbybase_ruby.html"&gt;KirbyBase&lt;/a&gt; that does exactly the same and little more.&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br/&gt;KirbyBase has some neat features that mirror the traditional RDBMS while still sticking to it's simple roots:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt; &lt;li&gt;Pure Ruby code&lt;/li&gt;&lt;br/&gt; &lt;li&gt;Data is kept in simple delimited files, allowing the modification in any text editor&lt;/li&gt;&lt;br/&gt; &lt;li&gt;It's not an in-memory DB. The data is actually stored on the disk&lt;/li&gt;&lt;br/&gt; &lt;li&gt;Allows various data types like String, Integer, Float, Boolean, Time, Date, DateTime, Memo, Blob, and YAML&lt;/li&gt;&lt;br/&gt; &lt;li&gt;Allows creating indexes on fields&lt;/li&gt;&lt;br/&gt; &lt;li&gt;Query results can be sorted&lt;/li&gt;&lt;br/&gt; &lt;li&gt;Allows to define one-many links between tables similar to joins in RDBMS&lt;/li&gt;&lt;br/&gt; &lt;li&gt;The columns can be defined with a formula, so the value will be calculated during insertion&lt;/li&gt;&lt;br/&gt; &lt;li&gt;Automatic lookup fields can be defined to lookup the related values from another table&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br/&gt;&lt;br/&gt;To give a simple example on how all this works, let's consider a scenario of Department and Employees. The simple requirements can be laid out as each employee has personal information and belongs to a department. Also, each department has a name and identifier and can contain multiple employees. Following is how the code going to look using KirbyBase. Please keep in mind that I have tried to write a reusable DAO, hence the code may look a little verbose. You can very well short circuit the whole thing and write very concise code.&lt;br/&gt;&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
#!/usr/bin/ruby -w

require 'rubygems'
require 'kirbybase'

class DAO
  attr_accessor(:employee_tbl, :department_tbl)

  #Initialize the KirbyBase engine
  def initialize
    db = KirbyBase.new(:local, nil, nil, '.')

    #Get/Create the Department table
    begin
      self.department_tbl = db.get_table(:department)
    rescue
      self.department_tbl = db.create_table(:department, :dept_name, {:DataType=&amp;gt;:String, :Key=&amp;gt;true, :Index=&amp;gt;1}, :employee, {:DataType=&amp;gt;:ResultSet, :Link_many=&amp;gt;[:recno, :employee, :dept_id]}) do &amp;#124;t&amp;#124;
        t.record_class = Department
      end
    end

    #Get/Create the Employee table
    begin
      self.employee_tbl = db.get_table(:employee)
    rescue
      self.employee_tbl = db.create_table(:employee, :dept_id, {:DataType=&amp;gt;:Integer, :Key=&amp;gt;true, :Index=&amp;gt;1}, :name, {:DataType=&amp;gt;:String, :Key=&amp;gt;true, :Index=&amp;gt;1}) do &amp;#124;t&amp;#124;
        t.record_class = Employee
      end
    end
  end

  #Get the department by name or if it does not exist, insert it 
  def get_department(name)
    dept = self.department_tbl.select_by_dept_name_index { &amp;#124;r&amp;#124; r.dept_name == name  }.first
    unless dept
      dept = Department.new do &amp;#124;x&amp;#124;
        x.dept_name = name
      end
      self.department_tbl.insert(dept)
      dept = self.department_tbl.select_by_dept_name_index { &amp;#124;r&amp;#124; r.dept_name == name  }.first
    end
    return dept
  end

  #Insert a new employee in table
  def insert_employee(dept, employee)
    employee_rs = self.employee_tbl.select_by_dept_id_name_index { &amp;#124;r&amp;#124; r.dept_id == dept.recno and r.name == employee.name }.first

    if employee_rs
     self.employee_tbl.update(employee) { &amp;#124;r&amp;#124; r.dept_id == dept.recno and r.name == employee.name }
    else
      employee_obj = Employee.new do &amp;#124;x&amp;#124;
        x.dept_id = dept.recno
        x.name = employee.name
      end
      self.employee_tbl.insert(employee_obj)
    end
    
  end

  #Get all employees for a department
  def get_all_employees(dept)
    employee_rs = self.employee_tbl.select_by_dept_id_name_index { &amp;#124;r&amp;#124; r.dept_id == dept.recno }.sort(:name)
  end
  
end

# The Department class
class Department
  attr_accessor(:recno, :dept_name, :employee)

  def Department.kb_create(recno, dept_name, employee)
    Department.new do &amp;#124;x&amp;#124;
      x.recno = recno
      x.dept_name = dept_name
      x.employee = employee
    end
  end

  def initialize(&amp;amp;block)
    instance_eval(&amp;amp;block)
  end
end

# The Employee class
class Employee
  attr_accessor(:recno, :dept_id, :name)

  def Employee.kb_create(recno, dept_id, name)
    Employee.new do &amp;#124;x&amp;#124;
      x.recno = recno
      x.dept_id = dept_id
      x.name = name
    end
  end

  def initialize(&amp;amp;block)
    instance_eval(&amp;amp;block)
  end
end

#Test everything now
dao = DAO.new
dept = dao.get_department(&amp;quot;IT&amp;quot;)

emp1 = Employee.new { &amp;#124;x&amp;#124; 
  x.name = &amp;quot;John&amp;quot;
}
dao.insert_employee(dept, emp1)

emp2 = Employee.new { &amp;#124;x&amp;#124;
  x.name = &amp;quot;Doe&amp;quot;
}
dao.insert_employee(dept, emp2)

#Get all empoyees in IT department and print
#Let's use the get_all_employees function first
puts &amp;quot;Employee in #{dept.dept_name} department&amp;quot;
dao.get_all_employees(dept).each { &amp;#124;x&amp;#124;
  puts x.name
}

#Alternatively we could use the dept.employee to get all employees
#Refresh the dept object
dept = dao.get_department(&amp;quot;IT&amp;quot;)
puts &amp;quot;Employee in #{dept.dept_name} department&amp;quot;
dept.employee.each { &amp;#124;x&amp;#124;
  puts x.name
}

&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;The output after execution will look like this:&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;Employee in IT department&lt;br/&gt;Doe&lt;br/&gt;John&lt;br/&gt;&lt;br/&gt;Employee in IT department&lt;br/&gt;John&lt;br/&gt;Doe&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;This should also generate 2 files in your current directory, department.tbl and employee.tbl. Let's look at content of these files now.&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;department.tbl&lt;/strong&gt;&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;000001|000000|Department|recno:Integer|dept_name:String:Key-&gt;true:Index-&gt;1|employee:ResultSet:Link_many-&gt;recno=employee.dept_id&lt;br/&gt;1|IT|kb_nil&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;&lt;strong&gt;employee.tbl&lt;/strong&gt;&lt;br/&gt;&lt;pre&gt;&lt;br/&gt;000002|000000|Employee|recno:Integer|dept_id:Integer:Key-&gt;true:Index-&gt;1|name:String:Key-&gt;true:Index-&gt;1&lt;br/&gt;1|1|John&lt;br/&gt;2|1|Doe&lt;br/&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;That's all there to it. It is very powerful and easy to work with library.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-8676670373094782618?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/jON0dAFc8MY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/8676670373094782618/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2007/03/simple-file-based-ruby-database.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/8676670373094782618?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/8676670373094782618?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/jON0dAFc8MY/simple-file-based-ruby-database.html" title="A simple file based Ruby Database - KirbyBase" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>4</thr:total><feedburner:origLink>http://www.khanspot.com/2007/03/simple-file-based-ruby-database.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEASXo6cCp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-1440874791265349016</id><published>2007-01-15T15:37:00.000-05:00</published><updated>2011-11-25T12:54:08.418-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T12:54:08.418-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="OpenLaszlo" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><title>Rich Web UI, Flash and DHTML - Bridge the gap</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/woMBDI4_PBpadrED_wYUiaTJpIc/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/woMBDI4_PBpadrED_wYUiaTJpIc/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/woMBDI4_PBpadrED_wYUiaTJpIc/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/woMBDI4_PBpadrED_wYUiaTJpIc/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;As the Web 2.0 grows in popularity, so does the urge for a lot of organizations to revamp their legacy applications and make them web based. Their are obvious benefits to this as the application becomes more accessible and requires less effort to deploy and maintain as there is single point of deployment and maintenance, the application server. What gets lost in all this excitement is the functionality that may have been available in the existing applications with rich user interfaces can not be easily replicated in the web application replicating it. By using the readily available javascript libraries and AJAX techniques some of this pain can be alleviated. It's not necessary that web applications may always lose the usability of functionality of the original application. In fact they can actually simplify some of the transactions if the user experience is considered from beginning during the rewrite process.&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br/&gt;I have been playing with &lt;a href="http://www.openlaszlo.org/"&gt;OpenLaszlo&lt;/a&gt; recently and it seems like a viable alternative for replacing the standalone applications with rich user interface. The most important feature of OpenLaszlo is the ability to write the user interface in XML based LZX language and export it to either Flash (.sfw) bytecode or DHTML. This functionality is only available with the upcoming Project Legals release of OpenLaszlo, which is already in beta.&lt;div style=”display:block;float:right;margin: 5px 5px 5px 5px;”&gt;&lt;pre&gt;&lt;!--adsense#small_button--&gt;&lt;/pre&gt;&lt;/div&gt; It has a rich set of components and event model that can all be used and programmed to using the LZX language. You can also write your own components using the LZX markup. The important thing to keep in mind is that OpenLaszlo is strictly a UI technology. You still need to get your data to display from the backend whether it being database of another middleware. This is where OpenLaszo excels. At the core it  can interact with a back end system using the RPC. Various RPC options include:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt;	&lt;li&gt;Java RPC&lt;/li&gt;	&lt;li&gt;SOAP&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;XML RPC&lt;/li&gt;&lt;br/&gt;	&lt;li&gt;XMLHttpRequest for Ajax&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;So, you can pretty much have you back end written in Java, PHP, Ruby or whatever you like as long as it supports either RPC, SOAP or  XMLHttpRequest. If you are wondering about what do you need on your server to run OpenLaszlo, it is basically a Java Servlet based web application. So, you do need the Java servlet container on your server to run OpenLaszlo. That shouldn't be an issue at all if you already use Java.&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br/&gt;&lt;br/&gt;If you do use Java on the server side and you have been trying to decide between various web application frameworks available and there are a ton of them :), OpenLaszlo can make your life a little simpler as you don't have to worry about the components or the component state management (JSF, Wicket, Tapestry etc). All you need is a solid framework that can preferably produce XML output and serve some data (Struts, WebWork, Spring MVC, RIFE) or any other similar framework and leave the UI aspect to OpenLaszlo. OpenLaszlo may not be suitable in all the cases, but it is worth a look if you want a web application with the look and feel and usability of a desktop application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-1440874791265349016?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/IaCAmaAgX4E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/1440874791265349016/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2007/01/rich-web-ui-flash-and-dhtml-bridge-gap.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/1440874791265349016?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/1440874791265349016?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/IaCAmaAgX4E/rich-web-ui-flash-and-dhtml-bridge-gap.html" title="Rich Web UI, Flash and DHTML - Bridge the gap" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://www.khanspot.com/2007/01/rich-web-ui-flash-and-dhtml-bridge-gap.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4MRH08eyp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-5765557699813065572</id><published>2006-12-12T11:52:00.000-05:00</published><updated>2011-11-25T13:16:25.373-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T13:16:25.373-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><title>When will Sun's JDK start following code conventions?</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LrM5KVFhb8YF-vpto-UAgggSTa4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LrM5KVFhb8YF-vpto-UAgggSTa4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LrM5KVFhb8YF-vpto-UAgggSTa4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LrM5KVFhb8YF-vpto-UAgggSTa4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;A lot of Java applications run on Sun's JDK due to various reasons. In fact till recently Sun had a very restrictive license policy for Java. So, effectively Sun's JDK has been a de facto standard. That's the reason Sun's JDK code is supposed and expected to be of high quality and following at least the coding conventions recommended by Sun in a 1999 &lt;a href="http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html"&gt;article&lt;/a&gt; that is widely used.&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense#link--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br/&gt;&lt;br/&gt;If you look under the hood of JDK, you will find a completely different picture. Here is an example from the Java 6 source code of &lt;strong&gt;StringBuilder&lt;/strong&gt; class. (I have noticed similar stuff in 1.4 and 1.5 releases.)&lt;br/&gt;&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
    // Appends the specified string builder to this sequence.
    private StringBuilder append(StringBuilder sb) {
  if (sb == null)
            return append(&amp;quot;null&amp;quot;);
  int len = sb.length();
  int newcount = count + len;
  if (newcount &amp;gt; value.length)
      expandCapacity(newcount);
  sb.getChars(0, len, value, count);
  count = newcount;
        return this;
    }

&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br/&gt;How many non-conformance instances can you find? Here is what I notice:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt; &lt;li&gt;&lt;strong&gt;Indentation &lt;/strong&gt;- not sure if it was edited in notepad (even &lt;strong&gt;vi&lt;/strong&gt; does indentation) or a result of source control merge?.&lt;/li&gt;&lt;br/&gt; &lt;li&gt;&lt;strong&gt;If clause doesn't use brackets&lt;/strong&gt;- Here is an excerpt from Sun's Java coding conventions.&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
The if-else class of statements should have the following form:

    if (condition) {
        statements;
    }

    if (condition) {
        statements;
    } else {
        statements;
    }

    if (condition) {
        statements;
    } else if (condition) {
        statements;
    } else {
        statements;
    }
     

Note: if statements always use braces {}. Avoid the following error-prone form:

    if (condition) //AVOID! THIS OMITS THE BRACES {}!
        statement;

&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;Need I say more?&lt;br/&gt;&lt;/li&gt;&lt;br/&gt; &lt;li&gt;&lt;strong&gt;Creating "null" string instance&lt;/strong&gt;- Why can't it be represented by a &lt;strong&gt;static final&lt;/strong&gt; constant and reused? All the string literals are stored in JVM in a String pool, even the ones defined as constants. Isn't it more optimized if you have a direct reference to it rather than JVM doing a lookup in the pool every time you call the method? &lt;br /&gt;&lt;strong&gt;Note:&lt;/strong&gt; After looking at the bytecode generated by the compiler, it looks like a direct reference is pushed on the stack for the string literal. So, it effectively doesn't matter if you use a literal or a constant. Still, if you are using a string literal over and over again, it may be a better idea to create a constant. This way if you need to change the string literal, there is only one place where you need to make change. So, you protect yourself against future changes. Thanks to Messi for pointing this out in the comments :).&lt;/li&gt;&lt;br/&gt; &lt;li&gt;&lt;strong&gt;Variables can be made final&lt;/strong&gt;-The method parameter &lt;code&gt;sb&lt;/code&gt; and local variables &lt;code&gt;len&lt;/code&gt; and &lt;code&gt;newcount&lt;/code&gt; can all be declared &lt;strong&gt;final&lt;/strong&gt; for optimization. &lt;a href="http://www-128.ibm.com/developerworks/java/library/j-jtp1029.html"&gt;This&lt;/a&gt; article has good explanation for it. &lt;br /&gt; &lt;strong&gt;Note:&lt;/strong&gt; Again after analyzing the bytecode it seems like compiler really doesn't care about the final declaration for the local variables. The method parameter are a different case as by declaring them final you make sure that they are not modified by mistake. Also, the local variables can be declared as final as a coding practice to mark them as immutable even though it doesn't affect the byte code. But it makes it clear for a person looking at your code that the variable can not be modified. Thanks to Messi and Kevin Riff for pointing this out in the comments :)&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;This is just an example. There are instances like this all over the JDK code base. I want to make it clear that I am not commenting on the performance aspect of JDK, just the code conventions and formatting (for the obvious reasons that the code should be properly formatted). Now, since Sun has released the JDK source code under GPL license, do we expect to see things like this continue? Do you think people will take more responsibility and clean up the JDK code? I hope so. I also hope that Sun does not blacklist me after this post :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-5765557699813065572?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/r_MVKRdJbd0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/5765557699813065572/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2006/12/when-will-sun-jdk-start-following-code.html#comment-form" title="11 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/5765557699813065572?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/5765557699813065572?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/r_MVKRdJbd0/when-will-sun-jdk-start-following-code.html" title="When will Sun&amp;#39;s JDK start following code conventions?" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>11</thr:total><feedburner:origLink>http://www.khanspot.com/2006/12/when-will-sun-jdk-start-following-code.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YFQ3wyeCp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-346618584723085302</id><published>2006-12-04T11:24:00.000-05:00</published><updated>2011-11-25T13:18:32.290-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T13:18:32.290-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><title>Java wish: A Reversible Enum</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Yf_CAlyVrZw10SXF2fx-ORSkWcM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Yf_CAlyVrZw10SXF2fx-ORSkWcM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Yf_CAlyVrZw10SXF2fx-ORSkWcM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Yf_CAlyVrZw10SXF2fx-ORSkWcM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;One of the biggest feature added with JDK 1.5 is &lt;strong&gt;enum&lt;/strong&gt; support. At last you can use a language construct to define constants in the system rather than using the &lt;code&gt;static final&lt;/code&gt; to define the constants. The obvious benefits of enums are type safety and type checking.&lt;br/&gt;&lt;br/&gt;Also enums let you define meaningful values for the constants. e.g.&lt;br/&gt;&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
public enum MathEnum {
  PI(3.14159),
  LOG_E(2.71828);

  private double mValue;

  MathEnum(final double value) {
    mValue = value;
  }

  public final Double getValue() {
    return mValue;
  }
}

&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;As you can see in the above example, you can use the enum constant PI across your code, but if you wanted to get the value of PI, you can do that by using &lt;code&gt;PI.getValue()&lt;/code&gt;.&lt;br/&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;This is where things get a little fuzzy. What if you have a double value representing either PI or LOG_E and you want to find out which constant in &lt;code&gt;MathEnum&lt;/code&gt; represents that value? This is the reverse lookup of enum. The Java implementation of enum does not allow reverse lookup by value. It is a very useful feature if you are working with an existing code base and an external system returns values for the constants that need to be translated into Java Enums.&lt;br/&gt;&lt;br/&gt;Here is how this problem can be solved by using the &lt;strong&gt;Reversible Enum Pattern&lt;/strong&gt;. First we need to create a &lt;code&gt;ReversibleEnum&lt;/code&gt; interface that will mark the Enums as reversible and define the required method.&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
/**
 * &amp;lt;p&amp;gt;
 * This interface defines the method that the {@link Enum} implementations
 * should implement if they want to have the reversible lookup functionality.
 * i.e. allow the lookup using the code for the {@link Enum} constants.
 * &amp;lt;/p&amp;gt;
 * @author Atif Khan
 * @param &amp;lt; E &amp;gt;
 *          The value of Enum constant
 * @param &amp;lt; V &amp;gt;
 *          The Enum constant to return from lookup
 */
public interface ReversibleEnum&amp;lt; E, V &amp;gt;
{
  /**
   * &amp;lt;p&amp;gt;
   * Return the value/code of the enum constant.
   * &amp;lt;/p&amp;gt;
   * @return value
   */
  public E getValue();

  /**
   * &amp;lt;p&amp;gt;
   * Get the {@link Enum} constant by looking up the code in the reverse enum
   * map.
   * &amp;lt;/p&amp;gt;
   * @param  E - code
   * @return V - The enum constant
   */
  public V reverse( E code );
}

&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;pre&gt;&lt;!--adsense#link--&gt;&lt;/pre&gt;&lt;br/&gt;Next, we need to define a &lt;code&gt;Map&lt;/code&gt; that will be used to store the enum constant values and for reverse lookup.&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
import java.util.HashMap;
import java.util.Map;

/**
 * &amp;lt;p&amp;gt;
 * A utility class that provides a reverse map of the {@link Enum} that is keyed
 * by the value of the {@link Enum} constant.
 * &amp;lt;/p&amp;gt;
 * @author Atif Khan
 * @param &amp;lt; K &amp;gt;
 *          The class type of the value of the enum constant
 * @param &amp;lt; V &amp;gt;
 *          The Enum for which the map is being created
 */
public class ReverseEnumMap&amp;lt; K, V extends ReversibleEnum&amp;lt; K, V &amp;gt;&amp;gt;
{
  private final Map&amp;lt; K, V &amp;gt; mReverseMap = new HashMap&amp;lt; K, V &amp;gt;();

  /**
   * &amp;lt;p&amp;gt;
   * Create a new instance of ReverseEnumMap.
   * &amp;lt;/p&amp;gt;
   * @param valueType
   */
  public ReverseEnumMap( final Class&amp;lt; V &amp;gt; valueType )
  {
    for( final V v : valueType.getEnumConstants() ) {
      mReverseMap.put( v.getValue(), v );
    }
  }

  /**
   * &amp;lt;p&amp;gt;
   * Perform the reverse lookup for the given enum value and return the enum
   * constant.
   * &amp;lt;/p&amp;gt;
   * @param enumValue
   * @return enum constant
   */
  public V get( final K enumValue )
  {
    return mReverseMap.get( enumValue );
  }
}

&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;br/&gt;You will notice that in both the &lt;code&gt;ReversibleEnum&lt;/code&gt; interface and the &lt;code&gt;ReverseEnumMap&lt;/code&gt; class the &lt;strong&gt;Generics&lt;/strong&gt; template is used. This is done to customize these based on the type of the enum that will use them and the type of the value of enum constants. If this sounds confusing, it will become more clear after we see the modified version of the &lt;code&gt;MathEnum&lt;/code&gt; class from earlier.&lt;br/&gt;&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
public enum MathEnum implements ReversibleEnum&amp;lt; Double, MathEnum &amp;gt; 
{
  PI(3.14159),
  LOG_E(2.71828);

  private double mValue;
  private static final ReverseEnumMap&amp;lt; Double, MathEnum &amp;gt; mReverseMap = new ReverseEnumMap&amp;lt; Double, MathEnum &amp;gt;(
    MathEnum.class );

  MathEnum(final double value) 
  {
    mValue = value;
  }

  public final Double getValue() 
  {
    return mValue;
  }

  public MathEnum reverse( final Double value )
  {
    return mReverseMap.get( value );
  }

  public static MathEnum getInstance()
  {
    return values()[0];
  }

}

&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;The changes you will notice here are:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt; &lt;li&gt;&lt;code&gt;MathEnum&lt;/code&gt; implements the &lt;code&gt;ReversibleEnum&lt;/code&gt; interface.&lt;/li&gt;&lt;br/&gt; &lt;li&gt;New variable for &lt;code&gt;ReversibleEnumMap&lt;/code&gt;&lt;/li&gt;&lt;br/&gt; &lt;li&gt;New method &lt;code&gt;reverse(final Double value)&lt;/code&gt; to do the reverse lookup. This is from the &lt;code&gt;ReversibleEnum&lt;/code&gt; interface.&lt;/li&gt;&lt;br/&gt; &lt;li&gt;New static method &lt;code&gt;getInstance()&lt;/code&gt; that just returns the first constant of the enum. This is kind of a hack to get a reference to an instant of the enum, so that the &lt;code&gt;reverse(..)&lt;/code&gt; method could be called on it.&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;Now to do a reverse lookup on the &lt;code&gt;MathEnum&lt;/code&gt;, all you need to do is:&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
MathEnum.getInstance().reverse(3.14159); // Will return PI

&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;Lets recap all the steps needed to be done to create a reversible enum:&lt;br/&gt;&lt;ol&gt;&lt;br/&gt; &lt;li&gt;Define an interface &lt;code&gt;ReversibleEnum&lt;/code&gt;. -- One time job.&lt;/li&gt;&lt;br/&gt; &lt;li&gt;Define a new class &lt;code&gt;ReverseEnumMap&lt;/code&gt;. -- One time job.&lt;/li&gt;&lt;br/&gt; &lt;li&gt;Implement the &lt;code&gt;ReversibleEnum&lt;/code&gt; interface and define a member variable of type &lt;code&gt;ReverseEnumMap&lt;/code&gt; in the enum that you want to be reversible. If you do not need the reverse functionality, you don't need to do any of this.&lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;&lt;br/&gt;So, effectively once you have the interface and map class created, it's minimal effort to create a reversible enum. I wish this was a built-in functionality in the JDK enum implementation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-346618584723085302?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/3BX0SdXMb6U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/346618584723085302/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2006/12/java-wish-reversible-enum.html#comment-form" title="20 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/346618584723085302?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/346618584723085302?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/3BX0SdXMb6U/java-wish-reversible-enum.html" title="Java wish: A Reversible Enum" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>20</thr:total><feedburner:origLink>http://www.khanspot.com/2006/12/java-wish-reversible-enum.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0YASX4zfSp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-2482169380101217204</id><published>2006-11-27T13:01:00.000-05:00</published><updated>2011-11-25T13:19:08.085-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T13:19:08.085-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><title>A Simple LRU Cache in 5 lines</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dCqkFIvRuaWIc8IDjFNpj0Fk-Go/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dCqkFIvRuaWIc8IDjFNpj0Fk-Go/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dCqkFIvRuaWIc8IDjFNpj0Fk-Go/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dCqkFIvRuaWIc8IDjFNpj0Fk-Go/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;The applications usually need to cache information in memory. The most often used classes to do this in Java are &lt;code&gt;HashMap&lt;/code&gt; and &lt;code&gt;Hashtable&lt;/code&gt;. If you need to do any sophisticated caching, then you can use &lt;a href="http://www.jboss.org/products/jbosscache"&gt;JBoss Cache&lt;/a&gt;, &lt;a href="http://www.opensymphony.com/oscache/"&gt;OSCache&lt;/a&gt; or &lt;a href="http://ehcache.sourceforge.net/"&gt;EHCache&lt;/a&gt;. Even if you use an external caching system, you may still want to cache some information locally within an object just to have fast access. The problem with this approach is that, if you are not careful and do not control the size of this in-memory cache, then it may grow too big and affect the performance of your application.&lt;br/&gt;&lt;br/&gt;A very simple solution to this problem is to set a maximum size for your in-memory cache and most preferably make it &lt;strong&gt;LRU&lt;/strong&gt; (Least Recently Used). This way you will have a predictable memory utilization and only the items used recently will be kept in the cache.&lt;br/&gt;&lt;br/&gt;Starting with JDK 1.4, a new (and very rarely used) collection class was added called &lt;strong&gt;&lt;code&gt;LinkedHashMap&lt;/code&gt;&lt;/strong&gt;. There are couple of benefits of using a &lt;code&gt;&lt;a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/LinkedHashMap.html"&gt;LinkedHashMap&lt;/a&gt;&lt;/code&gt;:&lt;br/&gt;&lt;ul&gt;&lt;br/&gt; &lt;li&gt;It is possible to preserve the order of items in the map. So, the order of iteration through the items is same as the order of insertion. A special constructor is provided for this purpose. This is very useful when you already have a sorted collection of data and you want to do some processing on it and return it as a &lt;code&gt;Map&lt;/code&gt;. Using a &lt;code&gt;TreeMap&lt;/code&gt; (the only other map that allows iteration in a given order) is too expensive for this scenario.&lt;/li&gt;&lt;br/&gt; &lt;li&gt;It exposes a method &lt;code&gt;removeEldestEntry(Map.Entry)&lt;/code&gt; that may be overridden to impose a policy for removing stale mappings automatically when new mappings are added to the map. This is what we are going to use to create a LRU cache.&lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;Check out the following snippet for an example of simple LRU cache.&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
import java.util.*;

public class SimpleLRU {

  private static final int MAX_ENTRIES = 50;

  private Map mCache = new LinkedHashMap(MAX_ENTRIES, .75F, true) {
    protected boolean removeEldestEntry(Map.Entry eldest) {
      return size() &amp;gt; MAX_ENTRIES;
    }
  };

  public SimpleLRU() {
    for(int i = 0; i &amp;lt; 100; i++) {
      String numberStr = String.valueOf(i);
      mCache.put(numberStr, numberStr);

      System.out.print(&amp;quot;\rSize = &amp;quot; + mCache.size() + &amp;quot;\tCurrent value = &amp;quot; + i + &amp;quot;\tLast Value in cache = &amp;quot; + mCache.get(numberStr));
      try {
        Thread.sleep(10);
      } catch(InterruptedException ex) {
      }
    }

    System.out.println(&amp;quot;&amp;quot;);
  }

  public static void main(String[] args) {
    new SimpleLRU();
  }
}

&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;&lt;pre&gt;&lt;!--adsense#link--&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;This code creates a simple LRU cache with maximum 50 entries. The magic happens during the creation of the &lt;code&gt;LinkedHashMap&lt;/code&gt; where a boolean flag for access order is set to true and the method &lt;code&gt;removeEldestEntry&lt;/code&gt; is overridden. Now, if you run the program, you can see that the cache size is fixed to 50 entries and the least recently used entries are removed from the map. It is possible to create a pruning thread to prune the map so you don't always necessarily maintain the maximum number of entries.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-2482169380101217204?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/hKFFM00H520" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/2482169380101217204/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2006/11/simple-lru-cache-in-5-lines.html#comment-form" title="17 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/2482169380101217204?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/2482169380101217204?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/hKFFM00H520/simple-lru-cache-in-5-lines.html" title="A Simple LRU Cache in 5 lines" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>17</thr:total><feedburner:origLink>http://www.khanspot.com/2006/11/simple-lru-cache-in-5-lines.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UGRXs6fCp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-1269957612514682781</id><published>2006-11-14T11:56:00.000-05:00</published><updated>2011-11-25T13:20:24.514-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T13:20:24.514-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Tools" /><category scheme="http://www.blogger.com/atom/ns#" term="Java" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><title>PMD bug with @SuppressWarnings annotation</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/PS_9GQNY9M3KtFjsoERxd4x7JLs/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PS_9GQNY9M3KtFjsoERxd4x7JLs/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/PS_9GQNY9M3KtFjsoERxd4x7JLs/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/PS_9GQNY9M3KtFjsoERxd4x7JLs/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;a href="http://pmd.sourceforge.net/"&gt;PMD&lt;/a&gt; is an open source static analysis tool for the Java source code. It has a pretty good set of standard rules and you can add new rules by using XPath or Java code against the AST (Abstract Syntax Tree) it generates from the source code. The code analysis tools help you to keep your code clean and simple and avoid common pitfalls.&lt;br/&gt;&lt;br/&gt;I recently found a bug while trying to analyze the code in the &lt;strong&gt;JDK 1.5&lt;/strong&gt; mode using PMD 3.8 version. The PMD seems to be ignoring all the violations for the class/method if you have a &lt;strong&gt;&lt;code&gt;@SuppressWarnings&lt;/code&gt;&lt;/strong&gt; annotation in it. According to the PMD documentation, only if you have &lt;code&gt;@SuppressWarnings("")&lt;/code&gt; in your code, it's supposed to ignore the violations for that class/method. But, the source code for PMD does not implement this logic. It just checks for the presence of &lt;code&gt;@SuppressWarnings&lt;/code&gt; annotation and not any values passed to it. The end result is that all the violations are ignored. This can be very annoying as you may miss a significant number of violations.&lt;br/&gt;&lt;br/&gt;To fix this issue, I made a couple of changes to the PMD source code. These are listed below with explanations:&lt;br/&gt;&lt;br/&gt;&lt;ul&gt;&lt;br/&gt; &lt;li&gt;&lt;br/&gt;          &lt;p&gt;&lt;strong&gt;net.sourceforge.pmd.ast.ASTAnnotation -&lt;/strong&gt; This is the class where the check for &lt;code&gt;@SuppressWarnings&lt;/code&gt; is implemented. I made changes to the &lt;strong&gt;suppresses(Rule rule)&lt;/strong&gt; method of this class to check if any values are passed to this annotation. If any values except &lt;code&gt;""&lt;/code&gt; are passed (e.g. &lt;code&gt;@SuppressWarnings("unchecked")&lt;/code&gt;), then all the PMD violations are written to the report. Otherwise if &lt;code&gt;""&lt;/code&gt; is passed, all the PMD violations are suppressed.&lt;/p&gt;&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
    public boolean suppresses(Rule rule) {
        /*Check for &amp;quot;suppress all warnings&amp;quot; case
           @SuppressWarnings(&amp;quot;&amp;quot;)
           TypeDeclaration
           Annotation
           NormalAnnotation
           Name:SuppressWarnings
        */

        if (!(jjtGetChild(0) instanceof ASTSingleMemberAnnotation) &amp;amp;&amp;amp; !(jjtGetChild(0) instanceof ASTNormalAnnotation)) {
          return false;
        }

        final SimpleJavaNode n = (SimpleJavaNode) jjtGetChild(0);
        if(!(n.jjtGetChild(0) instanceof ASTName) &amp;#124;&amp;#124; !((ASTName) n.jjtGetChild(0)).getImage().equals(&amp;quot;SuppressWarnings&amp;quot;)) {
          return false;
        }

        final List suppressionQualifierNodeList = n.findChildrenOfType( ASTLiteral.class );
        final Iterator suppressionQualifierNodeIt = suppressionQualifierNodeList.iterator();
        while(suppressionQualifierNodeIt.hasNext()) {
          final ASTLiteral literalNode = (ASTLiteral)suppressionQualifierNodeIt.next();
          if(literalNode == null) {
            continue;
          }
          final String literalImage = literalNode.getImage();
          if(literalImage != null &amp;amp;&amp;amp; literalImage.trim().equals( &amp;quot;\&amp;quot;\&amp;quot;&amp;quot; )) {
            return true;
          }
        }

        return false;
    }
          
&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;          &lt;p&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;/p&gt;&lt;br/&gt;        &lt;/li&gt;&lt;br/&gt;        &lt;li&gt;&lt;br/&gt;          &lt;p&gt;&lt;strong&gt;net.sourceforge.pmd.renderers.XMLRenderer -&lt;/strong&gt; You need to change this only if you generate your PMD reports in the XML format. The changes I made here are to improve the information presented for suppressed violations tag (&lt;code&gt;&amp;lt;suppressedviolation&amp;gt;&lt;/code&gt;). So, if you decide to use the &lt;code&gt;@SuppressWarnings("")&lt;/code&gt; annotation, at the end of reports their will be a section for suppressed violations. Another change I made is to enclose all the &lt;code&gt;&amp;lt;suppressedviolation&amp;gt;&lt;/code&gt; tags inside a &lt;code&gt;&amp;lt;file&amp;gt;&lt;/code&gt; tag for each file just like regular violations.&lt;/p&gt;&lt;br/&gt;           &lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  public String render( Report report )
  {

    StringBuffer buf = new StringBuffer(
      &amp;quot;&amp;lt; ?xml version=\&amp;quot;1.0\&amp;quot; encoding=\&amp;quot;UTF-8\&amp;quot;?&amp;gt;&amp;quot; + PMD.EOL + createVersionAttr()
        + createTimestampAttr() + createTimeElapsedAttr( report ) + &amp;quot;&amp;gt;&amp;quot; + PMD.EOL );
    String filename = null;

    // rule violations
    for( Iterator i = report.iterator(); i.hasNext(); ) {
      IRuleViolation rv = (IRuleViolation)i.next();
      if ( !rv.getFilename().equals( filename ) ) { // New File
        if ( filename != null ) {// Not first file ?
          buf.append( &amp;quot;&amp;quot; + PMD.EOL );
        }
        filename = rv.getFilename();
        buf.append( &amp;quot;&amp;lt;file name=\&amp;quot;&amp;quot; );
        StringUtil.appendXmlEscaped( buf, filename );
        buf.append( &amp;quot;\&amp;quot;&amp;gt;&amp;quot; ).append( PMD.EOL );
      }

      buf.append( &amp;quot;&amp;lt;violation line=\&amp;quot;&amp;quot; ).append( rv.getBeginLine() ).append( &amp;quot;\&amp;quot;&amp;quot; );
      buf.append( &amp;quot; rule=\&amp;quot;&amp;quot; );
      StringUtil.appendXmlEscaped( buf, rv.getRule().getName() );
      buf.append( &amp;quot;\&amp;quot;&amp;quot; );
      buf.append( &amp;quot; ruleset=\&amp;quot;&amp;quot; );
      StringUtil.appendXmlEscaped( buf, rv.getRule().getRuleSetName() );
      buf.append( &amp;quot;\&amp;quot;&amp;quot; );
      maybeAdd( &amp;quot;package&amp;quot;, rv.getPackageName(), buf );
      maybeAdd( &amp;quot;class&amp;quot;, rv.getClassName(), buf );
      maybeAdd( &amp;quot;method&amp;quot;, rv.getMethodName(), buf );
      maybeAdd( &amp;quot;externalInfoUrl&amp;quot;, rv.getRule().getExternalInfoUrl(), buf );
      buf.append( &amp;quot; priority=\&amp;quot;&amp;quot; );
      buf.append( rv.getRule().getPriority() );
      buf.append( &amp;quot;\&amp;quot;&amp;gt;&amp;quot; );
      buf.append( PMD.EOL );
      StringUtil.appendXmlEscaped( buf, rv.getDescription() );

      buf.append( PMD.EOL );
      buf.append( &amp;quot;&amp;lt;/violation&amp;gt;&amp;quot; );
      buf.append( PMD.EOL );
    }
    if ( filename != null ) { // Not first file ?
      buf.append( &amp;quot;&amp;lt;/file&amp;gt;&amp;quot; + PMD.EOL );
    }

    // errors
    for( Iterator i = report.errors(); i.hasNext(); ) {
      Report.ProcessingError pe = (Report.ProcessingError)i.next();
      buf.append( &amp;quot;&amp;lt;error &amp;quot; ).append( &amp;quot;filename=\&amp;quot;&amp;quot; );
      StringUtil.appendXmlEscaped( buf, pe.getFile() );
      buf.append( &amp;quot;\&amp;quot; msg=\&amp;quot;&amp;quot; );
      StringUtil.appendXmlEscaped( buf, pe.getMsg() );
      buf.append( &amp;quot;\&amp;quot;/&amp;gt;&amp;quot; ).append( PMD.EOL );
    }

    // suppressed violations
    if ( showSuppressedViolations ) {
      int count = 0;
      for( Iterator i = report.getSuppressedRuleViolations().iterator(); i.hasNext(); ) {
        Report.SuppressedViolation suppressed = (Report.SuppressedViolation)i.next();

        if ( !suppressed.getRuleViolation().getFilename().equals( filename ) &amp;#124;&amp;#124; count == 0 ) { // New
          
          // File
          if ( filename != null &amp;amp;&amp;amp; count &amp;gt; 0 ) {// Not first file ?
            buf.append( &amp;quot;&amp;quot; + PMD.EOL );
          }
          filename = suppressed.getRuleViolation().getFilename();
          buf.append( &amp;quot;&amp;lt;file name=\&amp;quot;&amp;quot; );
          StringUtil.appendXmlEscaped( buf, filename );
          buf.append( &amp;quot;\&amp;quot;&amp;gt;&amp;quot; ).append( PMD.EOL );
        }
        buf.append( &amp;quot;&amp;lt;suppressedviolation line=\&amp;quot;&amp;quot; ).append(
          suppressed.getRuleViolation().getBeginLine() ).append( &amp;quot;\&amp;quot;&amp;quot; );
        buf.append( &amp;quot; rule=\&amp;quot;&amp;quot; );
        StringUtil.appendXmlEscaped( buf, suppressed.getRuleViolation()
          .getRule()
          .getName() );
        buf.append( &amp;quot;\&amp;quot;&amp;quot; );
        buf.append( &amp;quot; ruleset=\&amp;quot;&amp;quot; );
        StringUtil.appendXmlEscaped( buf, suppressed.getRuleViolation()
          .getRule()
          .getRuleSetName() );
        buf.append( &amp;quot;\&amp;quot; suppressiontype=\&amp;quot;&amp;quot; );
        StringUtil.appendXmlEscaped( buf, suppressed.suppressedByNOPMD() ? &amp;quot;nopmd&amp;quot;
          : &amp;quot;annotation&amp;quot; );
        buf.append(&amp;quot;\&amp;quot;&amp;quot;);
        maybeAdd( &amp;quot;package&amp;quot;, suppressed.getRuleViolation().getPackageName(), buf );
        maybeAdd( &amp;quot;class&amp;quot;, suppressed.getRuleViolation().getClassName(), buf );
        maybeAdd( &amp;quot;method&amp;quot;, suppressed.getRuleViolation().getMethodName(), buf );
        maybeAdd( &amp;quot;externalInfoUrl&amp;quot;, suppressed.getRuleViolation()
          .getRule()
          .getExternalInfoUrl(), buf );
        buf.append( &amp;quot; priority=\&amp;quot;&amp;quot; );
        buf.append( suppressed.getRuleViolation().getRule().getPriority() );
        buf.append( &amp;quot;\&amp;quot; usermsg=\&amp;quot;&amp;quot; );
        StringUtil.appendXmlEscaped( buf, suppressed.getUserMessage() );
        buf.append( &amp;quot;\&amp;quot;&amp;gt;&amp;quot; );
        buf.append( PMD.EOL );
        StringUtil.appendXmlEscaped( buf, suppressed.getRuleViolation()
          .getDescription() );

        buf.append( PMD.EOL );
        buf.append( &amp;quot;&amp;lt;/suppressedviolation&amp;gt;&amp;quot; );
        buf.append( PMD.EOL );
        
        count++;
      }
      final String fileEndStr = &amp;quot;&amp;lt;/file&amp;gt;&amp;quot; +  PMD.EOL;
      if(!buf.substring( buf.length() - fileEndStr.length() ).equalsIgnoreCase( fileEndStr)) {
        buf.append( fileEndStr );
      }
    }

    buf.append( &amp;quot;&amp;quot; );
    return buf.toString();
  }
           
&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;           &lt;p&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;/p&gt;&lt;br/&gt;        &lt;/li&gt;&lt;br/&gt;        &lt;li&gt;&lt;br/&gt;          &lt;p&gt;&lt;strong&gt;net.sourceforge.pmd.util.StringUtil -&lt;/strong&gt; This was throwing &lt;code&gt;NullPointerException&lt;/code&gt; for the suppressed violations while generating the report. I just added a null check here.&lt;/p&gt;&lt;br/&gt;          &lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;  private static void appendXmlEscaped(StringBuffer buf, String src, boolean supportUTF8) {
    char c;

    if(src == null) {
      return;
    }
    .......
    .......
          
&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;        &lt;/li&gt;&lt;br/&gt;&lt;/ul&gt;&lt;br/&gt;&lt;br/&gt;You can just replace the whole methods for ASTAnnotation and XMLRenderer classes and add the code snippet for StringUtil class. Once you do that you are ready to do the build. Run following in the bin directory of pmd-3.8 or the directory where you extracted the source code:&lt;br/&gt;&lt;br/&gt;&lt;code&gt;ant dist&lt;/code&gt;&lt;br/&gt;&lt;br/&gt;That should create the pmd-3.8.jar in the lib directory. Now, you can use this jar whether you use the command line, ant or eclipse plugin to run PMD. If you have any questions, please leave me a comment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-1269957612514682781?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/AhuaaUU_J3U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/1269957612514682781/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2006/11/pmd-bug-with-suppresswarnings.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/1269957612514682781?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/1269957612514682781?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/AhuaaUU_J3U/pmd-bug-with-suppresswarnings.html" title="PMD bug with @SuppressWarnings annotation" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://www.khanspot.com/2006/11/pmd-bug-with-suppresswarnings.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UMRHk6fip7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-3090814950059194556</id><published>2006-11-09T08:44:00.000-05:00</published><updated>2011-11-25T13:21:25.716-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T13:21:25.716-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><title>Charts in Ruby - Using Gruff</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/0fJAUypmgN9kjSEu-zVmcBDihtY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0fJAUypmgN9kjSEu-zVmcBDihtY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/0fJAUypmgN9kjSEu-zVmcBDihtY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/0fJAUypmgN9kjSEu-zVmcBDihtY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;It is very common requirement for any reporting application to be able to draw charts based on some historical and statistical data. The languages with big user community like Java have various libraries available for creating charts. But when it comes to Ruby, there are not as many or as sophisticated choices. I was looking for a library in Ruby to do this sometime back and I found &lt;a target="_blank" title="Gruff" href="http://nubyonrails.com/pages/gruff"&gt;&lt;strong&gt;Gruff&lt;/strong&gt;&lt;/a&gt;. It's a very simple and efficient library.&lt;br/&gt;&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br/&gt;&lt;br/&gt;To install Gruff, all you need to do is:&lt;br/&gt;&lt;br/&gt;&lt;code&gt; gem install gruff&lt;/code&gt;&lt;br/&gt;&lt;br/&gt;You also need to have the &lt;a target="_blank" title="RMagick" href="http://rmagick.rubyforge.org/"&gt;&lt;strong&gt;RMagick&lt;/strong&gt;&lt;/a&gt; installed that needs the &lt;a target="_blank" title="ImageMagick" href="http://www.imagemagick.org/script/index.php"&gt;&lt;strong&gt;ImageMagick&lt;/strong&gt;&lt;/a&gt; to be installed. You can install &lt;strong&gt;ImageMagick&lt;/strong&gt; using the package manager of your Linux distribution or download it directly from &lt;a title="ImageMagick" target="_blank" href="http://www.imagemagick.org/script/index.php"&gt;ImageMagick&lt;/a&gt; website and install. The &lt;strong&gt;RMagick&lt;/strong&gt; installation can be done by either using &lt;strong&gt;gem&lt;/strong&gt; or using the native OS package manager. On my Mandriva Linux box, the gem installation kept on failing during compilation. So, I just installed it using &lt;strong&gt;urpmi&lt;/strong&gt; and it worked.&lt;br/&gt;I wrote a small module in Ruby to draw the line charts. This module can be included in the scripts where you need to draw the charts. This module is called charts.rb. Here is the source code for it:&lt;br/&gt;&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;require 'rubygems'
require 'gruff'
require 'RMagick'

module Chart
  def Chart.drawChart(title, dataHash, labelHash, path, scale, colors)
    begin
      g = Gruff::Line.new(700)
      g.title = title
      count = 0
      for dataTitle in dataHash.keys
        if colors &amp;amp;&amp;amp; colors[count]
          g.data(dataTitle, dataHash.fetch(dataTitle), colors[count])
        else
          g.data(dataTitle, dataHash.fetch(dataTitle))
        end
        count = count + 1
      end
      g.labels = labelHash
      g.marker_font_size = 16
      g.title_font_size = 20
      if dataHash.size == 1
        g.hide_legend = true
      end
      g.write(path)
      resize(path, scale)
    rescue Exception =&amp;gt; e
      puts e
    end
  end

  def Chart.resize(imagePath, scale)
    img = Magick::ImageList.new(imagePath)
    img.resize!(scale)
    img.write(imagePath)
  end

end

&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;The arguments for &lt;code&gt;drawChart&lt;/code&gt; function are as follows:&lt;br/&gt;&lt;ol&gt;&lt;br/&gt; &lt;li&gt;Title of the chart&lt;/li&gt;&lt;br/&gt; &lt;li&gt;A Hash of the data (the Caption for data =&gt; Array of data)&lt;/li&gt;&lt;br/&gt; &lt;li&gt;A Hash of labels for the X axis&lt;/li&gt;&lt;br/&gt; &lt;li&gt;Path of the final generated image&lt;/li&gt;&lt;br/&gt; &lt;li&gt;The scale of the image from the original chart size of 700px*700px&lt;/li&gt;&lt;br/&gt; &lt;li&gt;An array of hex colors if you do not want to use Gruff's default color scheme&lt;/li&gt;&lt;br/&gt;&lt;/ol&gt;&lt;br/&gt;Now, here is how you can use the &lt;code&gt;chart&lt;/code&gt; module and the &lt;code&gt;drawChart&lt;/code&gt; function:&lt;br/&gt;&lt;br/&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;
require 'chart.rb'
....
colors = ['#f9181e', '#f95818', '#f6f918', '#1862f9', '#1ef918']
....
Chart.drawChart(&amp;quot;Violations with Priorities 1 and 2 only&amp;quot;, Hash[&amp;quot;Priority1&amp;quot; =&amp;gt; violation1Arr, &amp;quot;Priority2&amp;quot; =&amp;gt; violation2Arr], timelineGHash, &amp;quot;violation.jpg&amp;quot;, 0.7, colors)

&lt;/code&gt;&lt;/pre&gt;&lt;br/&gt;&lt;br/&gt;&lt;center&gt;&lt;pre&gt;&lt;!--adsense#top_banner--&gt;&lt;/pre&gt;&lt;/center&gt;&lt;br/&gt;&lt;br/&gt;That's pretty much all the code. In the end you should have a chart generated like following:&lt;br/&gt;&lt;img style="width: 326px; height: 245px" id="image5" alt="A chart generated by Gruff" src="http://khanspot.com/blog/uploads/2006/11/violation.jpg" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-3090814950059194556?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/NLLhno1dqfQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/3090814950059194556/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2006/11/charts-in-ruby-using-gruff.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/3090814950059194556?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/3090814950059194556?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/NLLhno1dqfQ/charts-in-ruby-using-gruff.html" title="Charts in Ruby - Using Gruff" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>6</thr:total><feedburner:origLink>http://www.khanspot.com/2006/11/charts-in-ruby-using-gruff.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEFQXc-eSp7ImA9WhRREkk.&quot;"><id>tag:blogger.com,1999:blog-3032029158253338557.post-8751885471580689451</id><published>2006-10-31T11:50:00.000-05:00</published><updated>2011-11-25T12:53:30.951-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-25T12:53:30.951-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Programming" /><category scheme="http://www.blogger.com/atom/ns#" term="Ruby" /><category scheme="http://www.blogger.com/atom/ns#" term="Software" /><title>Path to Ruby Scripts</title><content type="html">
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HI6J9bLfTZRh3-Tn1G5cPIKu6BU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HI6J9bLfTZRh3-Tn1G5cPIKu6BU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HI6J9bLfTZRh3-Tn1G5cPIKu6BU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HI6J9bLfTZRh3-Tn1G5cPIKu6BU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;Ever wondered how to set the path to some Ruby scripts you have written, so you can use them using "require"? There is a very basic solution for this problem. You need to define a system variable called RUBYLIB and point it to the directory containing your Ruby scripts. Then in your script where you want to use the library or script you created, you can simply do a "require" with the name of the script.&lt;br/&gt;&lt;br/&gt;e.g. Supposed you created a script chart.rb in /home/foo/ruby/mylib direcory. Now, you want to use this in the app.rb located in  /home/foo/ruby/scripts. Here is how you can make it work in a Linux bash environment. You could very well do this in other environments as well with minimal modifications.&lt;br/&gt;In your ~/.bash_profile&lt;br/&gt;&lt;pre&gt;export RUBYLIB=$RUBYLIB:/home/foo/ruby/mylib&lt;/pre&gt;&lt;br/&gt;and then in the app.rb script:&lt;br/&gt;&lt;pre&gt;require 'chart'&lt;/pre&gt;&lt;br/&gt;That's it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3032029158253338557-8751885471580689451?l=www.khanspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/khanspot/ERWw/~4/DWPDHrU1F0Q" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.khanspot.com/feeds/8751885471580689451/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.khanspot.com/2006/10/path-to-ruby-scripts.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/8751885471580689451?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/3032029158253338557/posts/default/8751885471580689451?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/khanspot/ERWw/~3/DWPDHrU1F0Q/path-to-ruby-scripts.html" title="Path to Ruby Scripts" /><author><name>Atif Khan</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://www.khanspot.com/2006/10/path-to-ruby-scripts.html</feedburner:origLink></entry></feed>

