I'm gonna try to explain at my best.
I use Play Framework 2, and I will do a lot of CRUD actions. Some of them will be identitcal, so I'd like to KISS and DRY so at first I was thinking about an abstract class containing the list
, details
, create
, update
and delete
methods, with generic object, and extend this class by specifying which object to use (Model & Form) :
public abstract class CrudController extends Controller {
protected static Model.Finder<Long, Model> finder = null;
protected static Form<Model> form = null;
public static Result list() {
// some code here
}
public static Result details(Long id) {
// some code here
}
public static Result create() {
// some code here
}
public static Result update(Long id) {
// some code here
}
public static Result delete(Long id) {
// some code here
}
}
And a class that will use CRUD :
public class Cities extends CrudController {
protected static Model.Finder<Long, City> finder = City.find;
protected static Form<City> form = form(City.class);
// I can override a method in order to change it's behavior :
public static Result list() {
// some different code here, like adding some where condition
}
}
This would work if I wasn't in a static context.
But since it's the case, how can I do ?
This can be achieved using delegation: define a regular Java class containing the CRUD actions logic:
public class Crud<T extends Model> {
private final Model.Finder<Long, T> find;
private final Form<T> form;
public Crud(Model.Finder<Long, T> find, Form<T> form) {
this.find = find;
this.form = form;
}
public Result list() {
return ok(Json.toJson(find.all()));
}
public Result create() {
Form<T> createForm = form.bindFromRequest();
if (createForm.hasErrors()) {
return badRequest();
} else {
createForm.get().save();
return ok();
}
}
public Result read(Long id) {
T t = find.byId(id);
if (t == null) {
return notFound();
}
return ok(Json.toJson(t));
}
// … same for update and delete
}
Then you can define a Play controller having a static field containing an instance of Crud<City>
:
public class Cities extends Controller {
public final static Crud<City> crud = new Crud<City>(City.find, form(City.class));
}
And you’re almost done: you just need to define the routes for the Crud actions:
GET / controllers.Cities.crud.list()
POST / controllers.Cities.crud.create()
GET /:id controllers.Cities.crud.read(id: Long)
Note: this example produces JSON responses for brevety but it’s possible to render HTML templates. However, since Play 2 templates are statically typed you’ll need to pass all of them as parameters of the Crud
class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With