Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » e(fx)clipse » [Best Practices] UI Strucure & Events
[Best Practices] UI Strucure & Events [message #1096371] Wed, 28 August 2013 09:43 Go to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Sorry for spamming the forum, but since I almost start from zero (again), I'm not sure about the best practices when it comes to JavaFX.

Currently I follow the following approach (not the best thing, I guess):

my_package.ui.Main - primary stage
my_package.ui.RootWindowCreator - the name is speaking
my_package.ui.DeviceWindowCreator - a "sub"-page

my_package.ui.res.bundle - translations
my_package.ui.res.layout - fxgraph & fxml files

Main.java (simplified)
ResourceBundle bundle = ResourceBundle.getBundle("my_package.ui.res.bundle.strings", Locale.getDefault());
RootWindowCreator rootWindow = new RootWindowCreator(primaryStage, bundle);
Scene scene = new Scene(rootWindow.getRootWindow(), DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT);
primaryStage.setScene(scene);
primaryStage.show();


RootWindowCreator.java
public class RootWindowCreator {
	
	private final Stage stage;
	private final BorderPane rootWindow;
	
	private final ResourceBundle bundle;
	
	public Stage getStage() {
		return stage;
	}
	
	public BorderPane getRootWindow() {
		return rootWindow;
	}
	
	public ResourceBundle getBundle() {
		return bundle;
	}
	
	public RootWindowCreator(Stage stage, ResourceBundle bundle) throws IOException {
		this.stage = stage;
		this.bundle = bundle;
		FXMLLoader fxmlLoader = new FXMLLoader();
		fxmlLoader.setResources(bundle);
		this.rootWindow = (BorderPane) fxmlLoader.load(this.getClass().getResource("res/layout/Root.fxml").openStream());
		if (fxmlLoader.getController() instanceof RootController) {
			((RootController) fxmlLoader.getController()).setStage(stage);
		}
		fillNavigation();
	}

	private void fillNavigation() throws IOException {
		
		outer: for (Node node : rootWindow.getChildren()) {
			if (!node.getId().equals("splitPaneBody"))
				continue;
			for (Node childNode : ((SplitPane) node).getItems()) {
				if (!childNode.getId().equals("accordionNavigation"))
					continue;
				Accordion navigation = (Accordion) childNode;
				DevicesWindowCreator devicesWindow = new DevicesWindowCreator(stage, bundle);
				navigation.getPanes().add(devicesWindow.getPane());
				navigation.setExpandedPane(devicesWindow.getPane());
				break outer;
			}
			break;
		}
	}


DeviceWindowCreator.java
Alsmost the same as the the RootWindowCreator.java, but without the Navigation thingy.


And of course there are the *Controller classes. But there is my problem. When I want to trigger an Event, that needs to be consumed by a complete other part of the UI, I have no idea of how to achive this in a clean way.
My best idea would be a central Event Handler. Is there something like this in JavaFX already? Otherwise I would implement it by my self. But it would be a bit ugly, since I would need to hook it to the Controller classes (or implement an internal Event Listener class there and register it on the central Event Handler).

For example: The device window would contain a method to trigger the discovery of the devices and should trigger an Event, that a) shows a progress bar on the root window (it is already there but set to be invisible) and a cancel button. Obviously the windows don't really know each other and there is no such method as #findViewById(String) as Android has - knowing the ID I could try to find the progress bar on the primary stage, that is part of the window creator classes, but not the controller...

I don't simply know, if this is a "good" approach. I want to try have a program with code as clean as possible and without ugly hacks, if there already is a standardized mean of doing something like this.

Thanks four your input and greetings,
Daniel
Re: [Best Practices] UI Strucure & Events [message #1096540 is a reply to message #1096371] Wed, 28 August 2013 14:32 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
I would use an event-bus which apparently is already there for you
because you can use the EventAdmin service from OSGi. You can also make
use of the IEventBroker by adding org.eclipse.e4.ui.services to your
application.

If you are using Eclipse DI you can also make use of the @EventTopic stuff.

Tom

On 28.08.13 11:43, Daniel Zimmermann wrote:
> Sorry for spamming the forum, but since I almost start from zero
> (again), I'm not sure about the best practices when it comes to JavaFX.
>
> Currently I follow the following approach (not the best thing, I guess):
>
> my_package.ui.Main - primary stage
> my_package.ui.RootWindowCreator - the name is speaking
> my_package.ui.DeviceWindowCreator - a "sub"-page
>
> my_package.ui.res.bundle - translations
> my_package.ui.res.layout - fxgraph & fxml files
>
> Main.java (simplified)
>
> ResourceBundle bundle =
> ResourceBundle.getBundle("my_package.ui.res.bundle.strings",
> Locale.getDefault());
> RootWindowCreator rootWindow = new RootWindowCreator(primaryStage, bundle);
> Scene scene = new Scene(rootWindow.getRootWindow(),
> DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT);
> primaryStage.setScene(scene);
> primaryStage.show();
>
>
> RootWindowCreator.java
>
> public class RootWindowCreator {
>
> private final Stage stage;
> private final BorderPane rootWindow;
>
> private final ResourceBundle bundle;
>
> public Stage getStage() {
> return stage;
> }
>
> public BorderPane getRootWindow() {
> return rootWindow;
> }
>
> public ResourceBundle getBundle() {
> return bundle;
> }
>
> public RootWindowCreator(Stage stage, ResourceBundle bundle) throws
> IOException {
> this.stage = stage;
> this.bundle = bundle;
> FXMLLoader fxmlLoader = new FXMLLoader();
> fxmlLoader.setResources(bundle);
> this.rootWindow = (BorderPane)
> fxmlLoader.load(this.getClass().getResource("res/layout/Root.fxml").openStream());
>
> if (fxmlLoader.getController() instanceof RootController) {
> ((RootController) fxmlLoader.getController()).setStage(stage);
> }
> fillNavigation();
> }
>
> private void fillNavigation() throws IOException {
>
> outer: for (Node node : rootWindow.getChildren()) {
> if (!node.getId().equals("splitPaneBody"))
> continue;
> for (Node childNode : ((SplitPane) node).getItems()) {
> if (!childNode.getId().equals("accordionNavigation"))
> continue;
> Accordion navigation = (Accordion) childNode;
> DevicesWindowCreator devicesWindow = new
> DevicesWindowCreator(stage, bundle);
> navigation.getPanes().add(devicesWindow.getPane());
> navigation.setExpandedPane(devicesWindow.getPane());
> break outer;
> }
> break;
> }
> }
>
>
> DeviceWindowCreator.java
>
> Alsmost the same as the the RootWindowCreator.java, but without the
> Navigation thingy.
>
>
> And of course there are the *Controller classes. But there is my
> problem. When I want to trigger an Event, that needs to be consumed by a
> complete other part of the UI, I have no idea of how to achive this in a
> clean way.
> My best idea would be a central Event Handler. Is there something like
> this in JavaFX already? Otherwise I would implement it by my self. But
> it would be a bit ugly, since I would need to hook it to the Controller
> classes (or implement an internal Event Listener class there and
> register it on the central Event Handler).
>
> For example: The device window would contain a method to trigger the
> discovery of the devices and should trigger an Event, that a) shows a
> progress bar on the root window (it is already there but set to be
> invisible) and a cancel button. Obviously the windows don't really know
> each other and there is no such method as #findViewById(String) as
> Android has - knowing the ID I could try to find the progress bar on the
> primary stage, that is part of the window creator classes, but not the
> controller...
>
> I don't simply know, if this is a "good" approach. I want to try have a
> program with code as clean as possible and without ugly hacks, if there
> already is a standardized mean of doing something like this.
>
> Thanks four your input and greetings,
> Daniel
Re: [Best Practices] UI Strucure & Events [message #1097085 is a reply to message #1096540] Thu, 29 August 2013 08:01 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Hi Tom,

this first little program unfortuantly don't rely on OSGi... So no: There is no EventAdmin nor DI. But this more or less confirms me, that I could make use of a simple event dispatching mechanism I implemented (literally) years ago... (At least I've updated it yesterday to make use of generics. Yay!)

For the next project I will definitly use OSGi and then you are absolutly right: I will use this stuff instead of my implementation!

Thank you very much! I will keep all that in mind (as long as possible Wink ).
Daniel

EDIT: Just to clarify myself, why I didn't use OSGi in the fist place. I installed the target platform as you suggested and tried to run the sample application, as the third (?) tutorial suggested, but I couldn't start it because of some unresolved dependency issues, I couldn't figure out. The same happpend to an empty JavaFX-OSGi application, so I quit and started working on a pure JavaFX project.
I didn't wanted to bother everyone with my inability to start it and I have to admit I don't wanted to rely on the asynchronous forum communication. I needed to start and could play hours and hours... Sad

[Updated on: Thu, 29 August 2013 08:06]

Report message to a moderator

Re: [Best Practices] UI Strucure & Events [message #1097093 is a reply to message #1097085] Thu, 29 August 2013 08:18 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
This is weird! Only because you've mentioned the OSGi thing, I tried it just once again - and it works! I have done nothing different than the last time (and yes: I already had the target installed prior the tests)...

Ok, since I'm still in an early phase of the development, I can still switch to OSGi. I only have to re-think my approach. With OSGi I wanted to create a plugin mechanism (no e4, plain old plugin.xml - if this is not deprecated jet!). I want create a simple container application, which is able to load other parts in a navigation like way. And the other parts should be different bundles, different UIs. In short: Plugins.

Do I still benefit from things like Preferences with a plain OSGi-app? Is there still a platform support for loading classes from other bundles, like in the old 3.x versions? Loading classes defined within the other plugin.xml's?

Daniel
Re: [Best Practices] UI Strucure & Events [message #1097094 is a reply to message #1097085] Thu, 29 August 2013 08:17 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
Just in case - we have specialized DI-Support for FXML/FxGraph
controllers so you can get stuff injected there as well.

I'd also look at http://code.google.com/p/simpleeventbus/. You also may
want to look org.eclipse.fx.core.guice which provides DI in an none
OSGi-Env ontop of guice to use for FXML/FXGraph

Tom

On 29.08.13 10:01, Daniel Zimmermann wrote:
> Hi Tom,
>
> this first little program unfortuantly don't rely on OSGi... So no:
> There is no EventAdmin nor DI. But this more or less confirms me, that I
> could make use of a simple event dispatching mechanism I implemented
> (literally) years ago... (At least I've updated it yesterday to make use
> of generics. Yay!)
>
> For the next project I will definitly use OSGi and then you are
> absolutly right: I will use this stuff instead of my implementation!
>
> Thank you very much! I will keep all that in mind (as long as possible
> ;) ).
> Daniel
Re: [Best Practices] UI Strucure & Events [message #1097104 is a reply to message #1097093] Thu, 29 August 2013 08:33 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Hi Tom,

I already saw the Guice package and thought, that i might come in handy.
Have you read my other post following the answer, you just replied on?

Daniel
Re: [Best Practices] UI Strucure & Events [message #1097108 is a reply to message #1097093] Thu, 29 August 2013 08:38 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
On 29.08.13 10:18, Daniel Zimmermann wrote:
> This is weird! Only because you've mentioned the OSGi thing, I tried it
> just once again - and it works! I have done nothing different than the
> last time (and yes: I already had the target installed prior the tests)...
>
> Ok, since I'm still in an early phase of the development, I can still
> switch to OSGi. I only have to re-think my approach. With OSGi I wanted
> to create a plugin mechanism (no e4, plain old plugin.xml - if this is
> not deprecated jet!). I want create a simple container application,

See below - I'd suggest to go with Declarative Services

> which is able to load other parts in a navigation like way. And the
> other parts should be different bundles, different UIs. In short: Plugins.
>
> Do I still benefit from things like Preferences with a plain OSGi-app?

Sure preferences are an equinox concept! The e4 DI stuff can be used
without all the UI stuff. If you want to see things working check out
"org.eclipse.fx.demo.osgi.di". I'd advice you to go with e4 DI + OSGi.

> Is there still a platform support for loading classes from other
> bundles, like in the old 3.x versions? Loading classes defined within
> the other plugin.xml's?

Yes you can but I'm in favor of OSGi-Services which can be registered
using the Declarative Service support from equinox.ds (also used by the
sample app)

Tom

>
> Daniel
Re: [Best Practices] UI Strucure & Events [message #1097176 is a reply to message #1097108] Thu, 29 August 2013 10:28 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
I just had a look at the source code and found a typo... Are you interessted in it? Smile

PrintService#pring(String) - I'm pretty sure, it was intended to be #print(String)

Whatever: I have to admit, that I'm still a bit overwhelmed of e4 (the real thing - using the e4xmi models). It's simply to much information - I have a OOM-Error in my brains...
The simplyfied approach however of this Demo was ok - still a lot of stuff that looks like Magic to me, but otherwise it's ok. I was pleased to find an Activator for a change Wink

My questions would be:
a) Events - via IEventBroker (service)? Is that correct? Is this the way how to trigger events over the border of bundles?
b) Declarative Service - ok so far, I already worked with a small one a year ago - BUT: only with singleton implementations like your PrintServiceImpl
b.1) how should a Plugin-Service be implemented? Interface that returns either a "bundleclass:/" thing or another (instance of a) JavaFX-Pane?
b.2) scaling - how can I get multiple DS implementations, that means multiple plugins via DI? The Demo is using this, as I understand it
@Inject private PrintService service;
the PrintService's interface and implementation are already defined in the OSGI-INF/printservice.xml as fas as I understand it.

Sorry for bothering you with that, but as I mentioned: I still find it a bit overwhelming and try to figure it out somehow...

Daniel
Re: [Best Practices] UI Strucure & Events [message #1097401 is a reply to message #1097176] Thu, 29 August 2013 17:01 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
On 29.08.13 12:28, Daniel Zimmermann wrote:
> I just had a look at the source code and found a typo... Are you
> interessted in it? :)
>
> PrintService#pring(String) - I'm pretty sure, it was intended to be
> #print(String)

Sure file a bugzilla and if possible attach a patch ;-)

>
> Whatever: I have to admit, that I'm still a bit overwhelmed of e4 (the
> real thing - using the e4xmi models). It's simply to much information -
> I have a OOM-Error in my brains...
> The simplyfied approach however of this Demo was ok - still a lot of
> stuff that looks like Magic to me, but otherwise it's ok. I was pleased
> to find an Activator for a change ;)
>
> My questions would be:
> a) Events - via IEventBroker (service)? Is that correct? Is this the way
> how to trigger events over the border of bundles?

Yes.

> b) Declarative Service - ok so far, I already worked with a small one a
> year ago - BUT: only with singleton implementations like your
> PrintServiceImpl
> b.1) how should a Plugin-Service be implemented? Interface that returns
> either a "bundleclass:/" thing or another (instance of a) JavaFX-Pane?


If I'd design such a guy I'd have a service named UIComponent like this:

interface UIComponent {
String getLabel();
Image getIcon();
public void createUI(StackPane parent);
}

And each bundle contributes its UIComponent definitions through the
declarative service

> b.2) scaling - how can I get multiple DS implementations, that means
> multiple plugins via DI? The Demo is using this, as I understand it
> @Inject private PrintService service; the PrintService's interface and
> implementation are already defined in the OSGI-INF/printservice.xml as
> fas as I understand it.
>

@Inject can always only work with one component so you can not make the
DI-Container as of now inject a list of them. To work around this
problem my suggestion is that you create a 2nd singleton component which
collects the UIComponents and contributes this one to the OSGi-Service
registry

class UIComponentCollector {
private Vector<UIComponent> components = new Vector<>();

public void registerComponent(UIComponent c) {
}

public void unregisterComponent(UIComponent c) {
}
}

When contributing this component to the OSGi-Registry you tell him that
it references 0..n UIComponents and the let the system inject you the
UIComponentCollector

Tom
Re: [Best Practices] UI Strucure &amp;amp;amp; Events [message #1097808 is a reply to message #1097401] Fri, 30 August 2013 07:22 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Funny enough, for as long as I'm a developer now, I never needed to do that patching thing Smile
But as I tried it, I recognized it is not difficult at all, so here you can find it:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=416211

About the UIComponent approach: By collecting the UIComponent items, you suggest, that I use the bundle activator (or any place, where I retrieved a BundleContext in the first place ) to implement sth. like this:
public class Activator implements BundleActivator {
	
	private static BundleContext context;
	
	static BundleContext getContext() {
		return context;
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
	 */
	public void start(BundleContext bundleContext) throws Exception {
		Activator.context = bundleContext;
		UIComponentCollector collector = new UIComponentCollectorImpl();
		ServiceReference<UIComponent>[] refs = (ServiceReference<UIComponent>[]) context.getAllServiceReferences(UIComponent.class.getName(), null);
		for (ServiceReference<UIComponent> ref : refs) {
			UIComponent uic = context.getService(ref);
			collector.registerComponent(uic);
		}
		context.registerService(UIComponentCollector.class, collector, null);
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
	 */
	public void stop(BundleContext bundleContext) throws Exception {
		context.ungetService(context.getServiceReference(UIComponentCollector.class));
		Activator.context = null;
	}
}

Is that correct? I'm not perfectly sure if I understood your last sentence correctly...

Greetings,
Daniel

[Updated on: Fri, 30 August 2013 07:23]

Report message to a moderator

Re: [Best Practices] UI Strucure &amp;amp;amp; Events [message #1097860 is a reply to message #1097808] Fri, 30 August 2013 08:57 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Hi Tom,

as my last post suggests I might now understand, what you ment with the service thing. (Maybe you could comment that post.)

But now: I don't know how, but I somehow broke my configuration... Maybe because I imported efxclipse Git repository, I cannot - for an unknown reason - start the OSGi application anymore. When I try to start the application, I get the following error:

!ENTRY org.eclipse.equinox.app 4 0 2013-08-30 10:54:39.801
!MESSAGE javafx/application/Application
!STACK 0
java.lang.NoClassDefFoundError: javafx/application/Application
	at org.eclipse.fx.osgi.util.AbstractJFXApplication.start(AbstractJFXApplication.java:75)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.equinox.internal.app.AnyThreadAppLauncher.run(AnyThreadAppLauncher.java:26)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: javafx.application.Application cannot be found by org.eclipse.fx.osgi.util_0.9.0.201308270602
	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:455)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)
	at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	... 4 more








EDIT: I started another project - same settings (as far as I can see) - and this one works.
So please: ignore this question. Since I need to write everything from scratch, it's not a big deal to have "lost" this project.
But please comment the other post.







Thank you very much!
Daniel

[Updated on: Fri, 30 August 2013 10:41]

Report message to a moderator

Re: [Best Practices] UI Strucure &amp;amp;amp; Events [message #1098003 is a reply to message #1097860] Fri, 30 August 2013 13:06 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
I fiddled around a bit with it and finally understood, what you ment with the 0..n dependency:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" configuration-policy="require" name="UIComponent">
   <implementation class="ch.cnlab.swag.platform.app.service.UIComponentCollectorImpl"/>
   <service>
      <provide interface="ch.cnlab.swag.platform.app.service.UIComponent"/>
   </service>
   <reference bind="registerComponent" cardinality="0..n" interface="ch.cnlab.swag.platform.app.service.UIComponent" name="UIComponentCollector" policy="static" unbind="unregisterComponent"/>
</scr:component>


But I'm unsure, how to propagate this static instance again as another service, I tried this approach (another component definition in the OSGI-INF directory):
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" configuration-policy="optional" name="UIComponentCollector">
   <implementation class="ch.cnlab.swag.platform.app.service.UIComponentCollectorImpl"/>
   <service>
      <provide interface="ch.cnlab.swag.platform.app.service.UIComponentCollector"/>
   </service>
</scr:component>


But this isn't working - no errors/warnings in the log.

The code is more a less a 1:1 copy of yours:
public interface UIComponent {
	String getLabel();
	Image getIcon();	
	public void createUI(StackPane parent);
}

public class UIComponentImpl implements UIComponent {
	@Override public String getLabel() {return "Test";}
	@Override public Image getIcon() {return null;}
	@Override public void createUI(StackPane parent) {}	
}

public interface UIComponentCollector {
	void registerComponent(UIComponent c);
	void unregisterComponent(UIComponent c);	
	Vector<UIComponent> getComponents();
}

public class UIComponentCollectorImpl implements UIComponentCollector {
	private Vector<UIComponent> components = new Vector<>();
	@Override public void registerComponent(UIComponent c) {
		System.err.println("[register component] " + c.getLabel());
		components.add(c);
	}
	@Override public void unregisterComponent(UIComponent c) {
		System.err.println("[unregister component] " + c.getLabel());
		components.remove(c);
	}
	@Override public Vector<UIComponent> getComponents() {return components;}
}


I added created another bundle added the same dependencies as the "platform" would have, followed Lars Vogels example with start level, but the syserrs are never triggered and thus I cannot inject the UIComponentCollector into the main application UI class. Damn.
Re: [Best Practices] UI Strucure &amp;amp;amp; Events [message #1098086 is a reply to message #1098003] Fri, 30 August 2013 15:39 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Ok I somehow did it. I extracted the Service interfaces as Lars Vogel suggested it and put them into theire own bundle. Currently this bundle does have its own small (and useless) consumer, but I will remove that, soon.
Additionally I sorted all the start level (why is this stuff so important, if everyone else in all other cases says: don't touch that!). The "plugins" should most likly be started one start level prior to the platform itself, as far as I can understand it. I have only tryed this with one test plugin, so I need to confirm it first, before I go on...

Anyway thank you Tom! You pushed me into the right direction and to learn it the hard way ist most likly the only way to remeber it for real!

I hope that everything else will work out better than this poor start Wink

Greetings,
Daniel
Re: [Best Practices] UI Strucure &amp;amp;amp;amp; Events [message #1098174 is a reply to message #1098086] Fri, 30 August 2013 18:27 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
Think the time UIComponents are registered should not matter. You should
send out an event when a new component is registered this way you get a
fully dynamic UI where components can come and go ;-)

Tom

On 30.08.13 17:39, Daniel Zimmermann wrote:
> Ok I somehow did it. I extracted the Service interfaces as Lars Vogel
> suggested it and put them into theire own bundle. Currently this bundle
> does have its own small (and useless) consumer, but I will remove that,
> soon.
> Additionally I sorted all the start level (why is this stuff so
> important, if everyone else in all other cases says: don't touch that!).
> The "plugins" should most likly be started one start level prior to the
> platform itself, as far as I can understand it. I have only tryed this
> with one test plugin, so I need to confirm it first, before I go on...
>
> Anyway thank you Tom! You pushed me into the right direction and to
> learn it the hard way ist most likly the only way to remeber it for real!
>
> I hope that everything else will work out better than this poor start ;)
>
> Greetings,
> Daniel
Re: [Best Practices] UI Strucure &amp;amp;amp;amp; Events [message #1098179 is a reply to message #1098174] Fri, 30 August 2013 18:40 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
On 30.08.13 20:27, Tom Schindl wrote:
> Think the time UIComponents are registered should not matter. You should
> send out an event when a new component is registered this way you get a
> fully dynamic UI where components can come and go ;-)
>
> Tom
>
> On 30.08.13 17:39, Daniel Zimmermann wrote:
>> Ok I somehow did it. I extracted the Service interfaces as Lars Vogel
>> suggested it and put them into theire own bundle. Currently this bundle
>> does have its own small (and useless) consumer, but I will remove that,
>> soon.
>> Additionally I sorted all the start level (why is this stuff so
>> important, if everyone else in all other cases says: don't touch that!).
>> The "plugins" should most likly be started one start level prior to the
>> platform itself, as far as I can understand it. I have only tryed this
>> with one test plugin, so I need to confirm it first, before I go on...
>>
>> Anyway thank you Tom! You pushed me into the right direction and to
>> learn it the hard way ist most likly the only way to remeber it for real!
>>
>> I hope that everything else will work out better than this poor start ;)
>>
>> Greetings,
>> Daniel
>

Just to clear how I think it is done:

my.app.bundle:
+ class UIComponentCollector


<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
name="my.app.bundle.UIComponentCollector">
<implementation class="my.app.bundle.UIComponentCollector" />
<service>
<provide interface="my.app.bundle.UIComponentCollector" />
</service>
<reference bind="registerComponent" cardinality="0..n"
interface="my.app.framework.UIComponent" name="UIComponent"
policy="dynamic" unbind="unregisterComponent"/>
</scr:component>

-----------------------------

my.app.framework
+ interface UIComponent

-----------------------------

my.app.c1.bundle
+ class Comp1 implements UIComponent

<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
name="my.app.c1.bundle.Comp1">
<implementation class="my.app.c1.bundle.Comp1" />
<service>
<provide interface="my.app.framework.UIComponent" />
</service>
</scr:component>

-----------------------------

my.app.c2.bundle
+ class Comp2 implements UIComponent


<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
name="my.app.c2.bundle.Comp2">
<implementation class="my.app.c1.bundle.Comp2" />
<service>
<provide interface="my.app.framework.UIComponent" />
</service>
</scr:component>

-----------------------------


public class UIComponentCollector {
private Vector<UIComponent> components = new Vector<>();
@Override public void registerComponent(UIComponent c) {
System.err.println("[register component] " + c.getLabel());
// FIRE EVENT or make components an IObservableList (make sure
to use the correct realm!!!!)
components.add(c);
}
@Override public void unregisterComponent(UIComponent c) {
System.err.println("[unregister component] " + c.getLabel());
components.remove(c);
}
@Override public Vector<UIComponent> getComponents() {return
components;}
}
Re: [Best Practices] UI Strucure &amp;amp;amp;amp; Events [message #1099761 is a reply to message #1098179] Mon, 02 September 2013 07:08 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Hi Tom,

and thanks for all of your advice!
I didn't know that a Service Interface obviously don't need to be a Java Interface that's why there is another interface right now. I guess my DS defintion was kind of mixed up, but when I figured it out, I didn't wanted to post them again. Currently these files look pretty much like yours, with only one exception: The UIComponentCollector is registered as beeing "dynamic" while I used the "static" value. I'm unsure, what de difference between those two in this case is, but I think this is a minor thing...

You are right about the Event mechanism, but right now when I don't specify any start level, new "plugins" are not loaded (at least my simple System.err call don't kick in, which they do, if they were loaded correctly). Could this be an effect of the "dynamic" value?
And I have to admit, that I don't understand, what you mean by making the components an IObservable list and to use a correct realm (I guess this has nothing to to with application server realms).

Nevertheless: I have something to start working with. And I will.

Thanks and greetings,
Daniel

[Updated on: Mon, 02 September 2013 09:50]

Report message to a moderator

Re: [Best Practices] UI Strucure &amp;amp;amp;amp; Events [message #1099891 is a reply to message #1099761] Mon, 02 September 2013 10:56 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Another obstacle has occured Sad

The dependecy injection is not working in every case at the moment.
When I inject the collector into my main application, it is working. If I try this at another place, it's not.
What is the precondition for the DI to work properly?

Greetings,
Daniel

EDIT:

Strike that text! I just was foolish enough to assume, that everything would work miraculously out of the box. I forgot to make use of
ContextInjectionFactory.make(RootWindowCreator.class, context);

in my case. Is there any way - without digging into the depth of the Eclipse dependecy injection mechanism - to supply other classes for DI? Such as the primary stage? Otherwise it's a bit inconvenient to only have the zero-parameter constructor (agaion: in my specific case)...


EDIT2:
I hoped, that my worst problems are gone, but this isn't true unfortunatelly. My UIComponentCollectorImpl reports, that a UIComponent was registered, but when I fetch the UIComponentCollector-Service and try to iterate over the registered Components, there is nothing in the Vector... Can this be an impact of one of the bugs, mentioned on the E4/RCP/DI-Page? http://wiki.eclipse.org/Eclipse4/RCP/Dependency_Injection

[Updated on: Mon, 02 September 2013 12:27]

Report message to a moderator

Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp; Events [message #1099926 is a reply to message #1099891] Mon, 02 September 2013 11:59 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
There's not precondition - if the service is on the OSGi-Service
registry DI will work. Have you specified the bundles to be lazy loaded,
this is must when working on DS.

Tom

On 02.09.13 12:56, Daniel Zimmermann wrote:
> Another obstacle has occured :(
>
> The dependecy injection is not working in every case at the moment.
> When I inject the collector into my main application, it is working. If
> I try this at another place, it's not.
> What is the precondition for the DI to work properly?
>
> Greetings,
> Daniel
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp; Events [message #1099949 is a reply to message #1099926] Mon, 02 September 2013 12:32 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Hi Tom,

yes I did that, but I read about the ContextInjectionFactory - which might be the reason why it didn't work. With the modified code around and using factory it works (see my first EDIT).

But as I mentioned in my second EDIT, there is still the issue, that the "plugin" is getting registered, but it's not present in the injected UIComponentCollector for some reasons unknow to me. I guess this is not a problem of e(fx)clipse, so the question is, how useful it is to question it here at all...

Greetings,
Daniel

PS: I tried it the API-way - in this case I can access the "plugin"...
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp; Events [message #1099974 is a reply to message #1099949] Mon, 02 September 2013 13:16 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
I'm reading your messages through thunderbird so I don't see your edit
but yes without creating instances through CIF you won't get stuff injected.

I'm not sure what you mean by "I can access the plugin", ... - what is
the plugin? I guess you need to share some code somewhere so that I can
take a look what's going wrong.

Tom

On 02.09.13 14:32, Daniel Zimmermann wrote:
> Hi Tom,
>
> yes I did that, but I read about the ContextInjectionFactory - which
> might be the reason why it didn't work. With the modified code around
> and using factory it works (see my first EDIT).
>
> But as I mentioned in my second EDIT, there is still the issue, that the
> "plugin" is getting registered, but it's not present in the injected
> UIComponentCollector for some reasons unknow to me. I guess this is not
> a problem of e(fx)clipse, so the question is, how useful it is to
> question it here at all...
>
> Greetings,
> Daniel
>
> PS: I tried it the API-way - in this case I can access the "plugin"...
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp; Events [message #1100035 is a reply to message #1099974] Mon, 02 September 2013 15:09 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Hi Tom,

the problem was most likly the component.xml - or the fact that I split the stuff you did to two files. Using your file and updating the class names solved that. There is (and already were prior this change) two entries on the console about service references:
!ENTRY org.eclipse.equinox.ds 4 0 2013-09-02 17:03:08.111
!MESSAGE Could not bind a reference of component UIComponent. The reference is: Reference[name = UIComponent, interface = my.service.UIComponent, policy = static, cardinality = 0..n, target = null, bind = registerComponent, unbind = unregisterComponent]

!ENTRY org.eclipse.equinox.ds 4 0 2013-09-02 17:03:08.113
!MESSAGE Could not bind a reference of component UIComponent. The reference is: Reference[name = UIComponent, interface = my.service.UIComponent, policy = static, cardinality = 0..n, target = null, bind = registerComponent, unbind = unregisterComponent]


This is most likly for the problematic references, you solved within that one component.xml, but I don't see the actual problem.

Right now I started with the real work and only have only few remaining bigger tasks:
a) the UIComponent interface and what items I should make available and
b) the Event implementation where I'm still a bit unsure about - but hey - I said the same about DS just a week ago and beside the Dependency Injection, this has at least become a whole lot clearer to me (although I guess I'm still on the beginners side Wink )

Is there any particular tutorial or other page you could recommend for the EventAdmin stuff?

Thanks and have a good evening,
Daniel

PS: I'm on vacation for two days so I wont probably read any updates on this topic, so please excuse, if I'm not reacting very fast!

[Updated on: Mon, 02 September 2013 15:09]

Report message to a moderator

Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp; Events [message #1100078 is a reply to message #1100035] Mon, 02 September 2013 16:32 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
Now that you use DI you can make use if IEventBroker ;-) I also blogged
about EventAdmin some time ago in context of 3.x:

http://tomsondev.bestsolution.at/2011/01/03/enhanced-rcp-how-views-can-communicate/

Tom

On 02.09.13 17:09, Daniel Zimmermann wrote:
> Hi Tom,
>
> the problem was most likly the component.xml - or the fact that I split
> the stuff you did to two files. Using your file and updating the class
> names solved that. There is (and already were prior this change) two
> entries on the console about service references:
> [code]
> !ENTRY org.eclipse.equinox.ds 4 0 2013-09-02 17:03:08.111
> !MESSAGE Could not bind a reference of component UIComponent. The
> reference is: Reference[name = UIComponent, interface =
> my.service.UIComponent, policy = static, cardinality = 0..n, target =
> null, bind = registerComponent, unbind = unregisterComponent]
>
> !ENTRY org.eclipse.equinox.ds 4 0 2013-09-02 17:03:08.113
> !MESSAGE Could not bind a reference of component UIComponent. The
> reference is: Reference[name = UIComponent, interface =
> my.service.UIComponent, policy = static, cardinality = 0..n, target =
> null, bind = registerComponent, unbind = unregisterComponent]
> [code/]
>
> This is most likly for the problematic references, you solved within
> that one component.xml, but I don't see the actual problem.
>
> Right now I started with the real work and only have only few remaining
> bigger tasks:
> a) the UIComponent interface and what items I should make available and
> b) the Event implementation where I'm still a bit unsure about - but hey
> - I said the same about DS just a week ago and beside the Dependency
> Injection, this has at least become a whole lot clearer to me (although
> I guess I'm still on the beginners side ;) )
>
> Is there any particular tutorial or other page you could recommend for
> the EventAdmin stuff?
>
> Thanks and have a good evening,
> Daniel
>
> PS: I'm on vacation for two days so I wont probably read any updates on
> this topic, so please excuse, if I'm not reacting very fast!
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp; Events [message #1101968 is a reply to message #1100078] Thu, 05 September 2013 07:00 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Hi Tom,

looks easy enough for the sender (@Inject EventAdim eventAdmin; - no big deal). But I guess I still need to register the EventHandler instances the "old" way - via the context and #registerService... Am I correct?

Daniel
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp;amp; Events [message #1102014 is a reply to message #1101968] Thu, 05 September 2013 08:26 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
Yes - or like I said use the IEventBroker.

Tom

On 05.09.13 09:00, Daniel Zimmermann wrote:
> Hi Tom,
>
> looks easy enough for the sender (@Inject EventAdim eventAdmin; - no big
> deal). But I guess I still need to register the EventHandler instances
> the "old" way - via the context and #registerService... Am I correct?
>
> Daniel
Re: [Best Practices] UI Strucure &amp;amp;amp;amp; Events [message #1102015 is a reply to message #1097808] Thu, 05 September 2013 08:27 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
On 30.08.13 09:22, Daniel Zimmermann wrote:
> Funny enough, for as long as I'm a developer now, I never needed to do
> that patching thing :)
> But as I tried it, I recognized it is not difficult at all, so here you
> can find it:
>
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=416211
>

Can yoju please sign the CLA - I can't commit your patch without it.

Tom
Re: [Best Practices] UI Strucure &amp;amp;amp;amp; Events [message #1102100 is a reply to message #1102015] Thu, 05 September 2013 11:06 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Done.
Re: [Best Practices] UI Strucure &amp;amp;amp;amp; Events [message #1102120 is a reply to message #1102100] Thu, 05 September 2013 11:44 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
About the IEventBroker: I tried to inject it, but I only raise an exception, when trying...
Caused by: org.eclipse.e4.core.di.InjectionException: Unable to process "RootController.eventBroker": no actual value was found for the argument "IEventBroker".
	at org.eclipse.e4.core.internal.di.InjectorImpl.reportUnresolvedArgument(InjectorImpl.java:412)
	at org.eclipse.e4.core.internal.di.InjectorImpl.resolveRequestorArgs(InjectorImpl.java:403)
	at org.eclipse.e4.core.internal.di.InjectorImpl.inject(InjectorImpl.java:108)
	at org.eclipse.e4.core.internal.di.InjectorImpl.inject(InjectorImpl.java:84)
	at org.eclipse.e4.core.contexts.ContextInjectionFactory.inject(ContextInjectionFactory.java:73)
	at ch.cnlab.swag.platform.app.ui.RootWindowCreator.createWindow(RootWindowCreator.java:74)
	at ch.cnlab.swag.platform.app.MainApplication.run(MainApplication.java:45)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:56)
	... 17 more


As far as I can see, all dependecies (and more) are specified:
 org.eclipse.osgi;bundle-version="3.9.0",
 org.eclipse.osgi.services;bundle-version="3.3.100",
 org.eclipse.equinox.app,
 org.eclipse.equinox.ds;bundle-version="1.4.100",
 org.eclipse.equinox.event;bundle-version="1.3.0",
 org.eclipse.equinox.util;bundle-version="1.0.500",
 org.eclipse.e4.core.contexts;bundle-version="1.3.0",
 org.eclipse.e4.core.di;bundle-version="1.3.0",
 org.eclipse.e4.core.services;bundle-version="1.1.0",
 org.eclipse.fx.javafx,
 org.eclipse.fx.osgi.util,
 org.eclipse.fx.core.databinding,
 org.eclipse.fx.ui.databinding,
 org.eclipse.fx.ui.di,
 org.eclipse.fx.ui.theme;bundle-version="0.9.0"


Can this be a result of problems with some start levels?
Re: [Best Practices] UI Strucure &amp;amp;amp;amp; Events [message #1102147 is a reply to message #1102120] Thu, 05 September 2013 12:27 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
I checked and verified it, that the current IEclipseContext doesn't even know the class. I have the injected eclipse context and used the method #containsKey(Class<?>) to query for both IEventBroker and EventAdmin. While on querying the latter I receive a "true", the first always returns false. So I'm pretty sure, that this is an isse with those damned start levels.
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp; Events [message #1102280 is a reply to message #1102147] Thu, 05 September 2013 15:40 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
IEventBroker is created by a ContextFunction, I don't know from the top
of my head now which bundle holds it.

Tom

On 05.09.13 14:27, Daniel Zimmermann wrote:
> I checked and verified it, that the current IEclipseContext doesn't even
> know the class. I have the injected eclipse context and used the method
> #containsKey(Class<?>) to query for both IEventBroker and EventAdmin.
> While on querying the latter I receive a "true", the first always
> returns false. So I'm pretty sure, that this is an isse with those
> damned start levels.
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp; Events [message #1102876 is a reply to message #1102280] Fri, 06 September 2013 06:43 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
I'm relativly sure that the bundle is org.eclipse.e4.core.contexts, but regardless of my current start levels, it's not working - unfortunatly.
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp; Events [message #1103263 is a reply to message #1102876] Fri, 06 September 2013 14:52 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Maybe it would be a good idea to move this question to a appropriate part of the forum, but I don't know which one that would be... Equinox?
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp; Events [message #1103271 is a reply to message #1103263] Fri, 06 September 2013 15:13 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
Oh yeah now I remember it is org.eclipse.e4.ui.services which might
sound strange and is also because it does not really depend on UI.

I'll file a bug to move it down to e4.core.services but you can for the
time being simply add e4.ui.services and e4.ui.di.

Tom

On 06.09.13 16:52, Daniel Zimmermann wrote:
> Maybe it would be a good idea to move this question to a appropriate
> part of the forum, but I don't know which one that would be... Equinox?
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp; Events [message #1105005 is a reply to message #1103271] Mon, 09 September 2013 08:08 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Hi Tom,

I would like to give you a +1 for that! If it will ever happen, that we meet: I owe you a beer - or two! Wink

Now I can really focus on the rest of my fabulous implemention (*hüstel* mal sehen, was daraus wird...)

Thank you very much!
Daniel

PS: I've also informed Lars Vogel about this - maybe it's a good idea, if his Tutorial would mention this for non-e4-apps as long as the IEventBroker implementation stays within these bundles...
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp; Events [message #1105043 is a reply to message #1105005] Mon, 09 September 2013 09:12 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Ok, now it gets ridiculous: The EventBroker class is injected with a Logger - this one cannot be obtained, so the the injection will fail (the inject IEclipseContext can "see" the broker, but is not able to fetch it - if you try, you get the same error as when you try to inject the broker directly).

The error is sth. like
Caused by: org.eclipse.e4.core.di.InjectionException: Unable to process "EventBroker.logger": no actual value was found for the argument "Logger".


I guess that this can be solved by yet another dependecy, but if it is something like e4.ui.workbench it rather useless, don't you think?
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp; Events [message #1105093 is a reply to message #1105043] Mon, 09 September 2013 10:59 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
Nope - the logger in e4 is injected by the application bootstraping.
IMHO it should be made optional in future. So you need push your own
logger into the root-context.

The whole logging in e4 is one of the major unexplored areas and IMHO
the current log system is likely to be replaced by something completely
different.

Instead of depending on the e4.ui.services it might make sense to copy
the code into your own bundle and remove this freaking logger stuff.

Tom

On 09.09.13 11:12, Daniel Zimmermann wrote:
> Ok, now it gets ridiculous: The EventBroker class is injected with a
> Logger - this one cannot be obtained, so the the injection will fail
> (the inject IEclipseContext can "see" the broker, but is not able to
> fetch it - if you try, you get the same error as when you try to inject
> the broker directly).
>
> The error is sth. like
> Caused by: org.eclipse.e4.core.di.InjectionException: Unable to process
> "EventBroker.logger": no actual value was found for the argument "Logger".
>
>
> I guess that this can be solved by yet another dependecy, but if it is
> something like e4.ui.workbench it rather useless, don't you think?
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp; Events [message #1105101 is a reply to message #1105093] Mon, 09 September 2013 11:14 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
On 09.09.13 12:59, Tom Schindl wrote:
> Nope - the logger in e4 is injected by the application bootstraping.
> IMHO it should be made optional in future. So you need push your own
> logger into the root-context.
>
> The whole logging in e4 is one of the major unexplored areas and IMHO
> the current log system is likely to be replaced by something completely
> different.
>
> Instead of depending on the e4.ui.services it might make sense to copy
> the code into your own bundle and remove this freaking logger stuff.
>

So if you want to use Logging you can use the one we provide which is by
default based on java.util.logging (so that we have 0 dependencies) or
if you want to use log4j you can add "org.eclipse.fx.core.log4j" and
then you have log4j support.

You'll then write into your bean:

@Inject
@Log
org.eclipse.fx.core.log.Logger logger;

Tom
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp; Events [message #1105130 is a reply to message #1105101] Mon, 09 September 2013 12:05 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
A little late: I was doing some trial and error stuff, while writing this post. So by now you have already answered some question that I had.
And you already did with giving me the hint about using your provided Logger.
And thank you for giving me the loggers package Wink

Here the (slightly outdated) post:

--------------------------------------------------------------------------------

Just found this thread:
http://www.eclipse.org/forums/index.php/t/245307/

It looks like the posts you and the other guy did on this thread would provide a solution, if I do this "early enough" - say in the Activator of my bundle.
In this case I wouldn't need the first lines, because I already have the context, but I don't fully understand, how this would solve the issue, because it could trigger a NullPpointer access in the EventBroker implementation or am I wrong?

Update: I tried the approach I mentioned. As I thought, the Activator is a bad idea - I guess this is because the whole thing has nothing to do with OSGi, so it is the "wrong" place. I added the line "context.set(org.eclipse.e4.core.services.log.Logger.class, null);" to my MainApplication (the JFX starter) and it works.

Update2: It's a pitty that I couldn't find any hint, that the Events topics are not allowed to contain Dots. Also I was suprised to learn, that the approach "@Inject @Optional handle(@UIEventTopic(FOO) String bar);" doesn't work (in my case), but "@Inject handle(@Optional @UIEventTopic(FOO) String bar);" does. The mysteries of Equinox Wink

Daniel
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp; Events [message #1105284 is a reply to message #1105130] Mon, 09 September 2013 16:25 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
I stumbled (yes I know: I use that word far to often...) accross another inconveniece while firing of events:
In my plugins fxml controller classes I fire something like this, to trigger a tab to open in another part of the apps UI:
@FXML
public void handleAdminUIButton(ActionEvent event) {
	UIEvent evt = new UIEvent(UIComponentImpl.OPEN_ADMIN);
	broker.send(evt.getName(), evt);
}

UI Event is obviously just a wrapper containing the name and some data (this is optional and by default null).

The "platform" reacts by implementing the following method in one of its classes:
@SuppressWarnings("restriction")
@Inject
private void triggerOpenContent(@Optional @EventTopic(UIBaseEvents.OPEN_ALL) Object event) {
	System.err.println("trigger opening a tab: " + event);
	if (event == null) {
		return;
	}
	if (event instanceof UIEvent) {
		final UIEvent evt = (UIEvent) event;
		for (final UIComponent component : collector.getComponents()) {
			boolean trigger = false;
			for (String evtName : component.getEventNames()) {
				if (evt.getName().equals(evtName)) {
					trigger = true;
					break;
				}
			}
			if (trigger) {
				System.err.println("trigger opening a tab: " + evt.getName());
				Platform.runLater(new Runnable() {
					@Override
					public void run() {
						UITabComponent tab = component.updateTab(context.get(Stage.class), controller.getTabPaneContent(), evt.getName(), evt.getData());
						if (tab == null) {
							component.openTab(context.get(Stage.class), controller.getTabPaneContent(), evt.getName(), evt.getData());
						}
					}
				});
			}
		}
	}
}

Ugly code, I know...

The problem is: When I do this with only one "UIComponent"-plugin within the plugin mechanism, everythings works as expected. When I add another one I can trigger this for the first plugin, but when I switch to the other ones (my navigation is a left handed accordion, so I do the switch literally), in most of the cases (ca. 75% or more) no event is fired at all (even when switching back to the other plugin).
I debuged it and only saw, that the events are still triggered (the first code clock), but never reaches the listener.

And, of course: I have no clue...

Daniel
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp;amp; Events [message #1105294 is a reply to message #1105284] Mon, 09 September 2013 16:37 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
Hi,

I have no clue why it is not working, but let me check one thing for you
because the e4 framework sets some very special static on bootstrapping.

Can you file a bug and if you have time maybe you can attach a simple
set of samples to reproduce it?

Tom

On 09.09.13 18:25, Daniel Zimmermann wrote:
> I stumbled (yes I know: I use that word far to often...) accross another
> inconveniece while firing of events:
> In my plugins fxml controller classes I fire something like this, to
> trigger a tab to open in another part of the apps UI:
>
> @FXML
> public void handleAdminUIButton(ActionEvent event) {
> UIEvent evt = new UIEvent(UIComponentImpl.OPEN_ADMIN);
> broker.send(evt.getName(), evt);
> }
>
> UI Event is obviously just a wrapper containing the name and some data
> (this is optional and by default null).
>
> The "platform" reacts by implementing the following method in one of its
> classes:
>
> @SuppressWarnings("restriction")
> @Inject
> private void triggerOpenContent(@Optional
> @EventTopic(UIBaseEvents.OPEN_ALL) Object event) {
> System.err.println("trigger opening a tab: " + event);
> if (event == null) {
> return;
> }
> if (event instanceof UIEvent) {
> final UIEvent evt = (UIEvent) event;
> for (final UIComponent component : collector.getComponents()) {
> boolean trigger = false;
> for (String evtName : component.getEventNames()) {
> if (evt.getName().equals(evtName)) {
> trigger = true;
> break;
> }
> }
> if (trigger) {
> System.err.println("trigger opening a tab: " +
> evt.getName());
> Platform.runLater(new Runnable() {
> @Override
> public void run() {
> UITabComponent tab =
> component.updateTab(context.get(Stage.class),
> controller.getTabPaneContent(), evt.getName(), evt.getData());
> if (tab == null) {
> component.openTab(context.get(Stage.class),
> controller.getTabPaneContent(), evt.getName(), evt.getData());
> }
> }
> });
> }
> }
> }
> }
>
> Ugly code, I know...
>
> The problem is: When I do this with only one "UIComponent"-plugin within
> the plugin mechanism, everythings works as expected. When I add another
> one I can trigger this for the first plugin, but when I switch to the
> other ones (my navigation is a left handed accordion, so I do the switch
> literally), in most of the cases (ca. 75% or more) no event is fired at
> all (even when switching back to the other plugin).
> I debuged it and only saw, that the events are still triggered (the
> first code clock), but never reaches the listener.
>
> And, of course: I have no clue...
>
> Daniel
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp;amp; Events [message #1105300 is a reply to message #1105294] Mon, 09 September 2013 16:47 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
You can try to do the following, in the main method of your application
you call:

@PostConstruct
void run(
IApplicationContext applicationContext,
javafx.application.Application jfxApplication,
Stage primaryStage,
IEclipseContext appContext) {
ContextInjectionFactory.setDefault(appContext);
// proceed
}

Tom

On 09.09.13 18:37, Tom Schindl wrote:
> Hi,
>
> I have no clue why it is not working, but let me check one thing for you
> because the e4 framework sets some very special static on bootstrapping.
>
> Can you file a bug and if you have time maybe you can attach a simple
> set of samples to reproduce it?
>
> Tom
>
> On 09.09.13 18:25, Daniel Zimmermann wrote:
>> I stumbled (yes I know: I use that word far to often...) accross another
>> inconveniece while firing of events:
>> In my plugins fxml controller classes I fire something like this, to
>> trigger a tab to open in another part of the apps UI:
>>
>> @FXML
>> public void handleAdminUIButton(ActionEvent event) {
>> UIEvent evt = new UIEvent(UIComponentImpl.OPEN_ADMIN);
>> broker.send(evt.getName(), evt);
>> }
>>
>> UI Event is obviously just a wrapper containing the name and some data
>> (this is optional and by default null).
>>
>> The "platform" reacts by implementing the following method in one of its
>> classes:
>>
>> @SuppressWarnings("restriction")
>> @Inject
>> private void triggerOpenContent(@Optional
>> @EventTopic(UIBaseEvents.OPEN_ALL) Object event) {
>> System.err.println("trigger opening a tab: " + event);
>> if (event == null) {
>> return;
>> }
>> if (event instanceof UIEvent) {
>> final UIEvent evt = (UIEvent) event;
>> for (final UIComponent component : collector.getComponents()) {
>> boolean trigger = false;
>> for (String evtName : component.getEventNames()) {
>> if (evt.getName().equals(evtName)) {
>> trigger = true;
>> break;
>> }
>> }
>> if (trigger) {
>> System.err.println("trigger opening a tab: " +
>> evt.getName());
>> Platform.runLater(new Runnable() {
>> @Override
>> public void run() {
>> UITabComponent tab =
>> component.updateTab(context.get(Stage.class),
>> controller.getTabPaneContent(), evt.getName(), evt.getData());
>> if (tab == null) {
>> component.openTab(context.get(Stage.class),
>> controller.getTabPaneContent(), evt.getName(), evt.getData());
>> }
>> }
>> });
>> }
>> }
>> }
>> }
>>
>> Ugly code, I know...
>>
>> The problem is: When I do this with only one "UIComponent"-plugin within
>> the plugin mechanism, everythings works as expected. When I add another
>> one I can trigger this for the first plugin, but when I switch to the
>> other ones (my navigation is a left handed accordion, so I do the switch
>> literally), in most of the cases (ca. 75% or more) no event is fired at
>> all (even when switching back to the other plugin).
>> I debuged it and only saw, that the events are still triggered (the
>> first code clock), but never reaches the listener.
>>
>> And, of course: I have no clue...
>>
>> Daniel
>
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp;amp; Events [message #1105695 is a reply to message #1105300] Tue, 10 September 2013 07:07 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
Hi Tom,

before I start filing a bug there are two questions:
1) IApplicationContext != IEclipseContext --> I could obtain an object of the later and set it to default, but I can't use the IApplicationContext. Do you have any suggestions?
2) If I do indeed wanted to file a bug... Where? If this really is an issue, than I don't think it belongs to e(fx)clipse, but another project... Which one? e4?

Daniel
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp;amp; Events [message #1105704 is a reply to message #1105695] Tue, 10 September 2013 07:25 Go to previous messageGo to next message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
I solved it - kind of.

Just to make clear how I currently implement the UI, I will try to describe my approach:


  1. MainApplication - the entry point of the app with the @PostConstruct method you've mentioned earlier, it calls a class, I call something like the following
  2. *Creator - this class gets the IEclipseContext injected (or better: it is build via ContextInjectionFactory#make(Class<?>, IEclipseContext)) and this class is doing the FXMLLoader thing and injects the context into the controller for DI
  3. *Controller - pretty obvious
  4. ...


I follow this approach througout the other plugins as well, but there the entry point is the UIComponent implementaion.
Now I simply did the following: The event listening method was within the *Creator class and I just moved it to the *Controller... é voila. My guess would be, that somehow the *Creator was either garbage collected or otherwise disposed of and since the UI is "still there" the controller is not removed and thus the listener still exists and reacts after switching betweeen the UI components.
To conclude it: I thing this is an issue of Java, the GC or something, that I stumbled over (I really should stop using this word!).

Please let me know, if this issue is still worth looking into and if I should still file a bug (somewhere).

Thank you very much for your help so far!!!
Daniel
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp;amp;amp; Events [message #1105730 is a reply to message #1105704] Tue, 10 September 2013 07:58 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6651
Registered: July 2009
Senior Member
This event stuff can only work for classes who are created using CIF.make

Tom

On 10.09.13 09:25, Daniel Zimmermann wrote:
> I solved it - kind of.
>
> Just to make clear how I currently implement the UI, I will try to
> describe my approach:
>
>
> MainApplication - the entry point of the app with the @PostConstruct
> method you've mentioned earlier, it calls a class, I call something like
> the following
> *Creator - this class gets the IEclipseContext injected (or better: it
> is build via ContextInjectionFactory#make(Class<?>, IEclipseContext))
> and this class is doing the FXMLLoader thing and injects the context
> into the controller for DI
> *Controller - pretty obvious
> ...
>
>
> I follow this approach througout the other plugins as well, but there
> the entry point is the UIComponent implementaion.
> Now I simply did the following: The event listening method was within
> the *Creator class and I just moved it to the *Controller... é voila. My
> guess would be, that somehow the *Creator was either garbage collected
> or otherwise disposed of and since the UI is "still there" the
> controller is not removed and thus the listener still exists and reacts
> after switching betweeen the UI components.
> To conclude it: I thing this is an issue of Java, the GC or something,
> that I stumbled over (I really should stop using this word!).
>
> Please let me know, if this issue is still worth looking into and if I
> should still file a bug (somewhere).
>
> Thank you very much for your help so far!!!
> Daniel
Re: [Best Practices] UI Strucure &amp;amp;amp;amp;amp;amp;amp;amp;amp; Events [message #1105801 is a reply to message #1105730] Tue, 10 September 2013 09:42 Go to previous message
Daniel Zimmermann is currently offline Daniel ZimmermannFriend
Messages: 81
Registered: July 2009
Member
... and that is what I did. Since starting developing with OSGi and JavaFX two weeks agou I made this a habbit. Just to be sure, that I can make use of the DI stuff.

Daniel
Previous Topic:JavaFX browser
Next Topic:Cannot make off-line installation
Goto Forum:
  


Current Time: Thu Apr 18 07:51:41 GMT 2024

Powered by FUDForum. Page generated in 0.05263 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top