Tuesday, May 19, 2009

Sitemesh is the shit!

Once upon a time I was working on a project developing a ticket management application. Someone high up had decided that we should certain frameworks. Struts 1 was one of them. We made a fine ajax application with struts and prototype.js. Unfortunately I had to follow my love and quit before it was finished.
Since the app was ajax-driven, we didn't use any templating engine. But later on I learned about tiles. Tiles was the shit at the time. And since struts 1 means xml-hell the tiles-hell was alright. Then wildcards came with struts 2, and wildcards in tiles. And the hell got cooler.
Now, there is convention in Struts, and tiles doesn't have a convention nor is working very well anymore. So I must find something new.
Yesterday I found sitemesh. One of those things you don't find unless you know what you're looking for. And I love it. It's simple and does what it should. Just like you wan't it. Beats tiles any day!

Instead of graceful degradation I always try to build apps that doesn't degrade. So, all sites must be nice ajaxified and work just as well (but impression heavier) without javascript enabled. But how! Well here is where my search for sitemesh comes in. Basically what is needed is an action which renders a decorated full site when called without javascript and only the simple view for javascript calls and of course use the same files to do this (I work in AM, I want maintainability). On the road I've found two readworthy sites on the subject. rkcole has an excellent tutorial demonstrating how to decorate an already written views with sitemesh. raibledesigns has an explanation on exactly what I'm trying to do. I'm putting together small app with those concepts (and alot others as well). I'll get back when I'm not too ashamed of it...

Friday, May 15, 2009

Dysfunctional persistence in GAE

So, just how dysfunctional is the persistence API(s) in Google App Engine. I've been elaborating with alot of different mappings and queries lately to see what can be done. Well, not much. I've mainly given up on creating mappings and using keys instead. The latest released promised to improve on this, but I haven't taken the time to try it out yet.

Today, I stumbled upon a new horrifying error message (among others...)

java.lang.IllegalArgumentException: can't operate on multiple entity groups in a single transaction.

This means I cannot use transactions for assuring the datastore state when I have dependent entities, what is transactions for then?

Monday, May 4, 2009

Troubleshooting the GAE deployment:

I have alot of issues developing for GAE. So, I'll try to collect the issues I run into for later reference.

Issue: JPA not working.

Possible errors:
  • Query with name "jpa.query.get.user.by.username" was not found!
This one is quite obvious. The datanucleus enhancer has not been run properly on the classes you deploy, hence, it won't work.

Issue: The datanucleus is not running properly.

Possible errors:
  • Encountered a problem: Unexpected exception
    Please see the logs [/tmp/enhance1003542528074135516.log] for further information.

Well, if you check the logs you'll find the problem. Generally, it is because the App Engine datanucleus jar is referenced multiple times in the projekt. Possible sources:
  • The GAE SDK (this is the correct one)
  • war/WEB-INF/lib (the plugin, and maven, may copy the jar here)
  • ~/.m2/repository/???/ (maven handled reference, if you are using it

Issue: Persistence unit does not load

Possible errors:
  • No Persistence provider for EntityManager named transactions-optional

This is because you removed the jar from war/WEB-INF/lib to fix the previous error.

So, how to solve the above evil circle. Well, sometimes eclipse gets the bright idea to reference the "web app libraries", that is the jars in war/WEB-INF/lib. You have to remove that reference from the project build path, it it'll sort of the issues. You can however never reference GAE datanucleus provider in the POM if you are working in Eclipse and have an SDK attached to the project. Unfortunately, you cannot use the plugin to deploy the application if the SDK is not connected...

Saturday, May 2, 2009

GAE APIs for maven

Tim has an excellent post about setting up a maven project for GAE. It basically contains all you need to get started coding. However, he's missed some things. First (what I have discovered so far) is that the APIs are not included. Using the UserService API from google, this won't work. So we have to include it in maven. First, install the artifact locally from the SDK package from google.

mvn install:install-file -Dfile=lib/user/appengine-api-1.0-sdk-1.2.0.jar -DgroupId=com.google -DartifactId=appengine-api-sdk -Dversion=1.2.0 -Dpackaging=jar -DgeneratePom=true

Then add the dependency snippet to your POM

<dependency>
<groupId>com.google</groupId>
<artifactId>appengine-api-sdk</artifactId>
<version>1.2.0</version>
<scope>provided</scope>
</dependency>

Building an XWork snapshot

When working with Struts 2 development, it is often required to have a XWork snapshot to work against. Struts provides a maven profile to build against the XWork sources. However, when updating an XWork component used in a struts-depending project, you need to update the XWork artifact locally.

Assuming you got your hand in the latest XWork sources, run
mvn install
in the source root to install the XWork components locally. However, your project probably depends on xwork, an artifact which is not installed. You can change you project to depend on xwork-core instead. However this may result in leaving you with strange target invocation exceptions when using XWork injections. This is due to some missing classes, amongst others org.apache.commons.lang.xwork.StringUtils. The xwork artifact contains this class.

To install the the xwork artifact, enter the target directory of XWork core: core/target. In that directory run the following command
mvn install:install-file -DgroupId=com.opensymphony -DartifactId=xwork -Dversion=2.1.4-SNAPSHOT -Dfile=xwork-2.1.4-SNAPSHOT.jar -DpomFile=dependency-reduced-pom.xml
Change the versions as needed.