|
|
Re: How to @Inject a service into a called object [message #987837 is a reply to message #987749] |
Wed, 28 November 2012 10:55 |
Jeff Rickard Messages: 4 Registered: November 2012 Location: Munich, Germany |
Junior Member |
|
|
Thanks, Lars.
I had (of course ) read through this material (and other stuff) a couple of times before posting, but could not see what I was missing. I see now that the section on RunAndTrack is what I was after.
(I was thrown off the scent by the phrases "A RunAndTrack is basically a Runnable..." and "The runAndTrack() method allows a client to keep some external state synchronized...", neither of which I thought were applicable to my problem.)
My problem was that MyClass needed access to the IEclipseContext, and IEclipseContext.runAndTrack() provides a way of getting this. For completeness, here is my sample code, modified to work:
public class MyPart {
@PostConstruct
public void postConstruct(Composite parent, IEclipseContext context, IMyService myService) {
MyClass myObject = new MyClass();
context.runAndTrack(myObject);
myObject.test();
System.out.println("*myService = " + myService);
}
}
public class MyClass extends RunAndTrack {
IMyService myService;
@Override
public boolean changed(IEclipseContext context) {
myService = context.getActive(IMyService.class);
return false; // don't call on updates
}
void test() {
System.out.println("myService = " + myService);
}
}
The console output:
myService = com.example.services.MyService@190d8e1
*myService = com.example.services.MyService@190d8e1
|
|
|
Re: How to @Inject a service into a called object [message #987860 is a reply to message #987837] |
Wed, 28 November 2012 12:23 |
Thomas Schindl Messages: 6651 Registered: July 2009 |
Senior Member |
|
|
No, no, no. Your error is that you are creating the instance of the bean
your own instead of useing ContextInjectionFactory.make()
If you want to use DI don't do this:
MyClass myObject = new MyClass();
but do this:
MyClass myObject = ContextInjectionFactory.make(MyClass.class,context);
You don't need RunAndTrack!
Tom
Am 28.11.12 11:55, schrieb Jeff Rickard:
> Thanks, Lars.
>
> I had (of course :p ) read through this material (and other stuff) a
> couple of times before posting, but could not see what I was missing. I
> see now that the section on RunAndTrack is what I was after.
>
> (I was thrown off the scent by the phrases "A RunAndTrack is basically a
> Runnable..." and "The runAndTrack() method allows a client to keep some
> external state synchronized...", neither of which I thought were
> applicable to my problem.)
>
> My problem was that MyClass needed access to the IEclipseContext, and
> IEclipseContext.runAndTrack() provides a way of getting this. For
> completeness, here is my sample code, modified to work:
>
>
> public class MyPart {
>
> @PostConstruct
> public void postConstruct(Composite parent, IEclipseContext context,
> IMyService myService) {
> MyClass myObject = new MyClass();
> context.runAndTrack(myObject);
> myObject.test();
> System.out.println("*myService = " + myService);
> }
> }
>
>
> public class MyClass extends RunAndTrack {
>
> IMyService myService;
>
> @Override
> public boolean changed(IEclipseContext context) {
> myService = context.getActive(IMyService.class);
> return false; // don't call on updates
> }
>
> void test() {
> System.out.println("myService = " + myService);
> }
> }
>
> The console output:
>
> myService = com.example.services.MyService@190d8e1
> *myService = com.example.services.MyService@190d8e1
>
|
|
|
|
Re: How to @Inject a service into a called object [message #987867 is a reply to message #987862] |
Wed, 28 November 2012 12:46 |
Thomas Schindl Messages: 6651 Registered: July 2009 |
Senior Member |
|
|
No. @Creatable has the effect that an instance is created if needed by
another bean.
Say you have BeanA and BeanB.
BeanA {
@Inject
BeanB b;
}
BeanB {
@Inject
public BeanB(MyService service) {
}
}
If you now call:
CIF#make(BeanA,context) will normally croak and tell your that there's
no BeanB registered in context, so you'd be forced to do this.
context.set(BeanB.class, CIF#make(BeanB,context) );
BeanA a = CIF#make(BeanA,context)
If you add the @Creatable the DI container will itself create an
instance of BeanB if none is found.
Tom
Am 28.11.12 13:37, schrieb Dirk Fauth:
> Hi Tom,
>
> just to be sure I understand CIF now more clearly, MyClass has to be
> annotated with @Creatable so CIF.make() works. Is that correct?
>
> Greez,
> Dirk
|
|
|
|
Re: How to @Inject a service into a called object [message #988270 is a reply to message #987870] |
Thu, 29 November 2012 09:09 |
Jeff Rickard Messages: 4 Registered: November 2012 Location: Munich, Germany |
Junior Member |
|
|
Hi Tom,
ContextInjectionFactory.make() does not seem like the right solution in my particular case for two reasons:
- In my real code, MyClass has a private constructor which is wrapped in a getInstance() which cannot be passed to ContextInjectionFactory.make().
- In my real code, the MyClass constructor takes a bunch of parameters which are not appropriate to first put into the context, as the constructor is called with various parameters from various places. But even if this was done, using ContextInjectionFactory.make() would involve more complicated code than using RunAndTrack.
So I think RunAndTrack is better in my real code. If you disagree with my reasoning please say so.
(Another solution would be for MyClass objects to be created by a service. This may be a better solution overall. If I have time today I'll implement that and see if it feels better.)
@Lars: The bit in your tutorial about ContextInjectionFactory.make() in section "24.1. Accessing the context" I think needs clarification. Maybe instead of starting with the phrase "If you are outside of a model object..." it would be clearer if it started with something like "If a manually created object needs access to the context...", and then explicit mention that if you use new the created class will not be able to access the context. Depending upon Tom's response to this post, mention of RunAndTrack in that section may also be useful.
[Updated on: Thu, 29 November 2012 09:12] Report message to a moderator
|
|
|
|
|
|
Re: How to @Inject a service into a called object [message #988291 is a reply to message #988275] |
Thu, 29 November 2012 09:54 |
Jeff Rickard Messages: 4 Registered: November 2012 Location: Munich, Germany |
Junior Member |
|
|
Hi Dirk, Tom,
Dirk is right, using ContextInjectionFactory.inject() is a syntactically cleaner solution than RunAndTrack. (From caller it makes no difference, but it makes it more obvious in the MyClass which fields are injected.) This seems to be the right solution, at least in my case. @Lars might want to mention .inject() in the tutorial.
I think that in my case Tom's solution is more complicated than I need. In other cases it may be the best solution.
(Now I understand the solution, I see that much of this topic was already covered by http://www.eclipse.org/forums/index.php/m/982712/ - my previous searching did not find that - and that topic may contain some extra information for the next person to read this post.)
For completeness for the next person to google this question, here is the solution I have. This uses ContextInjectionFactory.inject() as an alternative to ContextInjectionFactory.make() for the case where the constructor has a parameter.
public class MyPart {
@PostConstruct
public void postConstruct(Composite parent, IEclipseContext context) {
MyClass myObject = new MyClass(123);
ContextInjectionFactory.inject(myObject, context);
}
}
public class MyClass {
@Inject IMyService myService;
MyClass(int param) {
}
}
[Updated on: Thu, 29 November 2012 09:54] Report message to a moderator
|
|
|
Powered by
FUDForum. Page generated in 0.02842 seconds