JDO query with base class gives null pointer - google-app-engine

I am getting this error when running junit test
Testcase: testGet_User(Authentication.UserManagerTest): Caused an ERROR
null
java.lang.NullPointerException
at org.datanucleus.store.appengine.query.DatastoreQuery.getMappingForFieldWithName(DatastoreQuery.java:1307)
at org.datanucleus.store.appengine.query.DatastoreQuery.addLeftPrimaryExpression(DatastoreQuery.java:1107)
at org.datanucleus.store.appengine.query.DatastoreQuery.addExpression(DatastoreQuery.java:871)
at org.datanucleus.store.appengine.query.DatastoreQuery.addFilters(DatastoreQuery.java:832)
at org.datanucleus.store.appengine.query.DatastoreQuery.performExecute(DatastoreQuery.java:230)
at org.datanucleus.store.appengine.query.JDOQLQuery.performExecute(JDOQLQuery.java:89)
at org.datanucleus.store.query.Query.executeQuery(Query.java:1489)
at org.datanucleus.store.query.Query.executeWithArray(Query.java:1371)
at org.datanucleus.jdo.JDOQuery.execute(JDOQuery.java:243)
at Authentication.UserManager.get(UserManager.java:86)
at Authentication.UserManagerTest.testGet_User(UserManagerTest.java:110)
code for get is:
public static UserBean get(User user) {
PersistenceManager pm = PMF.get();
// get user with id
Query query = pm.newQuery(UserCommon.class);
query.setFilter("id == idParam");
query.declareParameters("String idParam");
System.out.println("\t\tID:" + user.getUserId());
List<UserCommon> userDatas = (List<UserCommon>) query.execute(user.getUserId());
Where I have persistent classes that looks :
#PersistenceCapable(detachable="true")
#Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
public abstract class UserCommon {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private String id;
and
#PersistenceCapable(detachable="true")
public class Professor extends UserCommon {
and
#PersistenceCapable(detachable="true")
public class Student extends UserCommon {
basically, I'd like to have 2 types of users.
but while logging in, only information I have is their id.
Hence, I was trying to query on base class instead of either Professor or Student.
However, I got NullPointerException.
any suggestions to where I've made a mistake ?
Thanks in advance !

App Engine JDO has limited support for inheritance, and no polymorphic support http://code.google.com/appengine/docs/java/datastore/jdo/relationships.html#Polymorphic_Relationships
this includes queries.
Personally I would suggest using some other persistence wrapper rather than JDO such as http://code.google.com/p/objectify-appengine/ and http://code.google.com/p/twig-persist/
which do a better job using the advantages of GAE.

Related

Google App Engine Datastore how to get entity for Key<?>

I'm new to Datastore and now I'm developing Gae application with Datastore and Objectify. Entity class has the form
#Entity
public class MyClass1 {
public Key<MyClass2> field1;
#Id Long id;
and so on
}
MyClass2 has the form
#Entity
public class MyClass2 {
....
#Id public Long id;
#Index public String field2;
....
}
I have entity of MyClass1. How can I get the value of field2 ?
If I use DatastoreService1.get(myclass1.field1) I get
method get(Key) in the DatstoreService is not applicable for arguments (Key<MyClass2>)
Please help me
Your error doesn't really relate to the question, so I assume you want to get the value of field1, not field2.
The error is because the DatastoreService get() method expects a com.google.appengine.api.datastore.Key, but you are passing it a com.googlecode.objectifyKey<T>, which is an Objectify key - they're not the same thing. Here are the docs.
I would recommend using a Ref<MyClass2> as you can then just do something like:
MyClass2 myClass2 = myClass1.field1.get();
(using your code example).

JDO javax.jdo.JDOFatalUserException

First of all, I am kinda a noob on this. So, I am trying to build a WebApp using GWT2.6.1 and GAE1.9.9.
I've done something like this...
#PersistenceCapable
#Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
public abstract class Person implements IsSerializable {
#PrimaryKey
#Persistent
private String googleUserID;
#Persistent
private String name;
#Persistent
private String secondName;
#Persistent
private String surname;
#Persistent
private Boolean isActive = false; //default value
#Persistent
private String imageURL;
...
}
then,
#PersistenceCapable
#Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
public abstract class User extends Person implements IsSerializable{
#Persistent
private String email;
...
}
and finally,
#PersistenceCapable
#Inheritance(strategy = InheritanceStrategy.NEW_TABLE)
public class Admin extends User implements IsSerializable, Serializable {
private static final long serialVersionUID = 1L;
#NotPersistent
public static final AccountTypes accountType = AccountTypes.Admin;
...
}
Then I am getting the following error:
javax.jdo.JDOFatalUserException: Found inheritance strategy "new-table" on epusp.pcs.os.model.person.user.Admin. This strategy is not supported in this context. Please see the documentation for information on using inheritance with JDO: http://code.google.com/appengine/docs/java/datastore/dataclasses.html#Inheritance
I read the documentation, but I still don't understand what I am doing wrong. Can anyone give me a hint?
PS.: I know, I know, I plan to add some new attributes to Admin and User in the future. Basically what I want to do is to check if a User is registered in database using a GoogleID and then redirect him to a specifed URL based on his AccountType (it may be an Admin, SuperUser, Auditor ...). I was doing something like this:
PersistenceManager pm = PMF.get().getPersistenceManager();
Admin user = null;
try{
user = pm.getObjectById(User.class, userId);
}finally{
pm.close();
}
switch(user.getType()){
case Admin:
return "";
case Agent:
return "";
case Auditor:
return "";
case Monitor:
return "";
case SuperUser:
return "";
default:
return null;
}
Thanks for supporting!
The "new-table" inheritance strategy allows you to split the data for a single data object across multiple "tables," but since the App Engine datastore does not support joins, operating on a data object with this inheritance strategy requires a remote procedure call for each level of inheritance. This is potentially very inefficient, so the "new-table" inheritance strategy is not supported on data classes that are not at the root of their inheritance hierarchies.
Second, the "superclass-table" inheritance strategy allows you to store the data for a data object in the "table" of its superclass. Although there are no inherent inefficiencies in this strategy, it is not currently supported. We may revisit this in future releases.
Now the good news: The "subclass-table" and "complete-table" strategies work as described in the DataNucleus documentation, and you can also use "new-table" for any data object that is at the root of its inheritance hierarchy.

JDO / GAE inheritance + abstract superclass NPE

I would like to model a simple thing but getting in trouble when reading from datastore. I found this question in different flavours but none of the answers helped in my case (using an interface instead of abstract is no option) I´ve one abstract class Media:
#SuppressWarnings("serial")
#PersistenceCapable(identityType = IdentityType.APPLICATION,
detachable="true")
#Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
public abstract class Media implements Serializable{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Extension(vendorName="datanucleus", key="gae.encoded-pk",
value="true")
...
#Persistent
User owner;
}
Movie is extending it.
#SuppressWarnings("serial")
#PersistenceCapable(identityType = IdentityType.APPLICATION,
detachable="true")
public class Movie extends Media implements Serializable{
...
}
One User has a List of Media.
#SuppressWarnings("serial")
#PersistenceCapable(identityType = IdentityType.APPLICATION,
detachable="true")
public class User implements Serializable{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
#Extension(vendorName="datanucleus", key="gae.encoded-pk",
value="true")
protected String id;
#Persistent(mappedBy = "owner")
private List<Media> ownedMediaSet = new ArrayList<Media>();
}
The reading operation code is:
#Override
public List<UserDTO> readAllUser() throws IllegalArgumentException {
ArrayList<UserDTO> result = new ArrayList<UserDTO>();
PersistenceManager pm = pmf.getPersistenceManager();
Query q = pm.newQuery("select from " + User.class.getName());
List<User> res = null;
try {
res = (List<User>) q.execute();
for (User u : res) {
UserDTO uDTO = new UserDTO(u.getId(),null, u.getName(), u.getEmail());
result.add(uDTO);
}// for
} catch
This causes NPE:
java.lang.NullPointerException
at
org.datanucleus.store.appengine.DatastoreTable.addFieldMapping(DatastoreTable.java:531)
at org.datanucleus.store.appengine.DatastoreTable.initializeNonPK(DatastoreTable.java:440)
I dont get it. Without Media being abstract everything works fine. Maybe someone knows about the problem and can give me a hint.
Regards
You can not make a list of Media... because there is no instantiable class of media.
--> that means there is no "database table" media
Polymorph relationship doesen't work with GAE...
https://developers.google.com/appengine/docs/java/datastore/jdo/relationships#Polymorphic_Relationships
#Persistent(mappedBy = "owner")
private List<Media> ownedMediaSet = new ArrayList<Media>();
Make the Class Media not abstract then it works.
Or you make a List of movies...
#Persistent(mappedBy = "owner")
private List<Movie> ownedMediaSet = new ArrayList<Movie>();
but thats probably not what you want.
so the last option is what's in this artikle:
https://developers.google.com/appengine/docs/java/datastore/jdo/relationships#Polymorphic_Relationships
make a list of Keys:
#Persistent
private List<Key> ownedMediaSet = new ArrayList<Key>();
Try v2.0 of Googles JDO plugin and see how that goes. Likely it does nothing different yet, but if that is the case you can easily raise an issue with simple testcase at http://code.google.com/p/datanucleus-appengine/issues/list The fact is the v1 plugin did some things in illogical ways (see Sam's answer for some links that this illogical handling caused). You could also just set inheritance strategy to COMPLETE_TABLE since that is all that is really supported with BigTable (i.e each class has a "Kind" that holds all properties for that type).

GAE,JDO How to query primary key by Long/long type

I define a base class which have a Long primary key , just like this.
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
#Inheritance(strategy = InheritanceStrategy.SUBCLASS_TABLE)
public class ModelBase implements Serializable {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
and other pojo extends the ModelBase.
When I was query by jdoql like this code
public List<PersonalSetting> getByIds(Long... Ids) {
Query query = getQuery();
query.setFilter("id ==:id");
return (List<PersonalSetting>) query.execute(Ids);
}
but it just give me a exception.
java.lang.ClassCastException: [Ljava.lang.Long; cannot be cast to com.google.appengine.api.datastore.Key
I found the Key class have "Id" field, but I can't access it like "id.id == :id".
Is anyone could tell me how to fix it? Thank you very much!
Invalid JDOQL. If you want to find an element in a collection you do
":ids.contains(id)"
Obviously it would make sense to state what version of Googles persistence plugin you're using, and then the log/stacktrace

Google App Engine JDO persistence with HashMap child field

I have a parent class and I want to store a HashMap within it. However, every time I try to modify that HashMap I get the following error:
PM org.datanucleus.store.appengine.MetaDataValidator checkForIllegalChildField
WARNING: Unable to validate one-to-many relation com.monsters.server.MonUser.monsters
Any idea what that's about? Here is the code:
This is the code to the Parent class
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class MonUser {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent(serialized="true", mappedBy = "owner")
#Element(dependent = "true")
private HashMap<String,Monster> monsters;
...
#PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class Monster {
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private MonUser owner;
...
I've tried everything on the appengine page on relationships and nothing seems to help. Any info would be extremely helpful!
P.S. I've gotten it to work with ArrayLists and the like but not hashmaps, hashtables, maps, etc. If that helps at all.
Only the following Collections are supported by JDO:
java.util.ArrayList<...>
java.util.HashSet<...>
java.util.LinkedHashSet<...>
java.util.LinkedList<...>
java.util.List<...>
java.util.Set<...>
java.util.SortedSet<...>
java.util.Stack<...>
java.util.TreeSet<...>
java.util.Vector<...>
You can persist a HashMap with:
#Persistent(serialized = "true", defaultFetchGroup="true")
see JDO - HashMap within an embedded Class
To ensure persistence of changes you need to always create a new instance of HashMap see the end of:
http://gae-java-persistence.blogspot.de/2009/10/serialized-fields.html

Resources