Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse 4 » Dependency Injection outside Application Model(Plugin DI for POJO outside Application Model not working)
Dependency Injection outside Application Model [message #1047588] Tue, 23 April 2013 12:20 Go to next message
Don Smyth is currently offline Don SmythFriend
Messages: 35
Registered: April 2013
Member
DI works fine in Eclipse 4.2 RCP for Parts and Handers that are defined within the Application.e4xmi. eg:

public class SamplePart {

private Label label;
private TableViewer tableViewer;

@PostConstruct
public void createComposite(Composite parent) {
initialise();
.....

However when I call a class that is included within my plugin but is not defined as a part or handler such as this:

import javax.inject.Inject;
import org.eclipse.e4.core.services.log.Logger;
public class DataLogger {
@Inject Logger log;

public DataLogger(){
log.info("Message");
........

I get a org.eclipse.e4.core.di.InjectionException: java.lang.NullPointerException

Is there a way to register POJO's (I have a ton of classes that need to use Logger but have nothing to do with the UI) such that they can use DI?
Re: Dependency Injection outside Application Model [message #1047613 is a reply to message #1047588] Tue, 23 April 2013 12:50 Go to previous messageGo to next message
Christoph Keimel is currently offline Christoph KeimelFriend
Messages: 385
Registered: December 2010
Location: Germany
Senior Member
Check out ContextInjectionFactory in org.eclipse.e4.core.contexts
Re: Dependency Injection outside Application Model [message #1047955 is a reply to message #1047613] Tue, 23 April 2013 22:10 Go to previous messageGo to next message
Don Smyth is currently offline Don SmythFriend
Messages: 35
Registered: April 2013
Member
Thanks Cristoph,

Initially I tried:

public class CreateContextTest {

public void example(){
IEclipseContext context = EclipseContextFactory.create();
MyClass tester = new MyClass();
ContextInjectionFactory.inject(tester, context);
tester.diTest();
}

I struggled with org.eclipse.e4.core.di.InjectionException errors that I tracked down to IEclipseContext related.

Some google searches later I found that injecting IEclipseContext from the Application Model is required eg:

public class ChainInjection {

@Execute
public void testChainDI(IEclipseContext context){
MyClass tester = new MyClass();
ContextInjectionFactory.inject(tester, context);
}
}

The test class:

import javax.inject.Inject;

import org.eclipse.e4.core.services.log.Logger;

public class MyClass {
@Inject private Logger log;

@Inject
public void diTest(){
log.info("Just making sure DI works");
}
}

I note that the call tester.diTest() is not required in the ChainInjection class for the logger to log from within the diTest method!. I'll need to do more research on this.

Some helpful links I found were on:
stackoverflow - see how-to-use-eclipse-4-di-in-classes-that-are-not-attached-to-the-application-mode
eclipse.dzone - see eclipse-40-dependency
toedter blog - see June 25th 2010 archive
eclipsesource blog - see eclipse-4-e4-tutorial-soft-migration-from-3-x-to-eclipse-4-e4

Re: Dependency Injection outside Application Model [message #1048399 is a reply to message #1047955] Wed, 24 April 2013 12:11 Go to previous messageGo to next message
Sopot Cela is currently offline Sopot CelaFriend
Messages: 597
Registered: December 2010
Senior Member

It doesn't work that way. The context you are creating out of the blue contains nothing. Contexts are the suppliers of the injections and, being empty, they spawn the InjectionException in your case. The objects that get injected in 'Eclipse-powered' classes are splattered in a big context hierarchy (there are a lot of posts around here in the forums talking about the context hierarchy, just search for them) and what you get (or whether you get it) depends on where you are (more specifically in which context you ask for injection).

The context you want to provide your domain classes to when you call CIF#make or CIF#inject has to be linked to this big hierarchical context tree (through the createChildContext method). That way you will have access to the 'default' objects stored throughout this tree.
Re: Dependency Injection outside Application Model [message #1048763 is a reply to message #1048399] Wed, 24 April 2013 23:32 Go to previous messageGo to next message
Don Smyth is currently offline Don SmythFriend
Messages: 35
Registered: April 2013
Member
Thanks Sopot,

The way I undertand it is that to get to the context hierarchy, I need IEclipseContext from the Application Model. To use CIF and DI I would then need to pass IEC down through my code - which is not practical for the project at hand. I note a similar issue on the 'Trying to get E4 Services' thread and a reference therein to: "access a top level context and traverse
its children until you find a suitable context". How would I access a lop level context from a POJO outside the Application Model?
Re: Dependency Injection outside Application Model [message #1048985 is a reply to message #1048763] Thu, 25 April 2013 07:48 Go to previous messageGo to next message
Christoph Keimel is currently offline Christoph KeimelFriend
Messages: 385
Registered: December 2010
Location: Germany
Senior Member
Hi Don,

you can use EclipseContextFactory.getServiceContext(bundleContext) to get a basic IEclipseContext that at includes all your OSGi services.

Hope that helps.
Christoph
Re: Dependency Injection outside Application Model [message #1048998 is a reply to message #1048985] Thu, 25 April 2013 08:08 Go to previous messageGo to next message
Sopot Cela is currently offline Sopot CelaFriend
Messages: 597
Registered: December 2010
Senior Member

The context hierarchy is a simple tree-like data structure. Injection searches for objects in contexts in a leaf-to-root fashion. Suppose you have root R and children C1,C2,C3. Child C1 has children D2,D3,D4. D3 has childs E1,E2,E3. If you require something to be injected in your class in the E3 context the DI engine will do a lookup on E3, if it doesn't find it will search on D3, then C1, then R, then OSGi Bundle Context, then -> InjectionException.

So, if you want to have access to these nodes of context grab one of these contexts, say E3 and do E3#createChild. Say the resulting context is P. Use this P to do the CIF#make and CIF#inject and now the lookup sequence will be P-E3-D3-C1-R-OSGi and as a result you will have access to all the objects that are in those contexts.

These R-C-D-E are just notations for ease of understanding and in reality they are MApplication's (R), MWindow's (C), MPerspective's (D) and MPart's (E) context. Handlers are executed in the active part's context.
Re: Dependency Injection outside Application Model [message #1049915 is a reply to message #1048998] Fri, 26 April 2013 12:53 Go to previous messageGo to next message
Don Smyth is currently offline Don SmythFriend
Messages: 35
Registered: April 2013
Member
Thanks Guys,

Much appreciated. To keep the code simple I think I can work to get by without e4 services deeper in the application. At my level of limited RCP experience, keeping DI for the Application Model and closely related classes will be more straightforward.
Re: Dependency Injection outside Application Model [message #1051775 is a reply to message #1049915] Mon, 29 April 2013 08:05 Go to previous messageGo to next message
Sopot Cela is currently offline Sopot CelaFriend
Messages: 597
Registered: December 2010
Senior Member

Sure it's your choice.

Although my explanation may have sounded complex it translates into very simple code. One LOC is enough to link the POJO out of the model with the rest of the contexts and have it ready for injections.
Re: Dependency Injection outside Application Model [message #1052417 is a reply to message #1051775] Tue, 30 April 2013 03:47 Go to previous messageGo to next message
Don Smyth is currently offline Don SmythFriend
Messages: 35
Registered: April 2013
Member
Thanks Sopot,

I followed up your hierachy and I understand the E4/OSGi relationship a little more.

The 2 ways I could access the E4 model are then

A) using the EclipseContextFactory

1. Bundle bundle = FrameworkUtil.getBundle(POJO.class);
2. BundleContext bundleCntxt = bundle.getBundleContext();
3. IEclipseContext serviceCntxt = EclipseContextFactory.getServiceContext(bundleCntxt);

However line 2. throws a null error. I think I need to register the plugin that needs E4 service access as an OSGi consumer. I am working on this at the moment but haven't quite worked how to implement it yet.

B) If I follow correctly as per your hierachy tree, call eg. E3 in the hierachy from a POJO and do E3#createChild. Use the resultant context P do "ContextInjectionFactory.inject(POJO, context);"

B sounds like a better option to me. I hadn't quite understood it the first time I read it. I will follow up tonight. Thanks again.

[Updated on: Tue, 30 April 2013 03:51]

Report message to a moderator

Re: Dependency Injection outside Application Model [message #1076412 is a reply to message #1052417] Wed, 31 July 2013 11:02 Go to previous message
Thomas BöhmFriend
Messages: 2
Registered: July 2010
Location: Germany
Junior Member
I faced a similar problem:

index.php/fa/15786/0/

Transfered my POJO in a OSGi-Service (tutorials at vogella.de). @Inject ignored in bundle with contentProvider (outside application model)

You can solve this by:
//Get bundle of this class
Bundle bundle = FrameworkUtil.getBundle(this.getClass());
//Get context of this bundle
BundleContext bundleCntxt = bundle.getBundleContext();
//Alternative 1:
IEclipseContext context = EclipseContextFactory.getServiceContext(bundleCntxt);
yourOSGI-Service-Object object = (Type-cast)context.get("name");
//Alternative 2:
ServiceReference<?> serviceReference = bundleCntxt.getServiceReference("name");
yourOSGI-Service-Object object = (Type-cast) bundleCntxt.getService(serviceReference);

But isn't there a better solution so that I can use @Inject @Named("name")?
  • Attachment: DI.png
    (Size: 55.81KB, Downloaded 710 times)
Previous Topic:Toolbar seperator missing
Next Topic:Plugin / class reference in e4 Application
Goto Forum:
  


Current Time: Wed Nov 26 10:36:32 GMT 2014

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

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