Bug 331746 - Allow control over construction of contributions
Summary: Allow control over construction of contributions
Status: NEW
Alias: None
Product: Platform
Classification: Eclipse Project
Component: Runtime (show other bugs)
Version: 4.0   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: platform-runtime-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: helpwanted
Depends on:
Blocks: 331556
  Show dependency tree
 
Reported: 2010-12-03 03:38 EST by Sven Efftinge CLA
Modified: 2016-10-04 11:52 EDT (History)
11 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sven Efftinge CLA 2010-12-03 03:38:38 EST
With Equinox' extension registry a contribution is usually created by Equinox using the default constructor of the contributed class. This is often convenient, but generally the client is able to control how its objects are created and initialized by the means of an IExecutableExtensionFactory. This is important if you need to construct any contributed objects differently.

In e4 it seems that there is no such hook, and the EclipseContext is always responsible for creating and configuring the contributions. This is unpleasant because it is not possible to use a factory or any other construction pattern (e.g. dependency injection). 

Please provide something like an IExecutableExtensionFactory. 

In the style of e4 it could be an annotation like @Create which can specify arbitrary parameters which would be provided by e4.  

Example:

class MyFactory { 
  @Create
  MPart constructTheRealPart(Component parent, ModelService s) {
     ....
  }
}
Comment 1 Oleg Besedin CLA 2010-12-03 09:50:28 EST
Sorry, I don't understand this.

We are not changing how extension registry work. I'd like to do taht, but that is out of scope for the 4.1. Extension registry functionality remains unchanged between 3.x and 4.0/4.1.

If you are saying that it would be nice to customize objects created in DI, then I totally agree; moreover, we alcready provide this functionality.

In a simple example:

class MyPart { 
  @Inject
  public MyPart(Component parent, ModelService s) {
     ....
  }
} 

you can also add "@PostConstruct" method to "finalize" creation/injection process:

class MyPart { 
  @Inject
  public MyPart(Component parent, ModelService s) {
     ....
  }

  @PostConstruct
  public void init(@Optional ISelection initialSelection) {
     ....
  }
} 

you can have a factory classes by using IBinding:

InjectorFactory.getDefault().addBinding(MyPart.class).implementedBy(MyFactory.class)

or using ContextFunctions:

public class MyFactory extends ContextFunction {
 public Object compute(IEclipseContext context) {
  MPart result = ContextInjectionFactory.make(MyPart.class, context);
  doWhatever(result);
  return result;
}

Is there something missing?

(Note: factory functions are a bit more "advanced" topic and related APIs might change.)
Comment 2 Sven Efftinge CLA 2010-12-03 10:36:45 EST
E4 replaces a couple of extension points with the workbench model. E.g. action handlers are now contributed by the means of a workbench model snippet (or whatever you call it).

In Equinox the bundle where the contribution comes from can take care of the creation and initialization of objects. This is not possible in e4.

I suggest to allow to declare a factory instead of the actual type, such that e4 creates the factory and after that calls a certain method in order to obtain the real contributed object (e.g. action handler).

Some of the comments in Bug 331556 might help to understand my enhancement request.
Comment 3 John Arthorne CLA 2010-12-03 10:48:33 EST
I think the only thing missing is the magic line at the end, that checks if the constructed object is actually a factory, in which case it is replaced with the real part. This is the corresponding line in the extension registry:

// Deal with executable extension factories.
if (result instanceof IExecutableExtensionFactory)
	result = ((IExecutableExtensionFactory) result).create();

I don't think there is a corresponding place in e4 where the contributed object can be replaced. I imagine a simple change in somewhere like InjectorImpl#internalMake:

if (newInstance instanceof FactoryObject)
  newInstance = ((FactoryObject)newInstance).create();

I.e., we actually perform our injection into a factory object, which then creates the real object.
Comment 4 Paul Webster CLA 2012-01-04 08:09:02 EST
Can we look at this in M5?

PW
Comment 5 John Arthorne CLA 2012-04-24 11:11:02 EDT
Please review target milestone and bump to > 4.2 if appropriate.