Community contributed extensions

Play Siena module v2.x

The siena module automatically enables Siena support for your application for GAE/MySQL/PostgreSQL/H2 databases.

Release notes

NEW v2.0.4_work embeds siena-1.0.0-b6 & corrects bug in YAML loading of models with @Id field not named “id” and YAML loading of related entities

NEW v2.0.3 correcting bugs on EnhancedModel functions which were not enhanced at all (findById, getByKey & batch)

Note v1.x only supported GAE but this is not the case anymore. Other NoSQL Databases will be added later.

Note play-siena v2.0.4-SNAPSHOT embeds siena v1.0.0-b6: don’t worry about the beta5, the code is quite stable but there are lots of new features in this version and we need to evaluate them in real environments such as Play!




Enable Siena in your application

Install Siena module

play install siena

Configure your dependencies

In your /conf/dependencies.yml file, enable the Siena module by adding these lines:

require:
    - play -> play [1.2.1,)
    - play -> siena [2.0.0,)
    

With it, we ensure that you have at least Play 1.2.1 and siena 2.0.0.

Run play deps




Configure your database for Siena

Note Configure your database: Siena module simply uses database connectors configured and provided by Play.

Configure GAE database

For GAE, this is really simple as you don’t need anything else but the GAE module in your dependencies.yml

require:
    - play -> play [1.2.1,)
    - play -> siena [2.0.0,)
    - play -> gae 1.4

IMPORTANT Run play deps before running play run or you will have unknown classes error as the dependencies have not been resolved.

IMPORTANT Do not declare any SQL DB configuration in your conf/application.conf as it would prevail on GAE configuration.


Configure SQL database

Here, it uses exactly the configuration of Play so please directly read Play database documentation

Some examples:


#uses embedded H2 in memory provided by Play
db=mem

#uses embedded H2 in file provided by Play 
db=mem    
    
#uses MySQL 
db=mysql:user:pwd@database_name  
    
#uses Postgresql 
db.url=jdbc:postgresql:sienatest
db.driver=org.postgresql.Driver
db.user=sienatest
db.pass=sienatest




Configure SQL database DDL creation/update

In SQL, the database requires tables/indexes to be created according to your models.
Moreover, when you change your model, you would like the tables to be modified also.

Siena Module can do that for you (it uses Apache DDLUtils).

Yet, the behavior in PROD or DEV mode shouldn’t be the same.
In DEV mode, you certainly want the DB to be updated at each modification just by reloading your webpage (or you don’t sometimes).
In PROD mode, you certainly want the DB to be updated only when you want.

To configure Siena DDL, add the siena.ddl parameter to your conf/application.conf. Yet, it’s not mandatory to add it and Siena DDL has a default behavior (see below).

#siena.ddl can take values create/update/none
siena.ddl=create

siena.ddl possible values

siena.ddl can take the following values:

valuedescription
createSiena DDL tries to create the tables corresponding to your models if they don’t exist yet but it doesn’t alter anything if yet existing.
updateSiena DDL tries to upgrade the database to your current model by creating/deleting/altering.
noneSiena DDL doesn’t try to do anything


Siena DDL default behavior

If you don’t configure siena.ddl, here is the default behavior:

modedescription
DEVSiena DDL is by default in update mode and tries to upgrade your database
PRODSiena DDL is by default in none mode and doesn’t try to do anything

Note JPA parameters from your play config are not used at all.

Note Apache DDLUtils has some bugs so the version delivered with Siena module has been patched for a few ones. Moreover, the H2 support is not exactly perfect so some issues might appear. Don’t hesitate to contact me if you have any problem.




Activate Siena Lifecycle Annotations

To configure Siena DDL, add the siena.lifecycle parameter to your conf/application.conf.

#siena.ddl can take values create/update/none
siena.lifecycle=true

By default, Siena lifecycle annotations are NOT managed so you shall explicitly set the configuration to trigger it on

Note For more info on lifecycle annotations, go to Lifecycle Siena Doc




Using siena

For more informations check at the Siena documentation page.
p(note). Note This documentation is no more up to date as Siena has been deeply enhanced for v1.0.0 and we are going to write much more docs very soon. Meanwhile, here are a few information to begin.

Important remarks

A classical Siena model with auto-generated Long ID

@Table("employees")
public class Employee extends Model {
        
        @Id(Generator.AUTO_INCREMENT)
        public Long id;
        
        @Column("first_name")
        @Max(10) @NotNull
        public String firstName;
                
        @Column("last_name")
        @Max(200) @NotNull
        public String lastName;
        
        @Password
        @Column("pwd")
        public String pwd;
        
        @Column("contact_info")
        public Json contactInfo;       
        
        @Column("hire_date")
        public Date hireDate;
        
        @Column("fire_date")
        @DateTime
        public Date fireDate;
        
        @Column("boss") @Index("boss_index")
        public Employee boss;
        
        @Filter("boss")
        public siena.Query<Employee> employees;
               
        @Embedded
        public Image profileImage;
        
        @Embedded
        public List<Image> otherImages;

        @Embedded
        public Map<String, Image> stillImages;
        
        @EmbeddedMap
        public class Image {
                public String filename;
                public String title;
                public int views;
                public MyEnum itemEnum;
        }
              
        @Embedded
        public List<UserBlabla> items;
        
        @EmbeddedList
        public class UserBlabla {
          @At(0) public String item;
          @At(1) public String item2;
          @At(2) public MyEnum itemEnum;
        }
        
        public MyEnum enumField;
        
        public static enum MyEnum{
        	VAL1,
        	VAL2,
        	VAL3
        };
        
        public String toString() {
        	return firstName + " " + lastName;
        }

        public static Query<Employee> all() {
        	return Model.all(Employee.class);
        }
}


A classical Siena model with manual String ID

Remark the Generator.NONE to tell this is a manual ID

@Table("manual_string_models")
public class ManualStringModel extends Model{
    @Id(Generator.NONE)
    public String id;
    
    public String 	alpha;
    public short	beta;
    
    public String toString() {
    	return id + " " + alpha + " " + beta;
    }
    
    public static Query<ManualStringModel> all() {
        return Model.all(ManualStringModel.class);
    }
}


A classical Siena model with auto-generated Long ID with a non-“id” name

@Table("otherid_models")
public class OtherIdModel extends EnhancedModel{
    @Id(Generator.AUTO_INCREMENT)
    public Long myId;
    
    public String 	alpha;
    public short	beta;
    
    public String toString() {
    	return myId + " " + alpha + " " + beta;
    }
    
    public static Query<OtherIdModel> all() {
        return Model.all(OtherIdModel.class);
    }
}


A classical Siena model with UUID String ID

Remark the Generator.UUID to tell this is a UUID ID

@Table("uuid_models")
public class UUIDModel extends EnhancedModel{
    @Id(Generator.UUID)
    public String id;
    
    public String 	alpha;
    public short	beta;
    
    public String toString() {
    	return id + " " + alpha + " " + beta;
    }
    
    public static Query<UUIDModel> all() {
        return Model.all(UUIDModel.class);
    }
}

p.

==<br/>==
 

An enhanced Siena model for the lazy people

If like me, you are very lazy and don’t want to write the all() function, Siena module provides a new class called EnhancedModel which uses Play! runtime enhancing mechanism to add this function (and others) to your Siena Model.
I don’t know yet whether this class is useful or not. The future will decide it.

@Table("manual_string_models")
public class ManualStringModel extends EnhancedModel{
    @Id(Generator.NONE)
    public String id;
    
    public String 	alpha;
    public short	beta;
    
    public String toString() {
    	return id + " " + alpha + " " + beta;
    }
}

Then you can call:

ManualStringModel toto = ManualStringModel.all().filter("id", "toto").get();