are u sure u wont to proceed with that plan of changing out enhanced
JDO classes?
just sounds tooooo complicated.

-lp



On Mar 3, 5:21 am, Jason G <ja...@bobberinteractive.com> wrote:
> Hello everyone!
>
> We've run into a data migration-test problem, and I'm wondering if
> anyone would have any advice on how to proceed...
>
> We're building a system that needs to allow hot-swapping of
> application builds while customers are actively using our webapp, and
> that means we need to support data object "schema" migration in-
> place.  We do this by implementing LoadCallback for version migration,
> and @Deprecated-ing no-longer-used fields.  So far, so good.
>
> Thing is, we'd like to build up a test suite that allows developers to
> write unit tests for data migration against a local environment. That
> means no uploading to GAE, but using
> com.google.appengine.tools.development.testing.LocalServiceTestHelper
> instead.
>
> We have two "classes" directories: Both containing DataNucleus-JDO-
> enhanced .class files, one of the "old" schema, and one of the
> current.
>
> We have a MigrationTestHelper that creates a GroovyClassLoader with
> the old schema set as its classpath.  The targetted class under test
> is found, instantiated, and passed to a test-supplied Closure that
> initializes the object with the old data to be migrated.  The Helper
> calls PersistenceManager.makePersistent and returns
> pm.getObjectId(newlyPersisted).getKey().
>
> The second half of the test involves creating a new GroovyClassLoader
> and setting the context class loader:
> Thread.currentThread().setContextClassLoader(loader).  Then we use a
> different PersistenceManager (from a different
> PersistenceManagerFactory) to load the object by its Key.
>
> What happens is we get a ClassCastException:
> java.lang.ClassCastException: java.lang.Long cannot be cast to
> java.util.List
>         at com.x.model.User.jdoReplaceField(User.groovy)
>         at com.x.model.User.jdoReplaceFields(User.groovy)
>         at
> org.datanucleus.state.JDOStateManagerImpl.replaceFields(JDOStateManagerImpl.java:
> 2772)
>         at
> org.datanucleus.state.JDOStateManagerImpl.replaceFields(JDOStateManagerImpl.java:
> 2791)
>         at
> org.datanucleus.store.appengine.DatastorePersistenceHandler.fetchObject(DatastorePersistenceHandler.java:
> 480)
>
> It *appears* as though the JDOStateManagerImpl uses an array of fields
> to get/set values.  You can crack open the enhanced .class files and
> see there's a method called __jdoFieldNamesInit() that sets up a
> static list of Fields.
>
> The old User contains the field: "balance", which is a Long.
> The new User contains the fields: "balance", which is @Deprecated and
> is Long, and "_balances", which is a List.
>
> Looking in the .class files, it looks like each field is ordered
> alphabetically, so in old User, "balance" is index 0, where in new
> User, "balance" is index 1 and "_balances" is index 0.  Hence the
> ClassCastException.
>
> I'm stuck on how to proceed.  I'd have thought that fields would be
> replaced based on field name, not on an index...  Especially an index
> that we don't appear to be able to control.  But if it's the case that
> fields are placed by index on load, how does data migration work on
> AppEngine itself?  Our migration code works fine there...
>
> Is this a DataNucleus issue?  An issue with LocalServiceTestHelper?
> An issue of developer sanity? ;)
>
> Any insight would be greatly appriciated!
>
> Thanks!
> Jason

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to google-appengine-java@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.

Reply via email to