YAML
YAML syntax
Your application tests will often use data structures that consist of related model objects, which can be tedious to create programmatically in Java. Play includes a YAML parser which makes the task much simpler.
Create a YAML file like the following, in the conf
directory.
City(capitalfederal):
name: Capital Federal
state: Buenos Aires
User(john):
name: "John Smith"
email: [email protected]
lang: es
created: 2007-01-01
User(frank):
name: "Frank Franken"
email: [email protected]
lang: en
created: 2007-08-05
Neighborhood(villalugano):
name: Villa Lugano
city: capitalfederal
tags: "shopping, cafes"
users: [john, frank]
Neighborhood(coghlan):
name: Coghlan
city: capitalfederal
tags: "cafes, bars"
users: [john]
Play’s YAML syntax varies slightly from the standard. Each stanza must start with the name of the model class (eg Neighborhood
) and be followed by an identifier in brackets (eg villalugano
), which you can use to reference the object elsewhere in the file. This is different to standard YAML syntax, which uses the ampersand character to indicate a reference.
Play uses SnakeYAML, which has an excellent documentation page with many examples.
Model classes
The YAML file can contain one-to-many, many-to-one and many-to-many relationships. These relationships must be explicity annotated in the model classes, and you must indicate which is the “owning side” of the relationship.
City.java
package models;
import java.util.List;
import javax.persistence.*;
import play.db.jpa.Model;
@Entity
public class City extends Model {
public String name;
public String state;
// bi-directional one-to-many, inverse side
@OneToMany(mappedBy = "city", cascade = CascadeType.ALL)
public List<Neighborhood> neighborhoods;
}
Neighborhood.java
package models;
import java.util.List;
import javax.persistence.*;
import play.db.jpa.Model;
@Entity
public class Neighborhood extends Model {
public String name;
// bi-directional one-to-many, owning side
@ManyToOne
public City city;
public String tags;
// owning side
@ManyToMany
public List<User> users;
}
User.java
package models;
import java.util.*;
import javax.persistence.*;
import play.db.jpa.Model;
@Entity
//@Table(name = "`user`")
public class User extends Model {
public String name;
public String email;
public String lang;
public Date created;
// inverse side of the relation
@ManyToMany(mappedBy = "users")
public List<Neighborhood> neighborhoods;
}
Note that if you are using PostgreSQL you may need to explicitly set the name of the user
table with escape characters because user
is a reserved word.
Loading the data structure in your application
Typically you will load the data structure defined in the YAML file as part of a unit test. But sometimes you may wish to populate the database with specific data in other circumstances, for example when your application starts for the first time.
import play.*;
import play.jobs.*;
import play.test.*;
import models.*;
@OnApplicationStart
public class Bootstrap extends Job {
public void doJob() {
// Check if the database is empty
if(User.count() == 0) {
Fixtures.loadModels("initial-data.yml");
}
}
}
The objects will be created in the database, and you can then access them as you would any other model object.
City city = City.all().first();
List<Neighborhood> neighborhoods = city.neighborhoods;