Stig Runar Vangen homepage
Blog

Blog

Updated Gold Down Under

I've worked on improving Gold Down Under a little. For this updated version I've added sounds, particle effects and native resolution for the output game. The size of the game screen is hardcoded within the ForPlay library, which caused me to have to change these values in the library source, and then recompile the game using the updated sources. Let's hope the guys at Google fixes this problem soon.
Tuesday May 31. 2011

Gold Down Under

Another compo, another entry. This weekend I participated in Mini Ludum Dare #26. I called this game Gold Down Under. The game is a simple Bejeweled clone with a small twist. Instead of letting the play area be filled up when you remove gems, you will instead scroll down when the top row gets empty. The goal is then to reach the bottom of the hole.
Warning (2): Illegal string offset 'lang' [APP/View/Helper/AppHelper.php, line 37]
Sunday May 29. 2011

Updated Nitro Racer

I've made an updated version of Nitro Racer that does not crash if you are using an another browser that Firefox. There was a problem in how the sound was loaded and played back that caused problems when loading the game. I've also added a fix for Chrome that accured when low on health. A clip region of height zero caused Chrome to crash, while Firefox simply did not draw anything. There were also some problems related to the lap progression detection. The hit zones were way too small, and in some cases you would miss these predefined zones. These have been increased in size and moved slightly around.
Wednesday May 4. 2011

Nitro Racer

This weekend has been filled with gamemaking again. I've participated in Ludum Dare #20, which resulted in an overhead racer with a twist. Instead of trying to keep your opponents as far away from you as possible, you will in this game need to keep them close. I called this game Nitro Racer at the beginning of the competition, but I never ended up putting nitros in the game. That would make no sense when you consider that you need to keep your speed down anyway.
Warning (2): Illegal string offset 'lang' [APP/View/Helper/AppHelper.php, line 37]
Monday May 2. 2011

Updated Jigsaw Puzzle

After testing the Jigsaw puzzle game on a few computers, I found that it performed badly on some systems. During development I've only used my powerhorse of a computer, and never thought it would run badly on older computers, as it ran relly well on my computer. Back to the drawing board, and I did a small redesigned on how the puzzle is rendered. This resulted in an unheard of speed increase for the rendering. The end result is that the game now runs as smooth as I wanted it to on older systems as well.
Thursday April 14. 2011

Jigsaw Puzzle

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.
Warning (2): Illegal string offset 'lang' [APP/View/Helper/AppHelper.php, line 37]
Sunday April 3. 2011

Super Spoon Fighter

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.
Warning (2): Illegal string offset 'lang' [APP/View/Helper/AppHelper.php, line 37]
Sunday March 13. 2011

BeanModel generation with AutoBean support

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.
Monday February 7. 2011

ExtGWT and RequestFactory integration

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.
Friday February 4. 2011

Spring and GWT-RPC integration

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.
Thursday February 3. 2011