Key.toUrlSafe() - how to get entity by urlSafeKey? - google-app-engine

com.google.cloud.datastore.Key
has a toUrlSafe method()
how do I recreate the key from this url safe string? Key has only methods like getParent, getId, getName...
I tried with
com.google.cloud.datastore.Datastore
key factory, but I haven't found any methods that create key from url safe string.

It looks like you are using Java. In Java, the Key class has a static method fromUrlSafe (https://googleapis.dev/java/google-cloud-clients/latest/com/google/cloud/datastore/Key.html#fromUrlSafe-java.lang.String-).

Related

How to get a document from mongodb by using its string id and string collection name in SpringData

I know that generally, we need to do something similar to this for getting a document back from mongodb in spring data:
Define a class and annotate it with #Document:
#Document ("persons")
public class Person
Use MongoTemplete:
mongoOps.findById(p.getId(), Person.class);
The problem is that in runtime I don't know the class type of the document, I just have its string collection name and its string Id. How is it possible to retrieve the document using SpringData? Something like this:
db.myCollectionName.findOne({_id: myId})
The result object type is not a concern, it can be even an object, I just want to map it to a jackson JsonNode.
A possible workaround for this you can use the aggregate function of mongooperation like this
AggregationResults<Object> aggResults = mongoOps.aggregate(newAggregation(match(Criteria.where("_id").is(myId)) ,
myCollectionName, Object.class);
return aggResults.getUniqueMappedResult();

ApiTransformer for parametrized, unavailable type

I'm using Objectify and wish to have its Key<> type passed around in my API. I've created an ApiTransformer, but my questions is where to declare it, since the serialized Key<> class is not available, hence I cannot declare its transformer as a class annotation. I tried declaring it in the #Api annotation, but it doesn't work, I still get the error:
There was a problem generating the API metadata for your Cloud Endpoints classes: java.lang.IllegalArgumentException: Parameterized type com.googlecode.objectify.Key<[my package].User> not supported.
The ApiTransformer looks like:
public class KeyTransformer implements Transformer<Key<?>, String> {
public String transformTo(Key<?> in) {
return in.getString();
}
public Key<?> transformFrom(String in) {
return Key.valueOf(in);
}
}
And in my #Api I have:
#Api(name = "users", version = "v1",transformers = {KeyTransformer.class})
Unfortunately you can't. As you said you need to declare it on the Key class, your only chances to make this work are either.
1) Recompile the Key class for objectify with the #transformer annotation.
2) Extend the Key class with your own implementation and define the transformer there.
I don't really like any of those options so the way i usually resolve this is to hide the key object getter (by using #ApiResourceProperty(ignored=AnnotationBoolean.TRUE)) and only expose the id from that key.
That way you get a Endpoints frendly object, the only downside is you'll have to reconstitute the key using Key.create(YourClass.class, longId) manually whenever you need it.
You can add transforms to 3rd party classes by listing the transform in #Api annotation. I'm not dead sure it'll work parameterized class, but I don't see why not.
https://cloud.google.com/appengine/docs/java/endpoints/javadoc/com/google/api/server/spi/config/Api#transformers()

GAE get Data using JDO with key

I created Key with my unicue ID, and save into the database.
GoogleDrivePDF pdf = new GoogleDrivePDF();
key= KeyFactory.createKey(GoogleDrivePDF.class.getSimpleName(),"0B1IQEoiXFg3IWHhJNEtlMzlvQWs");
pdf.setKey(key);
pdf.setPdfName("NAME");
everything works!
But know I have one problem.
In order to get my Object From Db I must need Key string.
GoogleDrivePDF pdf = pm.getObjectById(GoogleDrivePDF.class, "agtsdHYtY2hlY2tlcnJoCxIRVXNlcnNQREZEb2N1bWVudHMiIXZha2h0YW5nLmtvcm9naGxpc2h2aWxpQGdtYWlsLmNvbQwLEg5Hb29nbGVEcml2ZVBERiIcMEIxSVFFb2lYRmczSVdIaEpORXRsTXpsdlFXcww");
how to create that key? I think it is enycrypted key. How can I now get this object?
P.S I think because of I have one to many relationship, that may does not work. Because When I create that pdf without 1:N it gets object very well. But I cant get another datas, which are in 1:N
I have that error:
Could not retrieve entity of kind GoogleDrivePDF with key GoogleDrivePDF("0ByMb_8ccYJRFOS1ibmFtamZ1b2M")
org.datanucleus.exceptions.NucleusObjectNotFoundException: Could not retrieve entity of kind GoogleDrivePDF with key GoogleDrivePDF("0ByMb_8ccYJRFOS1ibmFtamZ1b2M")
If you want to create a Key based on some other field of your Entity (say, for instance, a field called uniqueID), you should do something like this:
Persisting:
GoogleDrivePDF pdf = new GoogleDrivePDF();
pdf.setUniqueID("0B1IQEoiXFg3IWHhJNEtlMzlvQWs");
Key key = KeyFactory.createKey(GoogleDrivePDF.class.getSimpleName(),pdf.getUniqueID());
pdf.setKey(key);
pm.makePersistent(pdf);
BTW, it is generally not a good choice to make the key field publicly accessible. I think it is better to put the code for the creation of the key inside a specific constructor, like
public GoogleDrivePDF(String uniqueID) {
this.setUniqueID(uniqueID);
this.key = KeyFactory.createKey(GoogleDrivePDF.class.getSimpleName(),uniqueID);
}
Retrieving:
String idToBeRetrieved = "0B1IQEoiXFg3IWHhJNEtlMzlvQWs";
Key key = KeyFactory.createKey(GoogleDrivePDF.class.getSimpleName(),idToBeRetrieved);
pm.getObjectById(GoogleDrivePDF.class, key);
Solution was Unowned:
#Unowned
#Persistent
private Map <String,GoogleDrivePDF > pdfs;

Passing indefinite Query Parameters with RESTful URL and reading them in RESTEasy

I have a requirement to design a RESTful Service using RESTEasy. Clients can call this common service with any number of Query Parameters they would want to. My REST code should be able to read these Query Params in some way. For example if I have a book search service, clients can make the following calls.
http://domain.com/context/rest/books/searchBook?bookName=someBookName
http://domain.com/context/rest/books/searchBook?authorName=someAuthor& pubName=somePublisher
http://domain.com/context/rest/books/searchBook?isbn=213243
http://domain.com/context/rest/books/searchBook?authorName=someAuthor
I have to write a service class like below to handle this.
#Path("/books")
public class BookRestService{
// this is what I currently have, I want to change this method to in-take all the
// dynamic parameters that can come
#GET
#Path("/searchBook")
public Response searchBook(#QueryParam("bookName") String bookName,#QueryParam("isbn") String isbn) {
// fetch all such params
// create a search array and pass to backend
}
#POST
#Path("/addBook")
public Response addBook(......) {
//....
}
}
Sorry for the bad format (I couldn't get how code formatting works in this editor!). As you can see, I need to change the method searchBook() so that it will take any number of query parameters.
I saw a similar post here, but couldn't find the right solution.
How to design a RESTful URL for search with optional parameters?
Could any one throw some light on this please?
The best thing to do in this case would be using a DTO containing all the fields of your search criteria. For example, you mentioned 4 distinct parameters.
Book Name (bookName)
Author Name (authorName)
Publisher Name (pubName)
ISBN (isbn)
Create a DTO containing the fields having the following annotations for every property you want to map the parameters to:
public class CriteriaDTO{
#QueryParam("isbn")
private String isbn;
.
.
Other getter and setters of other properties
}
Here is a method doing that for your reference:
#GET
#Produces("application/json")
#Path("/searchBooks")
public ResultDTO search(#Form CriteriaDTO dto){
}
using following URL will populate the CriteriaDTO's property isbn automatically:
your.server.ip:port/URL/Mapping/searchBooks?isbn=123456789&pubName=testing
A similar question was asked here: How do you map multiple query parameters to the fields of a bean on Jersey GET request?
I went with kensen john's answer (UriInfo) instead. It allowed to just iterate through a set to check which parameters were passed.

What is dbReferenceProperty?

In the python app engine docs, I see something called dbReferenceProperty. I can't understand what it is, or how it's used. I'm using the java interface to app engine, so I'm not sure if there's an equivalent.
I'm interested in it because it sounds like some sort of pseudo-join, where we can point a property of a class to some other object's value - something like if we had:
class User {
private String mPhotoUrl;
private String mPhone;
private String mState;
private String mCountry;
.. etc ..
}
class UserLite {
#ReferenceProperty User.mPhotoUrl;
private String mPhotoUrl;
}
then if we had to update a User object's mPhotoUrl value, the change would somehow propagate out to all UserLite instances referencing it, rather than having to update every UserLite object instance manually,
Thanks
A db.ReferenceProperty simply holds the key of another datastore entity, which is automatically fetched from the datastore when the property is used.
There's some additional magic where the entity that is referenced has access to a query for entities of type Foo that reference it in the special attribute foo_set.
The Java datastore API instead has owned relationships, which serve the same purpose.

Resources