Header text

EssayTagger is a web-based tool to help teachers grade essays faster.
But it is not an auto-grader.

This blog will cover EssayTagger's latest feature updates as well as musings on
education, policy, innovation, and preserving teachers' sanity.
Showing posts with label code. Show all posts
Showing posts with label code. Show all posts

Friday, November 4, 2011

Avoiding Session conflicts on save() due to Hibernate lazy loading

With Java Reflection we can force Hibernate to instantiate lazily-loaded (aka proxy) member objects before we attempt to save the containing entity.

Yesterday I posted my Spring + Hibernate + Cloud SQL sample project code to help other developers get up and running with Hibernate and App Engine.

Today I had to make some DB changes and slightly rearchitected my code. That uncovered a problem. I'm using Spring's OpenSessionInViewFilter to support lazy loading in the view layer. It's dang convenient. And it's currently configured for singleSession=false. That means that it'll use a read-only Session for gets but a separate save/update Session for writes.

Calling getHibernateTemplate().save() had been working fine until my code reshuffling exposed a problem. If an entity has any member objects that have not yet been initialized (due to lazy loading), the save() call will throw a session conflict exception. Specifically:
org.springframework.orm.hibernate3.HibernateSystemException: illegally attempted to associate a proxy with two open Sessions

Here's a simple example:

The problem is that the read-only Session created the lazy-loading proxy Owner within oldCat but hasn't been asked to initialize the proxy yet. Then the save/update Session gets the newCat and tries to access its Owner and now both Sessions are trying to handle the non-initialized proxy, thus the "two open Sessions" complaint.

So folks will generally do something lame like this to get around it:

I'm not judging. I've done it in the past too. But it's clearly a crappy solution. If that chunk of code doesn't need to access any fields in Owner, it shouldn't have to just to make the DAO/ORM layers happy.

So here's my new solution: programmatically search for non-initialized proxies and call getHibernateTemplate().initialize() on them before we try to save.

This requires Reflection to inspect the Cat and look for fields that might need initialization.

Unfortunately my DAO doesn't have permission to access Cat's private member variables. So instead we scan for the public getters and look at their return types. If the return type is a domain object that is mapped by Hibernate, then we "get" it and initialize as needed.

How do we know it's mapped by Hibernate? I'm just filtering on the return type's package name; I only care about DTOs from com.essaytagger.model. The proxies that need initialization are easy to spot--they return true to (obj instanceof HibernateProxy) tests.

Here's the new version of my _GenericDaoHibernateImpl's save() method (my GenericDAO approach is kind of complicated. Track back through the Spring+Hibernate+CloudSQL post first and then see the more in-depth discussion of the original Objectify-based version that was adapted from David Chandler):

This GenericDAO work is getting me more and more into Java Reflection. It's pretty dang cool! But I'm not completely confident in this approach just yet. We'll see if any other odd use cases popup before we call this a win.

What do you think? See any problems down the road?

Wednesday, November 2, 2011

Spring + Hibernate on Google App Engine's new Cloud SQL!

Full project code for a Spring + Hibernate version of Google's "guestbook" sample webapp that accesses Cloud SQL!

Download the project code!

UPDATE: See the new version of my GenericDAO's save() method to avoid Session conflicts due to lazily-loaded member objects.

I was super-thrilled that Google approved my application to be part of the Cloud SQL limited preview. In gratitude I wanted to share the sample code that I used to do my proof-of-concept tests for accessing a SQL DB in App Engine.

I'm accustomed to using Hibernate with annotations for my ORM layer and was excited to be able to go back to that world in App Engine. But annotations won't work with App Engine as long as they limit the JPA spec to v1.x (I tried and failed to get around the limitation). So that means we're back to using Hibernate Tools and reveng.xml to generate the Hibernate *.hbm.xml mapping files. It's a pain and it feels like it's 2003 again, but whatever. Once you dust off that part of your memory it's not so bad.

Saturday, September 10, 2011

BitmapButton: A custom-skinnable ActionScript button

Source code for a simple, skinnable ActionScript button class that includes a really handy arbitrary data field.

Now that I'm a whole 20 days into learning how to code in Flash's ActionScript language, I'm getting pretty dang good.

Yesterday I needed to create a button for the Flash grading app, but I didn't want to use the default fl.controls.Button class that resembles standard HTML form buttons.

I wanted to be able to skin the button with my own Bitmaps that I would generate in Flash. I figured that the easiest way to do this would be to build my own custom button class. So I did:

Friday, July 22, 2011

How to programatically upload a file to Google Docs when you can't create a java.io.File in App Engine

Google's Data API (gdata) makes accessing their suite of tools and sites a lot easier than making direct HTTP calls to the Web-based service interfaces. But there don't seem to be too many code snippets out there--or at least not enough that do what I want to do.

I have a document that was uploaded through a Servlet and is now sitting in a byte[] array. Now I want to upload that file to my app's Google Docs account. Here's what Google's documentation offers:


Fairly straightforward, but there's one catch: The setFile() method is expecting a java.io.File. Normally that isn't a problem, but if you're developing in Google App Engine (GAE), then you know that you can't create filesystem files.

Digging through the DocumentListEntry code (thank you, Google, for making gdata open source!!) I was able to figure out how to avoid this File creation entirely:

Wednesday, July 20, 2011

Elegant coding with Objectify, Java generics, and interfaces

David Chandler posted code for an ObjectifyGenericDao on his blog. It takes care of all of the typical Objectify datastore operations you might need to perform on any kind of entity type.

It works great as-is. Here's a code snippet of the generic DAO in action:

Pretty simple. You define the generic type as you directly instantiate the DAO and you get instant access to ObjectifyGenericDao's suite of basic datastore operations.

But directly instantiating any service layer should set off an alarm in your head: "Wait! I'm supposed to code to interfaces!"