We are writing the first project on the Play Framework 2.0

On March 13, the second version of the scala / java framework Play was released. On a habra there was already an overview of new features of Play 2.0 . In the same article, I want to fill the gap in the absence of manuals in Russian for this interesting framework using the example of creating a simple Java application consisting of a list of categories and the vacancies associated with them.

The article is intended for those who are not at all familiar with Play and would like to “feel” it without spending a lot of time.

To work with Play 2.0 you need JDK 6 and above . For my ubuntu 11.10, I installed JDK 7 .

Create a project


1. Download Play 2.0 and unpack to where we have the rights to write and read, I have it /var/www/play20.

2. Go to the directory where you keep the sites and execute the script:

/var/www/play20/play new jobs


We leave the answer to the first question by default, to the second we select "2 - Create a simple Java application". For Windows, everything is similar, only you do not execute a shell script, but .bat.

3. Go to the created project, enter the play console and launch the project:

cd jobs
/var/www/play20/play
run


4. We check that we have succeeded: http: // localhost: 9000 . To start the project on another port, use "run port_number" (quotation marks are required).

5. Now, to start development on Play 2.0, it remains to configure the IDE. We stop the server and return to the console with the CTRL + D command and run eclipsify or idea depending on your development environment. For netbeans, there is no automatic project creation yet.

To connect sorts (it’s convenient to look through the open declaration sources) and javadoc we execute “eclipsify with-source = true” (do not forget about quotes).

6. Open the project, I use Eclipse :File> Import> General> Existing Projects into Workspace .

Category List


Create a category model app / models / Category.java :

package models;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import play.data.validation.*;
import play.db.ebean.Model;
@Entity
public class Category extends Model {
  @Id
  public Long id;
  @Constraints.Required
  public String title;
  public static Finder find = new Finder (
    Long.class, Category.class
  );
  public static List all() {
    return find.all();
  }
}


In the template for the main page views / index.scala.html, we display all categories:

@(categories: List[Category])
@main("Jobs") {
  
    @for(category <- categories) {
  • @category.title
  • }
}


The templates in play 2.0 are html + blocks of Scala code that start with the '@' character. It is also worth noting that the templates are similar to functions and have parameters that are described at the beginning of the file.

In order for autocompletion to work in the eclipse for newly created templates, the project must be run through the tilde: "~ run" , also in the Windows settings - Preferences - General / Workspace uncheck the box "Build automatically", check the boxes "Refresh using native hooks or polling", "Refresh on access. "

We transfer from the application controller app / controllers / Application.java to the template list of categories edited by us above:


import models.Category;
...
public class Application extends Controller {
  public static Result index() {
    return ok(index.render(	Category.all()));
  }
}


For simplicity, we will store the data for starters just in memory, for this we uncomment the lines in conf / application.conf :

db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
...
ebean.default="models.*"


We press F5 in the browser, we will be offered to execute the SQL query. Click on “Apply this script now!” And we should see an empty ul list: we don’t have any categories yet.

Adding Categories


Add the category adding form to the app / views / index.scala.html template :

@(categories: List[Category], categoryForm: Form[Category])
@import helper._
@main("Jobs") {
  
    @for(category <- categories) {
  • @category.title
  • }
@form(routes.Application.add()) { @inputText(categoryForm("title")) } }


In the template, we use functions from helper._ : the form function creates an HTML form with the action and method fields filled in, the inputText function generates text input.

We write the route in conf / routes :


POST    /add                        controllers.Application.add()


We add an action to app / controllers / Application.java that will create a new category using the data received from the form and update the template rendering call in the index action by adding a second parameter (form):

import play.data.Form;
...
public static Result index() {
  return ok(index.render(Category.all(), form(Category.class)));
}
public static Result add() {
  Form filledForm = form(Category.class).bindFromRequest();
  if (filledForm.hasErrors()) {
    return badRequest(index.render(Category.find.all(), filledForm));
  }
  Category category = filledForm.get();
  category.save();
  return redirect(routes.Application.index());
}


We update http: // localhost: 9000 and try to add categories.

At this point, my project broke down. To rebuild everything, exit the console, call / var / www / play20 / play clean-all and restart it.

Jobs


The job model app / models / Job.java, related one-to-many with categories:

package models;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import play.data.validation.*;
import play.db.ebean.Model;
import play.db.ebean.Model.Finder;
@Entity
public class Job extends Model {
  @Id
  public Long id;
  @Constraints.Required
  public String title;
  @ManyToOne
  public Category category;
  public static Finder find = new Finder(Long.class, Job.class);
}


Add feedback to the app / models / Category.java category model :

import javax.persistence.OneToMany;
...
@OneToMany(mappedBy="category")
public List jobs;


Click F5, apply the new SQL.

Now we can create an output template for the views / show.scala.html category with all its vacancies:

@(category: Category, jobForm: Form[Job])
@import helper._
@main("Jobs") {
  

@category.title

Вакансии:

    @for(job <- category.jobs) {
  • @job.title
  • }

Добавить вакансию

@form(routes.Jobs.аdd(category.id)) { @inputText(jobForm("title")) } }


Add the job controller app / controllers / Jobs.java , which allows you to add a new vacancy, leave the vacancy output for later:

package controllers;
import java.util.List;
import play.*;
import play.data.Form;
import play.mvc.*;
import views.html.*;
import models.*;
public class Jobs extends Controller {
  public static Result add(Long categoryId) {
    Form filledForm = form(Job.class).bindFromRequest();
    if (filledForm.hasErrors()) {
      Category category = Category.find.byId(categoryId);
      return badRequest(show.render(category, filledForm));
    }
    Job job = filledForm.get();
    job.category = Category.find.ref(categoryId);
    job.save();
    return redirect(routes.Categories.show(categoryId));
  }
  public static Result show(Long id) {
    return TODO;
  }
}


Refactor categories


It remains to implement the page for displaying the category and all its vacancies, at the same time we will remove the addition of categories from the Application controller.

Create a separate controller for the categories app / controllers / Categories.java :

package controllers;
import java.util.List;
import play.*;
import play.data.Form;
import play.mvc.*;
import views.html.*;
import models.*;
public class Categories extends Controller {
  public static Result add() {
    Form filledForm = form(Category.class).bindFromRequest();
    if (filledForm.hasErrors()) {
      return badRequest(index.render(Category.find.all(), filledForm));
    }
    Category category = filledForm.get();
    category.save();
    return redirect(routes.Application.index());
  }
  public static Result show(Long id) {
    Category category = Category.find.byId(id);
    return ok(show.render(category, form(Job.class)));
  }
}


Do not forget to add routes for adding vacancies, outputting categories and changing the route for adding new categories in conf / routes :

GET     /category/:id               controllers.Categories.show(id: Long)
POST    /category/add               controllers.Categories.add()
POST    /job/add                    controllers.Jobs.add(categoryId: Long)


In the template for the main page views / index.scala.html, we change the parameter of the form function, add links to the categories:

@(categories: List[Category], categoryForm: Form[Category])
@import helper._
@main("Jobs") {
  
  @form(routes.Categories.add()) {
    @inputText(categoryForm("title")) 
    
  }
}


At this step, I rebuilt the project once again with the play clean-all command .

Resources for further exploring Play 2.0:

Also popular now: