[REVIEW] Make controller instantiation customizable
Daniel Zwolenski
zonski at googlemail.com
Tue Dec 13 16:55:18 PST 2011
>
> But I am a little confused. In another email you mentioned the desire to
> not have this association between the FXML file and controller at all (ie:
> the controller loads the right view, not the other way around). But here
> you are advocating for the FXML file to load the correct Controller but use
> a name-based key instead of specifying a class or interface. I guess it is
> fair to say you want to be able to support both?
>
I'm hedging my bets :)
*Here's the crux:*
Currently the fx:controller in the FXML is used for two things:
1. defining the *API/contract* between the Controller and the FXML and
2. providing the *lookup/instantiation* details of the controller
implementation
The ultimate goal would be to move #2 (which breaks decoupling) out of the
FXML (and into a DI factory), while still keeping #1 (which gives us nice
tool support).
I personally could work with one of two options:
1) *Default controller*: No reference to the controller is specified in the
FXML at all. My factory passes the controller instance into the FXMLLoader
when it calls the load method and this controller is used for everything
within the FXML. I lose tooling support but I have decoupled my View and
Controller.
2) *Controller interface*: The FXML references the interface of the
controller only. The implementation is still chosen by my factory and it
passes this into the FXMLLoader. I still have tooling support based on the
interface and have avoided coupling between my view and the controller
implementation.
#2 is nice but FXML will need some changes to its support a Controller
interface (I don't think you can currently specify a @FXML on a method in
an interface that represents a property).
#1 is my best fallback and I admit that I only really want the 'named'
controller because I fully intend to cheat and use this if I don't get a
'default controller'. i.e. I will set my fx:controller to "controller" and
ignore this in the factory just returning the instance the loader told me
to use. Cowboy stuff but given FXML is making me compromise on design
anyway, I don't mind saddling up if I have to ;)
There is still the legitimate classloader issue which I see as a real
concern. I am most definitely going to be using FXML (possibly combined
with Velocity) to create dynamic forms that are not known about at compile
time. I will have a library of these, and some will have custom controllers
that will get loaded dynamically.
> Personally I'm torn: having fx:controller & fx:controller-class (as
> proposed above) solves the cases well enough, but complicates the FXML
> side. Having fx:controller be a String is nice from the "factory" side in
> that you can load when, how, and what you want. But it makes tooling pretty
> much impossible without also adding fx:controller-class (or something like
> it).
>
We could always think outside the box. I still really like my idea of
defining 'parameters' to the FXML file, with an optional type:
<param name="myController" type="com.myorg.MyControllerInterface"/>
<Button text="${myController.title}"
onAction=${myController.doSomeAction}"/>
Then instead of a Controller factory you just have a Lookup thing (possibly
the NameSpace) that resolves 'myController' to a concrete instance. Super
flexible, solves the tooling problem, gives people the option to define
concrete classes or interfaces, they can use one controller or many, they
can define models if they want, whatever. You can call onto sub-FXML by
passing through the relevant parameters too.
I tried putting that one forward before and didn't get any take, so I'm now
just looking for the next best thing - hence the bet hedging :)
More information about the openjfx-dev
mailing list