A small recap so far

classic Classic list List threaded Threaded
16 messages Options
Reply | Threaded
Open this post in threaded view
|

A small recap so far

aalmiray
Administrator
Here's a recap of what we've discussed so far, with some additions to continue related topics.

NOTE: any mentions of `framework` mean an JSR377 implementation, whichever it may be.

NOTE: you'll notice that this message usages a `weird` syntax. As a matter of fact that's asciidoc if you haven't seen it before. We'll use asciidoc to write down the specification so it'll be a good idea to familiarise ourselves with the syntax.

An `application` requires a lifecycle. At the minimum this means having 3 phases: `initialize`, `main` and `shutdown`. With the addition of MVC groups I'd say we'll need a 4th phase between `initialize` and `main` to take care of initialization and configuration of MVC groups. So we're looking at the following in terms of application lifecycle:

[horizontal]
Initialize:: this where the `framework` reads the configuration and setups whatever internals are needed to support the application, such as the resource handler/injector, JSR330 injector, and more.
Startup:: MVC groups are initialized during this phase. An application may have many types of mvc groups but only a few are initialized at this time. Applications must have at least 1 MCV group: the main one. This is the time where the `framework` reads previously persisted state and configures the running state.
Main:: this phase is where the application spends most of its time.
Shutdown:: here's the chance for the `framework` to close resources, persist state, etc.

The application interface (yet to be named by this spec) will define methods to handle each phase change (like JavaFX's Application class) does with start/init/shutdown.

So what are MVC groups? Basically a container/aggregator of 3 MVC members: Model, View and Controller. MVC groups have an unique identifier and are instantiated given their respective configuration, that is, the `main` MVC group is identified as such because the configuration states the following

[source,json]
----
mvcgroups = {
    main = {
        model      = 'org.example.MainModel',
        view       = 'org.example.MainView',
        controller = 'org.example.MainController'
    }
}
----

The previous configuration uses JSON as an example; the framework has the option to choose for any format it makes sense, be it XML, properties file, Java based, Groovy based, YAML or something else. As a matter of fact this is one of the areas where the (failed) JavaConfig JSR would help a lot. Frameworks may rely on link:http://tamaya.incubator.apache.org/[Apache Tamaya] for configuration. Bottom line is, whichever the preference for a configuration solution a `framework` may have this JSR should be able to support it, thus this JSR should not push for one way or another, it simply assumes the `framework` knows how to configure itself and the application.
The definition order of each mvc member is important, as the `framework` will invoke lifecycle methods on these members in the same order; in this case the `model` is initialized before the `view` and the `view` is initialized before the `controller`.

The `model` has the responsibility to hold the group's state, be it with simple properties (JavaBeans) or JavaFX bindable properties or whatever is best for the chosen (main) UI toolkit. What's important is that the `model` should have little to no logic unless it's for internal bookkeeping of the group's state. It also should not have a direct relationship with the `view` nor the `controller`.

The `view` defines the UI widgets and all methods that interact directly with UI widgets, for example a method that pops up a FileChooser. The `view` must know the `model`, as it can bind group state (`model` properties) to widget properties. It could also know the `controller` in order to hook behavior (say apply an ActionListener on a JButton, the listener invokes a `controller` method; more exactly an Action wraps a `controller` method, more on that later). The `view~ must be initialized inside the UI thread, whichever it may be; this initialization must be performed synchronously in order to assure that al MVC members are fully initialized and ready.

Finally the `controller` defines the logic for the group. It can refer to the `model` in order to read and alter the group's state. It can also refer to the `view` in order to invoke UI specific methods (such as the one that pops up the FileChooser). Or it *may not* be allowed to have a reference to the `view` and communicate with using events. This allows for a clean separation of responsibilities and lets `controller` and `model` be tested fully without any UI constraints.

The `framework` has the option to instantiate each MVC group using the JSR330 container. If done this way then MVC member can use @PostConstruct and @PreDestroy. Thus these annotations are out of scope of this JSR. Usage of these annotations guarantees that the DI container performs instance initialization once dependencies have been injected. This step is optional and totally unrelated to MVC lifecycle. Once all MVC members of a particular MVC group have been instantiated, their `mvcInit()` lifecycle method is invoke in the order these members were defined (see previous paragraphs). When an MVC group is destroyed the JSR300 container has the choice to invoke methods annotated with @PreDestroy (optional behavior). Destruction of an MVC group invokes the second lifecycle method named `mvcDestroy()`.

All MVC members have a direct relationship with their containing MVC group, that is, they have access to their owning MVC group instance. This will become more important when we discuss MVC group relationships.

Instances of MVC groups may be created at any time during the lifetime of the application. In order to instantiate an MVC group one needs to know it's type (in the previous example it would be `main`). Additional arguments may be specified when an MVC group is instantiated, for example:

[source,groovy]
----
MVCGroup group = createMVCGroup("tab", [tabName: "myTab"])
----

Arguments may be a Map<String,Object>. The example shows the usage of Groovy just because the language has great support for collection literals and because Groovy has excellent integration with Java. If written in Java the code would be more verbose but the effect would be the same. So what happens to these additional arguments? They can be sent to each MVC member through the `mvcInit()` method.

An MVC group instance may be used as a parent for another MVC group instance. Say you have a tabbed editor. Each tab is represented by it's own MVC group. Each tab has a reference to its parent group: the one that defines the tabbed container.

In summary:

 . Applications have a lifecycle with the following phases: Initialize, Startup, Main, Shutdown.
 . MVC groups define Model, View, and Controller members.
 . Each MVC member is initialized in a configurable order.
 . Views are initialized inside the UI thread.
 . MVC members have a well defined lifecycle.
 . JSR 330 container can inject dependencies annotated with @Inject
 . JSR 330 container may invoke methods annotated with @PostConstruct and @PreDestroy at very specific times.
 . Further communication between MVC members can be performed through the Event Bus.

We end up with the following interfaces/classes for the time being

 - javax.application.Application
 - javax.application.ApplicationPhase (enum)
 - javax.application.mvc.MVCGroup
 - javax.applicatiob.mvc.Model
 - javax.applicatiob.mvc.View
 - javax.applicatiob.mvc.Controller

All feedback is welcome.
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

Hendrik Ebbers
aalmiray wrote
The application interface (yet to be named by this spec) will define methods to handle each phase change (like JavaFX's Application class) does with start/init/shutdown.
Is the application instance already managed? Can we use @Inject here?

aalmiray wrote
So what are MVC groups? Basically a container/aggregator of 3 MVC members: Model, View and Controller. MVC groups have an unique identifier and are instantiated given their respective configuration, that is, the `main` MVC group is identified as such because the configuration states the following
About the unique identifier: Is it possible to create a MVC Group without defining the identifier? Will the framework automatically create an identifier in this case?

Will the spec define something like a MVC manager as a central class to load, find or create MVCGroups?

aalmiray wrote
The definition order of each mvc member is important, as the `framework` will invoke lifecycle methods on these members in the same order; in this case the `model` is initialized before the `view` and the `view` is initialized before the `controller`.
What is the benefit of a configurable order? Why don't we specify an Order?

aalmiray wrote
Finally the `controller` defines the logic for the group. It can refer to the `model` in order to read and alter the group's state. It can also refer to the `view` in order to invoke UI specific methods (such as the one that pops up the FileChooser). Or it *may not* be allowed to have a reference to the `view` and communicate with using events. This allows for a clean separation of responsibilities and lets `controller` and `model` be tested fully without any UI constraints.
I think the Controller needs to know the view in some cases. When using presenation models this isn't needed but not all developers will use this pattern. Maybe the view can be injected in the controller.
(View can inject model and Controller)
(Controller can inject model and view)
Introducing @View, @Controller and @Model Annotations?

aalmiray wrote
This step is optional and totally unrelated to MVC lifecycle. Once all MVC members of a particular MVC group have been instantiated, their `mvcInit()` lifecycle method is invoke in the order these members were defined (see previous paragraphs).
About MVCGroup: is this an Interface or an abstract Class? I think that a lot of the lifecycle definition can be defined in an abstract class or default methods.

aalmiray wrote
When an MVC group is destroyed the JSR300 container has the choice to invoke methods annotated with @PreDestroy (optional behavior). Destruction of an MVC group invokes the second lifecycle method named `mvcDestroy()`.
Does the MVCGroup has a destroy() method? How will a destroy be triggered? Will we support Veto events / listeners?

aalmiray wrote
Arguments may be a Map<String,Object>. The example shows the usage of Groovy just because the language has great support for collection literals and because Groovy has excellent integration with Java. If written in Java the code would be more verbose but the effect would be the same. So what happens to these additional arguments? They can be sent to each MVC member through the `mvcInit()` method.
Does the mvcinit() method has a Map param? Do we use a @Param annotation like JAX-RS?


aalmiray wrote
An MVC group instance may be used as a parent for another MVC group instance. Say you have a tabbed editor. Each tab is represented by it's own MVC group. Each tab has a reference to its parent group: the one that defines the tabbed container.
How can the parent be used? getParent() method in view, controller & model? @ParentGroup & Injection?
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

aalmiray
Administrator
Hendrik Ebbers wrote
aalmiray wrote
The application interface (yet to be named by this spec) will define methods to handle each phase change (like JavaFX's Application class) does with start/init/shutdown.
Is the application instance already managed? Can we use @Inject here?
This is a point for debate. I'd say the application instance is not managed, rather its helper classes (mvc manager, resource manager) and mvc members are. IOW, the application instance does not impose the same behavior like JavaFX's application class, that is, you must always extend from it. Related to this, the fact that JavaFX forces
a particular class to be extended (the Application class) is terrible, because it's an UI toolkit, not an application framework.

Hendrik Ebbers wrote
aalmiray wrote
So what are MVC groups? Basically a container/aggregator of 3 MVC members: Model, View and Controller. MVC groups have an unique identifier and are instantiated given their respective configuration, that is, the `main` MVC group is identified as such because the configuration states the following
About the unique identifier: Is it possible to create a MVC Group without defining the identifier? Will the framework automatically create an identifier in this case?

Will the spec define something like a MVC manager as a central class to load, find or create MVCGroups?
Yes, the unique identifier can be computed on the fly by the `framework`. A type must be defined though, otherwise the `framework` would not know what needs to be created. Identifiers can be defined by the developer when they want to keep track of a particular instance. This leads into a very curious problem: how do you deal with identifier clashes?

Also yes, there should be an MVC manager of sorts.

Hendrik Ebbers wrote
aalmiray wrote
The definition order of each mvc member is important, as the `framework` will invoke lifecycle methods on these members in the same order; in this case the `model` is initialized before the `view` and the `view` is initialized before the `controller`.
What is the benefit of a configurable order? Why don't we specify an Order?
This is just an example of how the configuration may be done for a particular `framework`, which may rely on JSON or other external formats. A different framework may use annotations (like @Order which may or may not be supplied by this JSR). The important aspect is that the MVC manager needs a configuration for each MVC group to be instantiated. The order of mvc members informs the MVC manager in which order they must be initialized.

Hendrik Ebbers wrote
aalmiray wrote
Finally the `controller` defines the logic for the group. It can refer to the `model` in order to read and alter the group's state. It can also refer to the `view` in order to invoke UI specific methods (such as the one that pops up the FileChooser). Or it *may not* be allowed to have a reference to the `view` and communicate with using events. This allows for a clean separation of responsibilities and lets `controller` and `model` be tested fully without any UI constraints.
I think the Controller needs to know the view in some cases. When using presenation models this isn't needed but not all developers will use this pattern. Maybe the view can be injected in the controller.
(View can inject model and Controller)
(Controller can inject model and view)
Introducing @View, @Controller and @Model Annotations?
Yes, the `controller` may know the `view` but then testing of controllers would be more difficult as you can not longer isolate it from the UI toolkit. Usage of presentation models makes a lot of sense as they define the group's state. And by presentation model I don't necessarily advocate for "remote" presentation models as provided by OpenDolphin. These models are simple data holders, defining properties with getters and setters; perhaps even some listeners. Once we agree how relationships betwen MVC members must happen we can decide if we use annotations such as @Controller, @Model, @View, @MVCGroup or something else.

Hendrik Ebbers wrote
aalmiray wrote
This step is optional and totally unrelated to MVC lifecycle. Once all MVC members of a particular MVC group have been instantiated, their `mvcInit()` lifecycle method is invoke in the order these members were defined (see previous paragraphs).
About MVCGroup: is this an Interface or an abstract Class? I think that a lot of the lifecycle definition can be defined in an abstract class or default methods.
My gut tells me we should define all base behavior with interfaces first and implement them in the RI. Then we'll figure out if the behavior is so common that abstract classes must be extracted form the RI and moved to the spec.

Hendrik Ebbers wrote
aalmiray wrote
When an MVC group is destroyed the JSR330 container has the choice to invoke methods annotated with @PreDestroy (optional behavior). Destruction of an MVC group invokes the second lifecycle method named `mvcDestroy()`.
Does the MVCGroup has a destroy() method? How will a destroy be triggered? Will we support Veto events / listeners?
Yes, it should have such method. The destroy can be triggered in at least two cases:
 - explicitly when a reference to an MVC group is had and the code calls `destroy()` directly. This may be the case when a parent group wnats to dispose of all of its children groups.
 - automatically at shutdown. The MVC manager keeps track of all instantiated MVC groups. During the Shutdown application phase the MVC manager invokes `destroy()` on all remaining MVC groups.

Hendrik Ebbers wrote
aalmiray wrote
Arguments may be a Map<String,Object>. The example shows the usage of Groovy just because the language has great support for collection literals and because Groovy has excellent integration with Java. If written in Java the code would be more verbose but the effect would be the same. So what happens to these additional arguments? They can be sent to each MVC member through the `mvcInit()` method.
Does the mvcinit() method has a Map param? Do we use a @Param annotation like JAX-RS?
Yes! We send the Map as a parameter to the `mvcInit()` method. No need to go overboard with annotations.

Hendrik Ebbers wrote
aalmiray wrote
An MVC group instance may be used as a parent for another MVC group instance. Say you have a tabbed editor. Each tab is represented by it's own MVC group. Each tab has a reference to its parent group: the one that defines the tabbed container.
How can the parent be used? getParent() method in view, controller & model? @ParentGroup & Injection?
`view.getGroup().getParentGroup()`. The parent-child relationship between group enables another thing: hierarchical contexts. A context is a container for key/value pairs. They can contain any kind of data the developer may need. A child context can shadow a key from its parent, but this does not alter the value on the parent, that is

[source,groovy]
----
MVCGroup parent = ...
parent.getContext().set("foo", "foo");
MVCGroup child = parent.createMVCGroup("child");
assert child.getParentGroup() == parent;
child.getContext().set("foo", "bar");
assert child.getContext().get("foo") == "bar";
assert parent.getContext().get("foo") == "foo";
----

Eclipse4 sports a very similar feature but they merge the injection context with it. This means you can add new elements at runtime and have them injected with @Inject. While useful in theory this brings trouble in practice (they have to define an @Optional annotation to avoid failed injections at specific times due to null values). I think keeping the injection context separate from hierarchical contexts would be good. The injection context is used `once` during the initialization phase; the group context is used at any time by a group and/or its members.

The application can define a root context that's the parent of all group contexts.
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

Sven Reimers
In reply to this post by Hendrik Ebbers
Comments inlined..
On Mon, Mar 23, 2015 at 8:10 AM, Hendrik Ebbers [via jsr377-api] <[hidden email]> wrote:
aalmiray wrote
The application interface (yet to be named by this spec) will define methods to handle each phase change (like JavaFX's Application class) does with start/init/shutdown.
Is the application instance already managed? Can we use @Inject here?
aalmiray wrote
So what are MVC groups? Basically a container/aggregator of 3 MVC members: Model, View and Controller. MVC groups have an unique identifier and are instantiated given their respective configuration, that is, the `main` MVC group is identified as such because the configuration states the following
About the unique identifier: Is it possible to create a MVC Group without defining the identifier? Will the framework automatically create an identifier in this case?
 
 

Will the spec define something like a MVC manager as a central class to load, find or create MVCGroups?
 

aalmiray wrote
The definition order of each mvc member is important, as the `framework` will invoke lifecycle methods on these members in the same order; in this case the `model` is initialized before the `view` and the `view` is initialized before the `controller`.
What is the benefit of a configurable order? Why don't we specify an Order?
Is there a MVC group hierarchy or shall be MVC groups be flat? 
aalmiray wrote
Finally the `controller` defines the logic for the group. It can refer to the `model` in order to read and alter the group's state. It can also refer to the `view` in order to invoke UI specific methods (such as the one that pops up the FileChooser). Or it *may not* be allowed to have a reference to the `view` and communicate with using events. This allows for a clean separation of responsibilities and lets `controller` and `model` be tested fully without any UI constraints.
I think the Controller needs to know the view in some cases. When using presenation models this isn't needed but not all developers will use this pattern. Maybe the view can be injected in the controller.
(View can inject model and Controller)
(Controller can inject model and view)
Introducing @View, @Controller and @Model Annotations?
Makes sense from point of view. On the other hand I assume the view is not  UI toolkit agnostic (or how will the view delegate to the real UI?) This will make the controller view dependant... Needs more thinking from my side.

aalmiray wrote
This step is optional and totally unrelated to MVC lifecycle. Once all MVC members of a particular MVC group have been instantiated, their `mvcInit()` lifecycle method is invoke in the order these members were defined (see previous paragraphs).
About MVCGroup: is this an Interface or an abstract Class? I think that a lot of the lifecycle definition can be defined in an abstract class or default methods.
Does it represent the model aspect of the MVCGroup or some UI aspects as well? Interface sounds good enough for me.

aalmiray wrote
When an MVC group is destroyed the JSR300 container has the choice to invoke methods annotated with @PreDestroy (optional behavior). Destruction of an MVC group invokes the second lifecycle method named `mvcDestroy()`.
Does the MVCGroup has a destroy() method? How will a destroy be triggered? Will we support Veto events / listeners?
Hmm, destroy vs. remove? Should there be a difference?  
aalmiray wrote
Arguments may be a Map<String,Object>. The example shows the usage of Groovy just because the language has great support for collection literals and because Groovy has excellent integration with Java. If written in Java the code would be more verbose but the effect would be the same. So what happens to these additional arguments? They can be sent to each MVC member through the `mvcInit()` method.
Does the mvcinit() method has a Map param? Do we use a @Param annotation like JAX-RS?


aalmiray wrote
An MVC group instance may be used as a parent for another MVC group instance. Say you have a tabbed editor. Each tab is represented by it's own MVC group. Each tab has a reference to its parent group: the one that defines the tabbed container.
How can the parent be used? getParent() method in view, controller & model? @ParentGroup & Injection?
What about hierarchy changes? Are they supported? How does this fit with injection?
 
Sven
 


If you reply to this email, your message will be added to the discussion below:
http://jsr377-api.40747.n7.nabble.com/A-small-recap-so-far-tp135p136.html
To start a new topic under jsr377-api, email [hidden email]
To unsubscribe from jsr377-api, click here.
NAML



--
Sven Reimers

* Senior Expert Software Architect
* Java Champion
* NetBeans Dream Team Member: http://dreamteam.netbeans.org
* Community Leader  NetBeans: http://community.java.net/netbeans
                              Desktop Java: http://community.java.net/javadesktop
* JUG Leader JUG Bodensee: http://www.jug-bodensee.de
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

Hendrik Ebbers
In reply to this post by aalmiray
aalmiray wrote
This is a point for debate. I'd say the application instance is not managed, rather its helper classes (mvc manager, resource manager) and mvc members are.
mmh, I don't know :) If the application is not managed you can't simply inject the mvc or resource manager. When developing an application you maybe don't need this managers / helper classes. Therefore I would like to provide them as optional features that can be injected (like an EntityManager in JavaEE). This must not mean that you use @Inject. Maybe we define our own annotation for the managers and reuse a Java Configuration annotation (@Property) to inject configuration properties in the application.

aalmiray wrote
IOW, the application instance does not impose the same behavior like JavaFX's application class, that is, you must always extend from it. Related to this, the fact that JavaFX forces
a particular class to be extended (the Application class) is terrible, because it's an UI toolkit, not an application framework.
I think the application should be an interface. therefore you need to implement it. Since there can only be one application class in an application we can use a service loader approach to generate it. Maybe we have an applicationFactory class as a singleton with a method createApplication(). This will find the application implementation and create it. But this will be implementation detail of the default implementation / RI.


aalmiray wrote
This is just an example of how the configuration may be done for a particular `framework`, which may rely on JSON or other external formats. A different framework may use annotations (like @Order which may or may not be supplied by this JSR). The important aspect is that the MVC manager needs a configuration for each MVC group to be instantiated. The order of mvc members informs the MVC manager in which order they must be initialized.
I still don't understand why a configurable order is needed.

aalmiray wrote
Yes, the `controller` may know the `view` but then testing of controllers would be more difficult as you can not longer isolate it from the UI toolkit. Usage of presentation models makes a lot of sense as they define the group's state. And by presentation model I don't necessarily advocate for "remote" presentation models as provided by OpenDolphin. These models are simple data holders, defining properties with getters and setters; perhaps even some listeners. Once we agree how relationships betwen MVC members must happen we can decide if we use annotations such as @Controller, @Model, @View, @MVCGroup or something else.
I'm with you when talking about presentation models. I think the big question is: How open do we want to be? If we will introduce a @MVCGroup annotation this can maybe used in the model. Because the group has access to the view the model can access the view by using the group. This is normally a dependency that you don't want. Currently I don't know if the spec should forbid such handling or if we only define best practices but a developer can do what he wants. <- It's like the runAndWait() discussion...


aalmiray wrote
My gut tells me we should define all base behavior with interfaces first and implement them in the RI. Then we'll figure out if the behavior is so common that abstract classes must be extracted form the RI and moved to the spec.
Sounds like a good plan :)

aalmiray wrote
Yes! We send the Map as a parameter to the `mvcInit()` method. No need to go overboard with annotations.
mmh, this looks a little to low level for me. By doing so you need to define an untyped map (Map<String,?>) or can only handle Strings (Map<String,String>). When using annotations you can define the type of your param directly and don't need to cast:
public void init(@Param("my-start-date-param") Date startDate) {...}

By doing so you can check in the RI if the param is defined and throw a RuntimeException if a needed param for a group is missing.


aalmiray wrote
`view.getGroup().getParentGroup()`. The parent-child relationship between group enables another thing: hierarchical contexts. A context is a container for key/value pairs. They can contain any kind of data the developer may need. A child context can shadow a key from its parent, but this does not alter the value on the parent, that is

[source,groovy]
----
MVCGroup parent = ...
parent.getContext().set("foo", "foo");
MVCGroup child = parent.createMVCGroup("child");
assert child.getParentGroup() == parent;
child.getContext().set("foo", "bar");
assert child.getContext().get("foo") == "bar";
assert parent.getContext().get("foo") == "foo";
----

Eclipse4 sports a very similar feature but they merge the injection context with it. This means you can add new elements at runtime and have them injected with @Inject. While useful in theory this brings trouble in practice (they have to define an @Optional annotation to avoid failed injections at specific times due to null values). I think keeping the injection context separate from hierarchical contexts would be good. The injection context is used `once` during the initialization phase; the group context is used at any time by a group and/or its members.
The structure sound good. Maybe we can define another annotation instead of @Inject. The context params are nothing that should be injected by using dependency injection (no scopes, etc.). I would like something like this:

public class MyGroup {

   @ContextProperty
   private Observable<String> viewTitle;

}

Because the value can change at runtime (getParentGroup.getContext().set("foo", "foo");) we can't simply inject a String. We need something that supports listeners. Therefore an Observable would be perfect (Don't know if java.util.Observable or a special interface.
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

Hendrik Ebbers
In reply to this post by Sven Reimers
Comments inlined..


Sven Reimers wrote
I think it's a great idea to show the comparable classes / interfaces of current UI and RCP Toolkits. Can anybody do the same for Eclipse (and maybe android / iOS).
I like the markForRestart method. Maybe this can be a flag in the shutdown method?

Sven Reimers wrote
Is there a MVC group hierarchy or shall be MVC groups be flat?
I think there should be a hierarchy

Sven Reimers wrote
Makes sense from point of view. On the other hand I assume the view is not
 UI toolkit agnostic (or how will the view delegate to the real UI?) This
will make the controller view dependant... Needs more thinking from my side.
If you define a good presentation model the controller doesn't need to know the view. In this case the controller and model are UI independent. I think the most important issue is to allow and prefer this pattern. If a developer doesn't want to use this approach (for a single view application that only runs on desktop) he should be allowed to access the view from the controller. In this case the controller class will become view and UI Toolkit dependent. And I think that the view will be UI toolkit agnostic. If you have a look at JavaScript toolkits (like Angular) you will always bind methods and data directly in the view: <button title={model.name} onAction="actionMethod()">. I really like this pattern and it would be a good fit for the spec. Currently most Java based UI toolkits use another approach: They inject the UI components in the controller like JavaFX / FXML does by using the @FXML annotation. By doing it this way you will always have UI Toolkit dependent controllers. Sadly the JavaScript approach can't simply coded by using FXML. But for me this is only an implementation detail and at the start you need a view class that loads the FXML and creates the bindings by hand.

Sven Reimers wrote
What about hierarchy changes? Are they supported? How does this fit with
injection?
I think this are 2 different topics. For hierarchy changes it would be perfect if you can register a listener for your parent MVC. Maybe we can define the parent as an observable. When changing the hierarchy your context can change, too. But as long as we can register listeners for the context or a specific context property this will be ok (see my last post for an example)
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

Sven Reimers
Inlined...

On Mon, Mar 23, 2015 at 10:57 AM, Hendrik Ebbers [via jsr377-api] <[hidden email]> wrote:
Comments inlined..


Sven Reimers wrote
I think it's a great idea to show the comparable classes / interfaces of current UI and RCP Toolkits. Can anybody do the same for Eclipse (and maybe android / iOS).
I like the markForRestart method. Maybe this can be a flag in the shutdown method?

In principle yes, but think about the scenario where you want to "flag" that the application shall restart on exit not only exit. Here it make perfect sense to expose the markForRestart as a seperate API. 
Sven Reimers wrote
Is there a MVC group hierarchy or shall be MVC groups be flat?
I think there should be a hierarchy
How will it work? Is that a view (UI) hierarchy? 

Sven Reimers wrote
Makes sense from point of view. On the other hand I assume the view is not
 UI toolkit agnostic (or how will the view delegate to the real UI?) This
will make the controller view dependant... Needs more thinking from my side.
If you define a good presentation model the controller doesn't need to know the view. In this case the controller and model are UI independent. I think the most important issue is to allow and prefer this pattern. If a developer doesn't want to use this approach (for a single view application that only runs on desktop) he should be allowed to access the view from the controller. In this case the controller class will become view and UI Toolkit dependent. And I think that the view will be UI toolkit agnostic.
 
The view will be UI toolkit agnostic? Really so we need another layer of indirection in the view, defining a minimum subset of UI controls / primitives to abstract over UI toolkits? Maybe I am missing something here...
 
If you have a look at JavaScript toolkits (like Angular) you will always bind methods and data directly in the view: <button title={model.name} onAction="actionMethod()">. I really like this pattern and it would be a good fit for the spec. Currently most Java based UI toolkits use another approach: They inject the UI components in the controller like JavaFX / FXML does by using the @FXML annotation. By doing it this way you will always have UI Toolkit dependent controllers. Sadly the JavaScript approach can't simply coded by using FXML. But for me this is only an implementation detail and at the start you need a view class that loads the FXML and creates the bindings by hand.

Sven Reimers wrote
What about hierarchy changes? Are they supported? How does this fit with
injection?
I think this are 2 different topics. For hierarchy changes it would be perfect if you can register a listener for your parent MVC. Maybe we can define the parent as an observable. When changing the hierarchy your context can change, too. But as long as we can register listeners for the context or a specific context property this will be ok (see my last post for an example)
Hmm, so we get Observables injected (at creation time) afterwards we get changes on the Observables? What happens during hierarchy changes?
 
Thanks for clarifying.
 
Sven 



If you reply to this email, your message will be added to the discussion below:
http://jsr377-api.40747.n7.nabble.com/A-small-recap-so-far-tp135p140.html
To start a new topic under jsr377-api, email [hidden email]
To unsubscribe from jsr377-api, click here.
NAML



--
Sven Reimers

* Senior Expert Software Architect
* Java Champion
* NetBeans Dream Team Member: http://dreamteam.netbeans.org
* Community Leader  NetBeans: http://community.java.net/netbeans
                              Desktop Java: http://community.java.net/javadesktop
* JUG Leader JUG Bodensee: http://www.jug-bodensee.de
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

aalmiray
Administrator
In reply to this post by Sven Reimers
Sven Reimers wrote
Comments inlined..
On Mon, Mar 23, 2015 at 8:10 AM, Hendrik Ebbers [via jsr377-api] <
[hidden email]> wrote:

>  aalmiray wrote
> The application interface (yet to be named by this spec) will define
> methods to handle each phase change (like JavaFX's Application class) does
> with start/init/shutdown.
>
> Is the application instance already managed? Can we use @Inject here?
>
Similiar to
http://bits.netbeans.org/8.0/javadoc/org-openide-util/index.html?org/openide/LifecycleManager.html
? See markForRestart... sounds like a good add-on.
Yes, the Application interface could look like that :-)

Sven Reimers wrote
> aalmiray wrote
> So what are MVC groups? Basically a container/aggregator of 3 MVC members:
> Model, View and Controller. MVC groups have an unique identifier and are
> instantiated given their respective configuration, that is, the `main` MVC
> group is identified as such because the configuration states the following
>
> About the unique identifier: Is it possible to create a MVC Group without
> defining the identifier? Will the framework automatically create an
> identifier in this case?


MVC groups are similiar to
http://bits.netbeans.org/8.0/javadoc/org-openide-windows/org/openide/windows/TopComponentGroup.html
?
Perhaps, however MVC groups can define elements at any level. Say you want to build a browser application, there will be a main MVC group (the main window) that holds a statusbar, toolbar and menubar. Then you have multiple instances of the tab MVC group (each one with their unique id but same mvc type). Tabs are not TopComponents, rather their attach themselves to a widget provided by a TopComponent (the main window).

Sven Reimers wrote
> Will the spec define something like a MVC manager as a central class to
> load, find or create MVCGroups?
>
Similiar to
http://bits.netbeans.org/8.0/javadoc/org-openide-windows/org/openide/windows/WindowManager.html
?
Yes, though I was thinking in something closer to https://github.com/griffon/griffon/blob/development/subprojects/griffon-core/src/main/java/griffon/core/mvc/MVCGroupManager.java as it does not define any UI specific behavior like WindowManager does.

Sven Reimers wrote
> aalmiray wrote
> The definition order of each mvc member is important, as the `framework`
> will invoke lifecycle methods on these members in the same order; in this
> case the `model` is initialized before the `view` and the `view` is
> initialized before the `controller`.
>
> What is the benefit of a configurable order? Why don't we specify an
> Order?
>
Is there a MVC group hierarchy or shall be MVC groups be flat?
There must be a hierarchy, starting with the topmost MVC group that defines the main entry point.

Sven Reimers wrote
> aalmiray wrote
> Finally the `controller` defines the logic for the group. It can refer to
> the `model` in order to read and alter the group's state. It can also refer
> to the `view` in order to invoke UI specific methods (such as the one that
> pops up the FileChooser). Or it *may not* be allowed to have a reference to
> the `view` and communicate with using events. This allows for a clean
> separation of responsibilities and lets `controller` and `model` be tested
> fully without any UI constraints.
>
> I think the Controller needs to know the view in some cases. When using
> presenation models this isn't needed but not all developers will use this
> pattern. Maybe the view can be injected in the controller.
> (View can inject model and Controller)
> (Controller can inject model and view)
> Introducing @View, @Controller and @Model Annotations?
>
Makes sense from point of view. On the other hand I assume the view is not
 UI toolkit agnostic (or how will the view delegate to the real UI?) This
will make the controller view dependant... Needs more thinking from my side.
The `view` is indeed *NOT* UI toolkit agnostic. This is the only MVC member that's strictly required to know the UI toolkit because this is the one that interacts with the widgets directly. The `model` uses whatever properties mechanism is available. Bear in mind that although the JavaFX Property and Observable classes are delivered by the jfxrt.jar it does not impose UI specific on them (at least not at the interface level, I know there are CSS related concerns attached to properties).

Sven Reimers wrote
> aalmiray wrote
> This step is optional and totally unrelated to MVC lifecycle. Once all MVC
> members of a particular MVC group have been instantiated, their `mvcInit()`
> lifecycle method is invoke in the order these members were defined (see
> previous paragraphs).
>
> About MVCGroup: is this an Interface or an abstract Class? I think that a
> lot of the lifecycle definition can be defined in an abstract class or
> default methods.
>
Does it represent the model aspect of the MVCGroup or some UI aspects as
well? Interface sounds good enough for me.
The MVCGroup represents the union of 3 elements and their lifecycle.

Sven Reimers wrote
> aalmiray wrote
> When an MVC group is destroyed the JSR300 container has the choice to
> invoke methods annotated with @PreDestroy (optional behavior). Destruction
> of an MVC group invokes the second lifecycle method named `mvcDestroy()`.
>
> Does the MVCGroup has a destroy() method? How will a destroy be triggered?
> Will we support Veto events / listeners?
>
Hmm, destroy vs. remove? Should there be a difference?
Only if we want to be consistent, i.e start/stop, create|init/destroy. Remove does not necessarily imply destruction, does it?

Sven Reimers wrote
> aalmiray wrote
> Arguments may be a Map<String,Object>. The example shows the usage of
> Groovy just because the language has great support for collection literals
> and because Groovy has excellent integration with Java. If written in Java
> the code would be more verbose but the effect would be the same. So what
> happens to these additional arguments? They can be sent to each MVC member
> through the `mvcInit()` method.
>
> Does the mvcinit() method has a Map param? Do we use a @Param annotation
> like JAX-RS?
>
>
> aalmiray wrote
> An MVC group instance may be used as a parent for another MVC group
> instance. Say you have a tabbed editor. Each tab is represented by it's own
> MVC group. Each tab has a reference to its parent group: the one that
> defines the tabbed container.
>
> How can the parent be used? getParent() method in view, controller &
> model? @ParentGroup & Injection?
>
What about hierarchy changes? Are they supported? How does this fit with
injection?
Hmm interesting question. At first glance I'd say there are no hierarchical changes between MVC groups. Although, coming back tot he multi tabbed editor/browser example: what if you had the capability to move one tab from one tabbed pane to another? Does this mean the parent group changes too? I agree there's a parent group in terms of who created the child group, but there's also an owner group in terms of who contains the child. If no hierarchical changes are allowed the creator and the owner are the same. If changes are allowed then the owner takes precedence over the creator (when resolving context key). Once set, the creator cannot be changed however the owner may. If no explicit owner is set then it resolves to the creator. Top level mvc groups (the main group is this example) have no parent/creator/owner but its parent context is the application's.
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

aalmiray
Administrator
In reply to this post by Hendrik Ebbers
Hendrik Ebbers wrote
aalmiray wrote
Yes! We send the Map as a parameter to the `mvcInit()` method. No need to go overboard with annotations.
mmh, this looks a little to low level for me. By doing so you need to define an untyped map (Map<String,?>) or can only handle Strings (Map<String,String>). When using annotations you can define the type of your param directly and don't need to cast:
public void init(@Param("my-start-date-param") Date startDate) {...}

By doing so you can check in the RI if the param is defined and throw a RuntimeException if a needed param for a group is missing.
The problem with @Param is that we force the `framework` to rely on reflection in order to invoke a lifecycle method that is supposed to be well known. Using the Map<String,Object> would be better though I agree in the loss of "type safety" in the arguments. One can always use a TypeConverter / PropertyEditor or explicit cast.

Hendrik Ebbers wrote
aalmiray wrote
`view.getGroup().getParentGroup()`. The parent-child relationship between group enables another thing: hierarchical contexts. A context is a container for key/value pairs. They can contain any kind of data the developer may need. A child context can shadow a key from its parent, but this does not alter the value on the parent, that is

[source,groovy]
----
MVCGroup parent = ...
parent.getContext().set("foo", "foo");
MVCGroup child = parent.createMVCGroup("child");
assert child.getParentGroup() == parent;
child.getContext().set("foo", "bar");
assert child.getContext().get("foo") == "bar";
assert parent.getContext().get("foo") == "foo";
----

Eclipse4 sports a very similar feature but they merge the injection context with it. This means you can add new elements at runtime and have them injected with @Inject. While useful in theory this brings trouble in practice (they have to define an @Optional annotation to avoid failed injections at specific times due to null values). I think keeping the injection context separate from hierarchical contexts would be good. The injection context is used `once` during the initialization phase; the group context is used at any time by a group and/or its members.
The structure sound good. Maybe we can define another annotation instead of @Inject. The context params are nothing that should be injected by using dependency injection (no scopes, etc.). I would like something like this:

public class MyGroup {

   @ContextProperty
   private Observable<String> viewTitle;

}

Because the value can change at runtime (getParentGroup.getContext().set("foo", "foo");) we can't simply inject a String. We need something that supports listeners. Therefore an Observable would be perfect (Don't know if java.util.Observable or a special interface.
Ahh well, perhaps. It only makes sense to inject context values as long as those values come form the parent/application context because the mvc group context is created at the same time as the group itself, so injection *will* fail if the group expects group specific data to be available. Therefore injecting context arguments doesn't seem like a good idea to me. OTOH context arguments are great for actions, or example

[source,java]
----
public class SampleController implements Controller {
    public void mvcInit(Map<String, Object> args) { ... }
    public void mvcDestroy() { ... }

    @Action
    public void login(@Contextual Credentials credentials) {
        ...
    }
}
----

Here the login action requires an argument that should be provided by the group's context. This argument may exists in the group context, or its parent. The `framework` is responsible for locating a suitable instance matching the arguments (the arguments may have qualifiers). A `framework` may treat the context as a proxy to the JSR-330 container: if a context is queried for a key named "credentials" and it does not exist (even all the way up the context chain) then a new value may be instantiated by the DI container, placed under the "credentials" key in the current context and supplied to the action. Roughly this is how the Eclipse4 platform does it (Tom please correct me if I'm wrong). Notice the usage of the @Contextual annotation, this avoids the problem Eclipse4 has with @Inject, where the latter is used for both standard dependency injection and argument injection.

In order for @Contextual to be resolved an action must be invoked by the `framework` using an ActionInterceptor that can enrich the action's arguments.
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

aalmiray
Administrator
In reply to this post by Sven Reimers
Sven Reimers wrote
On Mon, Mar 23, 2015 at 10:57 AM, Hendrik Ebbers [via jsr377-api]
> Sven Reimers wrote
> Similiar to
>
> http://bits.netbeans.org/8.0/javadoc/org-openide-util/index.html?org/openide/LifecycleManager.html
> ? See markForRestart... sounds like a good add-on.
>
> I think it's a great idea to show the comparable classes / interfaces of
> current UI and RCP Toolkits. Can anybody do the same for Eclipse (and maybe
> android / iOS).
> I like the markForRestart method. Maybe this can be a flag in the shutdown
> method?
>
> In principle yes, but think about the scenario where you want to "flag"
that the application shall restart on exit not only exit. Here it make
perfect sense to expose the markForRestart as a seperate API.
As I remember when working with the JDeveloper team, restarting an application can be tricky. NetBeans does a marvelous job at it, it's indeed flawless :-)
Keep in mind that we're targeting embedded Java, where automatically restarting an application may or may not be as important.

Sven Reimers wrote
> Sven Reimers wrote
> Is there a MVC group hierarchy or shall be MVC groups be flat?
>
> I think there should be a hierarchy
>
How will it work? Is that a view (UI) hierarchy?
It's not a UI hierarchy per se. Rather the groups define state hierarchy. The view member of each group defines the relevant UI part. Given that a child view may be aware of its parent/creator/owner (see other message) then it may attach its UI part at the right location.

Sven Reimers wrote
> Sven Reimers wrote
> Makes sense from point of view. On the other hand I assume the view is not
>  UI toolkit agnostic (or how will the view delegate to the real UI?) This
> will make the controller view dependant... Needs more thinking from my
> side.
>
> If you define a good presentation model the controller doesn't need to
> know the view. In this case the controller and model are UI independent. I
> think the most important issue is to allow and prefer this pattern. If a
> developer doesn't want to use this approach (for a single view application
> that only runs on desktop) he should be allowed to access the view from the
> controller. In this case the controller class will become view and UI
> Toolkit dependent. And I think that the view will be UI toolkit agnostic.

The view will be UI toolkit agnostic? Really so we need another layer of
indirection in the view, defining a minimum subset of UI controls /
primitives to abstract over UI toolkits? Maybe I am missing something
here...
Nope, the `view` must not be UI toolkit agnostic. That would lead to endless discussions about property and widget abstractions that we simply can't (and shouldn't) tackle. Let the views be as close to the metal as possible.

Sven Reimers wrote
> If you have a look at JavaScript toolkits (like Angular) you will always
> bind methods and data directly in the view: <button title={model.name}
> onAction="actionMethod()">. I really like this pattern and it would be a
> good fit for the spec. Currently most Java based UI toolkits use another
> approach: They inject the UI components in the controller like JavaFX /
> FXML does by using the @FXML annotation. By doing it this way you will
> always have UI Toolkit dependent controllers. Sadly the JavaScript approach
> can't simply coded by using FXML. But for me this is only an implementation
> detail and at the start you need a view class that loads the FXML and
> creates the bindings by hand.
>
> Sven Reimers wrote
> What about hierarchy changes? Are they supported? How does this fit with
> injection?
>
> I think this are 2 different topics. For hierarchy changes it would be
> perfect if you can register a listener for your parent MVC. Maybe we can
> define the parent as an observable. When changing the hierarchy your
> context can change, too. But as long as we can register listeners for the
> context or a specific context property this will be ok (see my last post
> for an example)
>
Hmm, so we get Observables injected (at creation time) afterwards we get
changes on the Observables? What happens during hierarchy changes?
I think the idea of a parent/creator vs owner group can help here. The first is set/injected at creation time of the child group and cannot be changed. The owner can be changed at any time, thus it may be made observable.
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

Sven Reimers
Thanks for detailing,
 
one thing that sticks out is the question how many hierarchies we will have. As far as I kept record, we had
 
- context
- MVC (model)
- MVC (ui)
 
and maybe
 
- MVC (controller) ???????
 
Not sure how this works out, but I it seems we need to figure out the details here to not confuse the different architectural aspects. I see traps here  if the hierarchy changes is some way, some other parts of the other hierarchies may have to updated to - but who know what?
 
Same goes for owner vs. creator - can the creator be deleted while the created "entity" still exists? What will happen?
 
BTW - What happend to those API's abstracting away i18n for all types of resources (loading them)?
 
Sven

On Mon, Mar 23, 2015 at 1:45 PM, aalmiray [via jsr377-api] <[hidden email]> wrote:
Sven Reimers wrote
On Mon, Mar 23, 2015 at 10:57 AM, Hendrik Ebbers [via jsr377-api]
> Sven Reimers wrote

> Similiar to
>
> http://bits.netbeans.org/8.0/javadoc/org-openide-util/index.html?org/openide/LifecycleManager.html
> ? See markForRestart... sounds like a good add-on.
>
> I think it's a great idea to show the comparable classes / interfaces of
> current UI and RCP Toolkits. Can anybody do the same for Eclipse (and maybe
> android / iOS).
> I like the markForRestart method. Maybe this can be a flag in the shutdown
> method?
>
> In principle yes, but think about the scenario where you want to "flag"
that the application shall restart on exit not only exit. Here it make
perfect sense to expose the markForRestart as a seperate API.
As I remember when working with the JDeveloper team, restarting an application can be tricky. NetBeans does a marvelous job at it, it's indeed flawless :-)
Keep in mind that we're targeting embedded Java, where automatically restarting an application may or may not be as important.

Sven Reimers wrote
> Sven Reimers wrote
> Is there a MVC group hierarchy or shall be MVC groups be flat?
>
> I think there should be a hierarchy
>
How will it work? Is that a view (UI) hierarchy?
It's not a UI hierarchy per se. Rather the groups define state hierarchy. The view member of each group defines the relevant UI part. Given that a child view may be aware of its parent/creator/owner (see other message) then it may attach its UI part at the right location.

Sven Reimers wrote
> Sven Reimers wrote

> Makes sense from point of view. On the other hand I assume the view is not
>  UI toolkit agnostic (or how will the view delegate to the real UI?) This
> will make the controller view dependant... Needs more thinking from my
> side.
>
> If you define a good presentation model the controller doesn't need to
> know the view. In this case the controller and model are UI independent. I
> think the most important issue is to allow and prefer this pattern. If a
> developer doesn't want to use this approach (for a single view application
> that only runs on desktop) he should be allowed to access the view from the
> controller. In this case the controller class will become view and UI
> Toolkit dependent. And I think that the view will be UI toolkit agnostic.

The view will be UI toolkit agnostic? Really so we need another layer of
indirection in the view, defining a minimum subset of UI controls /
primitives to abstract over UI toolkits? Maybe I am missing something
here...
Nope, the `view` must not be UI toolkit agnostic. That would lead to endless discussions about property and widget abstractions that we simply can't (and shouldn't) tackle. Let the views be as close to the metal as possible.

Sven Reimers wrote
> If you have a look at JavaScript toolkits (like Angular) you will always

> bind methods and data directly in the view: <button title={model.name}
> onAction="actionMethod()">. I really like this pattern and it would be a
> good fit for the spec. Currently most Java based UI toolkits use another
> approach: They inject the UI components in the controller like JavaFX /
> FXML does by using the @FXML annotation. By doing it this way you will
> always have UI Toolkit dependent controllers. Sadly the JavaScript approach
> can't simply coded by using FXML. But for me this is only an implementation
> detail and at the start you need a view class that loads the FXML and
> creates the bindings by hand.
>
> Sven Reimers wrote
> What about hierarchy changes? Are they supported? How does this fit with
> injection?
>
> I think this are 2 different topics. For hierarchy changes it would be
> perfect if you can register a listener for your parent MVC. Maybe we can
> define the parent as an observable. When changing the hierarchy your
> context can change, too. But as long as we can register listeners for the
> context or a specific context property this will be ok (see my last post
> for an example)
>
Hmm, so we get Observables injected (at creation time) afterwards we get
changes on the Observables? What happens during hierarchy changes?
I think the idea of a parent/creator vs owner group can help here. The first is set/injected at creation time of the child group and cannot be changed. The owner can be changed at any time, thus it may be made observable.



If you reply to this email, your message will be added to the discussion below:
http://jsr377-api.40747.n7.nabble.com/A-small-recap-so-far-tp135p145.html
To start a new topic under jsr377-api, email [hidden email]
To unsubscribe from jsr377-api, click here.
NAML



--
Sven Reimers

* Senior Expert Software Architect
* Java Champion
* NetBeans Dream Team Member: http://dreamteam.netbeans.org
* Community Leader  NetBeans: http://community.java.net/netbeans
                              Desktop Java: http://community.java.net/javadesktop
* JUG Leader JUG Bodensee: http://www.jug-bodensee.de
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

neugens
In reply to this post by aalmiray
On Sun, 2015-03-22 at 11:08 -0700, aalmiray [via jsr377-api] wrote:

> An `application` requires a lifecycle. At the minimum this means
> having 3 phases: `initialize`, `main` and `shutdown`. With the
> addition of MVC groups I'd say we'll need a 4th phase between
> `initialize` and `main` to take care of initialization and
> configuration of MVC groups.

The relationship between "application" and the various "mvc" is rather
important, so let me try to define this here better at the same time as
the discussion about MVC lifecycle goes on.

Application [Capital A, as in our JavaFX style Application Class] seems
a way to provide some "non essential" hooks inside the life cycle of the
application (the program), which I agree needs to be managed.

However, *everything* in the application is done via MVC triplets, so
the question is, what Application should really contain (from developer
point of view I mean)?

> [horizontal]
> Initialize:: this where the `framework` reads the configuration and
> setups whatever internals are needed to support the application, such
> as the resource handler/injector, JSR330 injector, and more.
> Startup:: MVC groups are initialized during this phase. An application
> may have many types of mvc groups but only a few are initialized at
> this time. Applications must have at least 1 MCV group: the main one.
> This is the time where the `framework` reads previously persisted
> state and configures the running state.

How does the framework know what to retrieve? An application may use a
database to store its settings, or rather the Preference API, or perhaps
need no configuration at all. I think the framework should only offer
the option to restore the saved state (and to restore it) to the app,
not do it directly.

> Main:: this phase is where the application spends most of its time.
> Shutdown:: here's the chance for the `framework` to close resources,
> persist state, etc.
>
> The application interface (yet to be named by this spec) will define
> methods to handle each phase change (like JavaFX's Application class)
> does with start/init/shutdown.

So now let's say we have such interface, those handler methods to be
called at some point of each phase change event (indeed, phase change
are events, I even would expect them to be issued on the event bus
probably, anyway that's for later). Note, programmers (i.e. users of the
377) don't really normally care what the framework does here, other than
to drive the code they can put in each specific method, for them, this
is just structured boilerplate code (our task: make this as clean and
small as possible!).

[source,java]
----
public class Application {

   /**
    * Called <strong>after</strong> the frameworks loads its own
    * initialisation stuff. No MVC have yet been created.
    */
    public void init() {}

   /**
    * The app should retrieve everything that it needed to work, like
    * saved state, etc... However, it should try to execute quickly.
    */
    public void start() {}

   /**
    * Stops the Application, stuff like the app configuration state
    * should be saved at this point.
    * It could go to start again from here if the framework feels
    * like (Android, iOS?), or to destroy().
    */
    public void stop() {}    

   /**
    * Called <strong>before</strong> the frameworks shutdowns,
    * gives the Application a chance to cleanup the last resources.
    * MVC.shutdown() have been already called before this method
    * executes.
    */
    public void destroy() {}
}
----

There are no parameter passed here, but we may decide to pass some sort
of context object etc... if we need so.

I would also like to add another method, to inform when a new MVC
triplet is added to the mix, something like (names made up, this
definitely needs some love):

[source,java]
----
    public void mvcAvailable(MVCDescriptor mvc) {}
----

This would allow the platform to do something with the new mvc. Perhaps,
an even better approach would be to allow the Application to be
registered to MVC lifecycle events, this would make this method
redundant while giving more flexibility.

> So what are MVC groups? Basically a container/aggregator of 3 MVC
> members: Model, View and Controller. MVC groups have an unique
> identifier and are instantiated given their respective configuration,
> that is, the `main` MVC group is identified as such because the
> configuration states the following
>
> [source,json]
> ----
> mvcgroups = {
>     main = {
>         model      = 'org.example.MainModel',
>         view       = 'org.example.MainView',
>         controller = 'org.example.MainController'
>     }
> }
> ----

Seems reasonable to me. This means we can specify the dependency graph
in a configuration file but perhaps we can allow the use of annotations,
and generate that graph ourselves. The drawback is to tie it to the
code, on the other end, most likely the code needs to be aware on the
structure anyway, since I expect 99% of the views - basically all minus
the main one - to really be subviews of some specific view which is
itself a subview of the main view.

BTW, I assume that the main mvc is the one responsible to actually
create the gui application, right?

For instance, the thing would follow as this:

1. Framework creates Application
2. Frameworks invokes Application.start() - no mvc are here yet?
3. exiting start gives control over MVC lifecycle
4. MVC triplets start flowing in, in particular, the main MVC has been
   initialised
5. main MVC starts its lifecycle, the triplet provides hooks for the
   rest of the MVC hierarchy.
6. Each MVC is added to the hierarchy more or less like services in an
   OSGi environment are, they are exposed to their parent MVC (based on
   configuration).

Is that what you have in mind, right?

> The definition order of each mvc member is important, as the
> `framework` will invoke lifecycle methods on these members in the same
> order; in this case the `model` is initialized before the `view` and
> the `view` is initialized before the `controller`.

I don't know, if we need to have an order, we should not let it to be
defined implicitly, it should be made explicit via a property. If this
is missing, we can revert to a default, which I agree is
Model->View->Controller (well, of course! :).

> The `view` defines the UI widgets and all methods that interact
> directly with UI widgets, for example a method that pops up a
> FileChooser. The `view` must know the `model`, as it can bind group
> state (`model` properties) to widget properties. It could also know
> the `controller` in order to hook behavior (say apply an
> ActionListener on a JButton, the listener invokes a `controller`
> method; more exactly an Action wraps a `controller` method, more on
> that later). The `view~ must be initialized inside the UI thread,
> whichever it may be; this initialization must be performed
> synchronously in order to assure that al MVC members are fully
> initialized and ready.

I'm not sure if the view should know the controller. All communication
between controller and view should happens on the event bus.

Also the controller could be optionally aware of the view, in order to
invoke its interface methods directly, but I would suggest to make the
default communication on the event bus again.

That is, a View could specify the method showFileChooser(), and the
controller could invoke that method directly, but the best way to handle
that would be, in my opinion, to fire an event ("hey, somebody here
needs to show a file chooser").

By doing via events, you can signal other part (other controllers)
what's going on ("a controller I know is asking to open a file chooser,
let's log this", or statusBarController: "a controller I know is opening
a file, let's put this info in the status bar", leftPaneFilesController:
"a controller I know is opening a file, let me put a spinning icon next
to it", etc..).

> Finally the `controller` defines the logic for the group. It can refer
> to the `model` in order to read and alter the group's state. It can
> also refer to the `view` in order to invoke UI specific methods (such
> as the one that pops up the FileChooser). Or it *may not* be allowed
> to have a reference to the `view` and communicate with using events.
> This allows for a clean separation of responsibilities and lets
> `controller` and `model` be tested fully without any UI constraints.
>

> Instances of MVC groups may be created at any time during the lifetime
> of the application. In order to instantiate an MVC group one needs to
> know it's type (in the previous example it would be `main`).
> Additional arguments may be specified when an MVC group is
> instantiated, for example:
>
> [source,groovy]
> ----
> MVCGroup group = createMVCGroup("tab", [tabName: "myTab"])
> ----
>
> Arguments may be a Map<String,Object>. The example shows the usage of
> Groovy just because the language has great support for collection
> literals and because Groovy has excellent integration with Java. If
> written in Java the code would be more verbose but the effect would be
> the same. So what happens to these additional arguments? They can be
> sent to each MVC member through the `mvcInit()` method.

Hmm, I need to think more about that. I like the idea in principle.

> In summary:
>
>  . Applications have a lifecycle with the following phases:
> Initialize, Startup, Main, Shutdown.
>  . MVC groups define Model, View, and Controller members.
>  . Each MVC member is initialized in a configurable order.
>  . Views are initialized inside the UI thread.
>  . MVC members have a well defined lifecycle.
>  . JSR 330 container can inject dependencies annotated with @Inject
>  . JSR 330 container may invoke methods annotated with @PostConstruct
> and @PreDestroy at very specific times.
>  . Further communication between MVC members can be performed through
> the Event Bus.
>
> We end up with the following interfaces/classes for the time being
>
>  - javax.application.Application
>  - javax.application.ApplicationPhase (enum)
>  - javax.application.mvc.MVCGroup
>  - javax.applicatiob.mvc.Model
>  - javax.applicatiob.mvc.View
>  - javax.applicatiob.mvc.Controller

Sounds good!

Cheers,
Mario


Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

neugens
In reply to this post by aalmiray
On Mon, 2015-03-23 at 02:13 -0700, aalmiray [via jsr377-api] wrote:
> Yes, the `controller` may know the `view` but then testing of
> controllers would be more difficult as you can not longer isolate it
> from the UI toolkit

If the controller talks to the view via a shared interface, you can
inject any kind of view in the controller, including mockups.

Of course, at some point you still need to explicitly invoke ui related
code on the correct thread, be it by wrapping controllers calls to ui
method in a Platform.invokeonUIThread() or do this in the receiver
method (as first thing in view.doSomething() for instance).

My favorite approach is to do everything over the event bus. The event
bus could be aware of the UI vs non UI communication by knowing the
source of the event the target, and deciding (we mark everything with
either annotations or some form of class hierarchy) so it may do the
right thing.

An of course, all this is can be very optional too, so we could allow
developers to go over their preferences (to be honest though, if
somebody wants to write apps without using the framework layout, they
would better served with other solutions).

What do you think?

Cheers,
Mario


Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

Tom Schindl
In reply to this post by Hendrik Ebbers
Hendrik Ebbers wrote
The structure sound good. Maybe we can define another annotation instead of @Inject. The context params are nothing that should be injected by using dependency injection (no scopes, etc.). I would like something like this:

public class MyGroup {

   @ContextProperty
   private Observable<String> viewTitle;

}

Because the value can change at runtime (getParentGroup.getContext().set("foo", "foo");) we can't simply inject a String. We need something that supports listeners. Therefore an Observable would be perfect (Don't know if java.util.Observable or a special interface.
If you are interest in the change then use a method-injection!
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

Tom Schindl
In reply to this post by aalmiray
aalmiray wrote
[source,groovy]
----
MVCGroup parent = ...
parent.getContext().set("foo", "foo");
MVCGroup child = parent.createMVCGroup("child");
assert child.getParentGroup() == parent;
child.getContext().set("foo", "bar");
assert child.getContext().get("foo") == "bar";
assert parent.getContext().get("foo") == "foo";
----

Eclipse4 sports a very similar feature but they merge the injection context with it. This means you can add new elements at runtime and have them injected with @Inject. While useful in theory this brings trouble in practice (they have to define an @Optional annotation to avoid failed injections at specific times due to null values). I think keeping the injection context separate from hierarchical contexts would be good. The injection context is used `once` during the initialization phase; the group context is used at any time by a group and/or its members.

The application can define a root context that's the parent of all group contexts.
The reason for @Optional is that there are situations where NULL absolutely make sense. I think about eg the current global selection - if there's currently none then this is NULL.

If you use context you also need to think about:
* where in the UI-Hierarchy are they
* what happens if elements move in this hiearchy => you need to reparent
* you need a notion of a Active-Context eg when actions (menu, toolbar, ...) are executed
Reply | Threaded
Open this post in threaded view
|

Re: A small recap so far

Tom Schindl
In reply to this post by Hendrik Ebbers
Hendrik Ebbers wrote
Comments inlined..


Sven Reimers wrote
I think it's a great idea to show the comparable classes / interfaces of current UI and RCP Toolkits. Can anybody do the same for Eclipse (and maybe android / iOS).
I like the markForRestart method. Maybe this can be a flag in the shutdown method?
Eclipse4 does not work with interfaces but annotations https://wiki.eclipse.org/Eclipse4/RCP/Lifecycle beside that all informations about components lifecycle are sent through the EventBus (creating, showing, hiding, destroying - note the there are 4 states!)

Eclipse4-SWT currently has no way of eg vetoing (https://bugs.eclipse.org/bugs/show_bug.cgi?id=398837) but the e4+JavaFX implementation has a way to veto things like closing of a Tab using @PreClose and @PreShow