JDO-GAE Key getting created even when IdGeneratorStrategy.IDENTITY is commented - google-app-engine

I have the following code,
public class UserAccount {
#PrimaryKey
#Persistent
private Long id;
....
so, creating the primary key via code, but when I view the datastore viewer through
http://localhost:8888/_ah/admin , I see key got populated via datastore (some encoded key). Is this an expected behavior ?. The problem however is when I try to connect my child objects with the parent objects. Thanks alot.

Yes, it's absolutely expected. For more info take a look at JDO Keys

Related

Find an object by ID that has a key member only

Im trying to query an object by ID that dosent have an ID field.
Doing key.getId() does return a number but will not work when using
//will not work due to parenting object
pm.getObjectById("EventModel", 5322);
public class EventModel extends Model
{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
protected Key key;
...
}
NOTE: this is object is parented by a different object
i tried to query using "key.id == idParam" and it fails because the object key is not embedded is there any way to make this work so i can query the object by id not just only the key
A workaround will be to save the an id field after the key is initiazlied and query it
but this adds 2 writes each time i create an object.
If you have any idea on how to make this work please share :)
Thanks

Google App Engine JPA getting com.google.appengine.datanucleus.EntityUtils$ChildWithoutParentException

Update: I found out the problem in my case is that I am generating the FbUser primary key by myself using keyfactory.createKey() method. If I change it to auto generate it works fine. But the problem is I don't want to because my data is in String format for the key. So I need to change the type from String to Key manually and then persist it.
I am using Google App Engine JPA and trying to have a oneToMany relationship amongst my entities.
#Entity
public class DummyParent{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
//#Unowned
#OneToMany(targetEntity=FbUser.class, mappedBy="dummyP", fetch=FetchType.LAZY, cascade = CascadeType.ALL)
private ArrayList<FbUser> users;
}
And here FbUser as the child :
#Entity
public class FbUser {
#Id
private Key id;
private String name;
#ManyToOne(fetch=FetchType.LAZY)
private DummyParent dummyP;
}
So after that I instantiate the parent class set its id and set the users. But I get the following exception:
Caused by: com.google.appengine.datanucleus.EntityUtils$ChildWithoutParentException: Detected attempt to establish DummyParent(no-id-yet) as the parent of FbUser("1322222") but the entity identified by FbUser("1322222") has already been persisted without a parent. A parent cannot be established or changed once an object has been persisted.
at com.google.appengine.datanucleus.EntityUtils.extractChildKey(EntityUtils.java:939)
at com.google.appengine.datanucleus.StoreFieldManager.getDatastoreObjectForCollection(StoreFieldManager.java:967)
at com.google.appengine.datanucleus.StoreFieldManager.storeFieldInEntity(StoreFieldManager.java:394)
Any idea why this is happening?
P.s. HRD is already enabled.
So you persisted FbUser without a parent entity and then try to change it at a later date, and GAE Datastore doesn't allow that (as the message says pretty clearly). You present no persistence code so no comment is possible other than guesswork.
Solution : persist it correctly (parent first, then child), or persist them as Unowned.

JDO on GAE - #Unowned fields returned as nulls

Let's say I have a very easy, classic setup: GAE(1.7.4) + GWT(2.5.0) Application, running on local Jetty (Development Server), using JDO for persistence.
Let's also say I have just 2 #PersistenceCapable classes: Person and Color. Every Person has exactly one favourite Color, but it does not mean that this Person owns this Color - many different Persons can have the same favourite Color. There is a limited number of well-known Colors and a Color may exist even if it is not anyone's favourite.
To model this I should use #Unowned relationship - please correct me if I am wrong:
#PersistenceCapable
public class Color { // just the most regular Entity class
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
String rgb;
// getter, setter, no constructor
}
#PersistenceCapable
public class Person {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
String surname;
#Persistent
#Unowned // here is the tricky part
Color color;
// getters, setters, no constructor
}
With some simple, well-known, PersistentManager-based code, I am able to successfully create and persist an instance of a Color class. I see it in GAE Development Console -> Datastore Viewer, having nice generated Key and ID/Name of (13), and my assigned RGB.
With very similar code, I am able to create an instance of Person class (in another request), assign a pre-existing Color as his favourite color (it pre-existed, I obtained it by pm.getObjectById()) and persist it. I see it in Datastore Viewer, with my nice generated Key and ID/Name of (15) and my assigned surname, and color_key_OID of (13). This looks very promising.
But then, when I fetch the Person(15) back from the DB (simple pm.getObjectById(), no transactions), it has my assigned surname correctly, but has null instead of Color(13)! Right - the Datastore Viewer gets it ok, but my code does not.
Oh, the problematic code? "Person p = pm.getObjectById(Person.class, key);".
(side notes: I am also having the same problem with #Unowned collections (nice list of values in Datastore Viewer, but null Collection field in my code.) My JDO jars on classpath are "datanucleus-api-jdo-3.1.1.jar" and "jdo-api-3.0.1.jar" so I assume they support #Unowned. There is no problem with not-#Unowned fields. I get no exceptions upon persisting or fetching, just plain nulls as field values.)
Either mark the color to be "eagerly fetched"
#Persistent(defaultFetchGroup="true")
#Unowned
Color color
or define your own fetchgroup like this:
#FetchGroup(name="eager", members={#Persistent(name="color")})
#PersistenceCapable
public class Person {
and use it if required by specifying the group to be fetched:
PersistenceManager pm = pmf.getPersistenceManager();
pm.getFetchPlan().addGroup("eager");
I was facing the same issue in one of my #Unowned Lists. I had more other two, which the Array is fetched perfectly.
What solved this issue for me was to change the name of property for a bigger one. In your case is like change the property name from "color" to something bigger, like "myfavoritecolor".
I have the same issue what you describe. How DataNucleus said you need to describe the whole lifecycle of the objects. In my case the problem was solved forcing getting the color, from the person object, before closing the PersistenceManager with the close() function.
Remember JDO uses the lazy-load technique to get objects.
I was able to solve this problem by adding fetch groups to the query and not to persistent manager.
PersistenceManager pm = PMF.get().getPersistenceManager();
logger.info("EVENTS FETCH GROUPS : " + pm.getFetchPlan().getGroups());
/*pm.getFetchPlan().addGroup("eventFetchGroup");
pm.getFetchPlan().setMaxFetchDepth(2);*/
Query q = pm.newQuery(Event.class);
q.getFetchPlan().addGroup("eventFetchGroup");
logger.info("EVENTS FETCH GROUPS : " +q.getFetchPlan().getGroups());
q.setFilter("date >= fromDate && date <= toDate");
q.declareParameters("java.util.Date fromDate, java.util.Date toDate");

Queries with Objectify: UmbrellaException

I am using Objectify to manage GAE Datastore for my GWT app. The problem is that I am not using queries properly and I get UmbrellaExceptions as per below:
Caused by: java.lang.RuntimeException: Server Error: java.lang.String cannot be cast to java.lang.Number
at com.google.web.bindery.requestfactory.shared.Receiver.onFailure(Receiver.java:44)
Say that I have a class Box with a unique field String id. I want to get the Box object whose id == "cHVQP6zZiUjM"
This is how I do it now:
public Box getBox(String boxId)
{
Objectify ofy = ObjectifyService.begin();
Query<Box> q=ofy.query(Box.class).filter("id",boxId);
Box targetBox = q.get();
return targetBox;
}
#Entity
public class Box extends DatastoreObject{
private String id;
private String title;
}
I tried doing this with ofy.load() but that method is not defined in my class Objectify (I don't know why).
Your key is encoded. Try using:
Box targetBox = ofy.get(Box.class, KeyFactory.stringToKey(boxId));
To decode your key.
The short answer: You are missing the #Id annotation in your entity.
The long answer: Id fields are special in the datastore. The id is not a real property, but rather a part of the Key that identifies the entity. You can't really filter on id fields, but you can filter on a special field called __key__. Objectify is somewhat clever about letting you filter by the id field and converting this to a __key__ filter under the covers, but it can't do it if you don't annotate the entity properly!
Actually I'm a little confused because Objectify shouldn't let you register the entity without an #Id field.
By the way, there are two sections of the documentation: Objectify4 (release coming soon) and Objectify3. Since you're using Ofy3, there is no load() method.
Another thing: Get-by-key operations are strongly preferred to queries when the operations are equivalent (as they are in your example).

How to auto-fetch JDO nested collection of entities?

Probably a very trivial problem.
I have an object that looks like this:
#PersistenceCapable
public class Parent {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private String _id;
#Persistent
private List<Child> _children;
//...
}
... the nested entity looks like this (I am forced to declare primary key as Key otherwise it won't persist):
#PersistenceCapable
public class Child {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key _id;
#Persistent
private String _whatever;
//...
}
When I persist everything gets persisted OK (including Child entities), but I would like to get back everything by getting the parent object (e.g. getObjectById), but the collection comes back as null.
Owned One-to-Many Relationships seem to be what I am looking for -- but I am having trouble to see how it can help me to get back the parent object with the populated collection of children entities.
Any help appreciated!
#Persistent(defaultFetchGroup = "true")
Does the trick, you're right.
The content of your _children attribute is loaded only when you access it (before pm.close !) for the first time. It's called lazy-loading. If you want to have the child Entity or Collection of Child Entities to be directly loaded by default, apply the above "trick".
In my app, in case of a Collection of child Entities, it generates an Error message (Datastore does not support joins..) on the Dev Server, but you can ignore this wrong error, it is working fine in Dev and Prod Environments.
Be aware that fetching a Collection through it's parent Entity costs 1 datastore fetch per Child Entity.
this seems to do the trick:
#Persistent(defaultFetchGroup = "true")
True, while setting
#Persistent(defaultFetchGroup = "true")
at the field is the way to auto-load the related object in main object during fetch, things may not work as expected for nested objects if not supported with right configuration. If your have class with related object hosting other related object down to level 2 or 3, then configuring maxFetchDepth appropriately is critical.
<property name="datanucleus.maxFetchDepth" value="2"/>
is the configuration element in your JDOconfig.xml file to configure how deep you want your default fetch group objects to be loaded with main fetch.

Resources