24 April 2009

Real world GAEJ Application

OK, this is a very sketchy view of developing a first time application with GAEJ. It is a rewrite (not a port) of an application I wrote a while back in Java using Spring and JPA. The application is a timetracker recording time I spend on various client projects, I will publish the URL once I've cleaned up a few things and I want to add GWT to the front end.

This is my experience, warts and all, maybe it will help others. I'm using the eclipse plugin for development.

Persistance

In my previous hack, I used JDO to see what it was like, I didn't much like it and decided to move back to JPA. I found JDO quite verbouse to use and especially did not like the way you have to declsre parameters for queries.

The first step was to create the persistance.xml file, as the eclipse plugin only provides the jdo configuration as default. Its easy enough, put it in the same place as your jdoconfig.xml file (in the META-INF directory).

You will need to identify the Entity classes by specifying them in the persistenace.xml file using the <class> tag.

See Setting Up JPA in the docs. Hmm, the line
EntityManager em = EMF.get().getEntityManager();
should be changed to:
EntityManager em = EMF.get()createEntityManager();

Wow! Changed the JDO persisted class to a JPA entity class by changing the annotations and implementing Serializable and.. it work!!



Security

Edit the deployment descriptor (web.xml to you and me) and include the
security-constraint tag. There is an example in the docs called Security and Authentication.

See Google Accounts Java API Overview in the docs.

OK, then how does one access the user principal using EL in a JSP page?



Looking at the user principal I see it is implemented as: com.google.apphosting.utils.jetty.
AppEngineAuthentication$AppEnginePrincipal



UserServiceFactory.getUserService().getCurrentUser() which return a com.google.appengine.api.users.User object. There mus be some relationship to AppEnginePrincipal, but its not via inheritance.

Some digging around and I see AppEnginePrincipal holds an instance of User, so I can do this in JSP:

${pageContext.request.userPrincipal.user.email}
or
${pageContext.request.userPrincipal.user.nickname}
apart from:
${pageContext.request.userPrincipal.name}

(of course, once the user is logged in)

Any resources specified in a security-constraint will cause a redirect to the google login page. Any User specified as a developer on the application will have admin role, not sure what role everybody else gets or how to get more roles.

The Turn Around

Under the persistance section I mentioned moving from JDO to JPA, I really don't like JDO from a usablility point of few, the stench is too high - I don't want to be that aware of my datastore.

But now I find myself going back to JDO for a number of reasons:
  1. Not enough documentation on GAEJ about using JPA
  2. The JPA implementation is basically JDO under the hood and I get the feeling not everything translates well.
  3. JDO is simpler for storing objects outside your domain (the User object springs to mind)
  4. There is a general ".. I don't know, use JDO.." attitude on the mailing list
  5. I plan to use GWT in the project and there are serious issues regarding serializing Entities - GWT-RPC broken in GAE/J.
bugger, I really don't want to do this, humph.

The DataNucleus Enhancer is starting to T me off, keeps on popping up in the console after you save any class in your project, perhaps it should only be kicked off when saving persistant objects or not output unless on error.

Ah, got it: under your project properties -> google -> appengine -> ORM you can specify the specific file/ packages you want enhanced. Nice.

And we are back with JDO. The data hasn't changed, the same data was accessed by JDO, then JPA, then back to JDO without issue.

=================================
Then there is a gap where I modify my J2ME MIDlet, faf around with getting data from the phone and add a domain to my application and run out of bandwidth. This is not a happy period.
=================================

Implicit params in the JDO queries will be supported in the next release. Meh

The other 'Duh' drops

Spent a lot of time trying to figure out relationships and how to implement it with GAE. Did some more reading and recommend these articles: Re-thinking Object-Relational Mapping in a Distributed Key-Store world and How I Learned to Stop Worrying and Love Using a Lot of Disk Space to Scale. I've simplified my initial design dramatically and geared it towards my end goals and a (gasp!) de-normalized the design.

The thing that bothers me most is using JDO/JPA for something like this.I'm going to have a look at the lower level APIs and see if they make more sense (at some stage)

It would be nice to include a restart button for the local web host within eclipse.

Sessions

Session support is not enabled in appengine-web.xml by default. To enable sessions, put <sessions-enabled>true</sessions-enabled> in that file.

I've read somewhere that read only session attributes are supported out the box, I guess that is why you have access to the UserPrincipal.

And while I'm on session:: it seems objects stored in the session must be serializable, not obvious under the test server, but going live will throw  exceptions.

And you can view your applications sessions via the data viewer in the application administrator.


I finally understand why a lot of people are against pure servlet/JSP/taghandler development, they were probably using eclipse. A NetBeans GAEJ module would be nice.

Conclusion of Sorts

The major headache is around data access at the moment. Working with BigTable requires a mind change if your are used to relational databases.

3 comments:

andy said...

1. JDO allows a lot of config, so maybe there are some settings to resolve whatever you think is verbose; why not mention what *it* is ?
2. JDOQL allows implicit parameters. Google didn't implement it in the early access. It is in SVN I'm told, and in the 1.0.1-RC1 that Max put out.
3. JDO also allows persistence.xml and persistence-units.
4. You could have used JDO annotations with JPA persistence actually ;-) And you can use JPA annotations with JDO persistence.
5. The DataNucleus enhancer doesn't pop up any window, that's Googles Eclipse plugin doing it and they are apparently working on it.
6. "I really don't like JDO from a usablility point of few, the stench is too high". How about something rational and specific ? We really want to know where people think there's a problem with an API, so please ... without the verbage ... we'd be pleased to help if necessary (DataNucleus Forum)

:-)

Brian Silberbauer said...

@andy: Yes, most of the blog was from the hip and opinionated.

The blog was more about my general feelings coding with the technology, I hope they help you in some way even if it is not specific or rational.

Thanks for contributing to the conversation :)

andy said...

Hi Brian,
opinionated is fine; there are lots of strong opinions out there :-) and yes, blogs like your GAEJ entries are indeed helpful in guiding us where we take the technology and what people see as a problem (don't forget, the developers of such software aren't really "users" so maybe miss what you may be seeing). Hope to see more in the future.