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;
}
Related
Can somebody please help me to restructure the following code using java8 features.
Here is my code.
private List<CreateChildItemResponse> createChildItems(String[] childUpcNumbers, String[] childItemNbrs,
ItemVo parentItem, UserVo user, boolean isEnableReverseSyncFlag, Integer parentItemNbr, Long parentUpcNbr,int childUpcNbrsize, ItemManagerDelegate managerDelegate) throws NumberFormatException, ValidationException,ChildNotFoundException, ResourceException, ChildItemException {
List<ItemVo> resultList = new ArrayList<ItemVo>();
List<CreateChildItemAssortmentResponse> relations = null;
CreateChildItemResponse response = new CreateChildItemResponse();
try {
for (int i = 0; i < childUpcNumbers.length; i++) {
// parentItem.setItemNbr(itemNumberList.get(i));
logger.info("-------Item Nbrs-----" + parentItem.getItemNbr());
ItemVo child = createItemForMigration(
populateChildItemVo(parentItem, getGtin(childUpcNumbers[i]), Integer.valueOf(childItemNbrs[i])),
user, isEnableReverseSyncFlag, managerDelegate);// null scales for all except scales integration
resultList.add(child);
}
relations = this.populateAssortmentRelationVo(parentItem.getItemNbr(), resultList);
response = getSuccessResponse(parentItemNbr, relations, parentUpcNbr);
// utx.commit();
} catch (Exception e) {
logger.info("Exception occurs while creating child item", e);
relations = this.populateAssortmentRelationVoForException(e, resultList);
response = getFailureResponseForException(parentItemNbr, relations, parentUpcNbr, e, resultList.size(),
childUpcNbrsize);
finalResponse.add(response);
throw new ChildItemException(e.getMessage(), finalResponse, e);
}
finalResponse.add(response);
return finalResponse;
}
here I am calling the below method in the above code
relations = this.populateAssortmentRelationVo(parentItem.getItemNbr(), resultList);
And the implementation is
private List<CreateChildItemAssortmentResponse> populateAssortmentRelationVo(Integer parentItemNumber,
List<ItemVo> childs) {
List<CreateChildItemAssortmentResponse> relationList = new ArrayList<CreateChildItemAssortmentResponse>();
for (ItemVo child : childs) {
CreateChildItemAssortmentResponse relation = new CreateChildItemAssortmentResponse();
relation.setItemNbr(child.getItemNbr());
relation.setUpcNbr(convertUpcToString(child.getEachGtin().getGtinNbr()));
relation.setStatus("SUCCESS");
relation.setMessage("");
relationList.add(relation);
}
return relationList;
}
Here I want to take a constructor for the populateAssortmentRelationVo() and how to use stream and mapper inside this.
First declare a mapping function:
private CreateChildItemAssortmentResponse> itemVoToResponse(ItemVo item) {
CreateChildItemAssortmentResponse response = new CreateChildItemAssortmentResponse();
response.setItemNbr(item.getItemNbr());
response.setUpcNbr(convertUpcToString(item.getEachGtin().getGtinNbr()));
response.setStatus("SUCCESS");
response.setMessage("");
return relationList;
}
and simply map all the elements of one list into another one:
relations = resultList.stream()
.map(this::itemVoToResponse)
.collect(toList());
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
}
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"
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.
I am facing a problem with hibernate with multithreading.
I am developing a swing based application where there are some number of POJO classes. The relations among the classes: Category has a set of Protocols, Protocol has a set of Step, Step has a set of Mode. All the collections are loaded lazily with fetch = FetchType.LAZY. I am maintaining a single session for the application. After getting the list of all Category, I need to start some threads to do some operations on the category list. Here I am getting LazyInitializationException. The test code is as follows:
final List<Category> cats = protocolDao.getCategoryList();
for (int i = 0; i < 10; i++) {
new Thread("THREAD_" + i) {
public void run() {
try {
for (Category category : cats) {
Set<Protocol> protocols = category.getProtocols();
for (Protocol protocol : protocols) {
Set<Step> steps = protocol.getStep();
for (Step step : steps) {
step.getModes());
}
}
}
System.out.println(Thread.currentThread().getName()+"SUCCESS" ;
} catch (Exception e) {
System.out.println("EXCEPTION ON " + Thread.currentThread().getName());
}
};
}.start();
}
The dao method is as follows:
public List<Category> getCategoryList() throws ProtocolException {
try {
Transaction transaction = session.beginTransaction();
List list = session.createCriteria(Category.class)
.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
.addOrder(Order.asc("categoryposition")).list();
transaction.commit();
return list;
} catch (Exception e) {
throw new ProtocolException(e);
}
}
When I try to run the above code I get the following exception for some of the threads:
SEVERE: illegal access to loading collection
org.hibernate.LazyInitializationException: illegal access to loading collection
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:363)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
at org.hibernate.collection.PersistentSet.toString(PersistentSet.java:332)
at java.lang.String.valueOf(String.java:2826)
at java.lang.StringBuilder.append(StringBuilder.java:115)
at com.mycomp.core.protocol.dao.test.TestLazyLoading$1.run(TestLazyLoading.java:76)
So some of the tasks are not completed. I cannot avoid multiple threads to work on the same category list(it works fine with single thread). Every thread requires to do its own task. The database is too big to avoid lazy loading. Can anyone help me how will I be able to work with multiple threads with the same category list?
You need to ensure that only the thread that gets your entities uses them. If you have a get ids and get by id method or similar:
final int[] catIds = protocolDao.getCategoryIds();
for (int i : catIds) {
new Thread("THREAD_" + i) {
public void run() {
Category category = protocolDao.getCategory(i);
Set<Protocol> protocols = category.getProtocols();
for (Protocol protocol : protocols) {
Set<Step> steps = protocol.getStep();
for (Step step : steps) {
step.getModes());
}
}
};
}.start();
}