TurboManage

David Chandler's Journal of Java Web and Mobile Development

  • David M. Chandler


    Web app developer since 1994 and Google Cloud Platform Instructor now residing in Colorado. Besides tech, I enjoy landscape photography and share my work at ColoradoPhoto.gallery.

  • Subscribe

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 231 other followers

  • Sleepless Nights…

    February 2010
    S M T W T F S
    « Jan   Mar »
     123456
    78910111213
    14151617181920
    21222324252627
    28  
  • Blog Stats

    • 998,375 hits

Archive for February 22nd, 2010

“Generic” Objectified ActionHandler for gwt-dispatch

Posted by David Chandler on February 22, 2010

WARNING: use of a generic ActionHandler for persistence as described in this post has significant security implications, especially if you’re not using the SecureDispatchService from gwt-dispatch. See comments for more details.

In response to a reader request, I’ve come up with “generic” gwt-dispatch Action/Result/ActionHandler classes using Objectify. It is not quite as satisfying as I would like because it doesn’t use parameterized types like the ObjectifyDao I recently posted; however, as noted in an earlier post, Objectify itself doesn’t require parameterized types and therefore a parameterized DAO really isn’t that useful (nor possible as explained at the conclusion of this posting).

So here’s a PutAction/PutResult/PutHandler that can persist any object in the Datastore. Thanks to Dan Billings for making a valiant effort at a parameterized version of these classes and prompting me to write this. Creating an Action/Result/Handler combo for each Objectify operation (delete, query, etc.) is left as an exercise to the reader…

PutResult.java

package com.turbomanage.gwt.shared;

import net.customware.gwt.dispatch.shared.Result;

import com.googlecode.objectify.Key;

public class PutResult implements Result {

       private Object obj;
       private Key key;

       protected PutResult()
       {
    	   // Needed for GWT-RPC
       }

       public PutResult(Object object, Key key) {
               this.obj= object;
               this.key = key;
       }

       public Key getKey() {
               return key;
       }

       public Object getObject() {
               return obj;
       }

}

PutAction.java

package com.turbomanage.gwt.shared;

import net.customware.gwt.dispatch.shared.Action;

public class PutAction implements Action<PutResult>
{
	private Object obj;

	public PutAction(Object object)
	{
		if (object == null)
			throw new IllegalArgumentException("Object cannot be null");
		this.obj = object;
	}

	protected PutAction()
	{
		// Needed for GWT-RPC
	}

	public Object getObject()
	{
		return obj;
	}

}

PutHandler.java

package com.turbomanage.gwt.server.handler;

import net.customware.gwt.dispatch.server.ActionHandler;
import net.customware.gwt.dispatch.server.ExecutionContext;
import net.customware.gwt.dispatch.shared.ActionException;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.turbomanage.gwt.shared.PutAction;
import com.turbomanage.gwt.shared.PutResult;

public class PutHandler implements
ActionHandler<PutAction, PutResult>{

	@Override
	public PutResult execute(PutAction action, ExecutionContext arg1) throws ActionException
	{
		Objectify ofy = ObjectifyService.begin();
		Object obj = action.getObject();
		Key<Object> key = ofy.put(obj);
		return new PutResult(obj, key);
	}

	@Override
	public Class<PutAction> getActionType()
	{
		return PutAction.class;
	}

	@Override
	public void rollback(PutAction arg0, PutResult arg1, ExecutionContext arg2)
		throws ActionException
	{
		// TODO Auto-generated method stub
	}

}

The handler must be registered in a Guice module as usual:

package com.roa.server.guice;

import net.customware.gwt.dispatch.server.guice.ActionHandlerModule;
import com.roa.common.domain.User;
import com.turbomanage.gwt.server.handler.PutHandler;
import com.turbomanage.gwt.shared.PutAction;

public class ServerModule extends ActionHandlerModule
{
	static {
		ObjectifyService.register(User.class);
	}

	@Override
	protected void configureHandlers()
	{
		...
		bindHandler(PutAction.class, PutHandler.class);
		...
	}
}

Note that I’ve sneaked (snuck?) the mandatory Objectify domain class registration into a static initializer here since we’re not using a DAO at all.

As I mentioned at the beginning, this is not quite as satisfying (or typesafe) as a parameterized version of the Action, Result, and Handler classes. The difficulty with parameterizing these types is that the generic domain class parameter T has to propagate all the way up to ActionHandler<T>. You can’t bind a parameterized ActionHandler in gwt-dispatch because Guice doesn’t allow it; rather, you would need a concrete ActionHandler for each type T, which would defeat the purpose of having a generic Action/Result/Handler in the first place.

As always, YMMV.

Advertisements

Posted in AppEngine, Google Web Toolkit | 15 Comments »

Salespeople vs. developers in a software startup

Posted by David Chandler on February 22, 2010

Joel Spolsky is one of my heroes, partly because I strongly agree with his people-first philosophy of management, partly because his flagship product, FogBugz, is a work of genius (calculates ship dates as a probability curve, not a binary event), and most of all because Joel has built a successful software company in one of the most overcrowded fields (bug tracking software) while living and working in one of the highest-rent cities in the world (NYC).

Joel’s latest is perhaps the single most memorable thing I have ever read on the subject of software quality and marketing. If you’re starting or running a software business, Joel on Headcount will be well worth the 2 minutes it takes to read it.

Posted in Business of Software | Leave a Comment »

 
%d bloggers like this: