For those who missed JavaOne this year, Sun has published the conference slides here a month later. I find these very useful especially for Java geeks as it provides an opportunity to learn some of the technical advancements around the Java platform and the momentum around the technology is healthy.

My top contenders this year were:
Building SOA Applications with JAX-WS, JAXRS, JAXB, and Ajax by Mark Hansen
Let’s Resync Concurrency Features in JDK™ 7 by Brian Goetz
Defective Java™ Code: Turning WTF code into a learning experience by William Pugh
More Effective Java by Joshua Bloch
Design Patterns Reconsidered by Alex Miller
JAX-RS: The Java™ API for RESTful Web Services by Marc Hadley and Paul Sandoz
Top 10 Patterns for Scaling Out Java™ Applications by Cameron Purdy
Groovy and Grails: Changing the Landscape of Java™ Platform, Enterprise Edition (Java EE Platform) Patterns by Graeme Rocher
Choosing a Java Web Framework: A Comparison by Richard Pack
Java™ Servlet 3.0 API: What’s new and exciting by Rajiv Mordani

Possibly Related Posts:


In my earlier blog entry on Jersey, I used HTTPClient API and curl command line utility as the clients. I had not mentioned about the Jersey Client API. It is part of the Jersey distribution. I would prefer using Jersey Client API as it is modeled around the concepts of JAX-RS spec. Let us quickly re-write our client using the Jersey API and see how easy is to write a client in Java.


import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import restful.impl.jaxb.MovieCollection;
import restful.impl.jaxb.MovieDetails;

import static java.lang.System.out;

public class JerseyClient {
    public static void main(String args[]) {
        Client client = Client.create();
        WebResource r = client.resource("http://localhost:9090/boxoffice/movies");
        MovieCollection movies = r.accept("application/xml").get(MovieCollection.class);
        for (MovieDetails movie : movies.getMovie()) {
            out.println("Title : " + movie.getTitle());
            out.println("Genres : " + movie.getGenres());
            out.println("Directed By : " + movie.getDirectedBy());
            out.println("Rank : " + movie.getRank());
        }        
    }
}

This program will print all the top box office movie details in the console. I will be discussing more about this client API in future posts.

The Jersey user forum is the first place to check for any Jersey related issues. The Jersey team is amazingly helpful in resolving any issues. You can also visit Paul’s blog here, Marc’s blog here and Jakub’s blog here. You can bookmark these blogs as they are really informative. Grab the Jersey team’s JavaOne 2008 presentation slide deck here.

You can download the NetBeans project for this sample movie application here.

Possibly Related Posts:


Jersey Jersey is a JSR 311 reference implementation for the JAX-RS spec (The Java API for RESTful Web Services). The JSR development is nearing its completion, but for most part the RI is stable enough for developers to start playing with RESTful services. JAX-RS is an elegant API built around the powerful REST architecture and modeled using resource providers. These resources can be described using WADL (Web Application Description Language). Let us build a basic movie resource which lists top box office movies. Just download the latest distribution of Jersey. I am using 0.8 release for this illustration. NetBeans 6.1 does provide support a Jersey plugin for 0.7 release. Add the jars from the distribution to the project classpath. JAX-RS requires JDK 1.5 as it uses annotations for implementing web resources.

The below XSD defines a basic movie schema.


<?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
              elementFormDefault="unqualified"> 
<xsd:element name="movieCollection">     
   <xsd:complexType>
      <xsd:sequence>
         <xsd:element name="movie" type="movieDetails" minOccurs="1" 
                          maxOccurs="unbounded"/>         
      </xsd:sequence>
   </xsd:complexType>
</xsd:element>
   <xsd:complexType name="movieDetails">
      <xsd:sequence>
         <xsd:element name="title" type="xsd:string"/>
         <xsd:element name="genres" type="xsd:string"/>
         <xsd:element name="directedBy" type="xsd:string"/>
      </xsd:sequence>
      <xsd:attribute name="rank" type="xsd:int"/>
   </xsd:complexType>
</xsd:schema>

Let us use JAXB to generate the Java classes for this schema using the “xjc” tool. This will generate MovieCollection and MovieDetails types in addition to the ObjectFactory. These types will be used in building the response object for our movie collection.

We will implement the “TopBoxOffice” web resource using the JAX-RS APIs.


import com.sun.jersey.spi.resource.Singleton;
import restful.impl.jaxb.MovieCollection;
import restful.impl.jaxb.MovieDetails;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.ProduceMime;
import javax.ws.rs.core.Response;
import static java.lang.System.out;

@Singleton
@Path("/boxoffice")
public class TopBoxOffice {
    private MovieCollection collection = new MovieCollection();
    private final String HTTP_RESPONSE_DATE_HEADER = "EEE, dd MMM yyyy HH:mm:ss zzz";
    private final String DATE_ONE = (new SimpleDateFormat(HTTP_RESPONSE_DATE_HEADER, Locale.US)).format(new Date(1));
    private static int rank = 0;
    
    public TopBoxOffice() {        
        init();
    }    
    
    @GET    
    @Path("/movies")
    @ProduceMime({"application/xml", "application/json"})
    public Response getTopBoxOfficeMoviesThisWeek() {                                
        out.println("Invoking getTopBoxOfficeMoviesThisWeek() ...");
        //Pragma and Expires headers are set to disable caching in IE
        return Response.ok(collection).header("Pragma", "no-cache").header("Expires", DATE_ONE).build();
    }
    
    final void init() {        
        MovieDetails movie = constructMovieObject("Indiana Jones and the Kingdom of the Crystal Skull", "Steven Spielberg", "Action/Adventure and Sequel");
        collection.getMovie().add(movie);
        movie = constructMovieObject("The Chronicles of Narnia: Prince Caspian", "Andrew Adamson", "Action/Adventure, Science Fiction/Fantasy and Adaptation");
        collection.getMovie().add(movie);
        movie = constructMovieObject("Iron Man", "Jon Favreau", "Action/Adventure, Science Fiction/Fantasy and Adaptation");
        collection.getMovie().add(movie);
        movie = constructMovieObject("What Happens in Vegas", "Tom Vaughan", "Comedy");
        collection.getMovie().add(movie);
        movie = constructMovieObject("Speed Racer", "Larry Wachowski, Andy Wachowski", "Action/Adventure, Science Fiction/Fantasy and Adaptation");
        collection.getMovie().add(movie);
        movie = constructMovieObject("Baby Mama", "Michael McCullers", "Comedy");
        collection.getMovie().add(movie);
        movie = constructMovieObject("Made of Honor", "Paul Weiland", "Comedy");
        collection.getMovie().add(movie);
        movie = constructMovieObject("Forgetting Sarah Marshall", "Nicholas Stoller", "Comedy");
        collection.getMovie().add(movie);
        movie = constructMovieObject("Harold and Kumar Escape From Guantanamo Bay", "Jon Hurwitz, Hayden Schlossberg", "Comedy and Sequel");
        collection.getMovie().add(movie);
        movie = constructMovieObject("The Visitor", "Tom McCarthy", "Comedy and Drama");
        collection.getMovie().add(movie);       
    }
    
    final MovieDetails constructMovieObject(String title, String direction, String genres) {        
        MovieDetails movie = new MovieDetails();
        movie.setTitle(title);
        movie.setRank(++rank);
        movie.setDirectedBy(direction);
        movie.setGenres(genres);
        return movie;
    }
}

The Singleton annotation ensures that only one instance of this class will be instantiated per web application. The movie collection resource will be populated when the first request to the movie list resource occurs. Remember this is RI specific feature and not part of JSR 311 API. The Path annotation defines the URI path to access the web resource. The resource is annotated using GET which populates top box office movies in the response. The response will be rendered using either XML or JSON. The default media type will be XML as it is the first one in the list provided to the ProduceMime annotation. If you need JSON response, you need to set the “Accept” header to “application/json” type. This will render JSON response. If you notice the response code, we are adding couple headers which basically disables caching in IE. You may set as many HTTP response headers on the response using the javax.ws.rs.core.Response class. This resource only implements the basic HTTP GET operation. Developing PUT, POST and DELETE operations on the resource can be quite easy too. The resource can be backed by a database where these HTTP operations can be easily translated into CRUD actions operating on the data.

The resource can now be deployed in a HTTP server. Let us use the Grizzly HTTP server to quickly deploy our resource and do some testing. Grizzly jars are bundled as part of the Jersey distribution. Add the required jars to the classpath. The below code starts the HTTP server at port 9090.


import com.sun.grizzly.http.SelectorThread;
import com.sun.jersey.api.container.grizzly.GrizzlyServerFactory;
import static java.lang.System.*;

public class Server {
    public static void main(String[] args) throws Exception {        
        SelectorThread server = GrizzlyServerFactory.create("http://localhost:9090/");
        out.println("Server running, hit return to stop...");
        in.read();
        out.println("Stopping server");
        server.stopEndpoint();
        exit(0);
        out.println("Server stopped");
    }    
}

If you want to use this within a servlet container, you can use the standard web.xml to describe a Jersey webapp.


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 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">
    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

Now you can access the URL “http://localhost:9090/boxoffice/movies” from a browser.
You should see the XML response as shown below.


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<movieCollection>
	<movie rank="1">
		<title>Indiana Jones and the Kingdom of the Crystal Skull</title>
		<genres>Action/Adventure and Sequel</genres>
		<directedBy>Steven Spielberg</directedBy>
	</movie>
	<movie rank="2">
		<title>The Chronicles of Narnia: Prince Caspian</title>
		<genres>Action/Adventure, Science Fiction/Fantasy and Adaptation</genres>
		<directedBy>Andrew Adamson</directedBy>
	</movie>
	<movie rank="3">
		<title>Iron Man</title>
		<genres>Action/Adventure, Science Fiction/Fantasy and Adaptation</genres>
		<directedBy>Jon Favreau</directedBy>
	</movie>
	<movie rank="4">
		<title>What Happens in Vegas</title>
		<genres>Comedy</genres>
		<directedBy>Tom Vaughan</directedBy>
	</movie>
	<movie rank="5">
		<title>Speed Racer</title>
		<genres>Action/Adventure, Science Fiction/Fantasy and Adaptation</genres>
		<directedBy>Larry Wachowski, Andy Wachowski</directedBy>
	</movie>
	<movie rank="6">
		<title>Baby Mama</title>
		<genres>Comedy</genres>
		<directedBy>Michael McCullers</directedBy>
	</movie>
	<movie rank="7">
		<title>Made of Honor</title>
		<genres>Comedy</genres>
		<directedBy>Paul Weiland</directedBy>
	</movie>
	<movie rank="8">
		<title>Forgetting Sarah Marshall</title>
		<genres>Comedy</genres>
		<directedBy>Nicholas Stoller</directedBy>
	</movie>
	<movie rank="9">
		<title>Harold and Kumar Escape From Guantanamo Bay</title>
		<genres>Comedy and Sequel</genres>
		<directedBy>Jon Hurwitz, Hayden Schlossberg</directedBy>
	</movie>
	<movie rank="10">
		<title>The Visitor</title>
		<genres>Comedy and Drama</genres>
		<directedBy>Tom McCarthy</directedBy>
	</movie>
</movieCollection>

In order to test the JSON rendering, let us write a Client developed using HTTP Client library. You need to have commons-logging and commons-codec in addition to the commons-httpclient jars in the classpath.


import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.commons.httpclient.Header;
import static java.lang.System.out;

public class Client {

  public static void main(String args[]) throws Exception {
    String url = "http://localhost:9090/boxoffice/movies";
    out.println("Sent HTTP GET request to the endpoint " + url);
    GetMethod get = new GetMethod(url);
    get.addRequestHeader("Accept", "application/json");
    HttpClient httpclient = new HttpClient();

    StringBuffer buffer = null;
    try {
      httpclient.executeMethod(get);

      if (get.getStatusCode() == HttpStatus.SC_OK) {
        InputStream is = get.getResponseBodyAsStream();
        Header[] headers = get.getResponseHeaders();
        for (Header header : headers) {
            out.println(header.getName() + " : " + header.getValue());
        }
        BufferedReader in = new BufferedReader(new InputStreamReader(is));
        buffer = new StringBuffer();
        String line = null;
        while ((line = in.readLine()) != null) {
          buffer.append(line);
        }
      } else {
        out.println("GET action raised an error: " + get.getStatusLine());
      }

    } finally {
      // Release current connection to the connection pool once you are done
      get.releaseConnection();
    }

    out.println("JSON RESPONSE : " + buffer.toString());
  }
}

The output of this program is shown below.


Sent HTTP GET request to the endpoint http://localhost:9090/boxoffice/movies
Pragma : no-cache
Expires : Wed, 31 Dec 1969 17:00:00 MST
Content-Type : application/json
Transfer-Encoding : chunked
Date : Tue, 27 May 2008 04:13:28 GMT
JSON RESPONSE : 
{"movieCollection":
{"movie":[
{"@rank":"1","title":"Indiana Jones and the Kingdom of the Crystal Skull","genres":"Action/Adventure and Sequel","directedBy":"Steven Spielberg"},
{"@rank":"2","title":"The Chronicles of Narnia: Prince Caspian","genres":"Action/Adventure, Science Fiction/Fantasy and Adaptation","directedBy":"Andrew Adamson"},
{"@rank":"3","title":"Iron Man","genres":"Action/Adventure, Science Fiction/Fantasy and Adaptation","directedBy":"Jon Favreau"},
{"@rank":"4","title":"What Happens in Vegas","genres":"Comedy","directedBy":"Tom Vaughan"},
{"@rank":"5","title":"Speed Racer","genres":"Action/Adventure, Science Fiction/Fantasy and Adaptation","directedBy":"Larry Wachowski, Andy Wachowski"},
{"@rank":"6","title":"Baby Mama","genres":"Comedy","directedBy":"Michael McCullers"},
{"@rank":"7","title":"Made of Honor","genres":"Comedy","directedBy":"Paul Weiland"},
{"@rank":"8","title":"Forgetting Sarah Marshall","genres":"Comedy","directedBy":"Nicholas Stoller"},
{"@rank":"9","title":"Harold and Kumar Escape From Guantanamo Bay","genres":"Comedy and Sequel","directedBy":"Jon Hurwitz, Hayden Schlossberg"},
{"@rank":"10","title":"The Visitor","genres":"Comedy and Drama","directedBy":"Tom McCarthy"}
]}
}

You can also use curl to test the above behavior. This approach is easier than the earlier one, if you have access to curl.


curl -i -H "Accept: application/json" http://localhost:9090/boxoffice/movies

WADL can be accessed at http://localhost:9090/application.wadl. This provides basic resource description as shown below.


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://research.sun.com/wadl/2006/10">
	<resources base="http://localhost:9090/">
		<resource path="/boxoffice">
			<resource path="/movies">
				<method name="GET">
					<response>
						<representation mediaType="application/xml"/>
						<representation mediaType="application/json"/>
					</response>
				</method>
			</resource>
		</resource>
	</resources>
</application>

RESTful web services has more potential use cases and Jersey provides extensions to the library so that developers can customize as per their needs.
The resource provider SPI allows pluggable custom resource providers. JAX-RS also supports pluggable type system for encoding and decoding of a Java type to/from an entity of an HTTP response/request. Some of these advanced concepts deserve more space and possibly another post.

Possibly Related Posts:


Message brokering markets were once dominated by heavy weights and required huge investments by enterprises for implementing such solutions. Vendors made huge bucks out of it by selling such solutions and support. Is this still considered a niche market? I personally don’t think so. I am definitely not against vendors offering such solutions, but the point I am making here is whether this market still deserves huge investments when mature open source alternatives are available.

You possibly have two options. Buy an OTS solution and forget about maintenance nightmare, typically argued by the so called “Enterprise Architects” because they assume it’s a safe bet. Such decisions make your enterprise tightly coupled with these kinds of solutions. You may never know sometimes you end up paying huge bucks for feature requests and lobbying for license costs and finally stuck with the custom solution for years. This choice comes at a huge price, but at some convenience as one need not blame you for lack of a feature or offering a buggy solution. Does this convenience worth anymore?

Historically, enterprises chose such solutions mainly because of the support and maintenance that comes bundled with the solution and they always awarded such contracts to market leaders. Finally, when the vendor decides to release newer versions of the product, customers had to upgrade and sometimes forcefully migrated to a newer version, just because earlier version does not scale or does not support a feature or possibly discontinued.

On the contrary, some enterprises (mostly small to mid-size) consider the option of implementing such messaging solution using open source alternatives and people who make this choice need to be really smart because of the liability that comes with their decision. In most situations, such decisions are made by experts who are aware of the complexity involved in such undertaking. For most part it will be straightforward to adopt such a solution and sometimes it could be painful when there is lack of technical expertise within the enterprise. But, it will definitely be a rewarding experience when working with smart people in such integrations. The open source community offers their best support in resolving any issues. This option will surely benefit enterprises in terms of licensing and support costs. But, the key assumption here is that you bet on your expertise on such engagements.

ActiveMQ 5.1Open source solutions are increasingly becoming a compelling choice for enterprises because of their mature feature set and wide adoption backed by strong user community. ActiveMQ is one such project in ASF where you see tons of features available to its users. I had experience working on similar commercial products, but ActiveMQ is absolutely mind blowing. Simplicity wins the heart of enterprise developers. Some commercial offerings take days to install and configure which requires special hardware (high-end servers) and sometimes on-site training from vendor. With projects like ActiveMQ, it is becoming more and more productive for teams to develop, test and roll out integration solutions in a shorter period of time. It just takes minutes to install and configure ActiveMQ in your desktop.

I recently downloaded ActiveMQ and played around with it. Let us analyze their startup messages and dissect some of them and see what they offer. This is just a tip of an iceberg.


 (1) D:\\apache-activemq-5.1.0\\bin>activemq.bat
 (2) ACTIVEMQ_HOME: D:\\apache-activemq-5.1.0\\bin\\..
 (3) ACTIVEMQ_BASE: D:\\apache-activemq-5.1.0\\bin\\..
 (4) Loading message broker from: xbean:activemq.xml
 (5) INFO  BrokerService                  - Using Persistence Adapter: AMQPersistenceAdapter(D:\\apache-activemq-5.1.0\\bin\\..\\data)
 (6) INFO  BrokerService                  - ActiveMQ 5.1.0 JMS Message Broker (localhost) is starting
 (7) INFO  BrokerService                  - For help or more information please see:http://activemq.apache.org/
 (8) INFO  AMQPersistenceAdapter          - AMQStore starting using directory: D:\\apache-activemq-5.1.0\\bin\\..\\data
 (9) INFO  KahaStore                      - Kaha Store using data directory D:\\apache-activemq-5.1.0\\bin\\..\\data\\kr-store\\state
(10) INFO  AMQPersistenceAdapter          - Active data files: []
(11) INFO  KahaStore                      - Kaha Store using data directory D:\\apache-activemq-5.1.0\\bin\\..\\data\\kr-store\\data
(12) INFO  TransportServerThreadSupport   - Listening for connections at: tcp://nandi:61616
(13) INFO  TransportConnector             - Connector openwire Started
(14) INFO  TransportServerThreadSupport   - Listening for connections at: ssl://nandi:61617
(15) INFO  TransportConnector             - Connector ssl Started
(16) INFO  TransportServerThreadSupport   - Listening for connections at: stomp://nandi:61613
(17) INFO  TransportConnector             - Connector stomp Started
(18) INFO  TransportServerThreadSupport   - Listening for connections at: xmpp://nandi:61222
(19) INFO  TransportConnector             - Connector xmpp Started
(20) INFO  NetworkConnector               - Network Connector default-nc Started
(21) INFO  BrokerService                  - ActiveMQ JMS Message Broker (localhost, ID:nandi-64041-1211065443740-0:0) started
(22) INFO  log                            - Logging to org.slf4j.impl.JCLLoggerAdapter(org.mortbay.log) via org.mortbay.log.Slf4jLog
(23) INFO  log                            - jetty-6.1.9
(24) INFO  WebConsoleStarter              - ActiveMQ WebConsole initialized.
(25) INFO  /admin                         - Initializing Spring FrameworkServlet 'dispatcher'
(26) INFO  log                            - ActiveMQ Console at http://0.0.0.0:8161/admin
(27) INFO  log                            - ActiveMQ Web Demos at http://0.0.0.0:8161/demo
(28) INFO  log                            - RESTful file access application at http://0.0.0.0:8161/fileserver
(29) INFO  log                            - Started SelectChannelConnector@0.0.0.0:8161
(30) INFO  FailoverTransport              - Successfully connected to tcp://localhost:61616

The following features are enabled by default when an ActiveMQ broker is started.

Line 8 – AMQStore is the default storage for AcitveMQ 5 and above.
Line 11 – KahaStore is an optimal performance storage solution used for message persistance.
Line 12 – OpenWire is a cross language Wire Protocol which allows native access to ActiveMQ from a number of different languages and platforms.
Line 14 – SSL transport allows clients to connect to a remote ActiveMQ broker using SSL over a TCP socket.
Line 16 – Stomp is used by non-Java clients talk to ActiveMQ server and other message brokers.
Line 18 – XMPP is used to connect to the broker & send and receive messages (Jabber).
Line 26 – ActiveMQ Web Console for managing the broker services such as queues, topics and subscriptions.
Line 28 – REST-ful API to messaging (JMS). Browsing of queues implemented using pluggable views such as ATOM and RSS feeds.
Line 30 – Failover transport used for reconnection.

There are tons of other features which is beyond the scope of this discussion. Some of the notable features include embedded message broker which comes handy in unit testing. You can refer to its complete feature set here. There are sub-projects within ActiveMQ such as NMS (for .NET) and CMS (for C++) which provides unified access to ActiveMQ from other programming language environments. Camel is another sub-project which implements enterprise integration patterns. Its a topic of interest for another blog entry.

This is more than compelling to adopt this solution. Enterprises sometimes face real complexity in terms of cost of ownership issues when trying to adopt such open source solutions. But, this could be overcome by choosing support offerings from companies like IONA, Covalent (now part of SpringSource) and OpenLogic. This may still work out to be cost effective when compared to OTS solutions. The market should favor such healthy adoption.

Possibly Related Posts:


Effective Java second edition finally started shipping this week. I dreamed of this day in one of my earlier blog post 🙂 As predicted, it finally made it this year during JavaOne. Even this year, Joshua had a session on “More ‘Effective Java'” – third in a row since 2006.

The book was published on May 8, 2008 and I pre-ordered at Amazon thinking the book will hit the stores only on May 28 as per their website. But, I then decided to order it at informIT as it was available immediately (not to mention the best deal I could get on the Internet). I should be getting it next week. You can read sample chapters from here and here. I had gone through the Generics chapter and its pretty impressive.

As always, its definitely a programmer’s asset. This second edition is reloaded with 21 more best programming practice primarily from JDK 1.5. You can read Joshua Bloch’s recent interviews at InfoQ and java.sun.com.

You can even buy an autographed version from craigslist. It comes at a premium of $50. Josh is always a rock star in the Java community.

Possibly Related Posts:


Apache CXF is an open services framework. It is more than just a Web Services stack. Its simple, powerful, and promising. Today, the CXF project graduated from incubation as a top-level Apache project. It has made several stable releases since its incubation. I know projects which still prefer to use first generation Axis due to its simplicity. XFire is also popular like Axis, but made a significant difference in providing highly performing XML based web services. The power and simplicity of XFire and feature rich Celtix (branded as ESB) merged to form Apache CeltixXFire (CXF).

IMO, CXF wins over Axis2 programming model. CXF documentation is an area for improvement. It has a lot of powerful undocumented features. The primary source of getting these information is cxf-user mailing list. The people are amazingly helpful. It features most of its core developers offering their timely help to the user community.

I developed a simple loan processing application based on JPA and CXF using the NetBeans 6.1. This is a simple standalone Java application, but still demonstrates the power of persistence and integration technologies in combination with a powerful IDE which provides a platform for developing quality software. I specifically used NetBeans for this illustration because its very productive and intuitive for developer of any class. MySQL support in NetBeans 6.1 has improved phenomenally. You can manage the MySQL database from within NetBeans IDE. This is yet another useful integration for RAD apart from many of its other key offerings which I am not going to discuss in this post.

You can access this step-by-step tutorial in the NetBeans community website.

Rock with NetBeans 6.1 today and contribute to the community.

NetBeans 6.1

(4/30/08 Update): Changed the new Apache CXF project URL. Also, updated the tutorial to use Apache CXF 2.1 release and NetBeans 6.1 final release and used soapUI plugin for testing secure web services. Thanks to Vidhya for suggesting soapUI tool. Nice tooling around web services testing.

Possibly Related Posts:


Effective Java Second Edition slips to ship in 2007, though Ted originally predicted in his 2006 Tech predictions. Finally, it is likely to be released around the time frame of Java One 2008 in May. I hope that Joshua does not change his original 2007 title “Effective Java: This Time It’s for Real” in JavaOne 2008. May be this time he carries a copy of this edition to the session hall:) His earlier two presentations shows only a glimpse of this book and he is busy debating closures controversy, which is a good thing for the future of the language.

Effective Java Reloaded in JavaOne 2008 : This Time It’s Not for Real

Effective Java Reloaded in JavaOne 2007 : This Time It’s Not for Real

Effective Java Reloaded in JavaOne 2006

Would the closure controversy come to an end this year? Joshua’s talk on “The Closures Controversy” in JavaPolis’07 may bring reasonable momentum in the Java community voicing concerns about the BGGA proposal. Remember this is just one proposal on closures. Bruce Eckel’s “Java: Evolutionary Dead End” is just the beginning. Neal defends on “Restricted Closures” and “What flavor of closures?” and how this can be accommodated as part of the JSR.

Who wins closure war: “Do Nothing” OR CICE+ARM OR BGGA ?

Java API recommendations from Kevin, Joshua and Doug “Java Class Libraries minor API change recommendations for JDK 7” may not make a big impact and its sole purpose is to fix the glitches. The next talk of the community is whether OpenJDK 6, JDK 7 will be shipping this year? Would Google Collections make its version 1.0 release, and possibly marry into Java Collections?

Does all this make the language powerful, and still retain “programmer portability”? Yes, I would think so.

Possibly Related Posts:


Today, Google released the Android platform SDK to the developer community. It comes with tools and APIs to develop applications on the open mobile platform using the Java programming language. It comes with an emulator and Eclipse plugin for development. The SDK is already available on Windows, Mac OS X (intel), and Linux (i386) platforms.

As part of today’s announcement, Google unveiled $10 million android developer challenge for developing applications on the Android platform. Android runtime is based on Dalvik VM. Each android application has its own VM which runs in its own process. The stack is built on top of Linux kernel version 2.6. The VM relies on the underlying kernel for threading and low-level memory management.

Google rocks!

Possibly Related Posts:


Joshua Bloch’s JavaOne’06 presentation on Effective Java Reloaded previewed his second edition of the most famous Java best practice guide in the Java developer community. Finally, the book is hitting the market on Nov 9, 2007 and it is available for Pre-Order from Amazon.com. But, you can start using some of these best practices today. Google Collections is home for some of these Java programming best practices. Not sure, when these features would become part of core library. They are simple to use and provide rich data structures and complement the Java collections library. Go for it, though its still in its alpha release. Google Collections is a natural home for these developer savvy features until we see them adopted in the core library. After all, Joshua is Google’s Chief Java Architect.

Possibly Related Posts:


Synthetic methods are often referred to as bridge methods in Java generics world. These methods are created by the Java compiler as a result of type erasure when the signature of the inherited methods change when a type extends or implements parameterized classes or interfaces. The compiler generates synthetic methods in subtypes of parameterized supertypes to make sure that subtyping works as expected.

For instance, let us try to extend the Lock interface defined in concurrency package and define an extended lock method which takes a type parameter. We use the hidden “-XD-printflat” compiler option to generate the java files after type erasure.

javac -d tmp -XD-printflat LockExImpl.java

LockEx interface

public interface LockEx extends java.util.concurrent.locks.Lock {
  //extended lock method
  void lockEx(T t);
}

LockExImpl Before Erasure

final class LockExImpl<T> extends java.util.concurrent.locks.ReentrantLock
			implements LockEx<LockExImpl>  {
  public void lockEx(LockExImpl mutex) {
    throw new UnsupportedOperationException("Not supported yet.");
  }
}

LockExImpl After Erasure

final class LockExImpl extends java.util.concurrent.locks.ReentrantLock
                                     implements LockEx {
  LockExImpl() {
    super();
  }

  public void lockEx(LockExImpl mutex) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  /*synthetic*/

  public void lockEx(Object x0) {
    this.lockEx((LockExImpl)x0);
  }
}

Possibly Related Posts: