Community contributed extensions

Why PlayMorphia

Morphia project has provided a lightweight and easy way to integrate power of MongoDB into Java application. There is absolute no problem to use Morphia directly in your Play application. So why do you bother with PlayMorphia module? Let’s see take a looks at a set of codes and understand why using PlayMorphia is a better approach when you are developing Play application:

Define entity model class

Given a very simple model class, PlayMorphia require the class to extends play.modules.morphia.Model. You don’t need to extend any class if you are using pure Morphia. However, you must declare an @ID field in your model class. In addition, the application developer needs to provide a way to ensure the model class is mapped.

CRUD and Query

PlayMorphia provides most natural way to do Create-Read-Update-Delete-Query operations on entity instance. Though it’s still quite easy to do that in pure Morphia also:

Statistics

Like all other interfaces provided, PlayMorphia provides a set of clean an simple interface for application developer to do statistics on their models:

TODO

More control on entity lifecycle management

In addition to existing Morphia lifecycle methods, PlayMorphia provides an new set of lifecycle annotation for application developer to use:

AnnotationDescriptionComment
@OnLoadcalled before an entity is filled with DB datanot used usually
@Loadedcalled after an entity is filled with DB datagood place to calculate derived properties, e.g. full name
@OnAddcalled before an new entity is persisted into DBgood place to calculate db properties from derived properties
@Addedcalled after an new entity is persisted into DBgood chance to do log/track etc
@OnUpdatecalled before an existing entity is persisted into DBgood place to calculate db properties from derived properties
@Uploadedcalled after an existing entity is persisted into DBgood place to do log/track etc
@OnDeletecalled before an existing entity is deletednot used usually
@Deletedcalledd after an existing entity is deletedgood place to do log/track etc
@OnBatchDeletecalled before a set of entities (specified by query) is deletedgood place to retrieve set of entity IDs;better to be declared on static method
@BatchDeletedcalled after a set of entities (specified by query) is deletedgood place to do log track;better to be declared on static method

These annotations could be put on methods of your model class. There is no requirement on method visible scope (e.g. private, package, protected, public). Methods shall not return any object. There is shall be no argument declared in annotated methods except @OnBatchDelete and @BatchDeleted. The methods with “batch” annotations must have one argument: play.modules.morphia.Model.MorphiaQuery. It’s recommended that “batch” annotated methods be declared as static methods, all other annotated methods be declared as non-static one, but this is not required.

In addition to the above annotations, PlayMorphia provides two events distribution mechanisms to enable application and/or plugin developers to inject their logic interactive with entity lifecycles. Please refer to Lifecycle events for details

Other fancy stuff

Converters annotation

This feature is only available on PlayMorphia v1.2.8-RC2 and later versions

Morphia provides @com.google.code.morphia.annotations.Converters annotation so that you could implement a customized encode/decode solution for certain objects. A typical use senario is to store Enum value using ordinal() inside mongodb. As shown in the source code, you must annotate the Converters annotation to the enum field declared in the entity class in morphia, meaning if the enum class is used in multiple entity classes, then you need to copy the Converters annotation to every place.

With PlayMorphia you can put the annotation on the Enum class declaration only, all model class with fields references to the Enum class will be automatically annotated by the tool. We just stick to DRY principle as much as we can!

Pure morphia case:

/**
 * the enum type
 */
public enum AEnum {
    One,
    Two;
    /**
     * The converter
     * @see http://code.google.com/p/morphia/source/browse/trunk/morphia/src/test/java/com/google/code/morphia/ext/EnumValueConverterTest.java?r=1801
     *  for detail implementation
     */
   public static class Converter {
        ...  implementation
   }
}
/**
 * A model reference to AEnum
 */
@Converters({AEnum.Converter.class})
@Entity public class AModel {
    ...
    public AEnum foo;
    ...
}
/**
 * Another model reference to AEnum
 */
@Converters({AEnum.Converter.class}) // see we need to repeat the declaration
@Entity public class BModel {
    ...
    public AEnum bar;
    ...
}

PlayMorphia case:

/**
 * the enum type
 */
// annotation goes here and will automatically picked by PlayMorphia and apply to
// entity classes which references to the AEnum type
@Converters({AEnum.Converter.class})
public enum AEnum {
    One,
    Two;
    /**
     * The converter
     * @see http://code.google.com/p/morphia/source/browse/trunk/morphia/src/test/java/com/google/code/morphia/ext/EnumValueConverterTest.java?r=1801
     *  for detail implementation
     */
   public static class Converter {
        ...  implementation
   }
}
/**
 * A model reference to AEnum
 */
@Entity public class AModel extends Model {
    ...
    public AEnum foo;
    ...
}
/**
 * Another model reference to AEnum
 */
@Entity public class BModel extends Model {
    ...
    public AEnum bar;
    ...
}