Sunday, November 20, 2011

Devoxx 2011

I attended the Devoxx 2011 conference in Antwerp, Belgium (thank you RSA Security).
This is the second large conference I've attended, the first being Java ONE in 2007, and I had a great time.

Stephan Janssenn and the Devoxx team did an excellent job organizing the conference.
The conference was packed with over 3,500 participants, 95% men, situated in Metropolis Antwerp Business Center.
The lecture halls were actually cinema theatres. Even though I haven't seen a movie in them (I missed the "Tintin 3D" feature film) they are hands-down the best cinema theatres I've been to, with more than enough leg room, extremely comfortable seats and arm rests which you don't need to fight over :)
Between lectures the screens showed the twitter wall, which was a brilliant idea I liked very much.



Every participant got a wrist band, very similar to the one I got a few months ago from the maternity ward when my son was born.
The thing is, it has to remain on your wrist until the conference is over. I can see why some people found this annoying but it actually worked in my favor, while sitting in the lobby of the hotel waiting for a taxi to take me to the conference the guy that sat next to me also wore the wristband so we ended up talking and sharing the ride.

Day 1: The Java SE keynote by Henrik Stahl was good. There was no big announcement, but I liked the message "Java will always be there for you".
I got a little bored in Cameron Purdy's Java EE keynote, where he promoted Weblogic and Oracle servers and left before it ended.
The "Play 2.0" talk was very good. I was impressed with the creativeness of Play 1.0 when I started using it, but these guys don't rest. They added innovative features to Play 2.0 continuing to make web development easier and faster.
"7 reasons to love JBoss AS 7" sounded promising but lacked technical details. It felt more like a marketing pitch. But it sounds promising and I'll need to check it out.
I then moved to the "JRuby enhancing Java developers' lives" talk, but it started off showing how to write web applications in Ruby, so I left and joined the "PhoneGap" talk, which was very amusing. I even managed to pick up a thing or two about mobile development, which is something I haven't tried (yet).
Next was "NoSQL for Java developers" which showed how a restaurant directory application would look like in an RDBMS (MySQL), a Key-Value store (Redis), a document store (mongoDB) and a multicolumn DB (Cassandra).
I think it's wrong to demonstrate all of them using the same use case. Each DB was built to solve a specific set of problems. Assuming the goal of the lecture was to show how non-relational DBs defer from relational DBs, then to show the strengths of every DB you need a different use case. E.g. show how your web application sessions would work with a KV store as opposed to RDBMS, how document stores have flexible schemas as opposed to rigid schemas in an RDBMS, and how queries performance differs as you scale out.
My day ended with an excellent talk from Brian Goetz about "Language/Library co-evolution in Java SE 8" which focused on Lambda and Closures, and how the existing JDK libraries might be enhanced to use these new features.

Day 2: The keynote from Tim Bray convinced me I should write mobile apps. I'm pretty sure I'm not gonna save the world, but I'm sure to it will be fun.
In the "Introducing Akka" talk I understood the concept of "Actors" and it sure sounds like a good tool to have in your developer toolbox.
"JMS 2.0" showed that there's not much to change in the JMS spec. If the spec wasn't 10 years old I would name the new spec version 1.2 :)
I then went to "Why we shouldn't target women", which about the state of female developers in the IT world. I was surprised to hear that in France and the UK only 15% of CS graduates are women. It was an interesting discussion without any conclusions.
"Java Posse live" was a comic relief. I got a beer and sat on the stairs to watch the show. I'm not sure this Posse podcast will provide much value to the listeners :)
"Having fun with Java and Home Automation" was a peek at the future. You'll be able to control and follow your house on twitter.
I ended the day with the "Code Generation" talk which got me thinking about the need for code generation in enterprise projects in the annotations era, see what Play! does in this area. I'm not sure it's very useful these days. I did learn a bunch of new stuff from the Xtext, Xtend and Spring Roo code generation demos.

Day 3: The final day began with a technical discussion panel which was interesting mostly because of the cynical remarks from Oracle and Google people.
I decided I had to go to one HTML5 talk so I entered "HTML5 Game Development" which was very good. Animation always make me feel I should brush up my Mathematics.
The last talk was about "Shazam", which is an app that identifies songs by hearing them. Roy van Rijn did a fantastic job explaining how he built a similar application in Java, including a good explanation about Fourier Transformation using a yellow stick. His talk ended with a lively discussion about software patents and violation after getting intimidating emails from Landmark (the company holding the Shazam patents).

Notes for next year:
  • Don't stay at Novotel Antwerp. It has no public transportation and no entertainment in its vicinity.
  • Set aside more time to see Antwerp. I have no idea what the city looks like.
  • Get a larger suitcase. My small trolley almost didn't have room for all the marketing items handed out at the booths.
See you again next year!

Sunday, February 6, 2011

Autoboxing puzzler

While performing code review I came across the following code (simplified for this post)

private void box(Long l) {
 if (l.equals(1)) {
  System.out.println("eq");
 }
 else {
  System.out.println("not eq");
 }
}

What will be printed when we call box(new Long(1))?
Can you spot the bug?

The condition l.equals(1) will always evaluate to false.

This happens due to the autoboxing specification and the implementation of the Long.equals() method.
According to the specification if the primitive value (1 in this case) is an int it is converted to a reference of class Integer.
The Long.equals() method starts with type comparison using the instanceof operator, which returns false for an instance of type Integer.

A possible solution is to compare the value to a reference of class Long value using if (l.equals(1L)), which boxes the value 1L to a Long.

Wednesday, November 3, 2010

Quickest JPA test-setup ever!

Have you ever wanted to test some JPA functionality? Were you discouraged to do so because of the long setup process?
I wanted to test some JPA functionality without the hassle of setting up a DB and configuring XML files, A simple, short piece of code that I was able to run immediately.

This can be done very easily with in-memory HSQLDB and configuration using annotations. You only need Hibernate and HSQLDB on your classpath.
Take a look:

package jpa;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

import org.hibernate.ejb.Ejb3Configuration;

@Entity
public class SimpleEntityTest
{
    @Id
    @GeneratedValue
    private Long id;
    
    private String name;
    
    public SimpleEntityTest()
    {
    }
 
    public Long getId()
    {
        return id;
    }
    
    public void setId( Long id )
    {
        this.id = id;
    }
    
    public String getName()
    {
        return name;
    }
    
    public void setName( String name )
    {
        this.name = name;
    }
    
    @SuppressWarnings("unchecked")
    public static void main( String[] args ) throws Exception
    {
        Ejb3Configuration cfg = new Ejb3Configuration();
        cfg.setProperty( "hibernate.connection.driver_class", "org.hsqldb.jdbcDriver" );
        cfg.setProperty( "hibernate.connection.username", "sa" );
        cfg.setProperty( "hibernate.connection.password", "" );
        cfg.setProperty( "hibernate.connection.url", "jdbc:hsqldb:mem:test" );
        cfg.setProperty( "hibernate.dialect", "org.hibernate.dialect.HSQLDialect" );
        cfg.setProperty("hibernate.hbm2ddl.auto", "create-drop" );
        cfg.addAnnotatedClass( SimpleEntityTest.class );
        EntityManager em = cfg.buildEntityManagerFactory().createEntityManager();
        
        System.out.println( "create the entity" );
        EntityTransaction trx = em.getTransaction();
        trx.begin();
        SimpleEntityTest ent = new SimpleEntityTest();
        ent.setName( "test" );

        em.persist( ent );
        trx.commit();
     
        System.out.println( "change the entity" );
        trx = em.getTransaction();
        trx.begin();
        List entlist = em.createQuery( "from " + SimpleEntityTest.class.getName() ).getResultList();
        for ( Object object : entlist )
        {
            SimpleEntityTest ent1 = (SimpleEntityTest)object;
            ent1.setName( "other" );
        }
        trx.commit();

        // check with a connection that is not managed by Hibernate
        Connection con = DriverManager.getConnection( "jdbc:hsqldb:mem:test", "sa", "" );
        Statement stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery( "select name from " + SimpleEntityTest.class.getSimpleName() );
        while ( rs.next() )
        {
            System.out.println( "Entity name: " + rs.getString( 1 ) );
        }
        rs.close();
        stmt.close();
        con.close();
   }
}

Even if you don't have anything installed you can be up and running in minutes using Maven (assuming you have Maven installed and working).
Follow 4 simple steps:
  • Create a Maven project: mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=jpa -DartifactId=jpa-test
  • Copy the above class to jpa-test/src/main/java/jpa
  • replace the pom.xml content with
    
     4.0.0
    
     jpa
     jpa-test
     1.0-SNAPSHOT
     jar
    
     jpa-test
     http://maven.apache.org
    
     
      UTF-8
     
    
     
      
       jboss.org
       Jboss Repo ORG
       default
       http://repository.jboss.org/maven2
       
        false
       
       
        true
       
      
     
    
     
      
       junit
       junit
       3.8.1
       test
      
      
       org.hibernate
       hibernate-core
       3.5.1-Final
      
      
       org.hibernate
       hibernate-annotations
       3.5.1-Final
      
      
       org.hibernate
       hibernate-entitymanager
       3.5.1-Final
      
      
       org.slf4j
       slf4j-api
       1.6.1
      
      
         org.slf4j
         slf4j-nop
         1.6.1
      
      
       hsqldb
       hsqldb
       1.8.0.10
      
     
    
     
      
       
        org.apache.maven.plugins
        maven-compiler-plugin
        
         1.6
         1.6
        
       
      
     
    
    
    
  • Build using Maven or your favorite IDE

Thursday, July 8, 2010

Running Play! framework JPA from a command line process

If you are using the Play! framework and wanted to run a command line process that uses the Play! JPA enhancements this post is for you.
It requires some classloader magic and is based on reading the source code of Play 1.0.x, I am not sure if this will be supported in future versions.

You need your Main class to prepare the Play! framework classes, set the classloader and load your "real" Main class using the Play! classloader.
This is how it's done:

public class LoaderMain
{
 public static void main( String[] args ) throws Exception
 {
        File root = new File(System.getProperty("application.path"));
        Play.init(root, System.getProperty("play.id", ""));
        Thread.currentThread().setContextClassLoader( Play.classloader );
        Class c = Play.classloader.loadClass( "com.incapsula.batch.PlayLoaderMain" );
        Method m = c.getMethod( "run" );
        m.invoke( c.newInstance() );
 }
}

Now since you are not invoking web services you need to execute the framework methods by yourself, e.g. initializing the plugins and openning a JPA transaction.
You'll have to get yourself familiar with the Play! framework source code for any dependencies your process has on the Play! frameowrk.

public class PlayLoaderMain
{
 public void run() throws Exception
 {
  new DBPlugin().onApplicationStart();
  new JPAPlugin().onApplicationStart();

  JPAPlugin.startTx( true );
  Fixtures.load( "initial-data.yml" );
  System.out.println( User.findAll() );
  JPAPlugin.closeTx( false );
 }
}

There are a few things to notice:
  • You need the Play jars in your classpath (play.jar, framework/lib jar files and module/lib jar files for every module you are using)
  • You need to point the "application.path" JVM property to your Play application
  • You need to initialize different Play! plugins if you need them (e.g. if you are using the Play! templates in your process you also need to initialize the MessagesPlugin)

Tuesday, July 6, 2010

JAXB, Sun and how to marshal a CDATA element

According to https://jaxb.dev.java.net/faq/index.html#marshalling_cdata there is no direct support in marshalling CDATA blocks, this is vendor specific.
I'll describe how this is done when using the built-in Sun implementation by an example.


Suppose this is my JAXB annotated class:
package org.oded;

import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Item
{
 @XmlAttribute public int id;
 
 public String text;
}

Next I run the Main class:
package org.oded;

import java.io.*;

import javax.xml.bind.*;

import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;

public class Main
{
 public static void main( String[] args ) throws Exception
 {
  Item i1 = new Item();
  i1.text = "hello";
  i1.id = 1;
  
  Item i2 = new Item();
  i2.text = "";
  i2.id = 2;
    
  Marshaller m = JAXBContext.newInstance( Item.class ).createMarshaller();
  
  m.marshal( i1, new OutputStreamWriter( System.out ) );
  System.out.println();
  m.marshal( i2, new OutputStreamWriter( System.out ) );
 }
}

The output is:
hello
<code><helloWorld/></code>

Now suppose I want to wrap the XML value of text in a CDATA element and avoid the escaping, I need to add specify an Adapter for text to surround the value in a CDATA element in the following way:

package org.oded;

import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Item
{
 @XmlAttribute public int id;
 
 @XmlJavaTypeAdapter(value=Adapter.class) 
 public String text;
 
 private static class Adapter extends XmlAdapter
 {

  @Override
  public String marshal( String v ) throws Exception
  {
   return "<![CDATA[" + v + "]]>";
  }

  @Override
  public String unmarshal( String v ) throws Exception
  {
   return v;
  }
  
 }
}

Now tell the Marshaller, in a Sun-specific way, not to escape the value of text:
package org.oded;

import java.io.*;

import javax.xml.bind.*;

import com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler;

public class Main
{
 public static void main( String[] args ) throws Exception
 {
  Item i1 = new Item();
  i1.text = "hello";
  i1.id = 1;
  
  Item i2 = new Item();
  i2.text = "";
  i2.id = 2;
    
  Marshaller m = JAXBContext.newInstance( Item.class ).createMarshaller();
  m.setProperty( "com.sun.xml.internal.bind.characterEscapeHandler", new CharacterEscapeHandler() {
   @Override
   public void escape( char[] ac, int i, int j, boolean flag, Writer writer ) throws IOException
   {
    // do not escape
    writer.write( ac, i, j );
   }
  });
  
  m.marshal( i1, new OutputStreamWriter( System.out ) );
  System.out.println();
  m.marshal( i2, new OutputStreamWriter( System.out ) );
 }
}

Now the output is:
<![CDATA[hello]]>
<![CDATA[]]>

Thursday, May 27, 2010

Using Play! precompiled classes

If you want to run Play! in PROD mode, after precompiling your code, you probably noticed that Play.usePrecompiled is set to false and doesn't change. This causes your code to be compiled when the PROD server starts.
I read somewhere that in the GAE module it's set to true.

Well, what if I want to deploy my Play! application without the sources and use my precompiled classes?
This only requires setting Play.usePrecompiled to true, writing a new module for this seems too much.
I thought the plugins architecture was the way to go, setting this in the onLoad() method, but without setting usePrecompiled Play! can not invoke my plugin.

I found an acceptable hack.
One of the first thing Play! does in the init() method is invoke initStaticStuff(), this method searches for files named "play.static" in the classpath, each line in the files must be a Java class name, and Class.forName() is invoked for each such class.
This doesn't do much but I can set the usePrecompiled value to true in a static initializer block.
I use a JVM property ("usePrecompile") to control the use of the precompiled classes.
I wrote a new class
package org.oded;

import play.Play;

public class Bootstrap {
 static {
  Play.usePrecompiled = Boolean.getBoolean( "usePrecompile" ) && Play.getFile( "precompiled" ).exists();
 }
}

I added a "play.static" file to my conf directory, the file has one line "org.oded.Bootstrap".

In addition I updated my build script, the one that invokes "play precompile", also creates a jar file in myserver/lib with only the Bootstrap file in it.

This is probably not the use that was intended for this hook, but it works.

Wednesday, May 12, 2010

Creating a log4j logger in an Eclipse template

private static Logger logger = Logger.getLogger( MyClass.class );
Are you tired of writing the same line of code over and over again?

No more!


Using the Eclipse templates you can generate this code easily.
Create the template by clicking Window -> Preferences -> Java -> Editor -> Templates -> New

Enter the template name
logger


Enter the pattern
private static Logger logger = Logger.getLogger( ${enclosing_type}.class );
${:import(org.apache.log4j.Logger)}
This pattern also takes care of the import statement.


Creating an Eclipse template




Now see it in action: