Open Source

Java template for WSDL-first web services using CXF (for Maven2 and Eclipse)

October 23rd, 2008 / Joe on Computing

This took me a while to put together so I thought I’d post it. I wanted the simplest possible template for building a web service in Java. I wanted it to be JAX-WS compliant, so I used the CXF open source implementation which is not only compliant, but also flexible and fast. I also wanted the template to be WSDL first, meaning that I should be able to edit the WSDL by hand to maintain total control over the service contract, then from that, generate Java code to make it easy to fill in the implementation.  (I consider that to be an important part of web service best practices. Doing it the other way - automatically generating WSDL from code - is simpler, but results in messy, sometimes incorrect WSDL that limits your ability to change web service implementations later.) Furthermore, I didn’t want to edit any generated code. I wanted to be able to fill in the implementation details by inheriting from a generated class or implementing a generated interface. Finally, I wanted to take advantage of Maven to build the project, but also be able to work on it in Eclipse, taking advantage of its Web Tools Platform (WTP) to allow synchronization with a live application server. Here’s the result in just under 300 lines of code. (Or you can cut to the chase and just download the zip file and follow the instructions at the end of this posting.)

First, here is the trade.xsd schema file containing the input and output datatypes used by the web services:

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema targetNamespace="http://com.joemo.schema.trade" xmlns="http://com.joemo.schema.trade"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">

	<!-- web service input types -->

	<xsd:element name="trade">
		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="security" type="xsd:string" minOccurs="1" maxOccurs="1" />
				<xsd:element name="quantity" type="xsd:integer" minOccurs="1" maxOccurs="1" />
				<!-- note the use of "unbounded"; comments can occur multiple times -->
				<xsd:element name="comments" type="comment" minOccurs="1" maxOccurs="unbounded" />
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>

	<xsd:complexType name="comment">
		<xsd:sequence>
			<xsd:element name="message" type="xsd:string" minOccurs="1" maxOccurs="1" />
			<xsd:element name="author" type="xsd:string" minOccurs="1" maxOccurs="1" />
		</xsd:sequence>
	</xsd:complexType>

	<!-- web service output types -->

	<xsd:element name="status">
		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="id" type="xsd:string" minOccurs="1" maxOccurs="1" />
				<xsd:element name="message" type="xsd:string" minOccurs="1" maxOccurs="1" />
			</xsd:sequence>
		</xsd:complexType>
	</xsd:element>

</xsd:schema>

Next, we need the trade.wsdl file which imports the schema file and completes the WSDL definition:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://com.joemo.schema.tradeservice"
	xmlns="http://com.joemo.schema.tradeservice"
	xmlns:tr="http://com.joemo.schema.trade"
	xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
	xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

	<wsdl:types>
		<xsd:schema targetNamespace="http://com.joemo.schema.tradeservice">
			<xsd:import namespace="http://com.joemo.schema.trade" schemaLocation="trade.xsd" />
		</xsd:schema>
	</wsdl:types>

	<wsdl:message name="tradeInput">
		<wsdl:part name="trade" element="tr:trade" />
	</wsdl:message>

	<wsdl:message name="tradeOutput">
		<wsdl:part name="status" element="tr:status" />
	</wsdl:message>

	<wsdl:portType name="TradeService">
		<wsdl:operation name="book">
			<wsdl:input message="tradeInput" />
			<wsdl:output message="tradeOutput" />
		</wsdl:operation>
	</wsdl:portType>

	<wsdl:binding name="TradeServiceHTTPBinding" type="TradeService">
		<wsdlsoap:binding style="document"
			transport="http://schemas.xmlsoap.org/soap/http" />
		<wsdl:operation name="book">
			<wsdlsoap:operation soapAction="" />
			<wsdl:input>
				<wsdlsoap:body use="literal" />
			</wsdl:input>
			<wsdl:output>
				<wsdlsoap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>

	<wsdl:service name="TradeServicePorts">
		<wsdl:port binding="TradeServiceHTTPBinding" name="TradeService">
			<wsdlsoap:address
				location="http://localhost:9084/tradeService/TradeServicePorts" />
		</wsdl:port>
	</wsdl:service>

</wsdl:definitions>

Now we need a Maven project file that will take this WSDL and generate the Java code. Here’s what the pom.xml file looks like. It’s long and messy but it does a lot. It specifies all the dependencies and the compiler level, includes the rule to generate Java code from WSDL whenever necessary, and includes Jetty and WTP support for testing and running the web services in different environments.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.joemo</groupId>
	<artifactId>ws-example</artifactId>
	<packaging>war</packaging>
	<version>0.1</version>
	<name>ws-example</name>
	<url>http://maven.apache.org</url>
	<properties>
		<cxf.version>2.1</cxf.version>
		<spring.version>2.5</spring.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-core</artifactId>
			<version>${cxf.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>${cxf.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>${cxf.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-common-utilities</artifactId>
			<version>${cxf.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.4</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<!-- Use Java 5 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.5</source>
					<target>1.5</target>
				</configuration>
			</plugin>

			<!-- CXF WSDL-to-Java code generation -->
			<plugin>
				<groupId>org.apache.cxf</groupId>
				<artifactId>cxf-codegen-plugin</artifactId>
				<version>2.0.6</version>
				<executions>
					<execution>
						<id>generate-sources</id>
						<phase>generate-sources</phase>
						<configuration>
							<sourceRoot>${basedir}/target/generated/src/main/java</sourceRoot>
							<wsdlOptions>
								<wsdlOption>
									<wsdl>src/main/resources/trade.wsdl</wsdl>
								</wsdlOption>
							</wsdlOptions>
						</configuration>
						<goals>
							<goal>wsdl2java</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<!-- Jetty support for testing -->
			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>maven-jetty-plugin</artifactId>
			</plugin>
		</plugins>
		<!-- Eclipse WTP support -->
		<pluginManagement>
			<plugins>
				<plugin>
					<artifactId>maven-eclipse-plugin</artifactId>
					<configuration>
						<wtpversion>2.0</wtpversion>
						<wtpapplicationxml>true</wtpapplicationxml>
						<wtpmanifest>true</wtpmanifest>
						<downloadSources>true</downloadSources>
						<downloadJavadocs>true</downloadJavadocs>
						<projectNameTemplate>[artifactId]-[version]</projectNameTemplate>
						<manifest>${basedir}/src/main/resources/META-INF/MANIFEST.MF</manifest>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
</project>

Among other things, the rules in this pom.xml file will generate a Java interface called TradeService (based on the names in the WSDL file). The only code we will have to write is the implementation of this interface. Although this generation is done automatically by any Maven commands that need it (e.g. mvn package or mvn install) you might want to force it to be done sooner rather than later, so that you can refresh your Eclipse project with the generated code, enabling Eclipse to recognize the interface that you’re trying to implement. You can do this using the commands:

mvn generate-sources
mvn eclipse:clean eclipse:eclipse

This generates Java code from the WSDL, then regenerates the Eclipse project files, after which you should be able to refresh the project in Eclipse. If you see errors about libraries not being found, you may need to configure Eclipse to know about your Maven repository, i.e. select Eclipse / Window / Preferences / Java / Build Path / Classpath Variables, then enter the appropriate settings, e.g.

Name: M2_REPO
Path: C:/Documents and Settings/MyAccount/.m2/repository

Once the project is properly configured in Eclipse, you can fill in the implementation:

package com.joemo.service;

import trade.schema.joemo.com.Comment;
import trade.schema.joemo.com.Status;
import trade.schema.joemo.com.Trade;
import tradeservice.schema.joemo.com.TradeService;

public class TradeServiceImpl implements TradeService {

	public Status book(Trade trade) {
		System.out.print ("Booking security ");
		System.out.print (trade.getSecurity());
		System.out.print (", quantity ");
		System.out.print (trade.getQuantity());
		System.out.println();
		if (trade.getComments() != null) {
			System.out.println ("Comments:");
			for (Comment c : trade.getComments()) {
				System.out.print (c.getAuthor());
				System.out.print (": ");
				System.out.print (c.getMessage());
				System.out.println();
			}
		}
		Status s = new Status();
		s.setId("12345");
		s.setMessage("ok");
		return s;
	}

}

We are almost done. We still need a web.xml file which will direct SOAP requests to the CXF infrastructure:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" 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">
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:appContext.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
</web-app>

Finally, we need the appContext.xml file, which is the Spring configuration file loaded by CXF that defines the web service endpoint:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"
	default-dependency-check="none" default-lazy-init="false">

	<!-- Load the needed resources that are present in the cxf* jars -->
	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

	<!-- Hook up the web service -->
	<jaxws:endpoint id="ws-example" implementor="com.joemo.service.TradeServiceImpl"
		address="/ws-example" />

</beans>

That’s everything. There are six files, only one of which contains any Java code. You need to make sure you put each file in the right place:

ws-example/pom.xml
ws-example/src/main/resources/trade.xsd
ws-example/src/main/resources/trade.wsdl
ws-example/src/main/resources/appContext.xml
ws-example/src/main/webapp/WEB-INF/web.xml
ws-example/src/main/java/com/joemo/service/TradeServiceImpl.java

A zip file of this example is available for download here. To build and run it, you will need Maven to be installed on your development system. Unzip the file, and in the directory containing the pom.xml file, run the command:

mvn jetty:run

That will generate the Java code from the WSDL, build the example, and run the web service in the Jetty container. You should be able to visit the URL http://localhost:8080/ws-example/ws-example?wsdl from a web browser and see the WSDL for the web service, test the web service using SoapUI, and so on.

Alternatively you can run the command:

mvn eclipse:eclipse

and follow the directions from my earlier blog entry to run the example using Eclipse WTP, which will allow you to edit the code while keeping it synchronized with a live application server.

Good luck! If you encounter any problems using this template, please email me or post a comment so that I can look into it and revise the instructions if necessary.

A maze of twisty little Java web service standards, all alike

October 22nd, 2008 / Joe on Computing

It’s almost impossible to keep up with all the fractal-like Java standards related to web services. As fast as each can be learned, Sun invents another, and a dozen open source implementations appear. For my own sanity I tried to create a rough map of some of them. I’ll try to avoid making recommendations; my main objective is to sketch out how they fit together.

First, it’s important to understand that there are three main players with implementations of of these standards: Sun, the Apache foundation, and Codehaus. There are many other open source implementations as well, but these are the three 800 pound gorillas, for a total of 2400 pounds, or almost exactly one metric tonne (for our international audience).

Second, keep in mind that there are three important APIs which are inter-related: JAX-WS, JAXB, and StAX. Once you understand how these fit together, everything else falls into place more easily.

JAX-WS

Let’s begin our journey with the latest Sun standard for creating and consuming web services: JAX-WS, which stands for Java API for XML Web Services. This standard was introduced in 2004. You can ignore JAX-RPC, since JAX-WS replaces it.

There are three noteworthy implementations of JAX-WS. The first is from Sun, and is called JAX-WS RI for the JAX-WS Reference Implementation (they always had a way with names). The second and third are both from the Apache Group and are called Axis2 and CXF. You can ignore Axis1, XFire, and Celtix, since they are all obsolete. There is also a web service framework called Spring-WS, but it’s not JAX-WS compliant.

So if you are creating web services in Java, the first order of business is to to choose an implementation to work with, and unless you have a reason not to, you should probably stick to one that complies with JAX-WS, which means either JAX-WS RI, Axis2, or CXF.

Related to these is an open source project from Sun called Web Services Interoperability Technologies (WSIT), previously known as Project Tango. This is an implementation of several web service standards (WS-SecurityPolicy, WS-ReliableMessaging, and so on). Metro is an open source web service stack which is a combination of JAX-WS RI and WSIT (so it’s actually a reasonable fourth option).

JAX-WS is oriented around SOAP web services, but many programmers are now using the REST approach. Sun is coming out with the JAX-RS API to support that, but it’s not quite ready yet.

JAXB

Web service development requires mapping between XML and Java objects. JAXB is the Sun API for that (also referred to as JAXB2 since the latest version is the important one). There are two noteworthy implementations: JAXB-RI (Sun’s reference implementation) and JaxMe (the unfortunately named contribution from Apache). JaxMe is in the incubation stage and is not formally part of Apache yet. There are many other interesting and popular XML/Java mapping frameworks, but most of them are not compliant with JAXB. Examples include Castor (from Codehaus), JiBX (a spectacularly fast open source implementation), and XMLBeans (a flexible implementation from Apache).

A recurring source of confusion is that in the past, Sun was less clear about the distinction between APIs and reference implementations, so people would take JAXB to mean both, and you would often see online articles like “Which is better: JAXB or JiBX?” But today developers should always try to use the JAXB API, which will enable a choice of compliant implementations such as JAXB-RI or JaxMe with minimal or no code changes.

StAX

For Java code that needs to read and write large XML documents quickly without necessarily mapping them to objects, there is the Streaming API for XML (StAX). There are several implementations of this API too. There is the Sun Java Streaming XML Parser called SJSXP (another snappy name from Sun), the Woodstox open source implementation which is excellent, and the StAX reference implementation from Codehaus which is referred to simply as StAX (unfortunately perpetuating the confusion between APIs and implementations). Xerces is a streaming XML processing library which used to be part of the Apache project, and work was underway to make it StAX compliant, but that was dropped.

Putting it all together

Web services need to process XML, sometimes mapping it to and from Java objects (e.g. for creating proxy objects and an RPC-like experience), and sometimes processing it directly (e.g. for streaming results when high performance is needed). Therefore Sun designed the JAX-WS API to rely on the JAXB API, which makes perfect sense; any JAX-WS compliant web service implementation should therefore be able to use any JAXB compliant mapping library. Other relationships between these APIs are up to individual implementations. For example, JAX-WS RI supports the StAX API, so you can use any StAX implementation for streaming. CXF also supports the StAX API, as well as a host of Java/XML mapping options including JAXB (allowing the use of any JAXB compliant implementation), XMLBeans, Castor, and JiBX. Yes, they are heroes.

So if you get confused, just ask yourself clarifying questions like: Does this Java web service library support JAX-WS? Which JAXB compliant Java/XML mapping implentation shall I use? Which is better for processing streaming XML? Woodstox or the StAX reference implementation?

If you’re still confused, then just accept the recommendations I promised not to make: Use CXF for your web services (which complies with JAX-WS), JAXB-RI for your Java/XML mapping (which complies with JAXB), and Woodstox for streaming (which complies with StAX).

Tomato: An antioxidant for your router

October 6th, 2008 / Joe on Computing

Every few months my Linksys WRT54G V4 home wireless router stops working and nothing short of a full reset gets it going again. This weekend it happened again. I got fed up and started Googling. I found out I’m not the only one to suffer from this problem. But then I found out that in 2003 Linksys, under pressure to comply with the GPL, released the router firmware and immediately afterward people started coming out of the woodwork improving it. (Doesn’t anyone have better things to do with their time?) Seriously, this has to be one of the best open source success stories ever. Some open-source variations of the firmware provide more features, giving this $60 router functionality similar to a $600 router. Others allow you to boost the RF signal. Still others provide a simplified and improved user interface. Most allow SSH or Telnet access to the router’s Linux kernel. All of them reportedly improve its reliability. I researched several of these and tried DD-WRT for a few hours. It’s very powerful and I was almost sold, but then I discovered Tomato. It’s perfect and I’m never going back.

From the Tomato home page: “Tomato is a small, lean and simple replacement firmware for Linksys’ WRT54G/GL/GS, Buffalo WHR-G54S/WHR-HP-G54 and other Broadcom-based routers. It features a new easy to use GUI, a new bandwidth usage monitor, more advanced QOS and access restrictions, enables new wireless features such as WDS and wireless client modes, raises the limits on maximum connections for P2P, allows you to run your custom scripts or telnet/ssh in and do all sorts of things like re-program the SES/AOSS button, adds wireless site survey to see your wifi neighbors, and more.”

It installed like a dream on top of DD-WRT, and the user interface is simple and clean. Most of the complexity is devoted to QoS functions, which I actually care about (unlike many of the obscure routing options provided by the original Linksys firmware) since I use my home computers for streaming music, Skype, and other network-intensive applications. Furthermore it provides nice usage monitoring and visualization tools. The user interface is a nice red color, the exact same shade as Campbell’s tomato soup.

After installation, my home network seems noticeably faster, but that may just be cognitive dissonance. (After all, if I spent an entire evening not making my network faster, that would make a pretty poor blog entry.) The main question now is whether my router’s reliability will improve, but from reviews online and my initial experience, I’m optimistic. We’ll see over the next few months.

If you decide to try installing Tomato, make sure your router hardware version is supported. For example, Tomato isn’t supported on the Linksys WRT54G V5 or later since Linksys removed half the RAM in all versions after V4.

Open source graph visualization tool - Graphite

June 28th, 2008 / Tech notes
Orbitz, the popular travel planning website, had recently brought some of their (previously proprietary) projects into the public domain by making them open source.

Graphite is a scalable, real-time graph visualization tool, released under the Apache License.

Some of the interesting aspects of the same (courtesy, the FAQ of the software):


  • Written in Python, based on the Django project.
  • The rendering engine is based on the Cairo framework, the same rendering engine used for the rendering of content in the Firefox 3 browser.
  • The input data has to be a numeric time series. (This seems intuitive since graph visualization schemes, differences ought to be based on some quantitative measure eventually). And then, of course - any categorical metric could be mapped to preset numerical values to achieve a similar effect.



Graphite, seems to achieve the scalability by storing the entries in a distributed in-memory database, similar to what LiveJournal implements using the memcached service. And more recently, microsoft has started offering Velocity , a competing product in the same space (with subtle differences though- which I will cover later ).

code.lab49.com

September 29th, 2007

Lab49 has created a public repository for open source software projects.

I have a few projects up that I’d like to tell you about.
Read the rest of this entry »

Declarative programming - have we gone too far?

July 7th, 2007

For some time I’ve been planning to write a blog entry highlighting the problems that can occur when declarative programming is taken to an extreme (I’m thinking about Spring here). What prompted me to actually write it was this post which conveyed my feeling, if not my exact technical point:

http://nutrun.com/weblog/no-more-jars/
Read the rest of this entry »

Indexing LINQ

May 24th, 2007

Microsofts LINQ presents a wonderful sql-like syntax for querying arbitrary collections of objects. Under the hood, however, that sql-like syntax is transformed into what is called a monoid comprehension, which, scary though it may sound, is basically one or more nested loops.

This nested loopiness means that if you do anything more complex than filtering or mapping on a collection, for example a join, you will rapidly end up in a world of performance pain and your query starts performing O(n^m), where m is the number of nested loops.

Consider the following LINQ query:

var q = from c in customers
join o in orders on c.Key equals o.Key
select new {c.Name, o.OrderNumber};

This code will get translated into something like this:

foreach (var c in customers)
foreach (var o in orders)
if (c.Key == o.Key)
yield return new { c.Name, o.OrderNumber };

For small collections, this approach is fine, but when they start to get larger, the number of times through the loop is going to get out of control.

Relational databases sometimes have to perform the same algorithm, but they also provide the possibility of indexing the collections, which in the case of the example above, would eliminate the necessity of scanning through all the orders checking each to see if its key matches a customer - instead, the index would be used to rapidly identify the small number of matching orders.

You can bet your bottom dollar that Microsoft has something in the works to address this issue - LINQ to objects is basically useless without indexes. In the mean time, however, there is i4o, a project to do exactly that:

Introducing i4o
Codeplex - i4o

Rich User Interface on the Web

January 10th, 2007

Applications with rich, desktop-like user interface delivered over the Web have been expected to go mainstream probably every year since a “browser” became a piece of software. There’s even a three-letter acronym for software to be enabled by this yet-to-be-decided winner, Rich Internet Application (RIA). Java started with the promise of applets aiming to accomplish exactly this but got sidetracked (I remember reams of texts on how to manipulate images on the client side with startling but useless effects). These days, the choice of technologies is broader than ever before. Let’s take a look at contenders, in the ascending order of successfulness, judged entirely subjectively by yours truly.

Read the rest of this entry »

Software Metrics

November 20th, 2006

The article The Good, the Bad and the BS by Larry O’Brien is a sad truth. We always want to do the best possible job, but how can we prove we really did? How can we compare if one developer/team/firm is better at cranking out software than another developer/team/firm? From estimation to hiring to delivering systems, we could definitely use some metrics to advance the software trade. After all, us software developers have been terribly good so far at doing impossible things, judging by the saying You can’t manage what you can’t measure (looks like Tom DeMarco said something like this as cited here), so we might as well start doing the mundane: collaborate on meaningful metrics, establish industry benchmarks, and use them. There are of course difficulties, many of them stemming from the young age of software development profession. Read the rest of this entry »

Hibernate Is Not the Only (or the Best) Java Object-Relational Mapper.

November 9th, 2006

Gavin King, the creator of Hibernate, is a brilliant engineer, but he’s an even better marketer. Although Hibernate wasn’t the first open source Java ORM, and it lacked some important features available from its competitors, he somehow managed to convince the rest of the industry to adopt the framework as a standard.

But if you’ve been frustrated with Hibernate’s limitations, and you’d like to take a look at an alternative, check out the Apache Software Foundation’s Cayenne. Not only has Cayenne been around longer than Hibernate, but it offers features that Hibernate doesn’t, such as a graphical modeling tool, and the ability to nest Units of Work.

Cayenne is available from: http://incubator.apache.org/cayenne/