h1. Why PlayMorphia

**"Morphia project":http://code.google.com/p/morphia/** has provided a lightweight and easy way to integrate power of "MongoDB":http://www.mongodb.org/ 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:

h2. <a name="model-class">Define entity model class</a>

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 <code>@ID</code> field in your model class. In addition, the application developer needs to provide a way to ensure the model class is "mapped":http://code.google.com/p/morphia/wiki/MappingObjects.

!images/why-model-class!

h2. <a name="crud-and-query">CRUD and Query</a>

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:

!images/why-model-usage!

h2. <a name="statistics">Statistics</a>

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

_TODO_

h2. <a name="life-cycle">More control on entity lifecycle management</a>

In addition to existing "Morphia lifecycle methods":http://code.google.com/p/morphia/wiki/LifecycleMethods, PlayMorphia provides an new set of lifecycle annotation for application developer to use:

|_. Annotation|_. Description|_. Comment|
|@OnLoad|called before an entity is filled with DB data|not used usually|
|@Loaded|called after an entity is filled with DB data|good place to calculate derived properties, e.g. full name|
|@OnAdd|called before an *new* entity is persisted into DB|good place to calculate db properties from derived properties|
|@Added|called after an *new* entity is persisted into DB|good chance to do log/track etc|
|@OnUpdate|called before an *existing* entity is persisted into DB|good place to calculate db properties from derived properties|
|@Uploaded|called after an *existing* entity is persisted into DB|good place to do log/track etc|
|@OnDelete|called before an *existing* entity is deleted|not used usually|
|@Deleted|calledd after an *existing* entity is deleted|good place to do log/track etc|
|@OnBatchDelete|called before a set of entities (specified by query) is deleted|good place to retrieve set of entity IDs;better to be declared on static method|
|@BatchDeleted|called after a set of entities (specified by query) is deleted|good 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 <code>@OnBatchDelete</code> and <code>@BatchDeleted</code>. 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.

p(note). 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":lifecycle#event for details

h2. Other fancy stuff

h3. <a name="converters">Converters annotation</a>

p(note). 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 <a href="http://code.google.com/p/morphia/source/browse/trunk/morphia/src/test/java/com/google/code/morphia/ext/EnumValueConverterTest.java?r=1801">store Enum value using @ordinal()@ inside mongodb</a>. As shown in the "source code":http://code.google.com/p/morphia/source/browse/trunk/morphia/src/test/java/com/google/code/morphia/ext/EnumValueConverterTest.java?r=1801, 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!

h4. Pure morphia case:

bc. /**
 * 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
   }
}

bc. /**
 * A model reference to AEnum
 */
@Converters({AEnum.Converter.class})
@Entity public class AModel {
    ...
    public AEnum foo;
    ...
}

bc. /**
 * Another model reference to AEnum
 */
@Converters({AEnum.Converter.class}) // see we need to repeat the declaration
@Entity public class BModel {
    ...
    public AEnum bar;
    ...
}

h4. PlayMorphia case:

bc. /**
 * 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
   }
}

bc. /**
 * A model reference to AEnum
 */
@Entity public class AModel extends Model {
    ...
    public AEnum foo;
    ...
}

bc. /**
 * Another model reference to AEnum
 */
@Entity public class BModel extends Model {
    ...
    public AEnum bar;
    ...
}