I'm copying Google Cloud Datastore entities from one namespace to an other with java like this:
Key newKey = Key.newBuilder(oldEntity.getKey()).setNamespace(NEW_NAMESPACE).build();
datastore.put(Entity.newBuilder(oldEntity).setKey(newKey).build());
Since the entities have numerid id's generated by Datastore and the id's of the copied entities need to remain the same I need to also let Datastore know to allocate these id's, for that I'm using DatastoreService.allocateIdRange
But this is giving me an error:
Exceeded maximum allocated IDs
Does this mean that there is no way to achieve what I'm trying to achieve?
EDIT 1
The code that allocates the ids:
#POST
public void post(
#QueryParam("namespace") String namespace,
#QueryParam("kind") String kind,
#QueryParam("id") long id,
#QueryParam("parentKind") String parentKind,
#QueryParam("parentName") String parentName,
#QueryParam("parentId") Long parentId
) {
NamespaceManager.set(namespace);
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
Key parent = null;
if (parentKind != null) {
if (parentName != null)
parent = KeyFactory.createKey(parentKind, parentName);
else
parent = KeyFactory.createKey(parentKind, parentId);
}
ds.allocateIdRange(new KeyRange(parent, kind, id, id));
}
I think you can skip the key creation. This is my code for updating namespaces:
GoogleCloudDatastore gds = new GoogleCloudDatastore();
Datastore ds = gds.getCredentials();
final KeyFactory keyFactory = ds.newKeyFactory().setKind(entityKind).setNamespace(NAME_SPACE);
Key newKey = ds.allocateId(oldEntity.getKey);
Entity newEntity= Entity.newBuilder(newKey).set("someParameterName", someParameterValue).build();
Hope this helps.
Here is an answer provided on Google's Issue Tracker:
allocateIdRange only works with Sequential contiguous IDs and not Scattered IDs which are above the Sequential ID range.
As explained in the 'Best Practices' documentation, if need be it is recommended to send an 'allocateIds' request to Datastore to find and allocate a contiguous range of unique IDs and use those to save entities to, instead of saving entities to the Datastore first which are auto-assigned Scattered IDs and cannot be allocated with allocateIdRange.
Related
I have to search users under the specific organization in liferay. At present we have a search available with
UserLocalService.search()
which is based on the companyId . I was wondering if there is any otherway even using the DynamicQueryFactoryUtil do fetch along with organization filter.
The dynamic query looks good, but I found an another way. We can pass the organization id using Map.
params.put("usersOrgs", orgId);
List<User> searchResult = liferayUserLocalService.search(companyId, keyword, WorkflowConstants.STATUS_APPROVED, params, 0, -1, "");
which will filter the users based on organization.
Of Course You can use DynamicQuery for achieving this.
This can be done in two phase ,
Fetch User Id associated with the given Organization.
Use search criterion along with the id received in first phase.
So, the code will look as following ,
// Fetch userId List form Organization id
long[] organiztionIds = UserLocalServiceUtil.getOrganizationUserIds(orgId);
DynamicQuery searchQuery = DynamicQueryFactoryUtil.forClass(User.class, UserLocalServiceUtil.class.getClassLoader());
Criterion searchCriteria = PropertyFactoryUtil.forName("companyId").eq(companyid);
//Add Organization Id in Criterion
if (organiztionIds.length != 0) {
searchCriteria =
RestrictionsFactoryUtil.and(RestrictionsFactoryUtil.in("userId", ArrayUtils.toObject(organiztionIds)), searchCriteria);
}
if (!firstName.isEmpty()) {
searchCriteria = RestrictionsFactoryUtil.or(RestrictionsFactoryUtil.eq("firstName", firstName), searchCriteria);
}
if (!middleName.isEmpty()) {
searchCriteria = RestrictionsFactoryUtil.or(RestrictionsFactoryUtil.eq("middleName", middleName), searchCriteria);
}
if (!lastName.isEmpty()) {
searchCriteria = RestrictionsFactoryUtil.or(RestrictionsFactoryUtil.eq("lastName", lastName), searchCriteria);
}
if (!screenName.isEmpty()) {
searchCriteria = RestrictionsFactoryUtil.or(RestrictionsFactoryUtil.eq("screenName", screenName), searchCriteria);
}
searchQuery.add(searchCriteria);
UserLocalServiceUtil.dynamicQuery(searchQuery);
P.S
I haven't tested this code. But this is the way to do it.
I Hope it helps you.
I generated all required java classes from crm.dynamics.com/XRMServices/2011/Discovery.svc?wsdl and crm.dynamics.com/XRMServices/2011/Organization.svc?wsdl schemas.
I authenticated in CRM with LiveId.
Now i need to create Product in Product Catalog. Here is code for this:
Entity newEntryInfo = new Entity();
AttributeCollection collection = new AttributeCollection();
addAttribute(collection, "name", "Tama Starclassic Performer");
addAttribute(collection, "productnumber", "1");
addAttribute(collection, "price", createMoney("100.0"));
addAttribute(collection, "isstockitem", Boolean.TRUE);
addAttribute(collection, "statuscode", 1);
newEntryInfo.setAttributes(collection);
newEntryInfo.setLogicalName("product");
Guid productGuid = serviceStub.create(newEntryInfo);
private void addAttribute(AttributeCollection collection, String key, Object value) {
KeyValuePairOfstringanyType values = new KeyValuePairOfstringanyType();
values.setKey(key);
values.setValue(value);
collection.addKeyValuePairOfstringanyType(values);
}
Execution shows error "The unit schedule id is missing."
Looks like i need to provide "Unit Group" and "Default Unit" for new product.
Question: How can i set those values? Should i use RelatedEntities (how create it) or Attributes (how create it)
As it is a lookup on the form, you should be able to set the value with an EntityReference.
Using your methods that would be:
addAttribute(collection, "fieldName", new EntityReference("entityName", new Guid("id"))
Where:
fieldName is the schema name of the field you want to populate
entityName is the schema name of the entity you want to populate the field with
id is the Guid of a record which is the same type as entityName.
To put that into a context (where I happen to know the schema names off the top of my head).
//Create a new contact first
Entity contact = new Entity("contact");
contact["lastname"] = "Wood";
Guid contactId = service.Create(contact);
//Create an incident/case which links to that new contact
Entity incident = new Entity("incident");
incident["customerid"] = new EntityReference("contact", contactId)
service.Create(incident)
As a side is there a particular reason you are using a such a long winded code style? The entity class has an index which links to underlying attribute dictionary. Its a bit more straight forward.
If you are looking for more examples check out: Use the Late Bound Entity Class in Code
Is this the correct way to set and get a string value using persistance in GAE ?
I'm receiving error :
com.google.appengine.api.datastore.EntityNotFoundException: No entity was found matching the key: jsonString("jsonString")
Adding to store :
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Key key = KeyFactory.createKey("jsonString", "jsonString");
Entity urlEntity = new Entity("jsonString" , key);
urlEntity.setProperty("urlVal", urlVal);
com.google.appengine.api.datastore.Key urlEntityKey = datastore.put(urlEntity);
Returning from store :
Key key = KeyFactory.createKey("jsonString", "jsonString");
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Entity entity = datastore.get(key);
Please review the below code, also you can find more details on how to use the app engine datastore API by reviewing the documentation here. Also review the notes in the Datastore Overview document.
DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
Entity e = new Entity("data");
e.setProperty("jsonString", "myValue");
Key key = ds.put(e);
Entity entity = ds.get(key);
System .out.println(entity);
I am using Java, spring, jpa for our application. I want to retrieve Id of insert row. Basically our ID is generated at the time of storing object into database.
RoleRequest role = new RoleRequest();
roleRequest.setUser(user);
roleRequest.setRole(role);
roleRequest.setRequestDate(new Date());
roleRequest.setStatusCode(Enum.PENDING);
Dao.persist(roleRequest);
So after storing this object, I need new generated id for this object, so that will perform some operation on it.
Dao.persist(roleRequest);
After this line, the id should be set, so you can just do
Long id = roleRequest.getId();
(assuming id as id column and Long as id type)
What about:
oleRequest role = new RoleRequest();
roleRequest.setUser(user);
roleRequest.setRole(role);
roleRequest.setRequestDate(new Date());
roleRequest.setStatusCode(RoleRequestStatusEnum.PENDING);
Dao.persist(roleRequest);
int myId = roleRequest.getId();
You may need to do EntityManager.flush() after EntityManager.persist() (YMMV).
I see a similar question in Problems while saving a pre-persisted object in Google App Engine (Java), and indeed I was not calling close() on my persistence manager. However, I am now calling close, but my object update is not being persisted. Specifically, I want to remove an element from a Set, and save that smaller set. Here is the persistence manager related code, that doesn't throw an exception, but doesn't save my data:
UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
PersistenceManager pm = PMF.get().getPersistenceManager();
UserProfileInfo userProfile = pm.getObjectById(UserProfileInfo.class,user.getUserId());
int presize = userProfile.getAccounts().size();
AccountInfo ai = userProfile.removeAccount(id);
int postsize = userProfile.getAccounts().size();
UserProfileInfo committed = (UserProfileInfo)pm.makePersistent(userProfile);
int postcommitsize = committed.getAccounts().size();
pm.close();
And here is the relevant part of the UserProfileInfo class:
#PersistenceCapable(identityType = IdentityType.APPLICATION)
class UserProfileInfo {
#Persistent
private Set<AccountInfo> accounts;
public AccountInfo removeAccount(Long id) throws Exception {
Iterator<AccountInfo> it = accounts.iterator();
StringBuilder sb = new StringBuilder();
while(it.hasNext()) {
AccountInfo acctInfo = it.next();
Long acctInfoId = acctInfo.getId();
if(acctInfoId.equals(id)) {
it.remove();
return acctInfo;
}
sb.append(" ");
sb.append(acctInfoId);
}
throw new Exception("Cannot find id " + id + " Tried " + sb.toString());
}
}
So it looks like the answer is owned objects cannot use a Long primary key. The datanucleus enhancer told me this for another object type I added. I'm not sure why it skipped this warning for my AccountInfo object.
I switched my key over to a String, and changed the annotations to use the string properly, and now I'm able to delete from the collection.
I'd have thought that the first thing to do when debugging anything would be to look at the log (DEBUG level). It tells you what states the objects are in at the different points. So what state is it in when you call makePersistent() ? and after ? and what happens when you call pm.close() ...