Bean Validation and Objectify - google-app-engine

I'm using Objectify to manage GAE Datastore persistence. I cannot find much useful documentation on Bean validation using Objectify. I tried using the Hibernate Validator, but it still allows me to persist invalid data.
To make things crystal clear, here's a simple example:
#Entity
public class Person {
#Id Long id;
// validate firstName is 1-20 characters, like Hibernate's #Length(min=1, max=20) annotation
#Index private String firstName;
// GETTERS & SETTERS
}
Any help is appreciated!

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).

Validate object to RESTeasy method using specific validation group

I am attempting to validate the input to a REST method using one or more specific validation groups, but so far I have been unable to figure out how to properly do it. I am using RESTeasy 3.X with Hibernate Validator 5.X.
I know that prior to the Bean Validation 1.1 spec, a RESTeasy method could be annotated with something like:
#ValidateRequest(groups=MyGroup.class)
However, this functionality no longer exists in Hibernate Validator 5.X.
Suppose I have an entity like:
#Entity
#Table(name = "example_table")
#XmlRootElement
public class ExampleEntity implements Mappable, Serializable
{
// ...
#Column(name = "title")
#NotEmpty(groups = Default.class, ExampleEntityGroup.class)
#Size(max = 255)
private String title;
#Column(name = "description")
#NotEmpty(groups = Default.class)
#Size(max = 255)
private String description;
// ...
}
Now I'd like to define a REST PUT method to update this entity, and I'd like the "description" field to allow an empty value. For this to happen I'd like to validate the entity using the ExampleEntityGroup group that I've defined (whereas the Default group would be used to validate POST requests that create new objects).
Right now my update method interface looks something like:
#Path("{id}")
#PUT
#Consumes(...)
#Produces(...)
ExampleEntity update(#PathParam("id"), ExampleEntity exampleEntity);
However, with this as written, it will always validate exampleEntity using the Default validation group. What would I do to force the update() method to use the other validation group?
The only documentation I could find that seems close to this is an example from the Bean Validation spec that uses an interceptor. Is there a better way?
RestEasy 3 with Bean Validation 1.1 will automatically validate constrained resource methods, i.e. it suffices to place a constraint annotation to a resource method parameter or return value and it will be validated. There is no way to validate a specific group, it will always be the default group. You could try and open a feature request for the RestEasy project for this.

Queries with Objectify: UmbrellaException

I am using Objectify to manage GAE Datastore for my GWT app. The problem is that I am not using queries properly and I get UmbrellaExceptions as per below:
Caused by: java.lang.RuntimeException: Server Error: java.lang.String cannot be cast to java.lang.Number
at com.google.web.bindery.requestfactory.shared.Receiver.onFailure(Receiver.java:44)
Say that I have a class Box with a unique field String id. I want to get the Box object whose id == "cHVQP6zZiUjM"
This is how I do it now:
public Box getBox(String boxId)
{
Objectify ofy = ObjectifyService.begin();
Query<Box> q=ofy.query(Box.class).filter("id",boxId);
Box targetBox = q.get();
return targetBox;
}
#Entity
public class Box extends DatastoreObject{
private String id;
private String title;
}
I tried doing this with ofy.load() but that method is not defined in my class Objectify (I don't know why).
Your key is encoded. Try using:
Box targetBox = ofy.get(Box.class, KeyFactory.stringToKey(boxId));
To decode your key.
The short answer: You are missing the #Id annotation in your entity.
The long answer: Id fields are special in the datastore. The id is not a real property, but rather a part of the Key that identifies the entity. You can't really filter on id fields, but you can filter on a special field called __key__. Objectify is somewhat clever about letting you filter by the id field and converting this to a __key__ filter under the covers, but it can't do it if you don't annotate the entity properly!
Actually I'm a little confused because Objectify shouldn't let you register the entity without an #Id field.
By the way, there are two sections of the documentation: Objectify4 (release coming soon) and Objectify3. Since you're using Ofy3, there is no load() method.
Another thing: Get-by-key operations are strongly preferred to queries when the operations are equivalent (as they are in your example).

Ignore field from database Spring Roo

I have a spring roo web service that I am currently building out but I have an entity that contains a field that should not be included in the database.
I would like the field to be in the entity and print it out with JSON to string methods, but I don't need that value saved. Is there any annotation or hack to make this happen?
Spring Roo uses JPA for persistence. You want to mark the field as #Transient:
#RooJavaBean
#RooEntity
class MyEntity {
private String column1;
#Transient
private String ignoreMe; // Ignore this field in JPA
}
You can also use the same annotation for bean methods that would otherwise be mapped:
#RooJavaBean
#RooEntity
class MyEntity {
private String column1;
#Transient
private String getAsJSON() {
return JSONHelper.toJSON(column1);
}
}

Ancestor Query with Objectify not returning results

I am using objectify 3.1 on appengine and attempting to do a ancestor query. I want to fetch all the children of an object that are of a certain kind. Below is my code:
#Cached
#Entity
public class Car {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String make;
private String model;
}
#Cached
#Entity
public class Tire {
#Id
public String keyName;
#Parent Key<Car> car;
private String brand;
private String size;
}
My query is this code:
List<Tire> list= ofy.query(Tire.class).ancestor(new Key<Car(Car.class,carID))).list();
When I create the tire objects I use this code to set the relationship:
newTire.setCar(new Key<Car>(Car.class,Car.getID()));
I know the Parent relationship is there because I can query for it in the datastore admin and it shows the parent in the decoded entity key:
Decoded entity key: Car: id=135172 > Tire: name=myCarUniqueID
This query always returns 0 results, and it seems like I have followed all the best practices on the objectify website. Any help would be appreciated!
Your code looks ok, so the only thing that might be wrong is a non-existing carID.
The Objectify javadoc listed on the site is actually for trunk version which is a forthcoming Objectify 4. What you need to look at is Objectify 3.1 javadoc: this version has fetch() on the query.
Also, #GeneratedValue is not an Objectify annotation.

Resources