How to use generic class with specific objects in a static context?
inheritance, java, playframework-2.0, static
Solution
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.
Problem
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 ?