1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package controllers;
import models.Computer;
import play.data.Form;
import play.data.FormFactory;
import play.libs.concurrent.HttpExecutionContext;
import play.mvc.Controller;
import play.mvc.Result;
import play.mvc.Results;
import repository.CompanyRepository;
import repository.ComputerRepository;
import javax.inject.Inject;
import javax.persistence.PersistenceException;
import java.util.Map;
import java.util.concurrent.CompletionStage;
/**
* Manage a database of computers
*/
public class HomeController extends Controller {
private final ComputerRepository computerRepository;
private final CompanyRepository companyRepository;
private final FormFactory formFactory;
private final HttpExecutionContext httpExecutionContext;
@Inject
public HomeController(FormFactory formFactory,
ComputerRepository computerRepository,
CompanyRepository companyRepository,
HttpExecutionContext httpExecutionContext) {
this.computerRepository = computerRepository;
this.formFactory = formFactory;
this.companyRepository = companyRepository;
this.httpExecutionContext = httpExecutionContext;
}
/**
* This result directly redirect to application home.
*/
private Result GO_HOME = Results.redirect(
routes.HomeController.list(0, "name", "asc", "")
);
/**
* Handle default path requests, redirect to computers list
*/
public Result index() {
return GO_HOME;
}
/**
* Display the paginated list of computers.
*
* @param page Current page number (starts from 0)
* @param sortBy Column to be sorted
* @param order Sort order (either asc or desc)
* @param filter Filter applied on computer names
*/
public CompletionStage<Result> list(int page, String sortBy, String order, String filter) {
// Run a db operation in another thread (using DatabaseExecutionContext)
return computerRepository.page(page, 10, sortBy, order, filter).thenApplyAsync(list -> {
// This is the HTTP rendering thread context
return ok(views.html.list.render(list, sortBy, order, filter));
}, httpExecutionContext.current());
}
/**
* Display the 'edit form' of a existing Computer.
*
* @param id Id of the computer to edit
*/
public CompletionStage<Result> edit(Long id) {
// Run a db operation in another thread (using DatabaseExecutionContext)
CompletionStage<Map<String, String>> companiesFuture = companyRepository.options();
// Run the lookup also in another thread, then combine the results:
return computerRepository.lookup(id).thenCombineAsync(companiesFuture, (computerOptional, companies) -> {
// This is the HTTP rendering thread context
Computer c = computerOptional.get();
Form<Computer> computerForm = formFactory.form(Computer.class).fill(c);
return ok(views.html.editForm.render(id, computerForm, companies));
}, httpExecutionContext.current());
}
/**
* Handle the 'edit form' submission
*
* @param id Id of the computer to edit
*/
public CompletionStage<Result> update(Long id) throws PersistenceException {
Form<Computer> computerForm = formFactory.form(Computer.class).bindFromRequest();
if (computerForm.hasErrors()) {
// Run companies db operation and then render the failure case
return companyRepository.options().thenApplyAsync(companies -> {
// This is the HTTP rendering thread context
return badRequest(views.html.editForm.render(id, computerForm, companies));
}, httpExecutionContext.current());
} else {
Computer newComputerData = computerForm.get();
// Run update operation and then flash and then redirect
return computerRepository.update(id, newComputerData).thenApplyAsync(data -> {
// This is the HTTP rendering thread context
flash("success", "Computer " + newComputerData.name + " has been updated");
return GO_HOME;
}, httpExecutionContext.current());
}
}
/**
* Display the 'new computer form'.
*/
public CompletionStage<Result> create() {
Form<Computer> computerForm = formFactory.form(Computer.class);
// Run companies db operation and then render the form
return companyRepository.options().thenApplyAsync((Map<String, String> companies) -> {
// This is the HTTP rendering thread context
return ok(views.html.createForm.render(computerForm, companies));
}, httpExecutionContext.current());
}
/**
* Handle the 'new computer form' submission
*/
public CompletionStage<Result> save() {
Form<Computer> computerForm = formFactory.form(Computer.class).bindFromRequest();
if (computerForm.hasErrors()) {
// Run companies db operation and then render the form
return companyRepository.options().thenApplyAsync(companies -> {
// This is the HTTP rendering thread context
return badRequest(views.html.createForm.render(computerForm, companies));
}, httpExecutionContext.current());
}
Computer computer = computerForm.get();
// Run insert db operation, then redirect
return computerRepository.insert(computer).thenApplyAsync(data -> {
// This is the HTTP rendering thread context
flash("success", "Computer " + computer.name + " has been created");
return GO_HOME;
}, httpExecutionContext.current());
}
/**
* Handle computer deletion
*/
public CompletionStage<Result> delete(Long id) {
// Run delete db operation, then redirect
return computerRepository.delete(id).thenApplyAsync(v -> {
// This is the HTTP rendering thread context
flash("success", "Computer has been deleted");
return GO_HOME;
}, httpExecutionContext.current());
}
}