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

  • Sleepless Nights…

    December 2009
    S M T W T F S
    « Nov   Jan »
     12345
    6789101112
    13141516171819
    20212223242526
    2728293031  
  • Blog Stats

    • 990,947 hits

Archive for December, 2009

Yet another way to get the Guice injector

Posted by David Chandler on December 16, 2009

I previously wrote about a way to get ahold of the Guice injector in a JSP by putting it in the ServletContext; however, I have another case where I need it in a class that doesn’t have access to the ServletContext, either. The class happens to be a background task that implements the Deferrable interface, which for sake of interface simplicity does not provide access to the ServletContext even though the task does in fact run in a servlet.

The solution is simply to create the Guice injector in a static factory:

package com.roa.server.guice;

import com.google.inject.Guice;
import com.google.inject.Injector;

public class GuiceFactory
{
	private static final Injector inj = Guice.createInjector(...);
	
	public static Injector getInjector()
	{
		return inj;
	}
}

Now any class that needs access to a Guice-managed object can get it easily, including the ultra-simplified Guice context listener that’s registered in web.xml:

package com.roa.server.guice;

import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;

public class GuiceConfig extends GuiceServletContextListener
{

	@Override
	protected Injector getInjector()
	{
		return GuiceFactory.getInjector(); 
	}
	
}

WARNING: this works fine in AppEngine because there’s only one WAR per JVM in that environment. If you’re not running in AppEngine and have multiple WARs in a single JVM, as is commonly the case, you may or may not want a single Guice injector for the whole JVM. I have not tested it, but I would think you wouldn’t be able to use Guice ServletModules in that case.

Advertisements

Posted in AppEngine, GIN / Guice | 3 Comments »

Unit testing with MockHttpSession and Guice

Posted by David Chandler on December 14, 2009

The more I learn about Guice, the more I like it. First, I discovered I could get access to the HttpSession inside my Guice-injected service classes (which are in turn called from my Guice-injected gwt-dispatch ActionHandlers) like this:

public class ROAUserServiceImpl implements ROAUserService
{
	@Inject
	Provider<HttpSession> httpSession;

	@Override
	public LoginInfo login(String requestUri)
	{
		httpSession.get().invalidate();
		...
	}
	...
}

Then came the unhappy moment that I ran my unit tests, which call ActionHandlers, all of which call ROAUserService to verify that the user is logged in. In my unit test environment, Guice cannot inject an HttpSession because my tests are not currently running in a servlet container; thus, every test fails.

I could bring in HttpUnit / ServletRunner, but that is really overkill for what I’m trying to do at this point, which is just to simulate one session attribute being set to represent the logged in user.

I could also create a mock ROAUserService and inject that in my ActionHandlers instead of the real one. But I’d prefer to use the real service for testing, and sooner or later, I’ll need to stuff something else in session, anyway.

Enter Guice Providers.

In the example above, the HttpSession is being injected by way of a Guice Provider, which in the real app, comes for free when your Guice injector includes a ServletModule. Fortunately, we can easily tell Guice to provide a mock HttpSession by using the @Provides annotation in a plain old AbstractModule (no ServletModule required):

package com.turbomanage.gwt.server.guice;

import javax.servlet.http.HttpSession;

import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.roa.test.mock.MockHttpSession;

public class DispatchTestModule extends AbstractModule
{
	@Override
	protected void configure()
	{
		// application bindings here
	}

	@Provides
	HttpSession getMockSession()
	{
		return new MockHttpSession();
	}
}

I could probably snag a mock session from some other framework, but all I need to do is get and set attributes, hence:

package com.roa.test.mock;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;

public class MockHttpSession implements HttpSession
{
	private Map<String, Object> attributes = new HashMap<String, Object>();

	@Override
	public Object getAttribute(String name)
	{
		return attributes.get(name);
	}

	@Override
	public void setAttribute(String name, Object value)
	{
		attributes.put(name, value);
	}

	// All other methods auto-generated
	...
}

Now my TestCase setUp() method can simulate user login, logout, etc. by calling the real ROAUserService, which Guice provides with our mock HttpSession.

		...
		User u = addTestUser();
		Injector inj = Guice.createInjector(..., new DispatchTestModule());
		ROAUserService userService = inj.getInstance(ROAUserService.class);
		userService.login(...);

Guice Providers can also accept user-defined annotations to allow you to select among multiple implementations of a provided class. That might be another handy testing tool…

Posted in GIN / Guice | 3 Comments »

How to inject Guice objects in a JSP

Posted by David Chandler on December 11, 2009

My current project is written mostly in GWT; however, the GWT module is hosted in a JSP page that needs to obtain the user’s first name from my user service, which is managed by Guice. Since I have only one elementary JSP page, it is not worth introducing Struts or another MVC framework with Guice integration already built in, so I need a way to way to get the Guice context inside the JSP.

It now occurs to me that my login servlet could simply put the needed information into the session, where it could easily be accessed via JSP sessionScope; however, lucky for you, I had to go the long way around before I thought of this. It’s pretty simple, really. In a Web application, Guice gets initialized at application startup in your subclass of GuiceServletContextListener. Normally, you only need to override the getInjector() method of this class, like this:

public class DispatchServletGuiceConfig extends GuiceServletContextListener
{
	@Override
	protected Injector getInjector()
	{
		return Guice.createInjector(new ServerModule(),
			new DispatchServletModule());
	}
}

However, this simple version does not permit direct access to the injector (and therefore instances managed by Guice) except in other classes created by Guice. Since the JSP servlet doesn’t know about Guice, we need to make the Guice injector available ourselves. Fortunately, the GuiceServletContextListener and JSP pages both share access to the ServletContext, so we can override the other two methods in our Guice context listener to put the injector in the ServletContext. The GuiceServletContextListener no doubt does this already, but not where we can predictably find it when a new version comes out, etc. Here’s the expanded implementation:

package com.roa.server.guice;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;
import com.turbomanage.gwt.server.guice.DispatchServletModule;

/**
 * This Guice context listener creates the Guice injector. It's a little
 * more complicated than the usual single-method version in order to
 * store the injector in ServletContext for access by JSPs.
 *
 * @author David Chandler
 */
public class DispatchServletGuiceConfig extends GuiceServletContextListener
{
	@Override
	protected Injector getInjector()
	{
		return Guice.createInjector(new ServerModule(),
			new DispatchServletModule());
	}

	@Override
	public void contextInitialized(ServletContextEvent servletContextEvent)
	{
		// No call to super as it also calls getInjector()
		ServletContext sc = servletContextEvent.getServletContext();
		sc.setAttribute(Injector.class.getName(), getInjector());
	}

	@Override
	public void contextDestroyed(ServletContextEvent servletContextEvent)
	{
		ServletContext sc = servletContextEvent.getServletContext();
		sc.removeAttribute(Injector.class.getName());
		super.contextDestroyed(servletContextEvent);
	}

}

Now in our JSP, we can access the injector via the ServletContext:

<%@ page import="com.google.inject.Injector"%>
<%@ page import="com.google.inject.Guice"%>
<%@ page import="com.roa.server.service.common.ROAUserService"%>
<%@ page import="com.roa.common.domain.User"%>
...
<%
	Injector inj = (Injector) pageContext.getServletContext().getAttribute(Injector.class.getName());
	ROAUserService roaUserService = inj.getInstance(ROAUserService.class);
	User user = roaUserService.getLoggedInUser();
%>

The merits of this approach in this case are admittedly debatable. However, it never hurts to have another tool in your toolbox…

Posted in GIN / Guice, Google Web Toolkit | 1 Comment »

ColdFusion meets AppEngine

Posted by David Chandler on December 10, 2009

What do you get when you combine the easiest Web language ever with the most powerful hosting platform ever?

Open BlueDragon for AppEngine

WatchPaul Kukiel’s short tutorial on setting it up.

Posted in AppEngine, ColdFusion | Leave a Comment »

Quick note on using gwt-presenter’s ActionException

Posted by David Chandler on December 9, 2009

It seems that the best way to use gwt-presenter‘s ActionException is to extend it, as exception chaining using ActionException does not appear to work. Here’s a working example:

package com.roa.common.exception;

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

public class UserNotLoggedInException extends ActionException
{
	private String loginUrl;

	// Required for GWT-RPC!
	private UserNotLoggedInException()
	{
		super();
	}

	public UserNotLoggedInException(String loginUrl)
	{
		super();
		this.loginUrl = loginUrl;
	}

	public String getLoginUrl()
	{
		return loginUrl;
	}
}

Extending ActionException is nice because all your handler execute methods already declare it. And this way, in client code, you can use instanceof in your exception handlers without the need for getCause(), checking for null, etc.

Thanks to the Apache Hupa mail project for a similar example (InvalidSessionException) that helped me see the light on this! While you’re checking out Hupa, have a look at the HupaCallback class, too. Pretty nifty way to achieve centralized error handling on the client combined with gwt-presenter’s DisplayCallback class.

Posted in Google Web Toolkit, Model-View-Presenter | Leave a Comment »

An MVP-compatible EnumListBox for GWT

Posted by David Chandler on December 7, 2009

A frequent request on the GWT and gwt-presenter forums is for a ListBox that implements HasValue like a TextBox. I recently needed one myself, and thought it would be especially cool if I could use it with a Java enum type like this:

	public static enum Frequency {DAILY, WEEKLY, MONTHLY};

	private ConstantsWithLookup enumLabels = GWT.create(EnumLabels.class);
	private EnumListBox<Frequency> freqBox;

	freqBox = new EnumListBox<Frequency>(Frequency.class, enumLabels);

In keeping with MVP philosophy, the presenter’s display interface only needs the HasValue type to get and set the selected value as well as add a ValueChangeHandler to respond to a new selection. Here as some relevant excerpts from a presenter that uses the EnumListBox:

	public interface Display extends WidgetDisplay
	{
		HasValue<Frequency> getFrequency();
	}
	...
	protected void onFirstRequest()
	{
		...
		display.getFrequency().addValueChangeHandler(new ValueChangeHandler<Frequency>()
		{
			@Override
			public void onValueChange(ValueChangeEvent<Frequency> event)
			{
				// Do something with the newly selected event.getValue()
				...
			}
		});
	}

Here’s a straightforward implementation of an EnumListBox that implements HasValue. Thanks to the gwt-ent project for the original idea for this.

package com.roa.app.client.ui.widget;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.ConstantsWithLookup;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.ListBox;
import com.roa.common.client.util.EnumTranslator;

public class EnumListBox<T extends Enum<T>> extends ListBox implements HasValue<T>
{

	private final Class<T> clazzOfEnum;
	private boolean valueChangeHandlerInitialized;

	public EnumListBox(final Class<T> clazzOfEnum, final ConstantsWithLookup constants)
	{
		if (clazzOfEnum == null)
			throw new IllegalArgumentException("Enum class cannot be null");

		this.clazzOfEnum = clazzOfEnum;
		EnumTranslator enumTranslator = new EnumTranslator(constants);

		T[] values = clazzOfEnum.getEnumConstants();

		for (T value : values)
		{
//			this.addItem(constant.toString(), constant.name());
			this.addItem(enumTranslator.getText(value), value.name());
		}
	}

	public T getSelectedValue()
	{
		if (getSelectedIndex() >= 0)
		{
			String name = getValue(getSelectedIndex());

			T[] values = clazzOfEnum.getEnumConstants();
			for (T value : values)
			{
				if (value.name().equals(name))
					return value;
			}
		}

		return null;
	}

	public void setSelectedValue(T value)
	{
		T[] values = clazzOfEnum.getEnumConstants();
		for (int i = 0; i < values.length; i++)
		{
			if (values[i] == value)
			{
				this.setSelectedIndex(i);
				return;
			}
		}
		throw new IllegalArgumentException("No index found for value " + value.toString());
	}

	/*
	 * Methods to implement HasValue
	 */

	@Override
	public T getValue()
	{
		return this.getSelectedValue();
	}

	@Override
	public void setValue(T value)
	{
		this.setValue(value, false);
	}

	@Override
	public void setValue(T value, boolean fireEvents)
	{
		T oldValue = getValue();
		this.setSelectedValue(value);
		if (fireEvents)
		{
			ValueChangeEvent.fireIfNotEqual(this, oldValue, value);
		}
	}

	@Override
	public HandlerRegistration addValueChangeHandler(ValueChangeHandler<T> handler)
	{
		// Initialization code
		if (!valueChangeHandlerInitialized)
		{
			valueChangeHandlerInitialized = true;
			super.addChangeHandler(new ChangeHandler()
			{
				public void onChange(ChangeEvent event)
				{
					ValueChangeEvent.fire(EnumListBox.this, getValue());
				}
			});
		}
		return addHandler(handler, ValueChangeEvent.getType());
	}

}

There’s really not much to it, just a little weirdness that always comes with generics. Notice that the constructor uses an EnumTranslator to populate the labels in the ListBox. This allows you to use a standard GWT ConstantsWithLookup inteface to supply localized text for the enum values instead of the constant names. ConstantsWithLookup is just like Constants, but with the important ability to find a value dynamically without invoking a method corresponding to the property name. Unfortunately, you still have to define a method for each value of the enum in your ConstantsWithLookup class, even though it’s never used directly. Here’s a sample interface:

public interface EnumLabels extends ConstantsWithLookup {
	// Enums
	String com_mypackage_MyClass_Frequency_DAILY();
	String com_mypackage_MyClass_Frequency_WEEKLY();
	String com_mypackage_MyClass_Frequency_MONTHLY();
	String com_mypackage_MyClass_Frequency_QUARTERLY();
	String com_mypackage_MyClass_Frequency_YEARLY();

And the corresponding default properties file EnumLabels.properties:

com_mypackage_MyClass_Frequency_DAILY=daily
com_mypackage_MyClass_Frequency_WEEKLY=weekly
com_mypackage_MyClass_Frequency_MONTHLY=monthly
com_mypackage_MyClass_Frequency_QUARTERLY=quarterly
com_mypackage_MyClass_Frequency_YEARLY=yearly

And finally, here’s my EnumTranslator:

package com.roa.common.client.util;

import com.google.gwt.i18n.client.ConstantsWithLookup;

/**
 * Does a properties file lookup to get text associated with an enum value
 * Property keys use the full class name with all dots and dollars
 * converted to underscores. Keys are case-sensitive and GWT requires a
 * method in the interface that extends ConstantsWithLookup, even though
 * the method is never called.
 *
 * Example:
 * String my_package_class_Frequency_DAILY();
 *
 * In the corresponding properties file:
 * my_package_class_Frequency_DAILY=daily
 *
 * @author David Chandler
 */
public class EnumTranslator
{
	private ConstantsWithLookup constants;

	public EnumTranslator(ConstantsWithLookup constants)
	{
		this.constants = constants;
	}

	public String getText(Enum e)
	{
		String lookupKey = e.getClass().getName() + "." + e.name();
		lookupKey = lookupKey.replace(".", "_");
		lookupKey = lookupKey.replace("$", "_");
		return constants.getString(lookupKey);
	}
}

This EnumListBox is a fairly hard-wired kind of ListBox. In the near future, I anticipate refactoring along these lines:

  1. Add a constructor that takes any java.util.List, not just an Enum.
  2. Create an interface HasSelectedValue that extends HasValue by adding a populateAllSelections() method. This would allow the available selections to come from the presenter through the Display interface and is thus even better for MVP. Versions of the new method could also take a java.util.List or Enum and would replace the constructor.
  3. Ditto for a HasSelectedValues interface to deal with multiple-select type ListBoxes.

Stay tuned.

	...

Posted in Google Web Toolkit, Model-View-Presenter | 11 Comments »

AppEngine SDK 1.2.8 now supports JAXB…and a lot more

Posted by David Chandler on December 5, 2009

In case you missed it, the latest AppEngine for Java release adds support for JAXB (the single most requested feature according to Google’s announcement!). In addition, AppEngine 1.2.8 significantly beefs up ORM support, now supporting inheritance, IN queries, and much more.

I had already found workarounds to these limitations for my current project, but the latest release further demonstrates Google’s commitment to a superior platform and eliminates many more excuses for not giving it a try.

Posted in AppEngine | Leave a Comment »

GWT-RPC exception handling gotcha

Posted by David Chandler on December 4, 2009

A few weeks ago, I posted some GWT-RPC serialization gotchas. At first, this looks like a GWT-RPC serialization problem:

SEVERE: [1259963134337000] javax.servlet.ServletContext log: Exception while dispatching incoming RPC call
com.google.gwt.user.client.rpc.SerializationException: Type 'javax.jdo.JDOFatalUserException' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.

Hmmm, GWT-RPC is probably trying to serialize JDOFatalUserException because one is being thrown somewhere. But why don’t I see it in my logs? I’m catching all RuntimeExceptions in my RemoteServiceServlet and logging a warning with the message.

On closer inspection, I found the warning message just prior to the stack trace; however, it was not clearly associated with JDOFatalUserException because I had used e.getMessage() instead of e.toString().

In the process, however, I discovered that GWT-RPC masks many exceptions. Here is the code in GWT’s RPC.class that actually executes your service method via reflection:

    try {
      Object result = serviceMethod.invoke(target, args);

      responsePayload = encodeResponseForSuccess(serviceMethod, result,
          serializationPolicy);
    } catch (IllegalAccessException e) {
      SecurityException securityException = new SecurityException(
          formatIllegalAccessErrorMessage(target, serviceMethod));
      securityException.initCause(e);
      throw securityException;
    } catch (IllegalArgumentException e) {
      SecurityException securityException = new SecurityException(
          formatIllegalArgumentErrorMessage(target, serviceMethod, args));
      securityException.initCause(e);
      throw securityException;
    } catch (InvocationTargetException e) {
      // Try to encode the caught exception
      //
      Throwable cause = e.getCause();

      responsePayload = encodeResponseForFailure(serviceMethod, cause,
          serializationPolicy);
    }

Note that the catch block for InvocationTargetException attempts to encode (serialize) the root cause exception to send it back to the client. If this fails, however, as in the case of JDOFatalUserException, RPC throws a SerializationException with no information about the root cause!

Moral: make sure your GWT-RPC service methods catch all RuntimeExceptions and log all the info you need. In light of this, I’ve now beefed up my gwt-dispatch service servlet to log a severe message and print a stack trace.

Posted in Google Web Toolkit | Leave a Comment »

Persisting enums with AppEngine Datastore

Posted by David Chandler on December 4, 2009

Much of Java’s appeal (not to mention JSF, ORM, and GWT with a little help) is the ability to code in terms of rich domain objects such as the enumerated type. My next several blog posts will demonstrate the use of enums throughout a GAE+GWT application, beginning with persistence.

According to the AppEngine docs,  Java enums are not one of the core value types, which might lead one to believe that they’re not supported. However, closer examination reveals that enums are indeed supported by DataNucleus JDO and JPA, which take care of mapping enums to Datastore core value types String (JDO + JPA) or Integer (JPA).

JDO

JDO mapping requires no special annotations and persists the enum as a String by name. One of the DataNucleus doc pages (search for “ordinal”) suggests it may be possible to persist by ordinal instead; however, I haven’t found this documented for JDO. Persistence by name is likely better, anyway, as it allows you the flexibility to add new enum values later in any ordinal position.

	public enum ScheduleMethod {RANDOM, FILL, CUSTOM};
	@Persistent
	private ScheduleMethod scheduleMethod = ScheduleMethod.RANDOM;

Note that Google does have a unit test for enum persistence in JDO.

JPA

JPA mapping requires the use of the @Enumerated annotation, which additionally lets you specify whether to map by name (String) or ordinal (Integer).

Roll-your-own

Of course, you can always roll your own mapping strategy if for some reason you need special behavior. With AppEngine Datastore, you can persist any object class by making it Serializable or Embedded, although the former has the disadvantage that you can’t use object properties in queries. You can also create a custom enum class and persist the enum by any core value type as in the example below.

	public static enum Frequency
	{
		DAILY(1),
		WEEKLY(7),
		MONTHLY(30),
		QUARTERLY(90),
		YEARLY(365);
		
		private int periodDays;

		Frequency(int periodDays)
		{
			this.periodDays = periodDays;
		}

		public int getPeriodDays()
		{
			return periodDays;
		}
		
		public static Frequency getValue(int i)
		{
			for (Frequency f : Frequency.values())
			{
				if (f.getPeriodDays() == i)
					return f;
			}
			throw new IllegalArgumentException("Invalid frequency period days: " + i);
		}
	}

	@Persistent
	private Integer periodDays = Frequency.WEEKLY.getPeriodDays();
	
	/**
	 * Convenience method to get frequency as an enum
	 * @return Frequency
	 */
	public Frequency getFrequency()
	{
		return Frequency.getValue(this.getPeriodDays());
	}
	
	public void setFrequency(Frequency f)
	{
		this.setPeriodDays(f.getPeriodDays());
	}

Posted in AppEngine, Java Data Objects | 1 Comment »

AppEngine Cold Starts

Posted by David Chandler on December 2, 2009

It appears that some of the startup delay I had previously blamed on GWT may actually have been due to the phenomenon that is popping up on the AppEngine forums lately. In order to conserve resources, AppEngine doesn’t keep your JVM “hot” unless it’s getting a lot of traffic, and it takes a few seconds to swap it back in. The resulting cold start delay, it would appear, is part of the price of “free.”

See this thread for more info.

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

 
%d bloggers like this: