filter_list

Jigsaw Puzzle

Sunday 03.04.2011

Lately I've been working on a HTML5 Jigsaw Puzzle. During this process I've learned a lot on how to write high quality JavaScript code. I've also found a lot of differences between browsers in their implementation of the HTML Canvas standard.

As an example, Firefox has problems with the globalCompositeOperation property. (demo) As described by Beej, Firefox renders some composition operations incorrectly, making it harder to make the masks I needed for my jigsaw puzzle pieces.

When drawing the paths for the pieces themselves, I encountered problems regarding the arcTo function using IE9. Although MSDN has the best documentation for this particular function, their implementation was not completely up to par. The arc itself was drawn correctly, but the path state was not updated in the same way as in the other browsers. Other browsers update the current position of the pen to be at the endpoint of the arc after drawing it. This does not happen correctly using IE9. When I draw two arcs in succession, they both start at the same position, with the end result looking like a sawtooth instead of a rounded edge. Therefore I had to add a lineTo call inbetween in order for the pen position to be updated after drawing the first arc.

It is said that one of the intents of HTML5 is to standardize how its features work across all major browsers, but this is not the case quite yet. I'm hoping that these bugs are corrected soon.

Super Spoon Fighter

Sunday 13.03.2011

This weekend I participated in the legendary Ludum Dare competition. The theme of MiniLD #25 was "The Worst Game I Have Ever Made". For this competition I made an entry called Super Spoon Fighter.

BeanModel generation with AutoBean support

Monday 07.02.2011

I've lately been working on converting our in the works web application from using GWT-RPC to using RequestFactory. While working on this, I've found that the ExtGWT 2 BeanModelGenerator is not capable of reading getters and setters from a proxy interface. This generator solves this problem.

package com.wis.wisweb2.intra.core.rebind;

import java.util.List;

import com.extjs.gxt.ui.rebind.core.BeanModelGenerator;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.requestfactory.shared.BaseProxy;

/**
 * BeanModel generator with support for GWT AutoBeans.
 * 
 * @author Stig Runar Vangen
 */
public class AutoBeanBeanModelGenerator extends BeanModelGenerator {

    @Override
    protected final void addGetters(final JClassType cls,
            final List methods) {
        // Ignore methods of Object
        if (cls.getSuperclass() != null) {
            addGetters(cls.getSuperclass(), methods);
            addClassGetters(cls, methods);
        }

        if (isAutoBean(cls)) {
            addClassGetters(cls, methods);
        }
    }

    /**
     * @param cls
     *            class to test
     * @return true if given class qualify for AutoBean generation
     */
    private boolean isAutoBean(final JClassType cls) {
        if (cls.getQualifiedSourceName().equals(BaseProxy.class.getName())) {
            return true;
        }

        for (JClassType classType : cls.getImplementedInterfaces()) {
            return isAutoBean(classType);
        }

        return false;
    }

    private void addClassGetters(final JClassType cls,
            final List methods) {
        for (JMethod m : cls.getMethods()) {
            if (m.isPublic() || m.isProtected()) {
                String name = m.getName();
                if ((name.matches("get.*") || name.matches("is.*"))
                        && m.getParameters().length == 0) {
                    methods.add(m);
                }
            }
        }
    }
}

This generator has to be references from the GWT module definition file.

    <!-- BeanModel for AutoBean -->
    <generate-with class="com.wis.wisweb2.intra.core.rebind.AutoBeanBeanModelGenerator">
        <when-type-assignable class="com.extjs.gxt.ui.client.data.BeanModelLookup" />
    </generate-with>

This definition should override the generator from the ExtGWT package.

ExtGWT and RequestFactory integration

Friday 04.02.2011

Sencha have been saying that the next version of ExtGWT will be closer to the standards that Google themselves are using for GWT. Earlier one has had to do a lot of custom code to make the data flow move optimally. We've tried to prepare our codebase for the release of ExtGWT 3, and a central part of this is the introduction of the RequestFactory. This helper reduces the amount of data transferred between client and server, which makes is to that we don't need to write as much code as we've earlier needed in order to change data on the client side. These changes span both the ser and client parts of the code.

Spring and RequestFactory

Uses temporarely a servlet defined in web.xml. This servlet is independent of what RequestContext you are using, but every implementation av these are not Spring compatible. This is on the list of things that needs to be improved.

ExtGWT and RequestFactory

Sencha says that in ExtGWT 3 they will do a better job at integration against GWT. This includes using the frameworks that already exists in GWT. One of these frameworks are the RequestFactory (introduced in GWT 2.1), which is a framework for reducing the traffic over the network. This is done by sending changes done to the model instead of the whole shebang. A fundamental introduction is provided here:

http://code.google.com/webtoolkit/doc/latest/DevGuideRequestFactory.html

The first thing that hits me when reading this documentation, is that Google has violated all rules of programming when making this framework. All methods for fetching data from the database are static methods on each entity. These static methods creates some problems regarding an integration towards Spring/Guice or similar. The fact that they are located on the entity itself makes it so that the code cannot be separated in code layers with makes further development easier. This has been improved in GWT 2.1.1, which contain a lot of improvements on the RequestFactory:

http://code.google.com/p/google-web-toolkit/wiki/RequestFactory_2_1_1

In this updated version of the framework it is possible to extract the implementation of the fetching of data from entities using locators. These implementation does not need to be static andy more, which eases the integration against Spring quite a lot. There are however very little documentation on this topic available yet. Neither Google nor the bloggers have started to write about this framework yet. There has therefore been a long process of trial and error in order to integrate RequestFactory into our systems.

RequestFactory GIN provider

public class ContactRequestFactoryProvider implements
  Provider {
 
  @Inject
  private CoreGinjector coreGinjector;
 
  @Override
  public final ContactRequestFactory get() {
    ContactRequestFactory contactRequestFactory =
      GWT.create(ContactRequestFactory.class);
    contactRequestFactory.initialize(coreGinjector.getEventBus(),
      coreGinjector.getRequestTransport());
    return contactRequestFactory;
  }
}

In order to create RequestFactory object we use a GIN provider. The result of this object is defined as a singleton through the GIN configuration. This is integrated using our global eventbus an a custom transport method. The reason why we need a custom transport method is that we fetch data from a different web context than the client itself.

RequestFactory

public interface ContactRequestFactory extends RequestFactory {
  ContactRequest contactRequest();
}

The factory in itself simply references a request implementation.

Contact request

@Service(value = ContactAdapter.class, locator = InstanceServiceLocator.class)
public interface ContactRequest extends RequestContext {

  Request get(String id);

  Request persist(ContactProxy contact);

  Request remove(ContactProxy contact);
}

This interface defines the methods used to communicate from the client to the server. These are the methods specific for the contact module. The classes in itself are annotated as a GWT service, where the implementation of these methods a located in the ContactAdapter class (does not need to be the entity class any more in GWT 2.1.1), while ContactLocator (locators are new from GWT 2.1.1) takes care of entity updates.

Contact RequestFactory adapter

@Component
public class ContactAdapter {

  private static ContactDao contactDao;

  public ContactAdapter() {
  }

  @Autowired
  public ContactAdapter(final ContactDao contactDao) {
    ContactAdapter.contactDao = contactDao;
  }

  public final Contact get(final String id) {
    Scanner scanner = new Scanner(id);
    scanner.useLocale(Locale.ROOT);
    if (scanner.hasNextLong()) {
      return contactDao.get(scanner.nextLong());
    }
    return null;
  }

  public final void persist(final Contact contact) {
    contactDao.saveOrUpdate(contact);
  }

  public final void remove(final Contact contact) {
    contactDao.delete(contact);
  }
}

This class implements all the methods defined in the request interface. The class is annotated with @Component so that Spring finds this class through package-scanning. We therefore will not need specific configuration for each module. A contact DAO is provided from the Spring context. This DAO is saved as a static variable. The reason for this is that RequestFactory initiates instances of its object independent os Spring. At application startup the DAO is provided from Spring, and all instances of this adapter will then get access to the DAO in question.

Instance ServiceLocator

public class InstanceServiceLocator implements ServiceLocator {
 
  private static final Log LOGGER = LogFactory
    .getLog(InstanceServiceLocator.class);
 
  @Override
  public final Object getInstance(final Class clazz) {
    try {
      Object newInstance = clazz.newInstance();
      return newInstance;
    } catch (InstantiationException ex) {
      LOGGER.fatal("Failed to create instance", ex);
    } catch (IllegalAccessException ex) {
      LOGGER.fatal("Failed to create instance", ex);
    }
    return null;
  }
}

This is a very simple ServiceLocator that simply creates a new instance of the class you request. It is possible that we on a later point in time will need to fetch object from the Spring context instead of creating standalone objects.

Entity proxy

@ProxyFor(value = Contact.class, locator = ContactLocator.class)
public interface ContactProxy extends BaseEntityProxy {

  String getAddress();

  String getFirstName();

  String getLastName();

  void setAddress(String address);

  void setFirstName(String firstName);

  void setLastName(String lastName);
}

Entity proxies are implemented as autobeans on the client side. These are a reflection of the entities on the server side. In the proxy on have to give names based on the Java Bean standard. This will most probably be a direct copy of the method names one finds in the entity. This because RequestFactory should be able to get data from the entity before they are transferred to the client. If these implementation does not match, one will get an error message while fetching data. Please note that we also reference a locator. This locator is of the type ServiceLocator, which are placed within a request.

 
@Entity
public class Contact extends AbstractDocumentEntity implements Serializable {

  private String firstName;
  private String lastName;
  private String address;

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

  public String getFirstName() {
    return firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
}

This is a simplified extract rom the entity that the autobean proxy points to. Please note that the method calls in the proxy calls the fields in the class, not the methods. Both class implementations follow the same rules for naeming of getters and setters.

Contact RequestFactory locator

public abstract class DocumentEntityLocator
  extends Locator {

  private static final Log LOGGER = LogFactory.getLog(DocumentEntityLocator.class);

  public DocumentEntityLocator() {
  }

  public abstract BaseDao getDao();

  @Override
  public final T create(final Class clazz) {
    try {
      Class entityClass = getEntityClass(clazz);
      if (entityClass != null) {
      T newInstance = entityClass.newInstance();
      getDao().saveOrUpdate(newInstance);
        return newInstance;
      }
    } catch (InstantiationException ex) {
      LOGGER.fatal("Failed to create instance", ex);
    } catch (IllegalAccessException ex) {
      LOGGER.fatal("Failed to create instance", ex);
    }
    return null;
  }

  @Override
  public final T find(final Class clazz, final Long id) {
    return getDao().get(id);
  }

  @Override
  public final Class getDomainType() {
    return getDao().getDomainType();
  }

  @Override
  public final Long getId(final T domainObject) {
    return domainObject.getId();
  }

  @Override
  public final Class getIdType() {
    return Long.TYPE;
  }

  @Override
  public final Object getVersion(final T domainObject) {
    return domainObject.getRevisionNumber();
  }

  @SuppressWarnings("unchecked")
  private  Class getEntityClass(
    final Class clazz) {
    Entity entity = clazz.getAnnotation(Entity.class);
    if (entity != null) {
      return (Class) clazz;
    }

    Class superclass = clazz.getSuperclass();
    if (superclass != null) {
      return getEntityClass(superclass);
    }

    return null;
  }
}

A locator can be called the glue between your model structure and Requestfactory. This class defines how one fetches an entity based on an ID. In addition this class also defines how one finds the ID, version and type from an entity. The DAO is provided using an abstract method.

@Component
public class ContactLocator extends DocumentEntityLocator {

  private static final Log LOGGER = LogFactory.getLog(ContactLocator.class);
  private static ContactDao contactDao;

  public ContactLocator() {
  }

  @Autowired
  public ContactLocator(final ContactDao contactDao) {
    ContactLocator.contactDao = contactDao;
  }

  @Override
  public final BaseDao getDao() {
    return ContactLocator.contactDao;
  }
}

This is an implementation of a locator for a given module. This class is annotated with @Component in order for Spring to process this class at startup. The static contact DAO will the be set. This will have to be static, as it is RequestFactory that at a later time will create instances of this, and is as earlier discussed not completely Spring compliant. The DAO is the given back to the abstract class using the implementation of the DAO getter. This makes it quickly and easily to set up new modules.

We plan to try to extend this RequestFactory implementation on the server side so that we won't be as dependent on static variables for Spring beans. This will make the code better suited for changes later on.

Spring and GWT-RPC integration

Thursday 03.02.2011

As a part of the implementation of the serverside part of Wisweb 2, I've done some job on the integration between GWT and Spring. In addition there has been some work on the client side to integrate RequestFactory introduces in GWT 2.1 against ExtGWT. This has a times been a frustrating experience, and I want to present some of the solutions we found here so that others don't have to share this frustration.

For GWT based RPC-calls we want to configure the location of the endpoints using Spring annoations. This creates the need for setting up Spring controllers instead of GWT servlets. This integration is done in the following code snippet.


public abstract class AbstractRpcController extends RemoteServiceServlet {

  private static final Log logger = LogFactory.getLog(AbstractRpcController.class);
  private ServletContext servletContext;

  @Override
  public final ServletContext getServletContext() {
    return servletContext;
  }

  @Autowired
  public final void setServletContext(final ServletContext servletContext) {
    this.servletContext = servletContext;
  }

  public abstract RemoteService getRemoteService();

  @RequestMapping("/")
  public final void request(final HttpServletRequest request,
      final HttpServletResponse response) {
    this.doPost(request, response);
  }

  @Override
  public final String processCall(final String payload)
      throws SerializationException {
    try {
      RPCRequest rpcRequest =
        RPC.decodeRequest(payload, this.getRemoteService().getClass());
      String result =
        RPC.invokeAndEncodeResponse(this.getRemoteService(),
          rpcRequest.getMethod(), rpcRequest.getParameters());
      return result;
    } catch (IncompatibleRemoteServiceException ex) {
      logger.error("Caught an exception", ex);
      return RPC.encodeResponseForFailure(null, ex);
    } catch (Exception ex) {
      logger.error("Caught a generic exception", ex);
      return RPC.encodeResponseForFailure(null, ex);
    }
  }
}

The core of this code is the last method. This method routes a GWT service in the GWT impementation of the RPC processing. This makes sure that we get a seamless integration between GWT and Spring. The reference to the GWT service is an avstract method so that every module implementation provides its own service implementation.


@Controller
@SystemController
@RequestMapping("/rpc/contact")
public class ContactRpcController extends AbstractRpcController {

  private ContactService contactService;

  @Autowired
  public final void setContactService(final ContactService contactService) {
    this.contactService = contactService;
  }

  @Override
  public final RemoteService getRemoteService() {
    return this.contactService;
  }
}

This is an example on a module specific RPC controller. The contact service is fetched from the Spring context, and is given back to the abstract implemenation as needed. This implementation makes it fast to add services to other modules.

PostMaster on Chrome Web Store

Friday 10.12.2010

Chrome Web Store was just launched, and I wanted to test how the publishing process compared to the process of publishing your application on Android Marketplace. I added a simple application in form of a web shortcut, and published PostMaster there.

Tic Tac Toe for Android

Monday 06.09.2010

Lately I've been playing around with the Android SDK, and made some interesting prototypes for apps and games. To test out how the Android Marketplace publishing process works, I've decided to port a simple old game I made way back over to Android. This game is called Tic Tac Toe.

Fuel injection for Wisweb

Saturday 06.03.2010

For little over a month ago I did some rather large changes to how Wisweb works. I rewrote the whole engine for page templates from ground up with a strong focus on performance and reliability. At the same time, the operations department changed the webserver. What did we gain by these changes?

Perfomance

The methods for fetching data from the database was completely rewritten. This rewrite resulted in an average reduction of database pressure by two thirds. In addition the techniques for building the pages were changed so much that the server generates the pages with minimal CPU usage. On top of this, we've added an internal cache for the generated pages which results in most pages does not get processed by the server at all. The sum of all these changes results in a lot more idle time for our servers, and we are ready to receive a lot more users.

Responsiveness

All these performance improvements resulted in a way better user experience for our users. Startup time for the intranet pages loads almost instantly. Both pages on the internet and the intranet are loaded way faster as a result of all this.

Predictability

This improvement is mostly for us who work with the system. With the changes I've made to the server we will always get the result we expect. This was also the case partially earlier too, but we now have no known weirdness factors.

Stability

The system will now give us better feedback when something does not go according to the plan. Some customers has lately experienced us calling them to tell them that the feature they couldn't get to work was finally working again. This without them taking contact with us to inform us about a problem. Their problem was found from the updated logs, and we knew from that which customer had problems. In addition I found a setting for our application server that let the users be logged in even though the servers has been down. Some customers has probably seen that they've been logged out of during the night if they left the computer logged into the system. Thse customers will not see this anymore unless they are working in the moment that we take down the application.

Conclusion

With the changes I've done to the systems lately, the system is in better shape than it has ever been. I've still got a lot of ideas on how it could be done better to give an even better performance, but that will have to wait for an another time. What we currently have will give us a lot more room as we start on the next version of the system.

Back to WIS

Monday 14.12.2009

Now that Funcom is financially troubled, a lot of us were laid off. Unfortunately I was one of them. I decided I wanted to go back to what I was working on earlier, and am now working for Waade Information System again. It will be interesting to see how their systems have evolved since I left.

Added search functionality

Sunday 29.11.2009

Search functionality have been added to these pages. It is now possible to search through the wast amount of material available on this site.

More content and better language switching

Friday 20.11.2009

I've added some information on more of the projects that I've worked on at Funcom. That list should now be complete as far as I remember. In addition I've changed how the language switcher for these webpages work slightly. When you selected language earlier, you were sent to the front page of that section. Now you remain at the same page whenever language changes. This does not apply for the blog, as those entries does not have both languages. Older entries are in norwegian only, while newer are in english only.

More functionality and content

Saturday 14.11.2009

I've added a new filter for projects, namely what technology a project uses. This will for example make it easier to find all projects I've worked on that uses Java.

In addition I've added a few more projects I've worked on. There will be more of these as I'll be gathering screenies and such.

Updated web pages

Thursday 12.11.2009

I've finally had time to update these webpages. The update has included a completely new design, converting the content that were there over to a nice CSS layout. I also decided to throw out all the code behind the page and use an existing framework. After trying out a few frameworks I found one that I really fell in love with, CakePHP.

CakePHP is a MVC framework that looked very promising from the start. While I was making these pages I run into some of problems, but the framework came to the rescue every time. I highly recommend it to everyone thinking of making a webpage.

Starting in a new job at Funcom

Monday 01.10.2007

It is time to move on, and I am now leaving my old job and starting in a new job at Funcom. Here I will be working on a for now undisclosed project.

Exporting images from Java

Thursday 16.08.2007

Lately I've been working on image processing for the Wisweb 2 project. I can safely say that the image processing we had in Wisweb 1 will be greatly improved. In addition to adding some new effects I've corrected a lot of bugs in the old version. Some functions also worked fine in the old version, but didn't always give optimal image quality. They will do that now.

The biggest issue I've met so far has been to export the generated images from Java after all processing has been done. This time we want to support correct export of transparent images. In the old version some pictures were in some cases turned opaque instead of transparent after some processing. All image operations does now support transaprent images.

The final piece of the puzzle is the export of images from a completely processed image to something that can be presented in a web browser. To begin with we want to support JPEG, GIF and PNG. There are many solutions out there, and there is not always the simplest or the most obvious solution which are the best. Java 6 does support export to all these formats, but there are some caveats with some of them.

JPEG

  • Java 6 - Top notch export of images. The quality can be fine tuned until you turn blue. Export of JPEG-images in Java has existes as a hidden library in the standard package since.. well.. not too long after the dawn of time, and is incredebly fast.

We decided to use the buildtin Java functionality without more hesitation here.

PNG

  • Java 6 - Pictures are exported perfectly, with correct transparency and all, but.. incredibly slow.
  • Catcode - Images did not preserve its transparency.
  • Objectplanet - Top notch speed, way better than the original. But.. some images got corrupted

The decision fell on the buildtin Java exporter, even though it was not as speedy as we wanted. If anyone knows of any alternative, please drop me a message.

GIF

An another challenge here: Convert true-color to 256 colors (color quantizing), transarency, blending.

  • Java 6 - Images were converted from true-color to an indexed palette, which resulted in a pretty bad color reduction, and lacked transaprency
  • ACME - Does not support color reduction.
  • Gurge - Does not support color reduction.
  • Gif4J - Really good color reduction. Transaprency were exported perfectly. Lacks blending only.

I've contaced the authors of Gif4J with regard to the blending, and got a positive feedback on this. Even without blending their library is the best library available today.

Process module

Thursday 09.08.2007

I've worked a lot on an editor for the process module of Wisweb lately. As a foundation for this module I've used a library called Open-jACOB Draw2D. This editor does not support the features we want out-of-the-box, which resulted in a lot of extra objects being added to this editor. I have to say that the end result looks great, as seen in the screenshot below.

One thing that is really impressive with this library, is its rate of updates. If you look at the project homepage, you'll see that the library has been updated nearly daily. Several of the features we implemented when we started on this project has already been implemented into the library by the original author. Some of these features we would like to add to our version as well, but we'll have to wait and see if more are added before we update the library. With the rate this guy updates this library, we'll be doing updates of this library until the end of days.

Human Factor - Finalized

Friday 18.11.2005

My last trip to Verdal. At least when it comes to the Human Factor project. We had a final demonstration of the applications and, we agreed that the test version we have now created was good enough. Hopefully we will have the possibility to continue on this project later on.

I got a job

Tuesday 15.11.2005

Finally. I will now be working at Waade Information System. Here I will in the start be working on their web publishing solution, WisWeb.

Human Factor - Final adjustments

Monday 14.11.2005

I am now doing the final adjustemt to the server and the client. This friday I will travel to Verdal and present the lastest version of the software. Tomorrow I will be starting on a new job, so I will have to finish this project off pretty soon.

Human Factor - Code session

Thursday 20.10.2005

I am going to Verdal to work with Torbjørn for two days on the Human Factor project. Hopefully this session will result in some progress.

2017

2016

2014

2013

2012

2011

2010

2009

2007

2005

2004

2003

2002

2001