Jello Entity is the core component which the application model is based on. Jello uses Objectify as the underlying ORM layer to map and store entities in the database. If you are familiar with Objectify or your application is already using Objectify, you will find it very easy and intuitive to migrate your app to Jello.
Jello has an improved persistence mapping model over the basic Objectify implementation. Its superior model using the entity full name to maps entities in different packages to the database, providing a better way to organize the code and shape your application authorization model.
You define a Jello Entity by extending the JelloEntity class. To expose it via RESTfull API, you will need to add the @Accessible annotation.
1 2 3 4 5 6 | package app; @Accessible public class Person extends JelloEntity { ... } |
The base class for all Jello persistence entities.
Marks the entity as accessible to all via REST requests. The @Accessible annotation can get authorization parameters (for data-access-control options, refer to the Jello Authorization Model).
Placed on a field or class. When placed on a class, sets the default state for all fields of the class. Indexed fields cost more space and cpu time to store, but can be queried on. Unless otherwise specified, all classes default to @Index. For more options like partial indexing, refer to Objectify annotation reference
Determine whether to add the entity to the search index. By default, Jello will treat all* entities as searchable. To override this behavior, add the following to app.yaml. (See also the application configuration file.)
servlet: jello.JelloServlet name: Jello init_params: jello.search.enabledByDefault: false
* For security reasons, an entity which contains instance level access will not be treated as searchable.
The entity key is composed of all fields annotated with @KeyElement and @GroupElement.
In addition to all fields specified by the user, Jello will add implicit __ID
key field to hold the entity key value.
In case no key element is specified, an auto generated UID will be assigned as the entity key.
In case one key element is specified, the entity key value will be the same as the key element value.
1 2 3 | // example of entity key: John Doe @KeyElement public String fullName; |
In case of multiple key elements:
1 2 3 4 | // example of entity key: Toyota::123456-CA @GroupElement String model @KeyElement String licensePlate; @KeyElement String registeredAtState; |
Field annotated with @groupElement
is a special type of key element typically used to establish strong association
and/or define strong persistence and transactions.
Only one field annotated with @GroupElement
can be defined per Entity.
(read more about strong association ad transactions).
Most of the data types supported by Google App Engine datastore are also supported by Jello.
In addition, Jello provides superior handling for the following types:
Marks the field as accessible to all via REST requests. This annotation affects only the REST API, while the Java access level is determined, as usual, by the field java access modifiers (public/private).
The @Expose annotation can get authorization parameters (for data-access-control options, refer to the Data Access Control section).
In case of exposure of a private field, the Jello annotation processor will issue a warning, letting you know that this field will be exposed via REST calls regardless of its 'private' modifier. To mute this warning, go to the project settings » Jello Framework » Annotation settings.
This annotation is valid only for multiple values fields (Set or List). Cardinality has priority over @Required and will override it.
Syntax:@Cardinality("number..number|*") // for example: @Cardinality("2..*")
Jello entities maintain Audit fields for all records. Each entity includes the following audit fields by default:
@Expose @Audit @ReadOnly private Date createdOn; @Expose @Audit @ReadOnly private User createdBy; @Expose @Audit @ReadOnly private Date changedOn; @Expose @Audit @ReadOnly private User changedBy;
Audit fields are not included in the REST response by default. To include Audit fields in the response, use the $audit=true query option (see REST Query Options - $audit). Note: Audit fields will be exposed only if the logged-in user has CREATE permission for the entity. (For data-access-control options, refer to the Data Access Control section.)
@Audit (jello.annotation.Audit)
Marks the field as an Audit field.
@label
annotation is optional).
@Expose public Color background; public enum Color { @Label("Red") RED, @Label("Green") GREEN, @Label("Blue") BLUE };
The Entity metadata will include the enumeration definition as shown below:
{ name: "background", type: "app.Box.Color" } ... enums: { app.Box.Color: [ { value: "RED", label: "Red" }, { value: "GREEN", label: "Green" }, { value: "BLUE", label: "Blue" } ] }
import java.util.function.Function; import java.util.function.Supplier; import com.googlecode.objectify.annotation.Ignore; public class EntityWithCalcField extends JelloEntity { // Simple Lambda expression @Expose Supplier<String> calcField = () -> "I am a calculated field"; // Lambda expression with 'this' instance context @Expose Function<EntityWithCalcField, String> calcFieldWithContext = (x) -> "I am a calculated field: " + x.getID(); // The old way: // Adding a method with the same name as the field with no parameters // The method must return the same type as the field's type @Ignore @Expose private String calculatedField; public String calculatedField() { return "I am calculated field: " + getID(); } }
Both Set
and List
collections are supported for the following types:
any core type, enums, reference type, and managed embedded type.
@Expose public List<String> messages; @Expose public Address managedAddress; @Expose public List<Color> colorsList; @Expose public Set<Color> colorsSet; enum Color {RED, GREEN} @Reference(Product.class) @Expose public List<Key> productsList; @Expose public Set<Key> productsSet; @Expose public List<Address> addressesList; @Expose public Set<Address> addressesSet; static class Address { String street; String city; String state; String zipCode; }
Entity elements can be annotated with UX annotations.
You can add any of the jello.ux
annotations such as Label
, Hint
, Control
, etc.
(see list of all available UX annotation).
In addition, you can define custom UX annotations which will be added to the element meta data object (see Define Custom UX Annotations).
Overrides the default JelloEntity empty methods. These functions are used for adding custom validation (see Server-Side validation) and records manipulation before and after saving the record. It applies to both REST (create, update) API calls and JAVA create(), save(), update() API.
These methods are handy especially since only the default empty constructor is invoked during REST call.
@Override protected Car beforeSave() throws IllegalRequestResource { // Here you can add code that will be executed before saving the record. if(this.text.contains("somethingfishy")) throw new IllegalRequestResource( "something fishy while trying to save " + this.getID() ) .forField("text"); return this; } @Override protected Car afterSave() { // Here you can add code that will be executed after saving the record. return this; }
@Override protected Car beforeDelete() throws IllegalRequestResource { // Here you can add code that will be executed before deleting the record. if(something-fishy) throw new IllegalRequestResource( "something fishy while trying to delete " + this.getID() ); return this; } @Override protected Car afterDelete() { // Here you can add code that will be executed after deleting the record. return this; }
Static entity serves as a service endpoint that can only expose static actions via REST calls. Any attempt to persist an instance of this entity in the database will fail.
@Accessible public class AppService extends StaticEntity { // Static actions only }
Was this page helpful? Let us know how we did:
Last updated March 11, 2019.