[2.3]Can a class extending Controller have a member attribute extending Controller

64 views
Skip to first unread message

Guillaume Bersac

unread,
Jul 17, 2014, 12:12:45 PM7/17/14
to play-fr...@googlegroups.com
Hi,

I am trying to implement the code describe here. The idea is to mutualize code by creating generic instance of a class within a controller.

So we have a Controller class which have an attribute extending Controller itself. That seems to be confusing for play because I receive the following error message :
ParentClass is already defined as object ParentClass
ParentClass being the class which contain a static instance of the class Crud.


Can a Controller have a controller instance attribute ?
Do you have a better idea to mutualize code for actions (ie: static functions which return a Result instance) ?

Julien Richard-Foy

unread,
Jul 18, 2014, 2:19:25 AM7/18/14
to play-fr...@googlegroups.com
Hi, what you want to achieve is not clear to me. Can you share your code?

Julien
--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Guillaume Bersac

unread,
Jul 18, 2014, 4:10:00 AM7/18/14
to play-fr...@googlegroups.com
Sure,

This is for the crud pages. They all have the same functions : listAll, newForm, updateForm...and everythings like that for every table of my database. The code of all this functions is almost the same, except that it is type specific. The idea is to code those functions once and make it generic so that I minimise code copy/past. The problem is, you can't make generic static function. One of the workaround explain here is to create non static functions in a generic class and instantiate it statically in a controller.

Here is a code example. First my crud class :
public class CrudController<Mdl extends Model>extends Controller
{
   
private final Model.Finder<String, Mdl>    find;
   
private final Form<Mdl>                    form;

   
public CrudController(Model.Finder<String, Mdl> find, Form<Mdl> form)
   
{
       
this.find = find;
       
this.form = form;
   
}

   
public Result create()
   
{
       
Form<Mdl> createForm = form.bindFromRequest();
       
if (createForm.hasErrors()) {
            createForm
.get().save();
            return badrequest("Error.");
       
}
        return ok("it's great !");
   
}
    [...]
}

Now I create a static instance of that class in a Controller class :

public class Application extends Controller
{
    public final static crud.CrudController<Company> crud = new
        crud.CrudController<Company>(Company.find, Form.form(Company.class));
    [...]
}

So that I could create the following route in my conf/routes file :
GET    /test/        controllers.Application.crud.create()

Because the generic class has play actions (functions which return a Result), this class must extend Controller. The problem is, when a class extending Controller have a member attribute extending Controller itself, I get the following error message :

ParentClass is already defined as object ParentClass

How to solve this error ?
Another question : How could I mutualize action code (this question should have its own thread) ?

Julien Richard-Foy

unread,
Jul 18, 2014, 4:24:09 AM7/18/14
to play-fr...@googlegroups.com
The problem is, when a class extending Controller have a member attribute extending Controller itself, I get the following error message :

ParentClass is already defined as object ParentClass

​Can you give the complete compilation output?

Guillaume Bersac

unread,
Jul 18, 2014, 4:30:23 AM7/18/14
to play-fr...@googlegroups.com
Here is the complete error output:

[info] Compiling 19 Scala sources and 23 Java sources to /home/thinkeo/appliGestion/rendu/target/scala-2.11/classes...
[error] /home/thinkeo/appliGestion/rendu/conf/routes: Application is already defined as object Application
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 0 s, completed Jul 18, 2014 10:29:14 AM

Guillaume Bersac

unread,
Jul 18, 2014, 4:31:49 AM7/18/14
to play-fr...@googlegroups.com
I should have mention that the error pop when I define the route :
GET    /test/        controllers.Application.crud.create()

If I don't there is no error.

Julien Richard-Foy

unread,
Jul 18, 2014, 4:56:22 AM7/18/14
to play-fr...@googlegroups.com
I think that, unfortunately, the routes compiler has evolved since the SO question has been answered, and it is now more strict: it only supports actions as static methods of the controller class [1]. You can not anymore use delegation, as in the SO answer.

So you probably have to implement the delegation for each action, as proposed in the second SO answer.

An alternative could be to use inheritance instead of delegation: keep the CrudController class as it currently is. Define Application as a class extending CrudController<Company> (don’t use a crud static field achieving delegation). Define a no-arg constructor calling the super-constructor appropriately. Use a “dynamic” route:

GET   /test/     @controllers.Application.create()

Then the router will instantiate the Application class for you and call its create() method, when the /test/ URL is requested.

You can even have a finer control on the instantiation process, e.g. in order to create one instance and reuse it during the whole application lifecycle, instead of re-creating an instance at each request, by using a dependency injection system (e.g. with JSR 330 you can use the @javax.inject.Singleton annotation to achieve this behavior).

Guillaume Bersac

unread,
Jul 18, 2014, 6:57:40 AM7/18/14
to play-fr...@googlegroups.com
Thanks for the quick answer.

I comment the SO answer to spread the fact that this solution is deprecated.

The alternative solution you are proposing is interesting, but I am rather thinking about using composition action to mutualise my code. I will maybe create a new thread about generic coce mutualisation for action in play 2.3+.
Reply all
Reply to author
Forward
0 new messages