Wednesday, October 5, 2011

JAX-RS in GWT with Errai

I blogged about the latest extension to the Errai Framework: Errai JAX-RS - http://errai-blog.blogspot.com/2011/10/jax-rs-in-gwt-with-errai.html

It simplifies the integration of REST-based services in GWT clients by generating proxies that take care of the HTTP request logic, serialization and deserialization. This adds on to what Errai is so good at: alleviating boilerplate code.

Saturday, August 6, 2011

Errai 1.3 Beta1 released!

If you like GWT as much as I do, you should definitely check out Errai! The latest release brings a deeper integration of CDI. Yes. CDI. In the browser! Read more about the release here.

All of Errai's glory can be found here: http://www.jboss.org/errai.

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.