Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse 4 » Dependency Injection: clarification needed
Dependency Injection: clarification needed [message #578349] Fri, 02 July 2010 06:03 Go to next message
No real name is currently offline No real name
Messages: 13
Registered: June 2010
Junior Member
Hello Everyone,

I am trying to understand when I can use injection in e4 and when not.

The following works very well in e4, but I do not like the solution:


public class MyClass {
@Execute
public String method1(@Named(IServiceConstants.ACTIVE_SHELL) Shell shell) {
return method2(shell);
}

private String method2(Shell shell) {
return method3(shell);
}

private String method3(Shell shell) {
FileDialog dialog = new FileDialog(shell, SWT.OPEN);
return dialog.open();
}
}

The following also works, and is better (the shell is now a global variable), but I still don´t like it since it creates an unecessary(???) piece of information that is available to the whole class but that nobody needs:

public class MyClass {
private Shell myShell;

@Execute
public String method1(@Named(IServiceConstants.ACTIVE_SHELL) Shell shell) {
myShell = shell;
return method2();
}

private String method2() {
return method3();
}

private String method3() {
FileDialog dialog = new FileDialog(myShell, SWT.OPEN);
return dialog.open();
}
}

To get rid of the global variable, I wanted to write something like the following:

public class MyClass {
@Execute
public String method1() {
return method2();
}

private String method2() {
return method3();
}

private String method3(@Named(IServiceConstants.ACTIVE_SHELL) Shell shell) {
FileDialog dialog = new FileDialog(shell, SWT.OPEN);
return dialog.open();
}
}

But this obviously does not work since I try to call method3(Shell) in method2() without arguments. And if give method3 a dummy shell (I am getting desperate at this point) as in the following:

public class MyClass {
@Execute
public String method1() {
return method2();
}

private String method2() {
return method3(new Shell());
}

@Inject
private String method3(IShellProvider shellProvider) {
FileDialog dialog = new FileDialog(shellProvider.getShell(), SWT.OPEN);
return dialog.open();
}
}

then method3 is called in the very begining of the application life cycle, before MyClass can be instantieted it seems like, and I get the following error:

ERROR: Unable to create class "MyClass" from bundle '675'
org.eclipse.e4.core.di.InjectionException: java.lang.IllegalArgumentException: Argument cannot be null
at org.eclipse.e4.core.internal.di.MethodRequestor.execute(Meth odRequestor.java:49)
at org.eclipse.e4.core.internal.di.InjectorImpl.inject(Injector Impl.java:79)
at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(In jectorImpl.java:242)
at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorIm pl.java:196)
at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorIm pl.java:189)
at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(Co ntextInjectionFactory.java:129)
at org.eclipse.e4.workbench.ui.internal.ReflectionContributionF actory.createFromBundle(ReflectionContributionFactory.java:1 83)
at org.eclipse.e4.workbench.ui.internal.ReflectionContributionF actory.create(ReflectionContributionFactory.java:159)
at org.eclipse.e4.workbench.ui.internal.E4Workbench.processHier archy(E4Workbench.java:201)
at org.eclipse.e4.workbench.ui.internal.E4Workbench.init(E4Work bench.java:108)
at org.eclipse.e4.workbench.ui.internal.E4Workbench.<init>(E4Workbench.java:67)
at org.eclipse.e4.ui.workbench.swt.internal.E4Application.creat eE4Workbench(E4Application.java:173)
at org.eclipse.e4.ui.workbench.swt.internal.E4Application.start (E4Application.java:79)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(Eclips eAppHandle.java:196)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher .runApplication(EclipseAppLauncher.java:110)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher .start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseS tarter.java:369)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseS tarter.java:179)
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.equinox.launcher.Main.invokeFramework(Main.java: 619)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)
at org.eclipse.equinox.launcher.Main.run(Main.java:1407)
at org.eclipse.equinox.launcher.Main.main(Main.java:1383)
Caused by: java.lang.IllegalArgumentException: Argument cannot be null
at org.eclipse.swt.SWT.error(SWT.java:4064)
at org.eclipse.swt.SWT.error(SWT.java:3998)
at org.eclipse.swt.SWT.error(SWT.java:3969)
at org.eclipse.swt.widgets.Dialog.error(Dialog.java:198)
at org.eclipse.swt.widgets.Dialog.checkParent(Dialog.java:164)
at org.eclipse.swt.widgets.Dialog.<init>(Dialog.java:127)
at org.eclipse.swt.widgets.FileDialog.<init>(FileDialog.java:109)
at MyClass.method3(MyClass.java:12)
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(Meth odRequestor.java:42)
... 25 more

In other words: I hope someone can explain to me when and how dependency injection can and cannot be used. Preferably by explaining what is going wrong in the last code samples.

I am using Eclipse e4 M6.

Many thanks in advance,
Karin
Re: Dependency Injection: clarification needed [message #578374 is a reply to message #578349] Fri, 02 July 2010 06:57 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas Schindl
Messages: 5013
Registered: July 2009
Senior Member
Hi,

I'm not sure what you are doing/solve here, what you present is a
handler implementation (i take this from your stacktrace).

In handlers you are NOT useing @Inject (we don't yet really support this
there - Paul could give you the reason on why this is not yet supported)
but only @Execute and @CanExecute.

The first class you show is the perfect solution when implementing a
handler, whenever your handler is executed it gets the current active
shell. I don't understand why the 2nd code is better in any way and the
3rd one would not even compile, 4th doesn't make sense at all in a Handler.

Tom

Am 02.07.10 12:03, schrieb karins.spam@gmail.com:
> Hello Everyone,
>
> I am trying to understand when I can use injection in e4 and when not.
> The following works very well in e4, but I do not like the solution:
>
>
> public class MyClass {
> @Execute
> public String method1(@Named(IServiceConstants.ACTIVE_SHELL) Shell
> shell) {
> return method2(shell);
> }
>
> private String method2(Shell shell) {
> return method3(shell);
> }
>
> private String method3(Shell shell) {
> FileDialog dialog = new FileDialog(shell, SWT.OPEN);
> return dialog.open();
> }
> }
>
> The following also works, and is better (the shell is now a global
> variable), but I still don´t like it since it creates an unecessary(???)
> piece of information that is available to the whole class but that
> nobody needs:
>
> public class MyClass {
> private Shell myShell;
>
> @Execute
> public String method1(@Named(IServiceConstants.ACTIVE_SHELL) Shell
> shell) {
> myShell = shell;
> return method2();
> }
>
> private String method2() {
> return method3();
> }
>
> private String method3() {
> FileDialog dialog = new FileDialog(myShell, SWT.OPEN);
> return dialog.open();
> }
> }
>
> To get rid of the global variable, I wanted to write something like the
> following:
>
> public class MyClass {
> @Execute
> public String method1() {
> return method2();
> }
>
> private String method2() {
> return method3();
> }
>
> private String method3(@Named(IServiceConstants.ACTIVE_SHELL) Shell
> shell) {
> FileDialog dialog = new FileDialog(shell, SWT.OPEN);
> return dialog.open();
> }
> }
>
> But this obviously does not work since I try to call method3(Shell) in
> method2() without arguments. And if give method3 a dummy shell (I am
> getting desperate at this point) as in the following:
>
> public class MyClass {
> @Execute
> public String method1() {
> return method2();
> }
>
> private String method2() {
> return method3(new Shell());
> }
>
> @Inject
> private String method3(IShellProvider shellProvider) {
> FileDialog dialog = new FileDialog(shellProvider.getShell(),
> SWT.OPEN);
> return dialog.open();
> }
> }
>
> then method3 is called in the very begining of the application life
> cycle, before MyClass can be instantieted it seems like, and I get the
> following error:
> ERROR: Unable to create class "MyClass" from bundle '675'
> org.eclipse.e4.core.di.InjectionException:
> java.lang.IllegalArgumentException: Argument cannot be null
> at org.eclipse.e4.core.internal.di.MethodRequestor.execute(Meth
> odRequestor.java:49)
> at org.eclipse.e4.core.internal.di.InjectorImpl.inject(Injector
> Impl.java:79)
> at org.eclipse.e4.core.internal.di.InjectorImpl.internalMake(In
> jectorImpl.java:242)
> at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorIm
> pl.java:196)
> at org.eclipse.e4.core.internal.di.InjectorImpl.make(InjectorIm
> pl.java:189)
> at org.eclipse.e4.core.contexts.ContextInjectionFactory.make(Co
> ntextInjectionFactory.java:129)
> at org.eclipse.e4.workbench.ui.internal.ReflectionContributionF
> actory.createFromBundle(ReflectionContributionFactory.java:1 83)
> at org.eclipse.e4.workbench.ui.internal.ReflectionContributionF
> actory.create(ReflectionContributionFactory.java:159)
> at org.eclipse.e4.workbench.ui.internal.E4Workbench.processHier
> archy(E4Workbench.java:201)
> at org.eclipse.e4.workbench.ui.internal.E4Workbench.init(E4Work
> bench.java:108)
> at
> org.eclipse.e4.workbench.ui.internal.E4Workbench.<init>(E4Workbench.java:67)
>
> at org.eclipse.e4.ui.workbench.swt.internal.E4Application.creat
> eE4Workbench(E4Application.java:173)
> at org.eclipse.e4.ui.workbench.swt.internal.E4Application.start
> (E4Application.java:79)
> at org.eclipse.equinox.internal.app.EclipseAppHandle.run(Eclips
> eAppHandle.java:196)
> at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher
> .runApplication(EclipseAppLauncher.java:110)
> at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher
> .start(EclipseAppLauncher.java:79)
> at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseS
> tarter.java:369)
> at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseS
> tarter.java:179)
> 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.equinox.launcher.Main.invokeFramework(Main.java: 619)
> at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574)
> at org.eclipse.equinox.launcher.Main.run(Main.java:1407)
> at org.eclipse.equinox.launcher.Main.main(Main.java:1383)
> Caused by: java.lang.IllegalArgumentException: Argument cannot be null
> at org.eclipse.swt.SWT.error(SWT.java:4064)
> at org.eclipse.swt.SWT.error(SWT.java:3998)
> at org.eclipse.swt.SWT.error(SWT.java:3969)
> at org.eclipse.swt.widgets.Dialog.error(Dialog.java:198)
> at org.eclipse.swt.widgets.Dialog.checkParent(Dialog.java:164)
> at org.eclipse.swt.widgets.Dialog.<init>(Dialog.java:127)
> at org.eclipse.swt.widgets.FileDialog.<init>(FileDialog.java:109)
> at MyClass.method3(MyClass.java:12)
> 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(Meth
> odRequestor.java:42)
> ... 25 more
>
> In other words: I hope someone can explain to me when and how dependency
> injection can and cannot be used. Preferably by explaining what is going
> wrong in the last code samples.
>
> I am using Eclipse e4 M6.
>
> Many thanks in advance,
> Karin
Re: Dependency Injection: clarification needed [message #578503 is a reply to message #578349] Mon, 05 July 2010 14:06 Go to previous messageGo to next message
Paul Webster is currently offline Paul Webster
Messages: 6850
Registered: July 2009
Location: Ottawa
Senior Member

Tom and Simon have described some of the annotations we use in e4. I'll
just talk a little about what's currently in the system.

@Inject, @PreDestroy, @PostConstruct are part of the object
creation/object initialization cycle for contributed code. In addition,
while the object is "alive" any relevant changes in the context will
cause @Inject methods or fields to be updated.


But we have a more dynamic use of DI in eclipse, specifically targetted
at points where the framework must call contributed code. @Execute,
@CanExecute, @Persist are examples. Unlike the @Inject methods, they
are invoked once by the framework. They involve DI at all so that the
contributed code can access any framework information or services it
needs in a dynamic way. Examples:

@Execute public void execute(IWorkbench workbench,
@Named(IServiceConstants.ACTIVE_SELECTION) IResource selection,
EPartService partService)

@Execute public void execute(EModelService modelService,
MWindow window)

The difference also has to do with use. Contribution code is
instantiated in a context (application, window, part, for example). But
something like a handler will be executed in a context, determined by
the running framework. That's why we don't currently recommend using
@Inject on handlers ... aside from the MApplication, what information
will be available in the execution IEclipseContext? The answer is ...
we're not sure of the best practice ATM, but if you specify it in your
@Execute then you'll probably be getting the appropriate information.

PW


--
Paul Webster
http://wiki.eclipse.org/Platform_Command_Framework
http://wiki.eclipse.org/Command_Core_Expressions
http://wiki.eclipse.org/Menu_Contributions
http://wiki.eclipse.org/Menus_Extension_Mapping
http://help.eclipse.org/galileo/index.jsp?topic=/org.eclipse .platform.doc.isv/guide/workbench.htm


Re: Dependency Injection: clarification needed [message #578609 is a reply to message #578349] Tue, 06 July 2010 03:45 Go to previous messageGo to next message
No real name is currently offline No real name
Messages: 13
Registered: June 2010
Junior Member
Thanks a bunch for all the great answers. I will spend some time now writing up an example to try it out, and I´ll let you know if I have any more questions. Thanks again!

Karin
Re: Dependency Injection: clarification needed [message #742305 is a reply to message #578503] Thu, 20 October 2011 07:25 Go to previous messageGo to next message
Parvez Ahmad Hakim is currently offline Parvez Ahmad Hakim
Messages: 31
Registered: May 2010
Member
Hello
Problem is simple. We know it is easy to show dialogs, message boxes, progress dialogs by implementing E4 commands and handlers.
How E4 allows toi show the same stuff like progress dialogs in
NON USER INTERFACE CODE, like classes which get called.
Do we need to create shell every time.
Is there some link.
Below code is no longer working in E4

PlatformUI.getWorkbench().getActiveWorkbenchWindow();
Shell shell = win != null ? win.getShell() : null;

can some body help.

Re: Dependency Injection: clarification needed [message #753418 is a reply to message #742305] Thu, 27 October 2011 03:52 Go to previous message
Parvez Ahmad Hakim is currently offline Parvez Ahmad Hakim
Messages: 31
Registered: May 2010
Member
Found solution, I use

if (showProgress) { 1.7 - IWorkbenchWindow win = PlatformUI.getWorkbench() 1.8 - .getActiveWorkbenchWindow(); 1.9 - Shell shell = win != null ? win.getShell() : null; 1.10 - new ProgressMonitorDialog(shell).run(true, true, op); 1.11 + //IWorkbenchWindow win = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); 1.12 + //Shell shell = win != null ? win.getShell() : null; 1.13 + new ProgressMonitorDialog( Display.getCurrent().getActiveShell()).run(true, true, op); 1.14 } else { 1.15 op.run(null);
Previous Topic:JavaDoc for e4 classes
Next Topic:UserAdmin osgi service inacessible
Goto Forum:
  


Current Time: Fri Apr 18 04:06:59 EDT 2014

Powered by FUDForum. Page generated in 0.07813 seconds