java google app engine get entity by key - java

I have a problem using GAEJ and JDO for storing the data.
This is what I'm working with:
class Usuari.java:
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
#Persistent
private String email;
#Persistent
private String rol="";
class DBUtils.java:
I've tried with two ways of doing the delete operation:
// This method removes a record from the database using its unique Key
public static boolean eliminar(Key k) throws Exception {
PersistenceManager pm = PMF.get().getPersistenceManager();
String kind;
Long id;
kind = k.getKind();
id = k.getId();
try {
if (k.getKind().equals("Usuari")) {
Usuari u = (Usuari)pm.getObjectById(k);
pm.deletePersistent(u);
_log.log(Level.INFO, "Deleted an entity->kind: " + kind + " id: " + id);
}
return true;
} catch (Exception e) {
_log.log(Level.SEVERE, "Unable to delete an entity->kind: " + kind + " id: " + id);
System.err.println(e.getMessage());
throw e;
}
finally {
pm.close();
}
}
// This method removes a record from the database using its unique Key - too
public static void eliminar2(Key k) throws Exception {
PersistenceManager pm = PMF.get().getPersistenceManager();
javax.jdo.Transaction tx = pm.currentTransaction();
try
{
tx.begin();
if (k.getKind().equals("Usuari")) {
Usuari u = (Usuari) pm.getObjectById(k);
pm.deletePersistent(u);
}
tx.commit();
}
catch (Exception e)
{
if (tx.isActive())
{
tx.rollback();
}
throw e;
}
}
I'm able to create new instances of some class "Usuari" but I can't delete them.
Everytime I call "eliminar" or "eliminar2" methods I get a "No such object" as result of trying to fetch it. I've checked manually and I see the object exists in my admin panel, with its ID and KIND, so I don't know what am I doing wrong.
Any help would be much appreciated.

PM.getObjectById does not take in a Key object, as per the JDO spec. It takes in an identity object, the same type as you would get from pm.getObjectId(obj); suggest you glance through the JDO spec. No doubt if you inspected what is returned from this method you would see that it can't find an object with that 'identity' because a Key is not an identity. You can also do
pm.getObjectById(Usuari.class, key);
which is shown very clearly in GAE documentation.
Still don't get why users are putting #Persistent on every field virtually every type is default persistent; only leads to making code more unreadable.

Related

Data On Init With Spring Command Line Runner

Here , I want to hardcode some things into db at the action of server starts with Spring commandline runner
Problem :- In this I have checked that if 1L isn't present then do entry for that with Id 1L but still it stores to incremental Id when 1L or 2L or 3L is not present there.
My Entity In which I'm doing entry :-
Product Type
#Data
#Entity
#Table(name = "tbl_product_type_chemical")
public class ProductType implements IBaseData<Long> {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
private Long id;
private String name;
#Column(columnDefinition = "text")
private String description;
}
This is method of Runner :-
private void loadProductTypeNew() throws Exception {
String SUBMODULE = " [Init Data] " + " [loadProductTypeNew()] ";
try {
ProductType fp = productTypeRepository.getOne(1L);
if (null == fp) {
fp = new ProductType();
fp.setId(1L);
fp.setName("FINISH PRODUCT");
productTypeRepository.save(fp);
}
ProductType rm = productTypeRepository.getOne(2L);
if (null != rm) {
rm = new ProductType();
rm.setId(2L);
rm.setName("RAW MATERIAL");
productTypeRepository.save(rm);
}
ProductType sm = productTypeRepository.getOne(3L);
if (null != sm) {
sm = new ProductType();
sm.setId(3L);
sm.setName("SUPPORTING MATERIAL");
productTypeRepository.save(sm);
}
} catch (Exception ex) {
ApplicationLogger.logger.error(SUBMODULE + ex.getMessage(), ex);
throw ex;
}
}
#Override
public void run(String... args) throws Exception {
loadProductTypeNew();`
}
Output :-
9 SUPPORTING MATERIAL
8 RAW MATERIAL
7 FINISH PRODUCT
10 FINISH PRODUCT
11 RAW MATERIAL
12 SUPPORTING MATERIAL
13 RAW MATERIAL
14 SUPPORTING MATERIAL
And I am calling it in run method.If anyone can solve thanks in advance
Nothing in your application should depend on specific values of the id field since it is generated by the database.
I suggest therefore to identify a business key (in your case the name), ensure it is unique with a primary key and use that to determine if a a row needs to be inserted in the database.
Your code would look similar to this
if (productTypeRepository.existsByName(""FINISH PRODUCT")) {
ProductType fp = new ProductType();
fp.setName("FINISH PRODUCT");
productTypeRepository.save(fp);
}

Removing/deleting from google datastore using endpoints, illegal arguement exception, delete with non-zero content length not supported

I'm trying to delete objects from the datastore (using cloud endpoints)
I know the connection is valid because I'm pulling/inserting objects with no problem
However when I try to delete using various approaches I get the same exception
java.lang.illegalArgumentException:DELETE with non-zero content length is not supported
approach 1(using the raw datastore service and the key I stored when inserting the item):
#ApiMethod(name = "removeRPurchase")
public RPurchase removeRPurchase(RPurchase purchase) {
NamespaceManager.set(purchase.getAccount());
DatastoreService d=DatastoreServiceFactory.getDatastoreService();
Key k=KeyFactory.stringToKey(purchase.getKeyrep());
try {
d.delete(k);
} catch (Exception e) {
e.printStackTrace();
purchase=null;
}
return purchase;
}
Approach 2
#ApiMethod(name = "removeRPurchase")
public RPurchase removeRPurchase(RPurchase purchase) {
NamespaceManager.set(purchase.getAccount());
Key k=KeyFactory.stringToKey(purchase.getKeyrep());
EntityManager mgr = getEntityManager();
RPurchase removed=null;
try {
RPurchase rpurchase = mgr.find(RPurchase.class, k);
mgr.remove(rpurchase);
removed=rpurchase;
} finally {
mgr.close();
}
return removed;
}
Ive also tried various variations with the entity manager and the Id, but all with the same exception
The object that i've passed in does contain the namespace in the account, and it does contain the 'KeytoString' of the key associated with the object
the endpoint is called as it should in an AsyncTask endpoint.removeRPurchase(p).execute();
Any help suggestions are appreciated
Make your API method a POST method like this:
#ApiMethod(name = "removeRPurchase" path = "remove_r_purchase", httpMethod = ApiMethod.HttpMethod.POST)
public RPurchase removeRPurchase(RPurchase purchase) {
NamespaceManager.set(purchase.getAccount());
DatastoreService d=DatastoreServiceFactory.getDatastoreService();
Key k=KeyFactory.stringToKey(purchase.getKeyrep());
try {
d.delete(k);
} catch (Exception e) {
e.printStackTrace();
purchase=null;
}
return purchase;
}
I had the same problem because I was using httpMethod = ApiMethod.HttpMethod.DELETE. The error it gives is correct. Simply change it to a POST and do whatever you want inside that API method like delete entities, return entities, etc.
How about trying out the following :
#ApiMethod(
name = "removeRPurchase",
httpMethod = HttpMethod.DELETE
)
public void removeRPurchase(#Named("id") String id) {
//Now take the id and plugin in your datastore code to retrieve / delete
}

GAE + JDO : Deleting Child object cause issue in google app engine java

I am using JDO in GAE. I have two JDO classes having one to many relationship. parent class is
#PersistenceCapable(detachable="true")
#FetchGroup(name="childerns", members={#Persistent(name="aliasName")})
public class IdentityProvider {
#PrimaryKey
#Persistent
private String url;
#Persistent
private String domainName;
#Persistent
#Element(dependent = "true")
private ArrayList<AliasDomain> aliasName = new ArrayList<AliasDomain>();
}
The child classes is
#PersistenceCapable(detachable = "true")
public class AliasDomain {
#Persistent
private String url;
#Persistent
private String aliasName;
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
}
I am just performing CURD operations on both entity. First i create the parent instance and then i create the child instance as
public void addAliasDomain(AliasDomain domain) {
String url = domain.getUrl();
PersistenceManager pm = PMFSingleton.get().getPersistenceManager();
IdentityProvider idp = null;
Transaction txn = null;
try {
txn = pm.currentTransaction();
txn.begin();
pm.getFetchPlan().addGroup("childerns");
idp = pm.getObjectById(IdentityProvider.class, url);
idp = pm.detachCopy(idp);
idp.getAliasName().add(domain);
pm.makePersistent(idp);
txn.commit();
} catch (Exception e) {
e.printStackTrace();
} finally {
if ( txn.isActive() ) {
txn.rollback();
}
pm.close();
}
}
My issue is created when i delete any child instance. As you see from the above function i link the child to the parents( means add child object into arrayList). So when child is deleted its reference in the parents is not deleted so at the detached time of parents object i got exception which is as
Object of type "user.oauth.jdo.model.IdentityProvider" and identity "yahoo.com" was not detached correctly. Please consult the log for any possible information.
org.datanucleus.exceptions.NucleusUserException: Object of type "user.oauth.jdo.model.IdentityProvider" and identity "yahoo.com" was not detached correctly. Please consult the log for any possible information.
at org.datanucleus.state.JDOStateManager.detachCopy(JDOStateManager.java:2942)
at org.datanucleus.ObjectManagerImpl.detachObjectCopy(ObjectManagerImpl.java:2591)
at org.datanucleus.api.jdo.JDOPersistenceManager.jdoDetachCopy(JDOPersistenceManager.java:1145 )
at org.datanucleus.api.jdo.JDOPersistenceManager.detachCopy(JDOPersistenceManager.java:1174)
at user.oauth.data.broker.IDPJDOBroker.retrieveDomainList(IDPJDOBroker.java:49)
The code of function retreiveDomainList in IDPJDOBroker is
public List retrieveDomainList() {
PersistenceManager pm = PMFSingleton.get().getPersistenceManager();
Query query = pm.newQuery(IdentityProvider.class);
List<IdentityProvider> list = null;
List<IdentityProvider> detachedList = null;
IdentityProvider idp = null;
try {
pm.getFetchPlan().addGroup("childerns");
list = (List<IdentityProvider>) query.execute();
detachedList = new ArrayList<IdentityProvider>();
for(IdentityProvider obj : list){
idp = pm.detachCopy(obj);
OAuthJDOBroker broker = new OAuthJDOBroker();
int actUsers = 0;
if ( idp.getHistory() != null && idp.getHistory().size() > 0) {
actUsers = broker.calculateActiveUser(idp.getUserActiveDuration(),idp.getDomainName());
}
idp.setActiveUsers(actUsers);
detachedList.add(idp);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
query.closeAll();
pm.close();
}
return detachedList;
}
Please tell me what to do? Is it not possible in JDO to delete the child? if it is possible then how to do it properly.
I have just seen this, but in case anyone arrives here, to delete a child object in a one to many relationship you must delete the reference from the parent, the child object will be deleted "transparently"

Oracle Berkeley DB Java Edition - Secondary key unicity

I have a simple entity class and it is supposed to include unique names on it.
#Entity
class Package {
#PrimaryKey(sequence = "ID")
public Long id;
#SecondaryKey(relate = Relationship.ONE_TO_ONE)
public String name;
private Package() {}
public Package(String name) { this.name = name; }
#Override
public String toString() { return id + " : " + name; }
}
I want to use deferred writing option because of extensive modification. Here is the test i tried and its output.
final String dbfilename = "test01";
new File(dbfilename).mkdirs();
EnvironmentConfig config = new EnvironmentConfig().setAllowCreate(true);
Environment environment = new Environment(new File(dbfilename), config);
StoreConfig storeConfig = new StoreConfig().setAllowCreate(true).setDeferredWrite(true);
EntityStore store = new EntityStore(environment, "", storeConfig);
PrimaryIndex<Long, Package> primaryIndex = store.getPrimaryIndex(Long.class, Package.class);
try {
primaryIndex.put(new Package("package01")); // will be put.
primaryIndex.put(new Package("package01")); // throws exception.
} catch (UniqueConstraintException ex) {
System.out.println(ex.getMessage());
}
store.sync(); // flush them all
// expecting to find one element
SortedMap<Long,Package> sortedMap = primaryIndex.sortedMap();
for (Package entity : sortedMap.values()) {
System.out.println(entity);
}
Output
(JE 5.0.73) Unique secondary key is already present
1 : package01
2 : package01
So my question is that even if it throws exception while putting second package, why does it lists two packages. Any way to avoid this without using transactions?
Thanks.

google app engine: problem getting objects from datastore in a task

My application constructs a Parent object in a static factory, along with it's predetermined Children, and then starts up tasks to run some computation on the Children, like so:
public static Parent make(User owner, List<Integer> data, int size) {
Parent result = new Parent(owner,data,size);
PersistenceManager pm = PersistenceSource.get();
Transaction tx = pm.currentTransaction();
try {
tx.begin();
result = pm.makePersistent(result);
for (int i=0; i<size; pm.makePersistent(new Child(result,i++)));
pm.close();
tx.commit();
} finally {
if (tx.isActive()) { tx.rollback(); result=null; }
}
if (result!=null) {
Queue q = QueueFactory.getDefaultQueue();
for (Child c : result.getChild()) {
q.add(url("/task/child").param("key", KeyFactory.keyToString(c.getKey())).method(Method.PUT));
}
}
pm.close();
return result;
}
however in the actual task
public void doPut(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
PersistenceManager pm = PersistenceSource.get();
Child c = pm.getObjectById(Child.class, KeyFactory.stringToKey(request.getParameter("key"))); //...
It dies trying to find the object:
Could not retrieve entity of kind Child with key Child(24)
org.datanucleus.exceptions.NucleusObjectNotFoundException: Could not retrieve entity of kind Child with key Child(24)
Any insights? Also, if it matters, the Parent-child relationship is defined by the parent as a field in the child (hence construction with the parent as an arg).
After some plugging around, the following will work to properly retrieve the desired Child:
Key k = new KeyFactory
.Builder(Parent.class.getSimpleName(), Long.valueOf(request.getParameter("parent")))
.addChild(Child.class.getSimpleName(), Long.valueOf(request.getParameter("child")))
.getKey();
Child c = pm.getObjectById(Child.class, k);
I'm still a bit mystified coming from the non-DataStore world as to why the type + id is insufficient to fetch what I want. That seems equivalent to knowing table + primary key in SQL land, and the documentation seems to indicate that the key contains all the parent info, such that having it should be sufficient to do a direct pm.getObjectId(Child, KeyFactory./* etc */).
public Object retrieveChildByKey(Key parent, Class childClass, int idChild){
try{
pm = PMF.get().getPersistenceManager();
Key objectKey = KeyFactory.createKey(parent, childClass.getSimpleName(), idChild);
Object result = pm.getObjectById(childClass, objectKey);
return result;
}
catch (DatastoreTimeoutException ex) {
// Display a timeout-specific error page
message = "Timeout: An error has occurred: Was not possible to retrieve the Object";
System.out.println(message);
ex.printStackTrace();
}
catch(Exception ex){
message = "Timeout: An error has occurred: Was not possible to retrieve the Object";
System.out.println(message);
ex.printStackTrace();
}finally{
pm.close();
}
return null;
}

Categories