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 223 other followers

  • Sleepless Nights…

    February 2010
    S M T W T F S
     123456
    78910111213
    14151617181920
    21222324252627
    28  
  • Blog Stats

    • 1,029,259 hits

Archive for February, 2010

How to distinguish between AppEngine dev and prod environments

Posted by David Chandler on February 27, 2010

How can you tell whether your server-side AppEngine code is running in dev or production? (Hopefully, you don’t need to know too often, but for purposes of substituting test email addresses, etc., it might come in handy). I’ve discovered this AppEngine system property tucked away in Vince Bonfanti’s Task Queue helper class Deferred.java:

    import com.google.appengine.api.utils.SystemProperty;
    ...
    private static boolean isDevelopment() {
        return ( SystemProperty.environment.value() ==
                    SystemProperty.Environment.Value.Development );
    }

If you need to distinguish between AppEngine environments in GWT code, you would have to make an RPC call, which would probably leave you with an if statement in your application code somewhere, although someone very clever might come up with a way to do something GWT-side similar to what Andy Stevko wrote up on StackOverflow a few weeks ago.

If you’ve done something like this in GWT or GIN, I’m all ears.

Posted in AppEngine, GIN / Guice, Google Web Toolkit | Leave a Comment »

Windoze performance tip

Posted by David Chandler on February 25, 2010

At Tuesday night’s AJUG on Java performance tuning, Kirk Pepperdine was discussing the evils of swap in a RAM-plentiful age and offered this interesting freebie: set your paging file size to ZERO (assuming you do actually have enough RAM to keep everything in memory). Besides the ~10% boost you get from not paging memory to/from disk, it saves battery life on laptops by not spinning the disk as much.

Posted in PC Tech | 5 Comments »

Presenting at DevNexus

Posted by David Chandler on February 24, 2010

For those readers in the Atlanta area, I’ll be presenting case studies on AppEngine and GWT at DevNexus Mar 8-9. I’ll be highlighting the frameworks I’ve written about here: gwt-presenter, gwt-dispatch, and Objectify, along with Guice and GIN.

If you plan to be there and want to see specific topics covered, you can post your request as a comment here.

Posted in AppEngine, GIN / Guice, Google Web Toolkit | 2 Comments »

Be careful with yesterday’s post

Posted by David Chandler on February 23, 2010

Just in case you missed the comments on yesterday’s “Generic” Objectified ActionHandler, the example code potentially exposes your Datastore to hackers who can spoof or otherwise modify GWT-RPC requests. Be sure to read the comments, and if you’ve never seen Paros, TamperData (Firefox plug-in) or the like, you might want to check those out to see just how easy it is to modify Web requests in ways the developer did not intend. It’s not as easy to modify GWT-RPC because it’s a binary (serialized) protocol, but it’s not encrypted so it certainly is possible.

Bottom line: your server-side code should always check user permissions one way or another. SecureDispatchService (gwt-dispatch) will restrict access to ActionHandlers to only authenticated users, but depending on how many hackers you have in your user base and how private the data needs to be, you may need additional permission checking on each persistence-related action.

You have been warned.

Posted in AppEngine, Google Web Toolkit, Web App Security | Leave a Comment »

“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.

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 »

A TextBox with input prompt for GWT

Posted by David Chandler on February 16, 2010

Here’s a nifty GWT widget that displays a prompt in a text box and erases it when you click or type in the text box. It looks simple, but is actually quite clever in design as it is entirely self-contained. Thanks to Geoffrey Wiseman for the inspiration for this.

package com.turbomanage.gwt.client.ui.widget;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.ui.TextBox;

public class PromptedTextBox extends TextBox implements KeyPressHandler, FocusHandler, ClickHandler
{
	private String promptText;
	private String promptStyle;

	public PromptedTextBox(String promptText, String promptStyleName)
	{
		this.promptText = promptText;
		this.promptStyle = promptStyleName;
		this.addKeyPressHandler(this);
		this.addFocusHandler(this);
		this.addClickHandler(this);
		showPrompt();
	}

	public void showPrompt()
	{
		this.addStyleName(promptStyle);
		this.setText(this.promptText);
	}

	public void hidePrompt()
	{
		this.setText(null);
		this.removeStyleName(promptStyle);
	}

	@Override
	public void onKeyPress(KeyPressEvent event)
	{
		if (promptText.equals(this.getText())
			&& !(event.getNativeEvent().getKeyCode() == KeyCodes.KEY_TAB))
		{
			hidePrompt();
		}
	}

	@Override
	public void onFocus(FocusEvent event)
	{
		this.setCursorPos(0);
	}

	@Override
	public void onClick(ClickEvent event)
	{
		if (promptText.equals(this.getText()))
			hidePrompt();
	}
}

All that’s needed to round it out is a little CSS to lighten up the prompt text:

.prompt {
	color: #999;
}

Enjoy!

Posted in Google Web Toolkit | 7 Comments »

Simplifying GWT Markup with HTML Widgets

Posted by David Chandler on February 11, 2010

The more I’ve worked with CSS and GWT, the more I’ve tried to simplify the markup that GWT creates. GWT spits out a lot of extraneous DIVs, which, while providing maximum flexibility, result in bloated markup. For example, here’s some GWT code to create a simple horizontal menu of hyperlinks:

	public void setMenu(List<MenuItem> items)
	{
		// userMenu is a HorizontalPanel
		userMenu.clear();
		for (int i=0; i<items.size(); i++)
		{
			MenuItem item = items.get(i);
			if (i>0)
			{
				userMenu.add(new Label ("|"));
			}
			Hyperlink y = new Hyperlink(item.getLabel(), item.getUrl());
			userMenu.add(y);
		}
	}

And here’s the resulting markup, courtesy of Firebug (an indispensable tool for CSS work, especially in GWT):

<table cellspacing="0" cellpadding="0" id="detail_menu">
	<tbody>
		<tr>
			<td align="left" style="vertical-align: bottom;">
				<div class="gwt-Hyperlink">
					<a href="#prayers">Prayers</a>
				</div>
			</td>
			<td align="left" style="vertical-align: bottom;">
				<div class="gwt-Label">|</div>
			</td>
			<td align="left" style="vertical-align: bottom;">
				<div class="gwt-Hyperlink">
					<a href="#manage_lists">Manage Lists</a>
				</div>
			</td>
		</tr>
	</tbody>
</table>

That’s quite a bit of markup for a simple menu of hyperlinks, albeit it requires very little CSS. The HorizontalPanel ensures the hyperlinks appear horizontally, so really all the CSS that’s needed is a little padding in each TD to space things out.

A simpler alternative for menus used by many Web designers is the humble unordered list. Unfortunately, GWT does not have widgets that spit out the lowly UL and LI tags. You can always do it manually using the HTML or InlineHTML widgets; however, it is more satisfying to use real widgets, so I created an UnorderedListWidget and ListItemWidget. Here is the previous GWT menu code rewritten using the new widgets:

	public void setMenu(List<MenuItem> items)
	{
		// userMenu is an UnorderedListWidget
		userMenu.clear();
		for (int i=0; i<items.size(); i++)
		{
			MenuItem item = items.get(i);
			if (i>0)
			{
				userMenu.add(new ListItemWidget("|"));
			}
			Hyperlink y = new Hyperlink(item.getLabel(), item.getUrl());
			userMenu.add(new ListItemWidget(y));
		}
	}

And here’s the much leaner markup (unfortunately, I do not know a way to get rid of the unnecessary Hyperlink DIVs apart from creating a lightweight Hyperlink widget):

<ul id="detail_menu" class="roa-hMenu">
	<li>
		<div class="gwt-Hyperlink">
			<a href="#prayers">Prayers</a>
		</div>
	</li>
	<li>|</li>
	<li>
		<div class="gwt-Hyperlink">
			<a href="#manage_lists">Manage Lists</a>
		</div>
	</li>
</ul>

Finally, here are the widgets. It’s easy to generate any HTML markup you need this way, thanks to GWT’s Document and Element hierarchies.

package com.turbomanage.gwt.client.ui.widget;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.UListElement;
import com.google.gwt.user.client.ui.ComplexPanel;
import com.google.gwt.user.client.ui.Widget;

public class UnorderedListWidget extends ComplexPanel
{
	public UnorderedListWidget()
	{
		setElement(Document.get().createULElement());
	}

	public void setId(String id)
	{
		// Set an attribute common to all tags
		getElement().setId(id);
	}

	public void setDir(String dir)
	{
		// Set an attribute specific to this tag
		((UListElement) getElement().cast()).setDir(dir);
	}

	public void add(Widget w)
	{
		// ComplexPanel requires the two-arg add() method
		super.add(w, getElement());
	}
}
package com.turbomanage.gwt.client.ui.widget;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

public class ListItemWidget extends SimplePanel
{
	public ListItemWidget()
	{
		super((Element) Document.get().createLIElement().cast());
	}

	public ListItemWidget(String s)
	{
		this();
		getElement().setInnerText(s);
	}

	public ListItemWidget(Widget w)
	{
		this();
		this.add(w);
	}
}

Enjoy!

Posted in Google Web Toolkit | 10 Comments »

Generic DAO for Objectify 2

Posted by David Chandler on February 9, 2010

Objectify 2 RC1 is available and I’ve updated the generic DAO I wrote about previously to use the improved Query interface. In addition, I’ve rewritten the query-by-example methods to filter on all non-null properties of the example object (but it ignores many types–see comments). Finally, note that Objectify 2 Query no longer passes through AppEngine’s TooManyResultsException if you try to do a get() which returns multiple entities. I liked this behavior, so I’ve added it back in the getByExample() method below for illustration. Enjoy.

package sandbox.server.dao;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.persistence.Embedded;
import javax.persistence.Transient;

import com.google.appengine.api.datastore.EntityNotFoundException;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Query;
import com.googlecode.objectify.helper.DAOBase;

public class ObjectifyGenericDao<T> extends DAOBase
{

	static final int BAD_MODIFIERS = Modifier.FINAL | Modifier.STATIC | Modifier.TRANSIENT;

	static
	{
		// Register all your entity classes here
		// ObjectifyService.register(MyDomain.class);
		// ...
	}

	protected Class<T> clazz;

	/**
	 * We've got to get the associated domain class somehow
	 *
	 * @param clazz
	 */
	protected ObjectifyGenericDao(Class<T> clazz)
	{
		this.clazz = clazz;
	}

	public Key<T> put(T entity)

	{
		return ofy().put(entity);
	}

	public List<Key<T>> putAll(Iterable<T> entities)
	{
		return ofy().put(entities);
	}

	public void delete(T entity)
	{
		ofy().delete(entity);
	}

	public void deleteKey(Key<T> entityKey)
	{
		ofy().delete(entityKey);
	}

	public void deleteAll(Iterable<T> entities)
	{
		ofy().delete(entities);
	}

	public void deleteKeys(Iterable<Key<T>> keys)
	{
		ofy().delete(keys);
	}

	public T get(Long id) throws EntityNotFoundException
	{
		return ofy().get(this.clazz, id);
	}

	public T get(Key<T> key) throws EntityNotFoundException
	{
		return ofy().get(key);
	}

	/**
	 * Convenience method to get all objects matching a single property
	 *
	 * @param propName
	 * @param propValue
	 * @return T matching Object
	 */
	public T getByProperty(String propName, Object propValue)
	{
		Query<T> q = ofy().query(clazz);
		q.filter(propName, propValue);
		return q.get();
	}

	public List<T> listByProperty(String propName, Object propValue)
	{
		Query<T> q = ofy().query(clazz);
		q.filter(propName, propValue);
		return asList(q.fetch());
	}

	public List<Key<T>> listKeysByProperty(String propName, Object propValue)
	{
		Query<T> q = ofy().query(clazz);
		q.filter(propName, propValue);
		return asKeyList(q.fetchKeys());
	}

	public T getByExample(T exampleObj)
	{
		Query<T> queryByExample = buildQueryByExample(exampleObj);
		Iterable<T> iterableResults = queryByExample.fetch();
		Iterator<T> i = iterableResults.iterator();
		T obj = i.next();
		if (i.hasNext())
			throw new RuntimeException("Too many results");
		return obj;
	}

	public List<T> listByExample(T exampleObj)
	{
		Query<T> queryByExample = buildQueryByExample(exampleObj);
		return asList(queryByExample.fetch());
	}

	private List<T> asList(Iterable<T> iterable)
	{
		ArrayList<T> list = new ArrayList<T>();
		for (T t : iterable)
		{
			list.add(t);
		}
		return list;
	}

	private List<Key<T>> asKeyList(Iterable<Key<T>> iterableKeys)
	{
		ArrayList<Key<T>> keys = new ArrayList<Key<T>>();
		for (Key<T> key : iterableKeys)
		{
			keys.add(key);
		}
		return keys;
	}

	private Query<T> buildQueryByExample(T exampleObj)
	{
		Query<T> q = ofy().query(clazz);

		// Add all non-null properties to query filter
		for (Field field : clazz.getDeclaredFields())
		{
			// Ignore transient, embedded, array, and collection properties
			if (field.isAnnotationPresent(Transient.class)
				|| (field.isAnnotationPresent(Embedded.class))
				|| (field.getType().isArray())
				|| (Collection.class.isAssignableFrom(field.getType()))
				|| ((field.getModifiers() & BAD_MODIFIERS) != 0))
				continue;

			field.setAccessible(true);

			Object value;
			try
			{
				value = field.get(exampleObj);
			}
			catch (IllegalArgumentException e)
			{
				throw new RuntimeException(e);
			}
			catch (IllegalAccessException e)
			{
				throw new RuntimeException(e);
			}
			if (value != null)
			{
				q.filter(field.getName(), value);
			}
		}

		return q;
	}
}

Posted in AppEngine | 25 Comments »

AppEngine Needs an AppStore revisited

Posted by David Chandler on February 1, 2010

I previously proposed that AppEngine needs an AppStore enabling AppEngine developers to easily market, deploy, and bill for applications. This idea got a little traction on the AppEngine mailing list, and readers pointed out that Microsoft already has an application gallery for Azure, and Amazon DevPay is right on the money as a billing solution for AWS apps.

So I was intrigued to discover that some folks are already installing their AppEngine application into multiple customer instances: http://groups.google.com/group/google-appengine/browse_thread/thread/4ce497229c8ff0aa?hl=en#. It’s not the ideal one-click experience, but it’s simple and works today.

Google, are you listening?

Posted in AppEngine | Leave a Comment »

 
%d bloggers like this: