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.

10 April 2009

Google Appengine Java Test Ride

Time to climb on the appengine-java-blog train.

9:45 OK, Bootsy Collins 'If 6 was 9' playing, check.

I've created a an app using appengine with python and as much as writting in python is fun, I don't like the maintenance aspect of it (trying to remember what methods classes had without looking it up again etc).

I really like the idea of appengine especially the ease of use in deploying and versioning your application, but especially the zero cost to try aspect. I'm dying to try amazon's service, but I can't try it without entering my credit card details and I don't have one at the moment.

So I've been looking forward to writing for appengine in java. Here is my first experience with it I timestamped to give you an idea of the time it takes to create and app. I've been programming in Java since 1995 and Servlets since 2000, so your experience may vary ;)

The kids are watching Asterix in the study, bit distracting but I have headphones, hence the musical references


10:02 So, eclipse plugin loaded, lets create a servlet and send it live.

10:04 Project created without GWT, creates a default servlet, bleh.

10:05 Simple single button project publishing, must create new application on appengine first.

The deploy dialog doesn't display application setting by default, need to open 'App Engine project settings..', not quite intuitive. Weird email completion too (got it wrong first time).

10:09 Up and running! Not bad, under ten minutes to create a new application and send it live, pretty painless.

Next: index.jsp -> link to servlet -> forward to index.jsp

hmm, creating a servlet using the wizard doesn't work, needs a web project and I can't enter one. Oh well, back to creating by hand, will look into that later..

rrr, prefer netbeans

10:19 editing web.xml -> added TestServlet, changed welcome file to index.jsp

10:21 Re-deploying the app I have to re-enter password, that could be improved.

10:22 Tested and working, yay!

Next lets try persisting some data (as soon as 'Maggot Brain' is finish)

JDO or JPA: I've used JDO long time we go, been using JPA since it came out, but there seems to be more documentation for JDO on the appengine site and I can't resist trying unfamiliar technology, so JDO it is.

Let me try vertical development and implement an object first without relationships and do some basic CRUD. later (10:28)

10:30 Going to read the docs about created JPA Entities in eclipse..

Once I've added the annotaions to the class, saving it triggers the enhancer as reported in the output: 'DataNucleus Enhancer completed with success', cool.

10:38 Created the persistent object with id, date, and string fields, painless. Now to look at the PersistenceManagerFactory, which google recommends wrapping as a singleton, I hope to use some DI framework in the project (Guice perhaps), but for the moment I'm going to hack it right into the servlets.


10:43 Alright, singleton copied from google code and modified slightly. Now to add some data.

I'll create a form on the index page with fields and submit it to an action servlet which will persist it (I won't create a service/business tier just yet) and forward back to the index page.

I'll also adding the created object to the request before the forward.
 
Eclipse: oh the irony of your name. hmm, no EL completion in JSP, mff, have to google for request attributes (requestScope, duh).


11:03 and deploy (and enter password)

11:06 Oops, overwrote doGet instead of doPost, fix and publish

The persistence seems to work, except the EL variable ${requestScope.object.field} is being displayed in plain text and not being interpreted, maybe I've missed something - back to the docs.

From the mailing list I discovered kindred soles: one needs to add <%@page isELIgnored="false" %> in the JSP, guess it is true by default. Its a pity they don't turn scriplets off by default, I see the docs show extensive use of scriplets within the JSP - there are beginners opening up a world of pain with scriplets in JSP.

Started using the local server for development.

11:22 yay! working

Next up, create a custom tag for displaying all records.

mothership connection coming to take back the pyramids - having a look at some of the mailing list queries.

11:27 SimpleTagHandler here we go. Ah, man: have to write the TLD by hand (well copy and paste and edit by hand).

do you remember September?

11:39 Almost there, need to look at JDO queries and add Tony Allen to the play list.

11:49 Working locally, now to publish..

11:52 And working live, nice. I think a little break, OK?


I'm impressed and looking forward to writing applications in java on appengine, I might even port my previous application from python to java. Apparently python and java can run side by side and against the same data.

Tweaks I'd like to see so far:
  • Use of EL by default in JSP pages
  • Saving password when deploying (at least for a session)
  • Deploy dialog to include fields for app name/version
  • Email field in the dialog box to be fixed
  • Maybe some better integration between the wizards and GAEJ (e.g. create servlets)