TurboManage

David Chandler's Journal of Java Web and Mobile Development

  • David M. Chandler


    Web app developer since 1994 and former Developer Advocate with Google 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 242 other followers

  • Sleepless Nights…

    March 2017
    S M T W T F S
    « May    
     1234
    567891011
    12131415161718
    19202122232425
    262728293031  
  • Blog Stats

    • 848,524 hits

Archive for the ‘AppEngine’ Category

Preserving the Datastore when using App Engine dev server with Maven

Posted by David Chandler on June 25, 2011

Problem

I’m currently working on a GWT+GAE Maven project and the local datastore gets wiped every time I start the dev server, whether using mvn clean gae:run or Google Plugin for Eclipse.

Cause

Per the official dev server doc, the local datastore is stored in WEB-INF/appengine-generated/local_db.bin. For most Maven projects, the WEB-INF directory is located under target/${project.build.finalName}, so local_db.bin is under the target directory, which gets wiped every time you mvn clean. It also gets wiped when launching dev mode with Google Plugin for Eclipse.

Solution

Specify an alternate path to the dev server datastore.

In Eclipse, edit the project’s Run Configuration and add this to the VM args:

-Ddatastore.backing_store=${project_loc}/local_db.bin

This will put the local datastore in the project root directory, where it won’t get wiped every time you launch the dev server.

In the project’s POM, add this to the configuration section for maven-gae-plugin:

<jvmFlags>
	<jvmFlag>-Ddatastore.backing_store=${project.basedir}\local_db.bin</jvmFlag>
</jvmFlags>

Many thanks to Marcel Overdijk for pointing the way on the maven-gae-plugin group.

Posted in AppEngine | 4 Comments »

Are Private Clouds Really Safer?

Posted by David Chandler on June 24, 2011

For the second time in two weeks (first in Detroit, then in Atlanta), I’ve listened to a panel discussion on cloud computing in which a panelist has claimed that private clouds are safer than “The Cloud.” In both cases, the panelist was a data center vendor (hmmm…) and in both cases, the other panelists were not so readily agreed. The vendor rep in Atlanta kept mentioning the possibility of network sniffing, as though someone might be able to penetrate Amazon’s hardware virtualization, gain access to the real Ethernet controller, put it in promiscuous mode, and then sniff traffic on … the one wire running to the switch?

Bob Reid of the kotter group asked the best question of the evening: is there any empirical evidence that public cloud computing is safer than private cloud? In other words, has anyone ever successfully penetrated Amazon’s hardware virtualization, App Engine’s VM, etc. and used it to obtain other customers’ data? Said data center vendor acknowledged that social engineering is a much more likely attack vector and can be used just as successfully in a private cloud as public, but then repeated his concerns about the public cloud without citing any evidence. Thankfully, Dennis Hurst, founder of the Cloud Security Alliance, nailed it: the studies show that most break-ins are due to application design flaws and have nothing to do with the hosting environment.

There’s no doubt that some CxOs get a warm fuzzy from knowing that their data is on “their own” servers; however, this would appear to be a false sense of security. If anything, public cloud providers are safer (Dennis Hurst alluded to this earlier in the discussion) because security is an inherent design consideration. All public cloud providers rely on some form of virtualization, whether at the hardware layer (AWS) or a Java VM with security restrictions like App Engine and no doubt do continuous testing to ensure the security of the virtualization layer. The strength of the security sandbox is fundamental to the offering, and public cloud providers can afford to employ the best and brightest to get it right (unlike regional data center vendors–are you sure you’ve got the latest patches?).

Furthermore, public cloud offerings are typically built around services like AWS’s SimpleDB and App Engine’s Datastore, which are not subject to attacks like SQL injection because the service APIs don’t allow you to execute arbitrary database commands. Service APIs significantly limit attack surface, which is one reason why I prefer App Engine’s approach to virtualization over Amazon’s (granted, I’m a little biased). With AWS, you’re still responsible to configure your virtual machine instances correctly, albeit you have to explicitly open network ports so you’re not wide open by default.

The question, I think stands: is anyone aware of an incident in which a public cloud customer obtained access to another customer’s data by penetrating the security sandbox? Methinks the cloud offerings of today are generally much safer than the shared Web hosting arrangements of the past because of the superior virtualization technology employed today. Once upon a time, you could use CFFILE on a mis-configured ColdFusion host or similar technique in ASP to gain access to the file system on the shared host. But as far as I know, no one has demonstrated such an exploit against AWS, App Engine, Azure, etc.

Social engineering, insider leaks, and application flaws (which are arguably *less* likely using public cloud services) remain the most likely attack vectors, and CxOs should carefully evaluate FUD from data center vendors before rejecting the public cloud on the basis of security concerns. And while I’m at it, unless a “private cloud” offers elasticity, multi-tenancy, and metered service, I don’t think it can properly be called cloud. Dedicated / colocated hosting has been around for a long time and has its merits, but please don’t “cloud” the vocabulary.

Posted in AppEngine, Web App Security | 1 Comment »

Using GWT RequestFactory with Objectify

Posted by David Chandler on March 25, 2011

I’ve put together a little sample project using GWT’s RequestFactory with Objectify. It’s not very sophisticated, but should get you started.

RequestFactory is a relatively new GWT feature that makes it especially easy to create data-oriented services. In this example, we’ll create a RequestFactory service backed by Objectify to manage arbitrary lists of items such as a ToDo list, grocery list, etc.

Domain Model

First, let’s look at our domain classes (ItemList, ListItem, and AppUser):

ItemList.java

package com.turbomanage.listwidget.domain;

import java.util.List;

import javax.persistence.Embedded;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.turbomanage.listwidget.shared.proxy.ItemListProxy.ListType;

/**
 * POJO that represents a list of items such as a ToDo list.
 * The items are stored as an embedded object.
 */
@Entity
public class ItemList extends DatastoreObject
{
	private String name;
	private Key<AppUser> owner;
	private ListType listType;
	@Embedded
	private List<ListItem> items;
        // Getters and setters omitted
}

DatastoreObject.java:

package com.turbomanage.listwidget.domain;

import javax.persistence.Id;
import javax.persistence.PrePersist;

public class DatastoreObject
{
	@Id
	private Long id;
	private Integer version = 0;

	/**
	 * Auto-increment version # whenever persisted
	 */
	@PrePersist
	void onPersist()
	{
		this.version++;
	}
	// Getters and setters omitted
}

ItemList is an Objectify @Entity. In order for it to work as an entity with RequestFactory, it must have ID and version properties, which are inherited from the DatastoreObject convenience class. Items in the list are stored as an embedded object using the @Embedded JPA annotation supported by Objectify. I could store the items in a separate entity in order to minimize the cost of the query to retrieve just the list names; however, most of the lists will contain only a few items so this serves our example better. Because it is embedded, ListItem is not an entity for purposes of Objectify or RequestFactory, just a simple value type.

ListItem.java:

package com.turbomanage.listwidget.domain;

import java.util.Date;

/**
 * POJO that represents an item in a list.
 */
public class ListItem // POJO
{
	private String itemText;
	private Date dateCreated;
        // Getters and setters omitted
}

AppUser represents a user of our application. It’s an Objectify @Entity and is referenced by the ItemList entity.

package com.turbomanage.listwidget.domain;

import javax.persistence.Entity;

/**
 * An application user, named with a prefix to avoid confusion with GAE User type
 */
@Entity
public class AppUser extends DatastoreObject
{
	private String email;

	public AppUser()
	{
		// No-arg constructor required by Objectify
	}
	// Getters and setters omitted
}

Persistence Layer

The persistence layer on the server side is just a standard ObjectifyDAO that handles all the CRUD operations. It has a static initializer that registers the entity types (ItemList and AppUser–for a later post). ItemListDao extends the generic ObjectifyDao and provides a bit of logic to restrict listAll() to those lists owned by the current user.

ItemListDao.java:

package com.turbomanage.listwidget.server.service;

import java.util.List;

import com.googlecode.objectify.Key;
import com.turbomanage.listwidget.domain.AppUser;
import com.turbomanage.listwidget.domain.ItemList;

public class ItemListDao extends ObjectifyDao<ItemList>
{
	@Override
	public List<ItemList> listAll()
	{
		return this.listAllForUser();
	}

	/**
	 * Wraps put() so as not to return a Key, which RF can't handle
	 *
	 * @param obj
	 */
	public void save(ItemList list)
	{
		AppUser loggedInUser = LoginService.getLoggedInUser();
		list.setOwner(loggedInUser);
		this.put(list);
	}

	public ItemList saveAndReturn(ItemList list)
	{
		AppUser loggedInUser = LoginService.getLoggedInUser();
		list.setOwner(loggedInUser);
		Key<ItemList> key = this.put(list);
		try
		{
			return this.get(key);
		}
		catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}

	/**
	 * Remove a list. Since items are embedded, they are removed automatically.
	 *
	 * @param list
	 */
	public void removeList(ItemList list)
	{
		this.delete(list);
	}
}

ItemListDao wraps the put() method from ObjectifyDao with a save() method that returns void. This is because put() returns a Key to the newly persisted object, but RequestFactory on the client doesn’t know about about types such as com.googlecode.objectify.Key that exist only on the server (remember that the GWT compiler requires Java source for all types used on the client).

Through the magic of RequestFactory, we can expose ItemListDao directly as a service to be called from the GWT client. This is simpler than GWT-RPC, which requires each service impl to extend RemoteServiceServlet, and much less code than the Command pattern, which typically utilizes Action, Result, and handler classes for each service method (albeit the Command pattern still gives you the most application control over caching, batching, and the like). All that’s needed is a trivial ServiceLocator class which is used by RequestFactory to request an instance of any RequestFactory service.

DaoServiceLocator.java:

package com.turbomanage.listwidget.server.locator;

import com.google.gwt.requestfactory.shared.ServiceLocator;

/**
 * Generic locator service that can be referenced in the @Service annotation
 * for any RequestFactory service stub
 *
 * @author turbomanage
 */
public class DaoServiceLocator implements ServiceLocator {
	public Object getInstance(Class<?> clazz) {
		try {
			return clazz.newInstance();
		} catch (InstantiationException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		}
	}
}

Unlike GWT-RPC, RequestFactory services do not directly implement the service interface. As we will see shortly, this is because RequestFactory service interfaces are intended only for the client side and do not use server-side entity types directly. Services do have to provide all the methods in the client-side interface; however, this is enforced via run-time validation, not at compile time as with GWT-RPC. The loss of some compile-time safety is one disadvantage of the RequestFactory approach.

Proxy Interfaces

When using an object-relational mapping framework like Objectify, entities typically contain annotations and other code from the ORM framework for which the Java source is not available to the GWT compiler. Therefore, the same entity representation cannot be used on both client and server. This problem can be partially solved by using the GWT super-src capability to supply a GWT-safe implementation of server-side classes. Objectify does this for its Key type and annotations so the same annotated domain class can be used on both client and server with GWT-RPC, and Gilead offers something similar for Hibernate.

Another approach to the problem is to use the DTO pattern. However, this has two main disadvantages. First, you now have two different representations of each entity class and must manually keep the code in sync. Second, every service call must copy data from the real entity to its client-safe DTO and vice versa. Again, there are frameworks to help with this, but it’s a pain.

The RequestFactory approach solves the entity / DTO problem in a unique way that overcomes the weaknesses of the classic DTO pattern. With RequestFactory, you declare a proxy interface for each entity. Unlike a classic DTO, the proxy interface exposes only method signatures so there are no implementation details to keep in sync. Furthermore, RequestFactory automatically populates client objects from the corresponding entities on the server and vice versa. Here are our proxy interfaces:

ItemListProxy.java:

package com.turbomanage.listwidget.shared.proxy;

import java.util.List;

import com.google.gwt.requestfactory.shared.ProxyFor;
import com.turbomanage.listwidget.domain.ItemList;
import com.turbomanage.listwidget.server.locator.ObjectifyLocator;

@ProxyFor(value = ItemList.class, locator = ObjectifyLocator.class)
public interface ItemListProxy extends DatastoreObjectProxy
{
	// Note: enums work!
	public enum ListType {NOTES, TODO}

	String getName();
	void setName(String name);
	List<ListItemProxy> getItems();
	ListType getListType();
	AppUserProxy getOwner();
	void setListType(ListType type);
	void setItems(List<ListItemProxy> asList);
}

Because ItemList is a Datastore entity with ID and version properties, ListItemProxy extends the EntityProxy interface. The @ProxyFor annotation specifies the domain type on the server, and the locator attribute specifies an entity locator class (see next section). Note that entities can define their own enum types, and they must be declared in the proxy interface, not the entity itself, in order for the enum type to be available on the client.

ListItemProxy.java:

package com.turbomanage.listwidget.shared.proxy;

import java.util.Date;

import com.google.gwt.requestfactory.shared.ProxyFor;
import com.google.gwt.requestfactory.shared.ValueProxy;
import com.turbomanage.listwidget.domain.ListItem;

@ProxyFor(value = ListItem.class)
public interface ListItemProxy extends ValueProxy
{
	String getItemText();
	void setItemText(String itemText);
	Date getDateCreated();
}

ListItem is not an entity. It doesn’t have ID and version properties because it is embedded within the ItemList entity. Therefore, ListItem extends the ValueProxy interface, which can be used for any “value type” (non-entity).

AppUserProxy.java:

package com.turbomanage.listwidget.shared.proxy;

import com.google.gwt.requestfactory.shared.ProxyFor;
import com.turbomanage.listwidget.domain.AppUser;
import com.turbomanage.listwidget.server.locator.ObjectifyLocator;

@ProxyFor(value=AppUser.class, locator=ObjectifyLocator.class)
public interface AppUserProxy extends DatastoreObjectProxy
{
	String getEmail();
}

Finally, AppUserProxy is an entity so it extends EntityProxy.

Generic Entity Locator

RequestFactory requires each entity to provide four Locator methods. These are used by RequestFactoryServlet to obtain an instance of an entity in order to populate it with property values from the client request before invoking the service method. Fortunately, the required methods can be implemented in a separate class which can be shared by all entities. Here is the generic ObjectifyLocator used with all the entities and specified in the @ProxyFor annotation for each entity proxy above.

package com.turbomanage.listwidget.server.locator;

import com.google.gwt.requestfactory.shared.Locator;
import com.googlecode.objectify.helper.DAOBase;
import com.turbomanage.listwidget.domain.DatastoreObject;

/**
 * Generic @Locator for objects that extend DatastoreObject
 */
public class ObjectifyLocator extends Locator<DatastoreObject, Long>
{
	@Override
	public DatastoreObject create(Class<? extends DatastoreObject> clazz)
	{
		try
		{
			return clazz.newInstance();
		} catch (InstantiationException e)
		{
		  throw new RuntimeException(e);
		} catch (IllegalAccessException e)
		{
			throw new RuntimeException(e);
		}
	}

	@Override
	public DatastoreObject find(Class<? extends DatastoreObject> clazz, Long id)
	{
		DAOBase daoBase = new DAOBase();
		return daoBase.ofy().find(clazz, id);
	}

	@Override
	public Class<DatastoreObject> getDomainType()
	{
		// Never called
		return null;
	}

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

	@Override
	public Class<Long> getIdType()
	{
		return Long.class;
	}

	@Override
	public Object getVersion(DatastoreObject domainObject)
	{
		return domainObject.getVersion();
	}
}

ObjectifyLocator makes use of the fact that all the entities extend DatastoreObject, which defines an ID property of type Long. If your entities don’t extend a common base class or interface, you can still use a generic entity locator by using reflection to call the getId() and getVersion() methods on the underlying entity.

RequestFactory Interface

The heart of RequestFactory is the interface in which you define your services. Each service stub is an interface that extends RequestContext having one or more service methods, and for each service you define an accessor method in the main RequestFactory interface. If you have a small number of services, you can define everything in one class as below.

ListWidgetRequestFactory.java:

package com.turbomanage.listwidget.shared.service;

import java.util.List;

import com.google.gwt.requestfactory.shared.Request;
import com.google.gwt.requestfactory.shared.RequestContext;
import com.google.gwt.requestfactory.shared.RequestFactory;
import com.google.gwt.requestfactory.shared.Service;
import com.turbomanage.listwidget.server.locator.DaoServiceLocator;
import com.turbomanage.listwidget.server.service.ItemListDao;
import com.turbomanage.listwidget.shared.proxy.ItemListProxy;

public interface ListwidgetRequestFactory extends RequestFactory
{
	/**
	 * Service stub for methods in ItemListDao
	 * 
	 * TODO Enhance RequestFactory to enable service stubs to extend a base interface
	 * so we don't have to repeat methods from the base ObjectifyDao in each stub
	 */
	@Service(value = ItemListDao.class, locator = DaoServiceLocator.class)
	interface ItemListRequestContext extends RequestContext
	{
		Request<List<ItemListProxy>> listAll();
		Request<Void> save(ItemListProxy list);
		Request<ItemListProxy> saveAndReturn(ItemListProxy newList);
		Request<Void> removeList(ItemListProxy list);
	}
	
	ItemListRequestContext itemListRequest();
}

ItemListRequestContext is a service stub and itemListRequest() is its accessor method. The @Service annotation specifies the implementation class on the server, and the locator attribute specifies a ServiceLocator class from which an instance of the service may be obtained–in this case, our generic DaoServiceLocator shown above.

Service method argument and return types use the proxy interfaces, not the real entity types. Server implementations use the real types and RequestFactory automatically maps between the two. In addition, all service methods return a Request object parameterized with the real return type (or rather, its proxy type). Server implementations return the real entity type directly. Services that have no return type should return Request in the client interface. The disparity between entity types on client and server prevents services from directly implementing the service interface as with GWT-RPC.

Again, note that we’re able to use a DAO directly as our service implementation. Furthermore, as of GWT 2.3, a service can be inherited from a base class (in this case, ObjectifyDao) as per this issue. This is a really powerful capability, as it allows you to implement the common CRUD operations in a single class on the server with no boilerplate code for each service impl. However, on the client side, service stubs cannot yet extend a base interface other than RequestContext, so each service stub must declare methods inherited from a base class as well as those implemented in the service class.

Wiring and Startup

Starting up your RequestFactory service layer in the client is as simple as

private final ListwidgetRequestFactory rf = GWT.create(ListwidgetRequestFactory.class);

In the sample app, I’ve done this in a factory class so it will be available to all presenter classes.

Using RequestFactory

First, let’s look at creating a new ItemList and persisting it to the server. Here is an excerpt from ListsActivity which creates a new instance of ItemListProxy and sends it to the server:

	public void persistList(String listName)
	{
		final ListwidgetRequestFactory rf = this.clientFactory
				.getRequestFactory();
		ItemListRequestContext reqCtx = rf.itemListRequest();
		final ItemListProxy newList = reqCtx.create(ItemListProxy.class);
		newList.setName(listName);
		newList.setListType(ListType.TODO);
		reqCtx.saveAndReturn(newList).fire(new Receiver<ItemListProxy>()
		{
			@Override
			public void onSuccess(final ItemListProxy savedList)
			{
				// Refresh table
				listDataProvider.getData();
				...
			}
		});
	}

Since ItemListProxy is an interface, how can we get an instance of it? By calling the create() method inherited from RequestContext. RequestFactory uses the new AutoBeans framework in GWT, which can be used to create an instance of any interface. Using AutoBeans, RequestFactory registers a visitor object for each setter in order to track all changes to the instance. This is what allows RequestFactory to send only changes to the server with each request.

Once we have an instance of our proxy, we can populate it using its setter methods and call the service method, which returns a Request but doesn’t actually do anything yet. In order to invoke the method on the server, we must fire() the Request and pass it a new Receiver object to handle the callback. Receiver is analogous to GWT-RPC’s AsyncCallback, but is hooked in via the return type (Request) instead of an additional service method argument as with GWT-RPC.

Now let’s look at a query to retrieve all ItemLists. Here is the getData() method from the AsyncDataProvider in ListsActivity that updates the CellTable showing all lists.

		private void getData()
		{
			logger.warning("getting data");
			// To retrieve relations and value types, use .with()
			Request<List<ItemListProxy>> findAllReq = rf.itemListRequest()
					.listAll().with("owner");
			// Receiver specifies return type
			findAllReq.fire(new Receiver<List<ItemListProxy>>()
			{
				@Override
				public void onSuccess(List<ItemListProxy> response)
				{
					updateRowCount(response.size(), true);
					updateRowData(0, response);
				}
			});
		}

The listAll() service call is similar to saveAndReturn() above with one important addition: the with(“owner”) method. This retrieves the related AppUser entity (using its proxy type, of course). The with() method specifies the bean-style name of a property to be populated with the request and is required to retrieve entity properties that are themselves proxy types (EntityType or ValueType), as RequestFactory does not retrieve related entities automatically. You can pass a comma-separated list of property names (“owner,creator,…”) and use dot notation to specify nested objects (“owner.address.city”).

Note: this post isn’t about CellTables, but observe that both updateRowData() and updateRowCount() are required to properly update the table when using an AsyncDataProvider.

Finally, let’s look at an example of updating an object previously returned from the server. Here is an excerpt from EditListActivity:

		public void update(int index, ListItemProxy item, final String newText)
		{
			ItemListRequestContext reqCtx = clientFactory.getRequestFactory()
					.itemListRequest();
			ListItemProxy editItem = reqCtx.edit(item);
			editItem.setItemText(newText);
			editList = reqCtx.edit(editList);
			editList.getItems().set(index, editItem);
			// Save the list since items are embedded
			reqCtx.save(editList).fire(new Receiver<Void>()
			{
				@Override
				public void onSuccess(Void response)
				{
					eventBus.fireEvent(new MessageEvent(newText + " updated",
							MessageType.INFO));
				}
			});
		}

This update() method changes the text of an item in an ItemList and takes an ItemListProxy argument that represents an ItemList previously returned from the server. Before any changes can be made to it, we must call RequestContext.edit() in order to make it mutable and allow RequestFactory to track changes. Then we can getItems(), set the new item text, and save the modified ItemList.

Summary

The combination of RequestFactory and Objectify makes it possible to write a service layer for GWT and App Engine with very little boilerplate code. Hopefully this will help you get started. Comments welcome, as well as contributions to the sample project referenced throughout. Enjoy!

Posted in AppEngine, Google Web Toolkit | 73 Comments »

GWT + Maven + GAE gotcha

Posted by David Chandler on March 8, 2011

It turns out that gwt-user-2.2.0, weighing in at 10.6 MB, is just over the App Engine size limit for a single file (10 MB) so you must enable jar splitting to deploy a GWT + Maven project to GAE. Actually, though, there is no need to deploy gwt-user because it’s only used for GWT compilation and GWT dev mode. The GWT Expenses sample POM correctly scopes the gwt-user dependency as “provided” in order to prevent this. However, the sample POM also says in the gwt-maven-plugin config:

<copyWebapp>true</copyWebapp>

This feature of gwt-maven-plugin copies src/main/webapp to the target folder in order for GWT dev mode (gwt:run) to work and inadvertently copies the gwt-user jar, too. Fortunately, if you’re using a POM with copyWebapp=true, you can configure the clean plugin to remove the gwt-user jar from the target folder before GAE deployment:

			<plugin>
				<!-- Don't deploy gwt-user jar to GAE -->
				<artifactId>maven-clean-plugin</artifactId>
				<version>2.3</version>
				<executions>
					<execution>
						<id>default-clean</id>
						<phase>clean</phase>
						<goals>
							<goal>clean</goal>
						</goals>
					</execution>
					<execution>
						<id>remove-gwt-user-jar</id>
						<phase>package</phase>
						<goals>
							<goal>clean</goal>
						</goals>
						<configuration>
							<excludeDefaultDirectories>true</excludeDefaultDirectories>
							<filesets>
								<fileset>
									<directory>${project.build.directory}/${project.build.finalName}/WEB-INF/lib</directory>
									<includes>
										<include>gwt-user*jar</include>
									</includes>
								</fileset>
							</filesets>
						</configuration>
					</execution>
				</executions>
			</plugin>

It should be noted that this is only an issue for Maven projects. Google Plugin for Eclipse has long excluded gwt-user.jar from WEB-INF/lib, so standard GPE projects don’t deploy it to App Engine. However, GPE Maven projects allow Maven to manage the classpath, so you’ll need the clean snippet above in your POM to exclude gwt-user from deployment.

A proposed fix is to enhance the gwt-maven-plugin’s copyWebapp feature (which, ironically enough, was contributed by Google) to exclude gwt-user*jar from the copy. Until then, use the clean snippet above or enable jar splitting.

Posted in AppEngine, Google Web Toolkit | 2 Comments »

New GWT+GAE book

Posted by David Chandler on January 31, 2011

Daniel Guermeur and Amy Unruh have written a fantastic new book on Web app development with GWT and GAE.

Google App Engine Java and GWT Application Development is an amazingly thorough and up-to-date guide. Loaded with example code, this tutorial walks you through all the moving parts of a real-world GWT+GAE app, including

  • Building a data model and service layer with App Engine Datastore and JDO
  • Calling GWT-RPC services with a wrapper for retries and error handling
  • GWT MVP (both roll-your-own and GWT 2.1 Activities and Places)
  • GWT mobile browser detection and MVP
  • Login integration with Facebook and Twitter via OAuth

In addition, the book features a number of advanced topics I’ve never seen in print:

  • Using Datastore transactions and entity groups / keys with JDO
  • Background processing with App Engine task queues and XMPP
  • Datastore caching with memcache and JDO lifecycle listeners
  • Browser push with the App Engine Channel API and GWT wrapper
  • Use of Datastore list properties to simulate joins

What more can I say? I’ve been doing GWT+GAE for a couple years now and I learned a ton of new things from this book. Congrats, Daniel and Amy, on creating a truly outstanding resource!

Posted in AppEngine, Google Web Toolkit | 1 Comment »

AppEngine Cold Starts Considered

Posted by David Chandler on March 26, 2010

I’ve been able to reduce my cold start time on AppEngine from an average of 8.1s to 2.5s, a 69% reduction. If you’re already familiar with the cold start issue, you can skip the next paragraph.

Cold starts seem to be the #1 complaint about AppEngine for Java. The root issue is that many developers coming to AppEngine are expecting it to work like the enterprise Java stacks they work on during their day jobs. AppEngine can indeed run an amazing variety of enterprise frameworks like Spring and JSF (see Will it play in AppEngine), but the reason Google can give it away for free to get started is because they’re not running dedicated servers just for your app. Instead, Google has done what few, if any, Web hosting companies have ever been able to do, which is to provide secure shared hosting for Java. If your app is not getting used at the moment, Google will swap out your JVM and fire it up again when a request comes in, thereby freeing up server memory for active apps. Unfortunately, for lightly used apps, this means AppEngine may have to spin up your JVM for every new user session. This includes initializing the servlet context and all frameworks your app may be using. Consequently, cold start times between 8-12s are not uncommon, and some larger stacks can’t even start within in the 30s request deadline.

Frankly, 10s isn’t a bad time to start up a Java stack. Most enterprise apps I’ve worked on take a minute or more. AppEngine doesn’t take that long because lots of AppEngine services are always running: Datastore, Memcache, etc. The problem is that due to the shared nature of the AppEngine platform, you have to pay this startup penalty very often. Lots of folks have asked Google to create a pay-for-warm-JVM option, which has recently been added to the AppEngine for Java roadmap. A nice way to do this might be set a minimum fee for billing-enabled apps that would guarantee you a JVM, but which you could credit toward actual resource usage.

For now, however, you can reduce your cold start time by rethinking (and refactoring) your app to work with AppEngine rather than trying to force your enterprise stack on the platform.

Let’s start with dependency injection. I love DI frameworks like Spring and Guice. But they’re not designed for shared hosting. They deliberately pre-load as much as possible at startup, which is the right thing to do on a dedicated server when startups are infrequent. But on AppEngine, it will cost you. Guice on AppEngine is configured via a servlet context listener. Unfortunately, this means that every servlet, including cron jobs and task invocations, trigger Guice initialization during a cold start, even though those servlets don’t need any Guice-provided objects. Worse, Guice eagerly loads all singletons in production mode, so all my gwt-dispatch ActionHandlers were getting loaded with every hourly cron job (which doesn’t even need the ActionHandlers). The solution was to replace Guice with gwt-dispatch’s basic LazyActionHandlerRegistry as described on the wiki. That saved me 5+ seconds.

Next, consider a fast-startup persistence framework like Objectify-appengine. JPA and JDO incur significant overhead to create a new PersistenceManager (by some reports, 2-3s). “So,” you say, “I’ll use a DI framework to create only one instance of the PM at startup,” and now you’re back to the previous paragraph. A better alternative for AppEngine is to use a lightweight persistence framework designed specifically for AppEngine. ObjectifyService.begin() takes only miliseconds, and IMHO is easier to use than JDO or JPA, although I appreciate that Google makes those APIs available for portability.

Bottom line: by eliminating DI frameworks and using Objectify for persistence, I’m seeing cold starts in 2.5s average. I am more than happy to pay this small penalty for the privilege of running my code for free on the world’s most scalable Java infrastructure. This approach also conserves community resources vs. running a useless cron job just to keep your app warm, which makes cold starts happen all that more often for the rest of us.

Of course, once my app traffic takes off or Google come out with a pay-for-JVM option, all this goes away and you can use dependency injection, cron jobs, etc. with abandon. But for now, the name of the game is, how small can you make your app? Personally, I love the challenge. I much prefer lightweight, plain old Java to layer upon layer of frameworks, anyway.

Posted in AppEngine, GIN / Guice | 10 Comments »

Adding info to GWT-RPC dispatch URL for logs

Posted by David Chandler on March 19, 2010

I was digging around GWT a little this week and found a neat way to append information to server requests sent by gwt-dispatch. By default, dispatch requests show up in the logs as just “/your_app_path/dispatch”. But it turns out you can add a few lines to your DispatchAsync class to append the action name, so you see “/your_app_path/dispatch/SomeAction” in the server logs.

This is really cool on AppEngine because the Dashboard aggregates the number of requests and total CPU for each URL. With the basic dispatcher, all requests to “/your_app_path/dispatch” get rolled up together, but with this enhancement, you get dashboard roll-ups for each Action.

All you need is a couple extra lines in StandardDispatchAsync. In addition, you must append a wildcard to your dispatch servlet mapping in web.xml, “/your_app_path/dispatch/*” (thanks to Ben Binford for pointing this out). The changes from gwt-dispatch are in lines 27 and 35-38.

package net.customware.gwt.dispatch.client.standard;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;

import net.customware.gwt.dispatch.client.AbstractDispatchAsync;
import net.customware.gwt.dispatch.client.DispatchAsync;
import net.customware.gwt.dispatch.client.ExceptionHandler;
import net.customware.gwt.dispatch.server.Dispatch;
import net.customware.gwt.dispatch.shared.Action;
import net.customware.gwt.dispatch.shared.Result;

/**
 * This class is based on the default implementation of {@link DispatchAsync}, which is
 * essentially the client-side access to the {@link Dispatch} class on the
 * server-side.
 *
 * This version appends the name of the Action class to the URL as extra path info.
 *
 * @author David Peterson
 * @author David Chandler
 */
public class StandardDispatchAsync extends AbstractDispatchAsync {

    private static final StandardDispatchServiceAsync realService = GWT.create( StandardDispatchService.class );
    private static final String baseUrl = ((ServiceDefTarget)realService).getServiceEntryPoint() + "/";

    public StandardDispatchAsync( ExceptionHandler exceptionHandler ) {
        super( exceptionHandler );
    }

    public <A extends Action<R>, R extends Result> void execute( final A action, final AsyncCallback<R> callback ) {
        // Append action class name as extra path info
        String className = action.getClass().getName();
        int namePos = className.lastIndexOf(".") + 1;
        className = className.substring(namePos);
        ((ServiceDefTarget)realService).setServiceEntryPoint(baseUrl + className);

        realService.execute( action, new AsyncCallback<Result>() {
            public void onFailure( Throwable caught ) {
                StandardDispatchAsync.this.onFailure( action, caught, callback );
            }

            @SuppressWarnings({"unchecked"})
            public void onSuccess( Result result ) {
                StandardDispatchAsync.this.onSuccess( action, (R) result, callback );
            }
        } );
    }
}

There are other possible uses of the extra path info. See this forum thread for discussion of security uses and the corresponding warnings.

Enjoy!

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

Which way to MVP? and other notes from DevNexus

Posted by David Chandler on March 10, 2010

I had the privilege of speaking at DevNexus this week (conf was a great success, with 300+ developers  from the Atlanta area), and the challenge of speaking on AppEngine and GWT MVP immediately after Google engineers spoke on the same topics. It was great to meet AppEngine for Java co-creator Toby Reyelts and GWT engineer Chris Ramsdale, both of whom are frequently seen on the forums.

Chris and I presented slightly different ways of doing MVP. Ray Ryan’s Google I/O 2009 presentation that started the MVP craze showed the approach taken by gwt-presenter (which I showed), where each view implements an interface defined by the corresponding presenter. Other Google teams have subsequently modified this approach and define interfaces for both presenter and view. This simplifies DOM event handling. In Ray Ryan’s original model, the presenter would add a ClickHandler to a Widget implementing HasClickHandlers. In the double-interface model, the view could instead add the ClickHandler and call a method on the presenter interface. I have definitely run into situations where the latter would be handy, but I don’t have a strong opinion either way, and Chris was very careful not to be dogmatic, either. There are lots of good ideas out there. Someone at my GWT talk asked if I had seen mvp4g (I hadn’t, thanks!), and claimed it has runAsync support for presenters, which sounds promising.

At the end of my talk on gwt-presenter and gwt-dispatch, I presented a few GWT development tools (Firefox Web Developer Toolbar and Firebug) and made the claim that they represent the best there is for WYSIWYG GWT development.

OOPS! Embarrassingly, I hadn’t tried Chrome Developer Tools yet! Google has raised the bar again.

Google raises the bar again

Speed Tracer also looks very promising for analyzing GWT, in particular.

Having been “heads-down” on AppEngine and GWT for the last 6 months, it was good to take a breather and catch up on new developments.

Posted in AppEngine, Google Web Toolkit | 2 Comments »

A few words on AppEngine logging (production)

Posted by David Chandler on March 5, 2010

The AppEngine production log viewer is the envy of most development and sysadmin teams I’ve ever worked with. It offers a a near real-time view into your application’s doings in a powerful Web-based interface. In addition to filtering on the standard JDK log levels, you can search a particular time period, filter any regex, and use labels to filter on

  • day,
  • month,
  • year,
  • hour,
  • minute,
  • second,
  • tzone,
  • remotehost,
  • identd_user,
  • user,
  • status,
  • bytes,
  • referrer,
  • useragent,
  • method,
  • path,
  • querystring,
  • protocol

The request log shows every request, even images and CSS, so you can see why you need to turn on expiration headers for static files 🙂 RPC calls, cron jobs, task servlets–they’re all there. Furthermore, if your app is enabled for Google account authentication, every request is tagged with the Google user id. This is a poor man’s “fish tag” and is extremely helpful for real-time customer support with your mother-in-law (“Mom! You’re using IE 5!”).

If you’re using gwt-dispatch, you’ll notice that all requests to the dispatcher are logged alike (which also causes the Dashboard CPU meter to aggregate all requests to your dispatch servlet). With this in mind, I’m thinking of having the dispatch servlet log the Action class being invoked so I can put together something akin to a click trail. In addition, I wonder if there’s a way for the GWT dispatcher to append the action name as extra path info or query string? This way, the Dashboard might be able to break out which Actions are consuming the most CPU.

The only unpleasantness I’ve found is that AppEngine clutters up the logs with a bunch of harmless warnings about FinalizableReferenceQueue. You can easily get rid of them, however, by putting these lines to your WEB-INF/logging.properties:

# Hide harmless
com.google.inject.internal.FinalizableReferenceQueue=WARNING
com.google.inject.internal.FinalizableReferenceQueue$SystemLoader=WARNING
com.google.appengine.repackaged.com.google.common.base.FinalizableReferenceQueue.level=WARNING

Actually, there is one more unpleasantness: the much-discussed cold start problem. If your app is not yet world-famous, AppEngine will cycle it out after only a few minutes of non-use. This issue has been beat to death on the forums, but suffice it to say it’s easy to spot: just look for the requests with CPU time in red that took 8 seconds after a period of inactivity. Lots of folks have said they’d be willing to stay “hot,” which seems like a good idea. For my part, I like the platform enough that I’m willing to bet Google will take this seriously.

Posted in AppEngine | 4 Comments »

A recipe for unit testing AppEngine task queues

Posted by David Chandler on March 3, 2010

One of the difficulties of testing AppEngine code has been the problem of running unit tests for code written against the Task Queue API. AppEngine provided no easy way to programatically control the task queue engine. In addition, tasks are servlets, so it’s not particularly easy to invoke them with the correct task payload in a unit test.

Fortunately, AppEngine 1.3.1 provides test helpers that greatly simplify writing unit tests against the Datastore and Task Queue APIs (as well as Memcache, Blobstore, and others). By default, the Datastore is configured with the NO_STORAGE property set to true (the default) so that each test method starts with a blank datastore. Also by default, the task queuing auto-run capability is disabled, which gives you the opportunity to programatically run a task once you have verified that it’s been enqueued properly.

The following BaseTest class initializes the Datastore and TaskQueue services. Once the AppEngine team fixes the bug that requires the LocalServerEnvironment override, it will be very simple, indeed. You can ignore the Guice injector stuff if you’re not using Guice.

BaseTest.java

package com.roa.test.helper;

import java.io.File;

import junit.framework.TestCase;

import com.google.appengine.tools.development.LocalServerEnvironment;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.appengine.tools.development.testing.LocalTaskQueueTestConfig;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.roa.server.guice.ServerModule;
import com.turbomanage.gwt.server.guice.DispatchTestModule;

/**
 * A simple test base class that can be extended to build unit tests that
 * properly construct and tear down AppEngine test environments.
 */
public abstract class BaseTest extends TestCase
{

	private static Injector inj;
	protected LocalServiceTestHelper helper;
	private LocalDatastoreServiceTestConfig datastoreConfig;
	private LocalTaskQueueTestConfig taskQueueConfig;

	/**
	 * Sets up the AppEngine environment and initializes Guice.
	 */
	@Override
	protected void setUp() throws Exception
	{
		super.setUp();
		datastoreConfig = new LocalDatastoreServiceTestConfig();
		taskQueueConfig = new LocalTaskQueueTestConfig();
		helper = new LocalServiceTestHelper(datastoreConfig, taskQueueConfig)
		{
			// Temp workaround until 1.3.2 to help task queue find war/WEB-INF/queue.xml
			@Override
			protected LocalServerEnvironment newLocalServerEnvironment()
			{
				final LocalServerEnvironment lse = super.newLocalServerEnvironment();
				return new LocalServerEnvironment()
				{
					public File getAppDir()
					{
						return new File("war");
					}

					public String getAddress()
					{
						return lse.getAddress();
					}

					public int getPort()
					{
						return lse.getPort();
					}

					public void waitForServerToStart() throws InterruptedException
					{
						lse.waitForServerToStart();
					}
				};
			}
		};

		helper.setEnvAuthDomain("auth");
		helper.setEnvEmail("test@example.com");
		helper.setEnvIsAdmin(true);
		helper.setEnvIsLoggedIn(true);
		helper.setUp();

		inj = Guice.createInjector(new ServerModule(), new DispatchTestModule());
	}

	@Override
	protected void runTest() throws Throwable
	{
		super.runTest();
	}

	/**
	 * Deconstructs the AppEngine environment.
	 */
	@Override
	protected void tearDown() throws Exception
	{
		helper.tearDown();
		super.tearDown();
	}

	/**
	 * Provide Guice injector to tests
	 */
	protected static Injector getInj()
	{
		return inj;
	}

}

Code under test will now have access to the Datastore and the TaskQueue API just as in dev and production environments.

The new task queue helper (LocalTaskQueueTestConfig) provides methods to inspect the task queue and verify task creation. When you call runTask(), the task queue test service will attempt to invoke the servlet associated with your task; however, unless you can figure out a way to run your unit test in a servlet container, your task servlet won’t actually be reachable by the runTask() call (at least, I’m assuming this is why I’m seeing “connection refused” errors).

Fortunately, we can easily simulate what the AppEngine task queue does by invoking the task servlet using ServletUnit. The test case below creates a simple test case using Vince Bonfanti’s Deferred task servlet, verifies that it has been enqueued properly, and then invokes it using ServletUnit.

package com.roa.test;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Map;

import javax.servlet.ServletException;

import org.xml.sax.SAXException;

import com.google.appengine.api.labs.taskqueue.dev.LocalTaskQueue;
import com.google.appengine.api.labs.taskqueue.dev.QueueStateInfo;
import com.google.appengine.api.labs.taskqueue.dev.QueueStateInfo.TaskStateInfo;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.tools.development.testing.LocalTaskQueueTestConfig;
import com.meterware.httpunit.PostMethodWebRequest;
import com.meterware.servletunit.ServletRunner;
import com.meterware.servletunit.ServletUnitClient;
import com.newatlanta.appengine.taskqueue.Deferred;
import com.newatlanta.appengine.taskqueue.Deferred.Deferrable;
import com.roa.test.helper.BaseTest;

public class SimpleTaskTest extends BaseTest implements Serializable
{

	@Override
	protected void setUp() throws Exception
	{
		super.setUp();
		// Do additional setup here
	}

	public class HelloUserTask implements Deferrable
	{
		private User user;

		public HelloUserTask(User u)
		{
			this.user = u;
		}

		@Override
		public void doTask() throws ServletException, IOException
		{
			System.out.println("Hello, " + user.getNickname());
		}
	}

	public void testTaskInvocation() throws IOException, SAXException
	{
		User testUser = UserServiceFactory.getUserService().getCurrentUser();
		HelloUserTask task = new HelloUserTask(testUser);
		// Queue the task
		Deferred.defer(task);

		// Verify that one task has been enqueued
		LocalTaskQueue taskQueue = LocalTaskQueueTestConfig.getLocalTaskQueue();
		Map<String, QueueStateInfo> allQueues = taskQueue.getQueueStateInfo();
		QueueStateInfo deferredQueue = allQueues.get("deferred");
		assertEquals(1, deferredQueue.getCountTasks());
		TaskStateInfo taskInfo = deferredQueue.getTaskInfo().get(0);
		String queuedTask = taskInfo.getBody();
		String taskName = taskInfo.getTaskName();

		// Run task will fail because no servlet container running
		// taskQueue.runTask("deferred", taskName);

		// Run using ServletUnit instead
		ServletRunner sr = new ServletRunner();
		sr.registerServlet("/_ah/queue/deferred", "com.newatlanta.appengine.taskqueue.Deferred");
		ServletUnitClient client = sr.newClient();
		client.sendRequest(new PostMethodWebRequest("http:/_ah/queue/deferred",
			new ByteArrayInputStream(queuedTask.getBytes()), null));

		// Flush task queue (removes all tasks)
		taskQueue.flushQueue("deferred");
	}

}

When you run this, you’ll see “Hello, test@example.com” written to the console by the task.

Using the AppEngine test helpers and ServletUnit, we now have an easy way to verify that tasks have been queued as expected AND a way to invoke the task servlets in the same test case.

Happy testing!

Posted in AppEngine | 13 Comments »

 
%d bloggers like this: