Let's
all day

Anton Sarov
JDay 2014, Lviv
About me
Java and Eclipse RCP developer by day
Play Framework developer by night
@duxanton

Workshop PREREQUIREMENTs
- JDK 8
- Play Framework 2.3.x
- IDE (IntelliJ preferred)
Create a new Play project
$ cd /somewhere/where/you/have/write/permissions
$ activator new ghjm play-javaAnatomy
- app
- conf
- project
- public
- test
Launch the Play Application
$ cd ghjm
$ activator run
go to http://localhost:9000Setting up the IDE
- Select File -> Import Project
- In the window that opens, select the ghjm project and click OK.
- On the next page of the wizard, select 'Import project from external model'
- On the same page choose SBT project and click Next.
- On the next page of the wizard, select additional import options
- Click Finish. OUr goal for today
Create a really cool job portal web application
But with some limitations (due to time pressure, like in real life)
- Job search functionality only
- Simple UI
models, views, CONtrollers
+
Actions & Routes
- Avaje Ebean
- JPA
- JDBC
Working with SQL databases
AVAJE ebean Orm
- uses JPA annotations
- but much simpler
- session less
Creating a model
- extend play.db.ebean.Model
- @Entity class annotation
- create a Model.Finder
- add your business logic
Our User model
package models;
import play.db.ebean.Model;
import javax.persistence.*;
@Entity
public class User extends Model {
public static Finder<Long, User> find = new Finder<>(Long.class, User.class);
@Id
private Long id;
...
}The ROUTES FILE
# Homepage
GET / controllers.Application.index()
# Display a person
GET /persons/:id controllers.Persons.show(id: Long)let's rest
views & templates
- Scala-based template engine
- plain HTML(5)
our index view
views/index.scala.html
<h1>Welcome to GHJM</h1>
<form action="@routes.Application.login()" method="post">
<input type="text" name="username"/>
<input type="submit" value="Login"/>
</form>our dashboard view
@(user: User)
<h1>Welcome @user.getName!</h1>views/dashboard.scala.html
calling webservices
libraryDependencies ++= Seq(
javaWs
)in your build.sbt file:
Promise<WSResponse> responsePromise = WS.url("http://www.jday.com.ua/").get();in your code:
using from your controller:
public static Promise<Result> index() {
return WS.url(someUrl).get().map(response ->
ok(response.asJson().findPath("name").asText())
);
}Webjars
libraryDependencies ++= Seq(
...
javaWs,
...
"org.webjars" % "angularjs" % "1.2.23"
...
)<script src="@routes.Assets.versioned("lib/angularjs/angular.js")"></script>in your views:
in your build.sbt file:
webjars
libraryDependencies ++= Seq(
javaJdbc,
javaEbean,
cache,
javaWs,
"org.webjars" % "angularjs" % "1.2.23",
"org.webjars" % "angular-leaflet-directive" % "0.7.7",
"org.webjars" % "leaflet" % "0.7.3"
)angularjs
-
data binding
-
directives
-
backend
angularjs
@(title: String)(content: Html)
<!DOCTYPE html>
<html ng-app="gitHubJobsMapApp">
...
<body>
<div>
<form ng-controller="Search">
<input type="search" ng-model="query"
placeholder="Enter a search term here"/>
<input type="submit" ng-click="search()" value="Search"/>
<hr>
<h1>All search results for {{query}}!</h1>
</form>
</div>
...
</body>
</html>main.index.scala:
angularjs
@(user: User)
@main(user.getName) {
<div ng-controller="Jobs">
<leaflet width="100%" height="500px" markers="markers"></leaflet>
<ul>
<li ng-repeat="job in jobs">{{job.location}} {{job.coordinates}}</li>
</ul>
</div>
}dashboard.scala.html:
angularjs
var app = angular.module('gitHubJobsMapApp', ["leaflet-directive"]);
app.factory('GHJM', function($http, $timeout) {
var jobsService = {
jobs: [],
query: function (query) {
$http({method: 'GET', url: '/jobs?q='+query}).
success(function (data) {
jobsService.jobs = data;
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
}
};
return jobsService;
});application.js:
angularjs
app.controller('Search', function($scope, $http, $timeout, GHJM) {
$scope.search = function() {
GHJM.query($scope.query);
};
});
app.controller('Jobs', function($scope, $http, $timeout, GHJM) {
$scope.jobs = [];
$scope.markers = [];
$scope.$watch(
// This function returns the value being watched.
function() {
return GHJM.jobs;
},
// This is the change listener, called when the value returned from the above function changes
function(jobs) {
$scope.jobs = jobs;
$scope.markers = jobs.map(function(job) {
return {
lng: job.coordinates.lng,
lat: job.coordinates.lat,
message: '<a href=\"'+job.url+'\">'+job.title+'</a>',
focus: true,
draggable: true
}
});
}
);
});application.js:
demo
Play Framework
next steps:
-
visit www.playframework.com
-
Work further on this demo project
-
Help translate the documentation: see github.com/antonsarov/translation-project
Thank you
Now ask all the questions :)
Let's Play all day
By duxanton
Let's Play all day
Presentation for the Play Framework workshop at the JDay 2014 conference in Lviv
- 849