Friday, April 11, 2008

DSL for time and money

(Well, for time anyway)

A couple of weeks ago, I did some work together with Eric Evans when he came to Uppsala to give his excellent course in domain driven design, which was co-hosted by Citerus and Patrik Fredriksson.

Eric is the project leader of the Time and Money Java library, which makes working with dates, time intervals, currencies and so on a breeze. However, inspired by this article by Guillame Laforge, I wanted to see if I could create something similar by leveraging Groovy and the Time and Money library. These are a few simple examples that I came up with in an hour:


println 1.minute

=> '1 minute'


println 5.minutes + 1.minutes

=> '6 minutes'


println "2003-05-16" + 3.weeks - 50.years

=> 'Sat Jun 06 01:00:00 CET 1953'

Looking at these statements from top to bottom, we first have

1.minute

The number 1 is of course an instance of java.lang.Integer, a full-blown object. On that instance, we access something called minute, which kind of looks like a field, but is actually a JavaBean property thanks to Groovy's built-in support for those. So what we really have is an invocation of Integer.getMinute(), a method that doesn't exist. But don't worry - here's how we can use metaprogramming to add that method to the Integer class:

Integer.metaClass.getProperty = {symbol ->
switch (symbol) {
case ["minute"]:
return Duration.minutes(delegate)
default:
return null
}
}

In Groovy, every class has a corresponding open metaclass, the ExpandoMetaClass, that may be used to dynamically add methods on classes. The method getProperty is invoked when a JavaBean property is accessed, and here we assign a closure to be evaluated on invocation. The closure recieves one argument, symbol, which is a String containing the name of the property accessed, in this case "minute". This particular case is chosen to be converted to a Time and Money datatype, Duration, by passing the delegate (that's the instance we're invoking the getter on, i.e. 1) to the appropriate factory method. The result is that a Duration instance is returned, representing one minute.

Moving on to the next one, we have

5.minutes + 1.minute

The terms being added are familiar by now, although we need to expand the previous closure to this:

Integer.metaClass.getProperty = {symbol ->
switch (symbol) {
case ["minute"]:
return Duration.minutes(delegate)
case ["years", "quarters", "months", "weeks", "days", "hours", "minutes", "seconds"]:
return Duration.getMethod(symbol, int).invoke(null, delegate)
default:
return null
}
}

Fortunately, the Time and Money library has nicely named methods that correspond exactly to how we want to express durations in this DSL, so we can be very efficient and use reflection invocation of factory methods. Oh, and it's very nice to be able to switch on lists, isn't it? :-)

But there's one more thing to it: the overloading of the + operator. We've already established that both 1.minute and 5.minutes are instances of Duration, and luckily the Duration class already has a plus(Duration) method on it, that Groovy will automatically evalute. It's not always the case that there is such a method available though, as we find out when we move on to the third case:


"2003-05-16" + 3.weeks - 50.years

Evaluating from left to right, we're initially adding a String and a Duration, but String does not have any plus(Duration) method, so we're going to have to add that:


String.metaClass.plus = {Duration duration ->
return duration.addedTo(TimePoint.parseGMTFrom(delegate, "yyyy-MM-dd"))
}

Here, we're using the Time and Money API to represent the String as a TimePoint, to which a Duration may be added, producing another TimePoint. Continuing our evaluation, we now have to subtract a Duration from a TimePoint, which should be quite familiar by now:

TimePoint.metaClass.minus = {Duration duration ->
return duration.subtractedFrom(delegate)
}

These are just a few examples, and the possibilities are vast.

Thursday, April 10, 2008

Grails Pet Store 0.2 released

I finally managed to wrap up a semi-stable milestone of Grails Pet Store, and the roadmap is now available in the form of tagged issues. Hopefully there will be a live instance available Real Soon - watch this spot for updates.

Sunday, March 02, 2008

Podcast from JFokus available

The JFokus presentations are finally available online. Both my presentation on Grails and my collegue Patrik Fredriksson's presentation on the specification pattern are available here. Type your name, press login, then press Play on the next page. Don't ignore the yellow information box if you're running Mac :-)

Tuesday, February 26, 2008

Damn you DBUnit!

I simply can't get over how powerful the Groovy XML and SQL support is, especially when you combine the two. Did you ever find yourself in the position where you wanted to convert a Hypersonic database to a DBUnit dataset? I did, and I told my co-worker, somewhat disgruntled, that "I bet this could be done with 30 lines of Groovy". Well, it could:


import groovy.sql.Sql
import groovy.xml.MarkupBuilder

def sql = Sql.newInstance("jdbc:hsqldb:my_db", "sa", "", "org.hsqldb.jdbcDriver")

def sw = new StringWriter()
def xml = new MarkupBuilder(sw)

xml.dataset {
sql.eachRow "select * from system_tables where table_type != 'SYSTEM TABLE'", {
table(name:it.TABLE_NAME.toLowerCase()) {
sql.rows("select * from ${t}", { md ->
md.columnCount.times {
column md.getColumnName(it + 1).toLowerCase() ?: ""
}
}).each { r ->
row {
r.size().times {
value r[it]
}
}
}
}
}
}

println sw

This is why I like Groovy - it's powerful, yet elegant.

Sunday, February 24, 2008

Groovy power

The concurrent API that was added to Java 5 is very powerful for sumbitting tasks to a worker thread pool, but when you combine it with the Groovy ability to implement single-method interfaces with closures you have a real winner.


import java.util.concurrent.Callable
import java.util.concurrent.Executors

def executorService = Executors.newFixedThreadPool(4)

def x = {
20.times {
println "X"
}
} as Callable

def y = {
20.times {
println " Y"
}
} as Callable

executorService.invokeAll([x, y])

executorService.shutdown()

which of course has an output similar to this:

X
Y
Y
Y
X
Y
X
Y
X
Y
Y
X
X
Y
X
Y
Y
X
X
X

Pretty neat, huh?

Friday, November 30, 2007

Shameless plug

For all my swedish readers who aren't either working for Citerus or are regular guests in the same IRC channel as I am (should amount to about zero people, I'm afraid) - here's an introductory article on the excellent Grails framework that I've written for PNEHM, Citerus' newsletter on agile development.

I will also host a short (20 minutes) oral presentation on the same subject at the upcoming JFokus conference, in January.

Tuesday, September 18, 2007

Advisor summary

It's been a while since the last post, I've been busy with my new assignment that begun right after my vacation. Anyway, here a nifty little routine to quickly get an overview of which beans are woven by what advice, and also what advice weaves which beans in a Spring context:


ApplicationContext context = ... ; // Create your context

String perBeanSummary = "--- Advisors per bean ---\n";
Map<String,Advised> beanMap = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, Advised.class);
Map<Advisor,Set<String>> advisorMap = new HashMap<Advisor, Set<String>>();

// This gathers advisors per bean and beans per advisors,
// and builds the presentation of advisors per bean
for (String beanName : beanMap.keySet()) {
Advised advised = beanMap.get(beanName);
perBeanSummary += beanName + ":\n\t";
for (Advisor advisor : advised.getAdvisors()) {
perBeanSummary += advisor.getAdvice().getClass().getName() + "\n";
Set<String> beans = advisorMap.get(advisor);
if (beans == null) {
beans = new HashSet<String>();
advisorMap.put(advisor, beans);
}
beans.add(beanName);
}
perBeanSummary += "\n";
}

// Builds the presentation of beans per advisor
String perAdvisorSummary = "+++ Beans per advisor +++\n";
for (Advisor advisor : advisorMap.keySet()) {
perAdvisorSummary += advisor.getAdvice().getClass().getName() + "\n";
for (String beanName : advisorMap.get(advisor)) {
perAdvisorSummary += "\t" + beanName + "\n";
}
perAdvisorSummary += "\n";
}

System.out.println(perBeanSummary);
System.out.println(perAdvisorSummary);

Monday, August 13, 2007

Grooeat work, JetBrains!

The first day after the vacation was fairly productive, after all. In preparation for an upcoming PNEHM article, I've successfully installed a snapshot of IDEA 7.0 and built a Subversion snapshot of the Groovy/Grails plugin. This is the first thing I tried out - it looks very promising:


Dynamic typing and completion!

Update: it turns out IDEA also completes the Groovy additions to the JDK. Not completely unexpected when you've seen the screenshot above, but nevertheless very nice!

Thursday, July 12, 2007

Implementing ActiveRecord in Java

The ActiveRecord (AR) design pattern is very popular right now, forming the base of web application frameworks such as Ruby on Rails and the Groovy-based Grails. Martin Fowler defines the pattern as follows:

An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.

AR is very closely related to the concept of an Object-Relational Mapper (ORM), and is an alternative to the Data Access Object (DAO) and Repository patterns. In the latter two patterns, persistent data operations are separated from the domain object into one or more dedicated interfaces.

AR is very attractive if you want to build a more powerful domain model, as opposed to using it as a simple data container. It ties the most obvious domain logic into the domain object (namely CRUD), and opens up possibilities to write higher-level properties and operations on your domain objects.

It can also aid in normalizing the three-tier architecture, by which I mean avoiding the all too common situation where you have a request mapped to an object in the MVC layer, which calls the service layer, which initiates a transaction and calls the DAO layer, which calls the ORM, which stores the object in the database. It might be even worse - you may need to convert the bound request data from a form bean to a Data Transfer Object, both of which could be separate from the domain object. Normalizing this operation would mean binding request data to a domain object, which then stores itself.

So, building an ActiveRecord base class in Java means that at least the following methods must be implemented:

public class ActiveRecord<T> {
public static <T> T load(Long id) { .. }
public void store() { .. }
public void delete() { .. }
public static <T> List<T> findAll() { .. }
}

Derived classes will add all sorts of operations, notably a number of specialized finders with similar signatures to findAll().

In order to be able to access non-domain services we need a way to access external services, preferably through Dependency Injection. It's also mandatory that we are able to isolate the domain object for test purposes, and to be able to mock or stub dependencies, all of which is enabled by using DI.

It's also natural to use a full-fledged ORM - Java now has a standard API for that (JPA), and there are a number of different implementations available: Hibernate, TopLink, OpenJPA etc. There's also JDO, iBatis and of course you could also use plain JDBC if you really have to.

I've been using (surprise, surprise!) Hibernate as ORM tool, and Spring for DI and transaction demarcation, all of which are using annotations and build-time weaving using AspectJ and AJDT. Dependency injection of service beans into domain objects is taken care of by the @Configurable annotation, and transaction demarcation by the the @Transactional annotation, so those problems are very cleanly solved.

However
: static methods, such as loaders and finders, don't seem to be woven by transactional advice, at least not when using compile-time weaving. I need to investigate this further, but I believe it might be caused by the fact that a "this" joinpoint is being used here. Workarounds include writing transactional advice manually, using TransactionTemplate for example, or following the mixed AR/Repository pattern suggested below. The best solution would be to have an aspect that's able to read transaction attributes from annotations even in a static context.

The first roadblock is how to gain access to the ORM in a static context, the loader and finder methods. We need a reference to the unit-of-work (session) provider - the SessionFactory in this case - in order to create or obtain the current session for performing data operations. Since we don't have an instance of AR or a derived class, we can't access any injected SF reference.

I've thought long and hard about this, and tried a number of different approaches, but the way I see it, you basically have to give up either static loaders/finders or give up dependency injection. Any way you look at it, you will need some sort of static handle to the SF - you might make the SF member of the AR class static, or you could use some variation of SessionFactoryUtil, or maybe use some sort of lightweight holder object that's instantiated, injected and finally discarded as part of the static operation. The problem with static references, and the ServiceLocator pattern, is that you can't isolate objects completely - there can be only one implementation per class loader at a time, and all instances of a class with a static reference must share the same implementation. This makes testing harder and less robust, compared to a pure DI environment: you must make sure to "reset" the service locator reference after each test, even in case of failures, so you'll end up with a number of try - finally blocks everywhere, and you can't run tests in parallell since you can't guarantee what implementation the factory will return. (Crazy) Bob Lee talks a little about that in this Guice presentation.

So, as far as I can tell, you will need to give up DI, or at least mix DI and ServiceLocator in your application, if you want "pure" ActiveRecord. I'll be very interested if anyone can show a way to use AR and DI together, though :-). For now, I prefer a mix between AR and Repository, but more about that in a little while. If you decide to go for pure AR by using a static SF reference, your next problem will be how to tell the ORM which class to load, without adding redundant data in derived classes, such as overriding load() or keeping a static class member pointing to its own class.

When performing a load, you will need to know what class, or sometimes what table, to load the data from, in addition to the supplied identifier property. Optimally, the implementation of load() exists in the top class ActiveRecord only, and should return a correctly typed object. In short, we want to use the API like this:

Customer c = Customer.load(1);
Item item = Item.load(125);

where Customer and Item both inherit ActiveRecord.

Typing is taken care of by generics, as you can see a few paragraphs earlier. But since it's a static method, there's no "this" to ask for the current class, so finding the current class to feed to Session.load(id, clazz) is harder. There is no API access point in Java, and I've fiddled with various reflection hacks against sun.reflect.Reflections for example, to peek at the call stack, but to no avail. I did however find a way by using the "call" joinpoint in AspectJ and the following construct:

/*
* Keep the traditional load() signature as access point.
*/
public static <T> T load(Long id) {
throw new RuntimeException("This body should never be reached, weaving has not been performed");
}

/*
* This method performs an actual load.
*/
protected static <T> T doLoad(Long id, Class clazz) {
return (T) getSession().load(id, clazz);
}

/*
* This inner class aspect intercepts the call to load, and inspects the join point
* to determine what class the static call was made on, and reroutes the call to
* doLoad() with the correct class parameter.
*/
@Aspect
protected static class ClassIdentifier {

@Before("call (* load(Long)) && args(id)")
public T interceptLoad(ProceedingJoinPoint pjp, Long id) {
Class clazz = pjp.getSignature().getDeclaringType();
return ActiveRecord.doLoad(id, clazz);
}

}

So, if you are prepared to give up reliable replacement of the ORM interface reference, ActiveRecord is within reach. In fact, you might find that you rarely or never mock or stub something like the SessionFactory, but instead simply use a dedicated data source for testing which is loaded with test data. That's perfectly reasonable imo, if you work directly against the ORM API, but it gets a bit more complicated if you keep your own DAO layer around, tested separately from the domain object, and inject that into your domain objects instead.

If you want to go for pure DI, I would argue that it's reasonable to split CRUD operations between the domain objects and a shared "read only"-repository. Operations that work on an actual instance, such as user.store() or item.delete() (non-static by nature), are placed in the domain objects. But operations that result in one or more instances are retrieved according to various criteria, loaders and finders, are placed on a separate service. Those are the same methods that would be static in ActiveRecord.

This approach is DI-compliant, because each domain object instance has its own non-static reference to the ORM, and the Repository service also is injected with an ORM reference. The repository can be regarded as a third party, where you go to retrieve instances of domain objects. By clever use of generics, the amount of code can be kept low, and a single @Transactional annotation at class level on the implementation marks every method for execution in a read-only transaction.

interface Repository {
// Typing on the methods instead of the interface
// allows us to share this interface across the domain model
<T> T load(Long id, Class clazz);
<T> List<T> findAll(Class clazz);

// Various specific finders are added as they are needed.
Customer findByUsername(String username);
List<Item> findDeliveredItems();

// Some kind of generic query-object method might be added too
}

This distinction between instance-tied domain logic versus third-party is then extrapolated throughout the application.

Wednesday, June 27, 2007

Weird but useful generics trick

I stumbled upon the following piece of code while programmatically creating AspectJ proxies with Spring:

// create a factory that can generate a proxy for the given target object
AspectJProxyFactory factory = new AspectJProxyFactory(targetObject);

// add an aspect, the class must be an @AspectJ aspect
// you can call this as many times as you need with different aspects
factory.addAspect(SecurityManager.class);

// you can also add existing aspect instances, the type of the object supplied must be an @AspectJ aspect
factory.addAspect(usageTracker);

// now get the proxy object...
MyInterfaceType proxy = factory.getProxy();

(Pasted from here)

If you look carefully, you'll notice that A) the AspectJProxyFactory class is not parameterized, and B) the proxy creation is assigned to a MyInterfaceType without a cast. I found this to be rather confusing, and took a quick peek at the AspectJProxyFactory source:

public class AspectJProxyFactory extends ProxyCreatorSupport {

[...] // Stuff

public <T> T getProxy() {
return (T) createAopProxy().getProxy();
}

}
The return type is inferred by the assignment, regardless of the (lack of) type on the owning class, which effectively looks and feels like dynamic and static typing all at the same time!

Kind of weird, but might be useful. I, for one, was not aware of this technique.

Wednesday, May 30, 2007

Making JDOM run faster

It's time for another cool AspectJ hack here on RMA, once again leveraging Codehaus' excellent Maven plugin. Still working on the same project as the last post, we've decided to move from standard JAXP to JDOM for programmatic XML handling (the JDOM api is so much nicer to work with it's not even funny). As the returning reader may recall, the model in the MVC part of our application basically consists of a number of XML documents, and the view rendering technology is Freemarker. Freemarker is supposed to be able to handle both JAXP, JDOM and dom4j, but a closer look will reveal that it's more or less only JAXP that's up to date, the other wrappers are deprecated and don't work correctly anymore, which is a shame.

Using JDOM, there is a simple workaround however: the DOMOutputter, which is capable of converting an org.jdom.Document to an org.w3c.dom.Document which can then be handed to Freemarker. There is a speed penalty of course, and when profiling we found that almost all the time is spent in this method, in JAXPDOMAdapter:

public Document createDocument() throws JDOMException {

try {
// We need DOM Level 2 and thus JAXP 1.1.
// If JAXP 1.0 is all that's available then we error out.
Class.forName("javax.xml.transform.Transformer");

// Try JAXP 1.1 calls to build the document
Class factoryClass =
Class.forName("javax.xml.parsers.DocumentBuilderFactory");

// factory = DocumentBuilderFactory.newInstance();
Method newParserInstance =
factoryClass.getMethod("newInstance", null);
Object factory = newParserInstance.invoke(null, null);

// jaxpParser = factory.newDocumentBuilder();
Method newDocBuilder =
factoryClass.getMethod("newDocumentBuilder", null);
Object jaxpParser = newDocBuilder.invoke(factory, null);

// domDoc = jaxpParser.newDocument();
Class parserClass = jaxpParser.getClass();
Method newDoc = parserClass.getMethod("newDocument", null);
org.w3c.dom.Document domDoc =
(org.w3c.dom.Document) newDoc.invoke(jaxpParser, null);

return domDoc;
} catch (Exception e) {
throw new JDOMException("Reflection failed while creating new JAXP document", e);

You're probably wondering why the hell they're using this much reflection just to create an empty Document (we did, anyway). It avoids compile-time dependencies on certain javax.xml classes, but it sure isn't designed with high performance in mind!

In addition to that, the call trace from DOMOuputter to JAXPDOMAdapter contains private methods, so you can't simply inherit and override with your own implementation. So, what now? AspectJ to the rescue, of course!

What we realy want to do is replace this implementation with one that performs the sam thing but statically, so we wrote this around advice (DocBuilder creation omitted for brevity):

@Aspect
public class FastDOMDocumentCreator {

@Around("execution (* org.jdom.output.DOMOutputter.createDOMDocument(..))")
public Object createDOMDocument(ProceedingJoinPoint pjp) throws Throwable {
return docBuilder.newDocument();
}

}

This is a lot faster than the default way. But how do we perform weaving of JDOM classes, that are in an external jar? Actually, it's really simple: just place this snippet in the AspectJ plugin section in the pom-xml (details here):

<configuration>
<weaveDependencies>
<weaveDependency>
<groupId>jdom</groupId>
<artifactId>jdom</artifactId>
</weaveDependency>
</configuration>

If you're using AJDT (which I highly recommend), make sure you add the JDOM jar to the inpath in the configuration dialog, that way this weaving runs on the fly just like regular compilation. On a sidenote, AJDT has some really cool features such as contextual information on "weaves" and "weaved by". It supports annotation-style aspects too.

The weaved jar is exploded under the output directory, with the new weaved classes instead of the vanilla ones. This trick pushed the JDOM-to-JAXP document converstion from the top way down on the hotspot list, with a fairly small amount of work.

Update: While examining the situation a bit closer, we found that in fact it's possible to accomplish the same thing without having to weave the JAXPDOMAdapter. Extending AbstractDOMAdapter using the same code as in the aspect, and passing the new class' name to the DOMOutputter constructor will work too. Nevertheless, the technique is still interesting and may be applicable (as the only solution) somwhere else.

Wednesday, May 16, 2007

Clean solutions are the best

Don't you love it when things just seem to fit together exactly as you want them to? It doesn't happen all too often, but when it does, you just want to blog at the top of your lungs...

I'm working on a project where we communicate with an index server over HTTP, and recieve the query results in XML format. It's a data source, which basically boils down to this interface - the DocumentSource:

Document retrieveDocument( URL url );

The contract of this component is that if the document retrieval succeeds, we get a parsed and ready org.w3c.Document back, and in all other cases it throws some kind of exception. Handling exceptions is done in another part of the application, so don't worry about that right now.

Now, a failure can be either uncontrolled, for example if the index application hits a bug, if there's a network problem, the server might be on fire and so on. It could also be a problem with our implementation of of the afromentioned interface (not likely). In either case, the component will throw an exception to the caller, possibly wrapped in some way.

But a failure can also be controlled, which means that the index server returns a valid XML error message along with HTTP status 200 (OK), if the query is invalid in any way. This is also considered an error, and we handle in like this:

if (isErrorResult(document)) {
throw new IndexErrorException(method, document);
}

The method variable is the HttpMethod that we tried to execute, containing host, port and query information, and document is the parsed XML response from the index, in this case an error message.

What we want to do now is log this error, as transparently as possible. The snippet above expresses that we're not really interested in handling the error in detail, we just leave it at "ok, there was an error, so let's throw an exception. Here's all the information I have on why and where the error occurred".

That's all very well, but we still have to inspect the XML error message to present the error in a readable way. The best way to do that is of course the message property of the exception.

Here's where another aspect of our application comes in: we use Freemarker to build views (HTML and others) using the XML data we retrieve from the DocumentSource interface shown above. And since the error message is also XML, and we want to build a kind of view - a String - why not use the same approach here? That way we won't have to deal with cumbersome Java DOM apis, and we have maximum power to extract and format the error message the way we want. Sounds like a good idea.

It's also the case that we've abstracted away a lot of the fuss around the template engine, as well as the fact that we're using Freemarker, behind this very simple TemplateService interface:

String mergeTemplateIntoString( String templateName, Map model );

This service is a component, a Spring bean, in our application. It would be great if this service could be used to render the logged string from the document and the HTTP method, but in that case we have to supply the newly instantiated exception with a reference from the context. Sure, this could be accomplished by holding an (otherwise useless) reference in the DocumentSource implementation that is passed along the exception, but I prefer it when things Just Work.

Enter @Configurable and compile-time AspectJ weaving! We slap on an a TemplateService setter and an annotation (with autowire=Autowire.BY_NAME to avoid the need for a boilerplate bean definition) on the exception class. We're using AspectJ aspects for various other tasks already, and weaving is done at compile-time to avoid the proxy problem. The Codehaus Maven plugin works great!

In order to weave the Spring AnnotationBeanConfigurerAspect, we add the following to pom.xml:

<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>

And the aspect must be made aware of the Spring context (in any application context file):

<aop:spring-configured />
So from here on, the exception message may be rendered like this:

@Override
public String getMessage( ) {
return templateService.mergeTemplateIntoString( "error", model );
}

where "error" is the name of a template, and the model contains the XML document and some other stuff. The error message is now ready to be read and logged, for example in an @AfterThrowing aspect, but that's another story.

Sunday, May 06, 2007

Integrating Struts 1 and Spring

If you want to manage Struts 1 actions with Spring, for example to inject dependencies at runtime, you are going to need a bridging context that essentially duplicates every single action as a bean. (details are here). If you're working on an existing application with lots of actions, writing the bridge context XML will be a pain, so here's a quick Groovy hack that I came up with to generate the Spring context file from the Struts config file:

import groovy.xml.MarkupBuilder

def strutsConfig = new File("path/to/struts-config.xml")

def fromXml = new XmlParser().parse(strutsConfig)

def writer = new StringWriter()
def toXml = new MarkupBuilder(writer)

toXml.beans(
xmlns:"http://www.springframework.org/schema/beans",
"xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
"xsi:schemaLocation":"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd",
"default-autowire":"byName") {
fromXml."action-mappings".action.each {
bean(name:it["@path"],class:it["@type"])
}
}
}

// This simply dumps the XML to stdout, you could of course write to an actual file as well
println writer

This little snippet creates a <bean name="/foo" class="bar.Baz"/> for every <action path="/foo" type="bar.Baz"/> element in the struts-config.xml file, using a few neat Groovy tricks (GPath, closures, GroovyMarkup).

Still, you could do better. You could use a hook such as BeanFactoryPostProcessor that parses the Struts config and dynamically creates beans corresponding to the actions, or even write an XSD that allows Spring to interpret the Struts config file as a context file directly. There's an entry in the SpringIDE blog that shows how you could write a namespace that works in German, so for example <bean/> becomes <bohne/> and so on. That principle might be applicable to this context too.

Wednesday, April 25, 2007

Bandwidth saver

I never miss an opportunity to push for Freemarker, the most powerful template engine in the world, so here's a quick tip on how to strip all whitespace from your HTML pages:

<#assign out>
<#compress>
!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>

// Your page here

</BODY>
</HTML>
</#compress>
</#assign>
${out?replace('\n','')}


It assigns the compressed body of the outer assign macro to the variable "out", and the finally writes the value of "out" with all newlines stripped.

The entire page is now a singe line of HTML - a developer's nightmare, but a nice a bandwidth saver.

Combined with Sitemesh, another one of my favorite tools, this is easily and transparently applied to all your pages.

Tuesday, April 17, 2007

A quick peek at SpringIDE 2.0

There are a number of cool new features coming in SpringIDE 2.0, currently at milestone 3. One example is the new SpringExplorer, which is a comprehensive tree view of a Spring context, another is content assist for custom namespaces.

But the by far neatest new feature is the ability to evaluate AspectJ expressions in XML on the fly, and displaying what beans will be advised! Take a close look at this screenshot...an <aop:advisor> element is highlighted on the left, with an AspectJ pointcut expression. On the right, you can see what methods will be advised (the "advises" arrow). A godsend!

Thursday, April 12, 2007

One more thing...

I forgot one thing about Test-NG...they switched the order of "expected value"/"actual value" in the assert statements! So after finally having learned the hard way that the "expected" value should be first (JUnit 3), I now have to revert to (the more intuitive but less standard way of) putting the "actual" value first :-)

Today I'm struggling with an issue related to this: http://forum.springframework.org/archive/index.php/t-36086.html

Basically, an @Around expression with "&& args(foo)" works fine when the Eclipse compiler is being used, but not when Maven compiles the sources with Sun Javac 1.6, no matter how much debug info I turn on :-/

Wednesday, April 11, 2007

A week with Test-NG

On my latest assignment (I work as a consultant), we've decided to let go of the old workhorse that is JUnit 3, and go with one of the new, fancy @Nnotations-driven frameworks JUnit 4 or Test-NG. After a short evaluation period, which consisted of verifying basic Eclipse and Maven support and skimming a few tutorials, the feature sheet of Test-NG looked a bit stronger. The two major selling points of Test-NG over JUnit 4 were the ability to group tests and that Test-NG can run only the tests that failed the previous round.

However, the first week of day-to-day usage of Test-NG has been less than stellar, mostly (but not limited to) the poor IDE integration. My list of pros and cons versus the trusted old JUnit 3, when used inside Eclipse:

Pros:
  • The test class is only instantiated once, not once for each method in the test class. As it should be.
  • Better setup granularity with both @BeforeClass and @BeforeMethod entry points
  • @DataProvider is a nice feature, especially in conjunction with Selenium.
And the cons:
  • No built-in macro expansion in Eclipse that creates a test method - in a class that extends the JUnit 3 class TestCase, just type "test" and press Ctrl-Enter, and you have a method skeleton. Removing the need to inherit means more work in this case.
  • Keyboard shortcut Ctrl-Alt-X N does not work, so I have to use the mouse every time I want to run a test.
  • Can't run more than one test class at once, using multi-select in the file tree browser.
  • Can't run an entire package hierarchy of test classes in one shot.
  • Can't run a single test method by right-clicking a method name in the "green bar" view.
  • Using JMock is a lot more work, either by re-inventing half of MockObjectTestCase manually, or by using plain old inheritance.
  • No automatic static imports (a weakness of Eclipse's, to be fair), which forces me to write Assert.assertEquals() instead of just assertEquals() or write the static import manually.
So, a lot of annoyances on the ground level, and we haven't really started to see the benefits of large-scale features such as grouping and run-failed-tests-only. The verdict so far is that Test-NG is as good as or worse than JUnit 3, when counting in IDE integration.

And really, what is so fantastic about not having to inherit TestCase and naming your methods testXXX? Here's the number of times that has been a limiting factor in my work as a Java developer: 0.

Also, annotations are good for a lot of things (@Entity and @Transactional are great), but sometimes you get the feeling that various framework authors are going "OK, we now have annotations in Java, how can we possibly shoe-horn that into JMyFramework4J 2.0?"

Saturday, March 24, 2007

TSSJS 2007, full time

TSSJS 2007 is over, or at least it will be in about ten minutes. I left the last session a bit early since it focused a bit too much on SOA(P) and too little on raw XML processing, which was my area of interest. It's a real shame that there's no official after-party with a chance to mingle with the Java in-crowd, everybody just seem to go home. We are staying until Sunday morning, so Friday evening and Saturday will be a mini-vacation.


The second half has been mixed, as was the first one. This morning's keynote was an endless stream of three-letter acronyms and buzzwords from a top Oracle executive, Tomas Kurian. He outlined how Oracle see the future of computing, which was quite painful to sit through. At least until an interesting announcement was made: Oracle buys Tangosol Coherence. Cameron outshone the Oracle guys with his demo, which while it wasn't very substantial, it did actually work. The Demo Devil apparently spares no one, not even senior Oracle engineers.

But the absolute highlight of the entire conference was the "Java performance myths - how do JVMs really work" session with Brian Goetz. He crammed in probably around 150% more words that the average speaker (he talks fast), and it was extremely valuable information. He went through a number of long-loived Java performance myths (object allocation is slow, garbage collection is slow, synchronizarion is slow etc) and explained why they are no longer true. His advice can be summarized into the following sentence:

The JVM is always smarter than you.

Java isn't an interpreted language, it's dynamically compiled, which enables the JVM (or the JIT compiler) to gather statistical data, at runtime, on how code is being executed to aid in optimization of the code. Also, the JVM is tuned to recognize commonly found patterns of execution and optimize them as best it can. This means that the more well-designed, clean code you write, the bigger the chance that the JVM (JIT compiler) will recognize code patterns and be able to do a good job at optimizing the code. Since the compilation into native code happens at runtime, and can even vary over time (code can be re-analyzed and re-compiled dynamically), it's very difficult to try and predict how the source code you write actually will be compiled and executed. This also has the side-effect that writing isolated benchmarks is often useless and/or misleading, since they don't properly reflect real-world usage. Just write as clean, readable and maintainable code as you can, and safely assume that the JVM will do a better job than you at optimization.

One interesting aspect of synchronization improvements in recent JVMs (Sun Java 6, I believe) is that there is no longer any performance difference between using StringBuffer (syncronized) and StringBuilder (not synchronized), since the JVM automatically detects that synchronization isn't needed, and the code executed will be equivalent. I can actually back this up with test data I gathered around the time I wrote about how the Java bytecode compiler automatically converted String concatenation using the + operator to StringBuffer/StringBuilder (depending on which version of javac used). I found no speed difference whatsoever between the two, which profiling a webapp during load-test with several hundred simultaneous threads, which at the time made me quite confused, but now I have an explanation. So the old truth "Concatenating Strings is slow, use StringBuffer" and the not so old truth "StringBuffer is slow, use StringBuilder" are now both false*, and can instead be reduced to "it doesn't matter at all". Since performance is equal, readability wins - use regular concatenation (+).

Of course, in most cases the application bottlenecks aren't in your code at all, but in I/O operations against databases etc.

I wrote a small benchmark (even though I just said that benchmarks are useless) that you can check out and play around with.


* if the JVM comes to the conclusion that StringBuffer synchronization isn't needed, which is often the case.

Thursday, March 22, 2007

TSSJS 2007, half time

I'm writing this as I'm waiting for the the presentation "Agile Development Metrics" by Neal Ford to begin. I attended a presentation on Selenium that he did yesterday, and that was one of the better ones so far. The overall quality of the sessions has been mixed, ranging from fairly shallow (Rod on "Spring 2.0 and beyond") or way too basic (Mark Richards on "Advanced (bah!) JPA", Adrian Colyer on "Simplifying Enterprise development with AOP") to very good. Hani biled the JPA session, and my feelings were exactly the same. "Hey, if you add fetch=FetchType.EAGER to your annotation, the relation is no longer lazy!". Duh. Also, showing how to make a POJO transactional using AOP isn't exactly jaw-dropping in 2007.

What is jaw-dropping however is the scale of operations run by investment banks, that John Davis talked about this morning. Java is widely used in the banking world, and outperforms C/C++ a lot of the time, but a 50 ms garbage collection run is unacceptable since it would mean missing business opportunities worth millions of dollars. The solution: hardware garbage collection. He also explained that the speed of light was a limiting factor for performance. Yes, that's right. The speed of light. A theoretical best-case roundtrip for light to travel between New York to Chicago is around 8 ms, which is enough to motivate moving the physical system from NY to Chicago if you need to talk to another system in Chicago, for example. XML isn't widely adopted either, for performance reasons. If it's used at all, you often have a situation with a single element with 4000 attributes, to minimize the number of angle brackets to parse. And when it comes to reliable messaging, no JMS vendor can match the SWIFT system, used by 8000 banks world-wide to transfer money between them. They guarantee 100% reliability, to the point where they will refund any amount submitted to the system that is lost. However, in the 30 years that they've been operating, they haven't yet lost a single message. They average around 12 million messages a day. The particular investment bank that John talked about handled around $500,000,000,000 (five hundred thousand million dollars, or half a trillion) a day, so that's why even milliseconds matter. Quite a few "whoooa!" moments during the speech :-).

The second half of TSSJS contains a few sessions that I hope will be interesting, mainly around clustering and JVM and XML performance and scalability, which will be relevant in my current work assignment right away. There's one presentation held by a Swedish developer, Jonas Bonér of Terracotta fame which I'll be watching. Terracotta has gotten quite a few mentions in other presentations, and it seems really useful in some situations.

Next up is Cameron Purdy from Tangosol. I'll be back with a review of the second half on Saturday, I think.

Monday, March 19, 2007

Viva Las Vegas

Oh how hard it is to come up with headlines for non-technical posts...anyway, I'm going to The ServerSide Java Symposium in Las Vegas tomorrow, which I'm sure will be a fantastic experience. My room at The Venetian is almost as big as my apartement, and both the weather and the schedule look very promising indeed.

So, if you're reading this and are going to TSSJS, say hi if you recognize me (I have a little bit shorter hair than on the photograph right now). My guess is, however, that the only two people in the world that fit both categories are on the same plane as I am...