Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [equinox-dev] Question about DI/ DS and Application model

Pascal,

I think there are deeper problems here than just the lifecycle. Neither DS nor the Eclipse extension registry were particularly designed to work together.

In DS objects are created for only two purposes: (a) To be published to the world as a service, and/or (b) to have an independent lifecycle delimited by activate/deactivate method, giving the object the opportunity to, say, open a socket, run a polling thread, etc. If an object is neither published nor "active", then there is no point in DS creating it!

The extension registry is not so different. Let's disregard pure metadata extensions that do not have some kind of class attribute. An extension is a little factory that is published to the world much like services are, albeit with some additional notions of scope provided by extension point IDs. Extensions do not have an independent lifecycle, so their only purpose is to be published.

These worlds are separate. Imagine for a moment trying to do the opposite of what you ask: invoke an extension-contributed class from a DS-instantiated component. The component cannot be injected with the extension, so it would have to go to the extension registry explicitly and run a query just like everybody else. Now flip it back to your problem, the extension registry always instantiates objects directly or via an IExecutableExtensionFactory (IEEF); we cannot tell it to pick a service instead. So you have to go to the service registry explicitly and run a query.

Actually there are tricks we can perform with IEEF that will allow us to grab services, by specifying an OSGi service filter string in the configuration data for the IEEF. I have experimented with this approach and actually gave some demos at EclipseCon 07. But there is a further impedence mismatch: extensions are factories and consumers of extensions expect to get a new object each time, whereas services are reused. Try reusing an IPreferencePage object... you'll get SWT Widget Disposed errors the second time you open the prefs dialog.

An alternative approach that might work for you is to use the new Blueprint Container. In Blueprint, not every bean needs to be published as a service, but the container itself for a bundle is published as a service and allows access to the beans within. Martin Lippert wrote a reusable IEEF that worked exactly this way with Spring-DM before Blueprint existed; I'm sure it can be updated to the new API. Furthermore Blueprint solves the problem of reuse of objects: any bean can be declared with prototype scope, turning it into a mini-factory where a new instance is created on each request.

Neil


On Thu, Sep 17, 2009 at 7:46 PM, Pascal Rapicault <Pascal_Rapicault@xxxxxxxxxx> wrote:

I agree that for this particular example where only one service is acquired the usage of DS is probably overkill. However if several services had been needed, I think it would have probably been better to use DS over writing all the service handling manually.
As for the relevance of the example, I would argue that it is very relevant as this is probably the simplest thing that one can do: write a little piece of code that uses services to perform a task and then maybe make it available as a application (or an action, or...). It does not need nor want to publish a service.

At this point the two root causes seem to be:
- The only way for DS to provide the objects resulting from the injection is through services and this is cumbersome and ends up polluting the service space.
- Bridging the service and extension world so that created extensions can get things injected to them.

I looked at the code in the solution3 package and if I understand it correctly, it seems to be an implementation of 1.2 since the RepositoryDumper is registered by DS and then acquired by the application itself.

PaScaL

Inactive hide details for John Arthorne---09/16/2009 09:58:08 PM---Eventually someone has to decide which implementation of IMeJohn Arthorne---09/16/2009 09:58:08 PM---Eventually someone has to decide which implementation of IMetadataRepositoryManager is going to be used. I think in the case of


From:

John Arthorne/Ottawa/IBM@IBMCA

To:

Equinox development mailing list <equinox-dev@xxxxxxxxxxx>

Date:

09/16/2009 09:58 PM

Subject:

Re: [equinox-dev] Question about DI/ DS and Application model





Eventually someone has to decide which implementation of IMetadataRepositoryManager is going to be used. I think in the case of an application it is quite reasonable for the application to make this decision directly (by looking up the service, perhaps with some filter that helps to select the manager to use). By moving the lookup of IMetadataRepositoryManager into a DS component it just hides the fact that it is a simple service lookup and doesn't seem to offer any advantage.

I think because both the service declaration, the implementation, and the client are all in the same bundle it's not a particularly interesting case. However I could imagine in more complex cases something like your solution 3 would be interesting. An executable extension factory could allow the services required by an executable extension to be injected into it rather than having the extension reach out.

You'll see another package "solution3" in the bundle where I was playing around with another approach. I'm not sure it's any better than your solution 1 but you can take a look.

John


Pascal Rapicault/Ottawa/IBM@IBMCA
Sent by: equinox-dev-bounces@xxxxxxxxxxx

09/16/2009 04:00 PM

Please respond to
Equinox development mailing list <equinox-dev@xxxxxxxxxxx>

To
Equinox development mailing list <equinox-dev@xxxxxxxxxxx>
cc
Subject
[equinox-dev] Question about DI/ DS and Application model




Today I have done some more DI exploration using DS to see how it fits with the constructs we have in eclipse and I'm struggling to integrate in a nice way with the application model (I mean without using static) and I'm looking to know how others are doing this?
The one line summary of my experiment is: I have a class that does some work (named RepositoryDumper), it needs a service (RepoMgr). I want now to create an eclipse application that invokes the RepositoryDumper and I would like to not have to acquire the RepoMgr service manually.

Here is what I have been exploring with:
Solution 1:
I have an application declared in the plugin.xml. I have created a DS component that instantiates RepositoryDumper. However the question now is how does the application (remember that an eclipse application extension needs to provides n class) can get a hold of the RepositoryDumper instance that got created by DS:
- 1.1: Ugly -> Store the instance RepositoryDumper in the Activator of the plug-in
- 1.2: Get the RepositoryDumper be registered as a Service and have the application get this service. I don't like this because now RepositoryDumper is visible to everybody just so I can get access to it

Solution 2:
This solution assumes that the declarative approach to the eclipse application model is the hindrance and works around it by registering an ApplicationDescriptor (org.osgi.service.application). To do so I create a DS component that instantiates the RepositoryDumper and also register an ApplicationDescriptor as a service. This has the nice attribute that everything gets injected and that the application is only available to run if all the necessary pieces are available. However it requires a lot of code since one has to implement ApplicationDescriptor and ApplicationHandle, and I don't think this application would even be launchable using the -application argument.

Solution 3:
This solution is an hybrid between 1 and 2 using the IExecutableExtensionFactory.
There is a DS component that creates the RepositoryDumper and register a service, let's call it X. Then let's make the class specified in application extension (in the plugin.xml) implements IExecutableExtensionFactory and have it get the service X. This solution allows to have the application construction be completely done by injection however given that the application is contributed through extension registry it still is visible even though not ready to run.

How are others doing this? Is this a real problem or is it just me? Should I just not worry about that and use static fields?
Btw, the code is available /cvsroot/rt org.eclipse.equinox/incubator/p2/bundles/org.eclipse.equinox.p2.diagnostic Only solution 1 and 2 are available.

Thx for your attention and feedback

PaScaL
_______________________________________________
equinox-dev mailing list
equinox-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/equinox-dev
_______________________________________________
equinox-dev mailing list
equinox-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/equinox-dev



_______________________________________________
equinox-dev mailing list
equinox-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/equinox-dev


GIF image

GIF image


Back to the top