Thursday, April 21, 2011

Errai CDI integration

The Errai CDI integration module has support for event qualifiers and conversations now. Here's the link to the errai blog post: Latest enhancements to the Errai CDI integration module.

Thursday, December 23, 2010

magicktiler

Check out magicktiler, a Java tool and embeddable library for converting images into formats suitable for publishing as zoomable Web images. It supports a variety of tiling schemes (TMS, Zoomify, Google Maps, ..). You can find some detailed information in the slides I used for my talk at the Toronto JUG.

It has a CLI, a Scala-Swing based GUI and can be used as a Java lib:
public static void main(String... args) {
    try {
        File input = new File("/path/to/your/image.jpg");
        File output = new File("/tileset/output/path");
        
        MagickTiler tiler = new GoogleMapsTiler();
        // optional settings (these are the default values)
        tiler.setTileFormat(ImageFormat.JPEG);
        tiler.setJPEGCompressionQuality(75);
        tiler.setBackgroundColor("#ffffffff");
        tiler.setWorkingDirectory(new File("."));
        tiler.setGeneratePreviewHTML(true);
                
        // create the tiles
        TilesetInfo info = tiler.convert(input, output);
    } catch (TilingException te) {
        te.printStackTrace();
    }
 }

Tuesday, September 14, 2010

API compatibility

Today I was stumbling across in interesting page about what changes are allowed to an existing API without breaking compatibility to existing clients which I think is worth a read: http://wiki.eclipse.org/Evolving_Java-based_APIs_2 .

What surprised me was that adding/deleting checked exceptions to a method is not breaking binary compatibility. That means that clients compiled against the old API won't have problems to call the modified method.

Anyway, as soon as the exception is thrown the legacy client might behave unpredictable because of subsequent exceptions e.g. ClassNotFound or UndeclaredThrowable or things like that.

Thursday, August 12, 2010

cassandraentitytransfomer

I have been playing around with Cassandra lately using its Java (Thrift) client API. In order to map different classes (entities) to a list of ColumnOrSuperColumns, I have created a generic entity transformer.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.ColumnOrSuperColumn;
import org.apache.cassandra.thrift.Mutation;

public abstract class CassandraEntityTransformer<T> {
  public static final String CHARSET = "UTF-8";

  public abstract List<ColumnOrSuperColumn> getColumns(T entity) throws Exception;
  public abstract T getEntity(List<ColumnOrSuperColumn> columns) throws Exception;

  public List<Mutation> listMutations(T oldEntity, T newEntity) throws Exception {
     List<Mutation> mutations = new ArrayList<Mutation>();
     List<ColumnOrSuperColumn> oldColumns = getColumns(oldEntity);
     List<ColumnOrSuperColumn> newColumns = getColumns(newEntity);

     if(oldColumns.size()!=newColumns.size())
        throw new IllegalArgumentException("incompatible entities");

     for(int i=0; i<newColumns.size(); i++) {
        if(!Arrays.equals(newColumns.get(i).getColumn().getValue(),
                oldColumns.get(i).getColumn().getValue())) {
           mutations.add(
               new Mutation().setColumn_or_supercolumn(newColumns.get(i)));
        }
     }
     return mutations;
  }

  protected ColumnOrSuperColumn createColumn(Column column) {
     ColumnOrSuperColumn c = new ColumnOrSuperColumn();
     c.setColumn(column);
     return c;
  }
}
Subclasses of this class are responsible for providing the columns of concrete entities, like for the token entity in the following example. I found this quite handy, especially as getMutations works out of the box for all entities.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.cassandra.thrift.Column;
import org.apache.cassandra.thrift.ColumnOrSuperColumn;

public class CassandraTokenTransformer extends CassandraEntityTransformer<Token> {
   private static final String VALUE_COLUMN_NAME = "value";
   private static final String EMAIL_COLUMN_NAME = "email";

   @Override
   public List<ColumnOrSuperColumn> getColumns(Token token) throws Exception {
      List<ColumnOrSuperColumn> columns = new ArrayList<ColumnOrSuperColumn>();

      long timestamp = System.currentTimeMillis();

      // the value column.
      columns.add(createColumn(
              new Column(VALUE_COLUMN_NAME.getBytes(CHARSET),
              token.getValue().getBytes(CHARSET), timestamp)));

      // the email column.
      columns.add(createColumn(
              new Column(EMAIL_COLUMN_NAME.getBytes(CHARSET),
              token.getEmail().getBytes(CHARSET), timestamp)));

      return columns;
   }

   @Override
   public Token getEntity(List<ColumnOrSuperColumn> columns) {
      Token token = null;

      Map<String, String> fields = new HashMap<String, String>();
      for (ColumnOrSuperColumn column : columns) {
         fields.put(new String(column.column.name), 
                 new String(column.column.value));
      }
      if(fields.containsKey(VALUE_COLUMN_NAME))
         token = new Token(fields.get(VALUE_COLUMN_NAME),
                           fields.get(EMAIL_COLUMN_NAME));

      return token;
   }
}
Alternatives would have been to use an annotation based mapping mechanism for entities to Cassandra columns, or a JSON based API. Maybe they are out there, and I have just missed them?

Thursday, March 18, 2010

presenting some GWT magic

Rainer's recent papers give all the background on a map annotation tool we have implemented using GWT as frontend technology. Here are some interesting blog posts: http://aboutgeo.no5.at/?p=19 and http://aboutgeo.no5.at/?p=25.

The tools have been implemented on top of our image annotation tool as part of the:
LEMO annotation framework, published in the International Journal of Digital Libraries.

Finally, here is the link to the tool in case you like to play around with it: Image Annotation Toolset

Feedback is highly appreciated.

Wednesday, December 2, 2009

a workflow system for data processing on virtual resources

Extended work on our Job Submission Service has been published in the International Journal on Advances in Software. It can be downloaded from: http://www.iariajournals.org/software/soft_v2_n23_2009_paged.pdf. The paper is titled 'A Workflow System for Data Processing on Virtual Resources' and gives a more in-depth view of the surrounding software architecture.

Tuesday, October 13, 2009

a case for scala

For quite some time now I have been putting off a rather simple implementation task for exposing HTML representations of entities based on an RDF/XML model in my JAX-RS application. Mainly because it either requires an XSL transformation or parsing the whole graph into an object model and using templates to create the HTML. Both cases are usually time consuming and somewhat unexciting. I have learned to like the idea of being able to use XML as a first-class citizen in the progamming language when I did some work with ActionScript 3 recently. So I decided to finally give Scala a chance and it turned out to integrate really well. The code snippet below actually shows a Scala class extending a Java class and overriding a Java method, both tagged with JAX-RS annotations. Path and resource names have been changed.
@Path("/Resource")
class HtmlResourceController extends AbstractResourceController {
   @GET
   @Path("/{id}")
   @Produces(Array(MediaType.TEXT_HTML))
   override def findResourceById(@PathParam("id") id:String) : Response = {
      val rdfXmlRes = super.findResourceById(id);    
      ...
   }
}
The Array declaration within @Produces is only needed for the scala compiler. Within this method I now get the full and yet easy to use XML processing power of Scala, as described here: Scala and XML.

The drawbacks are the additional dependency to Scala and having to maintain two programming languages within the same project but I can live with that for now, especially as it gives me access to a whole set of interesting language features like mixins, closures, currying, and so forth.