This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
Bug 398728 - [DI] ExtendedObjectSupplier annotations ignored if requested item is satisfied by the PrimaryObjectSupplier
Summary: [DI] ExtendedObjectSupplier annotations ignored if requested item is satisfie...
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: Runtime (show other bugs)
Version: 4.2.1   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: 4.4 M6   Edit
Assignee: Brian de Alwis CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 378694 (view as bug list)
Depends on:
Blocks:
 
Reported: 2013-01-22 07:39 EST by Martin Herbst CLA
Modified: 2014-05-01 11:32 EDT (History)
7 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Herbst CLA 2013-01-22 07:39:32 EST
I have added the following method to the implementation of a part:

@Inject @Optional
void dontExecute(@UIEventTopic("Invalid Topic") Object x)
{
   System.out.println("is executed");
}

When my application starts, this method is always executed even if no event of the subscribed topic was fired.

After changing the type of parameter "x" from "Object" to "String" the method behaves as expected and is only executed if an event of topic "Invalid Topic" was fired.
Comment 1 Thomas Schindl CLA 2013-01-22 10:47:18 EST
so what is the value you get? It looks like something is pushing something as key "java.lang.Object" into the context!
Comment 2 Martin Herbst CLA 2013-01-22 10:56:52 EST
The passed object "x" is of type org.eclipse.equinox.console.command.adapter.CommandProviderAdapter
Comment 3 Brian de Alwis CLA 2013-02-24 15:57:43 EST
This is a fun bug.  The problem is that org.eclipse.equinox.console's activator registers a CommandProviderAdapter as java.lang.Object (see org.eclipse.equinox.console.command.adapter.Activator line 178).  Since EclipseContextOSGI is the root context, the normal lookup mechanism for "java.lang.Object" succeeds and so the extended suppliers are never consulted.

Even if we were able to change o.e.e.console's activator to register as something other than java.lang.Object, this situation could recur.

An immediate workaround is to add a @Named annotation to ensure that the context lookup should never succeed:

   @Inject @Optional
   void dontExecute(@UIEventTopic("Invalid Topic") @Named("XXX") Object x)
   {
      System.out.println("is executed");
   }

The fundamental issue here is: do we have the concepts of primary and extended suppliers reversed?  Should the use of a custom annotation indicate a particular supplier?  My thinking is that they do.
Comment 4 Brian de Alwis CLA 2013-03-08 15:38:28 EST
Retitled.
Comment 5 Brian de Alwis CLA 2014-01-20 16:32:14 EST
Fix submitted to Gerrit: https://git.eclipse.org/r/20843
Comment 6 Paul Webster CLA 2014-01-24 15:57:03 EST
So we're saying the lookup strategy is:

1. Provder<T>

2. ExtendedObjectSupplier

3. Temporary object supplier (usually a context object supplier)

4. Primary object supplier (usually a context object supplier)

Does that make sense?

I'm cautious here although I think on the surface the change seems reasonable.

What's the role of the Provder<T> here (I can see all the other ones)?

PW
Comment 7 Paul Webster CLA 2014-01-28 19:19:53 EST
(In reply to Brian de Alwis from comment #5)
> Fix submitted to Gerrit: https://git.eclipse.org/r/20843

Brian, if you comment on my comment #6 we can get this in :-)

PW
Comment 8 Brian de Alwis CLA 2014-01-28 23:38:42 EST
(In reply to Paul Webster from comment #7)
> Brian, if you comment on my comment #6 we can get this in :-)

Sorry Paul, time's unfortunately in short supply :-(

(In reply to Paul Webster from comment #6)
> So we're saying the lookup strategy is:
[...]

That's right.  So ExtendedObjectSuppliers take precedence.

It's worth mentioning that switching this order will result in a slight performance impact as we'll be checking each annotation to find a possible extended supplier.  The impact should be small since these lookups are just hash map lookups.

> What's the role of the Provder<T> here (I can see all the other ones)?

Provider<T> is a JSR330 defined approach for delaying obtaining values until they're actually needed; i.e., to avoid possibly expensive calls to obtain the injectable value.

Our implementation currently only supports using Provider<T> from the primary supplier.  Although I don't see any reason that we shouldn't support using Provider<T> for extended suppliers too, that would seem slightly at odds with the multiple-instances aspect described in the javadoc:

 * Compared to injecting {@code T} directly, injecting
 * {@code Provider<T>} enables:
 *
 * <ul>
 *   <li>retrieving multiple instances.</li>
 *   <li>lazy or optional retrieval of an instance.</li>
 *   <li>breaking circular dependencies.</li>
 *   <li>abstracting scope so you can look up an instance in a smaller scope
 *      from an instance in a containing scope.</li>

So I'm happy to leave it for now.
Comment 10 Brian de Alwis CLA 2014-05-01 11:32:20 EDT
*** Bug 378694 has been marked as a duplicate of this bug. ***