Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse 4 » Provide multiple service implementations via ContextFunction?
icon5.gif  Provide multiple service implementations via ContextFunction? [message #1745467] Tue, 11 October 2016 09:06 Go to next message
Roman Zimmer is currently offline Roman ZimmerFriend
Messages: 27
Registered: November 2010
Junior Member
Hey @ll,

for our e4 RCP application I created several plugins. One should be responsible to provide domain specific service implementations (interface + implementation class), which should be injectable in the other plugins. I started with one service, which I could successfully add to the MApplication's context using a ContextFunction as described in Eclipse 4 Context Functions - Tutorial. This works as expected, the service is successfully injected for example in the UI plugin.

Now to my question: Is it possible to provide multiple services via the plugin's component.xml, e.g. by declaring multiple ContextFunctions? If yes, how do you do it?

I could think of these approaches:

  • "Hijack" the plugin's ContextFunction and register multiple service implementations at the IEclipseContext instance of the MApplication'. But which object is to return via compute()?
  • Create different components, each providing exactly one service implementation. This feels like too much overhead for the given use case...


I'm grateful for every hint or suggestions to best practices! Thank you in advance!

PS: Eclipse Neon is used as development and target platform for the RCP application.

[Updated on: Tue, 11 October 2016 09:17]

Report message to a moderator

Re: Provide multiple service implementations via ContextFunction? [message #1745475 is a reply to message #1745467] Tue, 11 October 2016 10:54 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2902
Registered: July 2012
Senior Member
First, it is a bad practice to keep interface and implementation class in the same bundle/plugin.
Second, why do you use a ContextFunction for this? Do you need access to other objects available in the context (e.g. application model components)? Otherwise simply create multiple different services.

Regarding your questions:
Quote:
Is it possible to provide multiple services via the plugin's component.xml

One component XML file, one service. A ContextFunction is only a special type of declarative service that supports access to the EclipseContext. So the answer is no. There is nothing like a "plugin's context.xml", but you can have multiple component XML files to specify multiple services in one plugin.

Quote:
"Hijack" the plugin's ContextFunction and register multiple service implementations at the IEclipseContext instance of the MApplication'.

That doesn't make sense. You can not register multiple service instances in the EclipseContext. You can register multiple services in the ServiceRegistry. But in fact you could use a ContextFunction to determine the service that should be returned based on a context value. That is the purpose of a ContextFunction, to deliver an object based on the context.

Quote:
Create different components, each providing exactly one service implementation. This feels like too much overhead for the given use case.

Well, when you are talking about components, than it should be exactly like that. But then there is no need for a ContextFunction! In that case you would simply create declarative service implementations that are registered in the ServiceRegistry. I'm not sure about your use case, as you didn't specified it, but for me it sounds like you don't need a ContextFunction. You need declarative services!

If you specify multiple service implementations for the same interface you would still have the issue which service would be returned on injection in the UI (part, handler, etc.). Using Eclipse injection mechanisms the answer would be to use a ContextFunction.
Re: Provide multiple service implementations via ContextFunction? [message #1745486 is a reply to message #1745475] Tue, 11 October 2016 13:28 Go to previous messageGo to next message
Roman Zimmer is currently offline Roman ZimmerFriend
Messages: 27
Registered: November 2010
Junior Member
Thanks for your clarifying words! I'm relatively new to these technologies and as it seems I misunderstood and mixed up some concepts.

My use case is that I want several (service) objects I define in one bundle/plugin to be injectable in a RCP application and other plugins using e4 DI via @Inject or ContextInjectionFactory.inject().

For example, let's say I have the following plugin which should provide the service instances, optionally as singletones:

org.example.services
├── plugin.xml
├── META-INF
│   └── MANIFEST.MF
└── src
    └── org
        └── example
                └── services
                    ├── DomainModelServiceImpl.java
                    ├── DomainModelService.java
                    ├── TestSpecificationServiceImpl.java
                    └── TestSpecificationService.java


(BTW: Consider this just for simplicity, you're totally right about keeping interfaces and implementations together in one bundle is bad practice!)

In the the e4 RCP application bundle I want to use instances like this:

public class ModelHandler {

	@Inject
	private DomainModelService domainModelService;

       @PostConstruct
       public void init() {
          	Model model  = domainModelService.createNewModel("NEW");
                ....
       }
}

or
public class AddTestCaseHandler {

	@Execute
	public void execute(@Optional @Named(IServiceConstants.ACTIVE_SELECTION) TopicCluster topicCluster,
			TestSpecificationService testSpecificationService) {
		TestCase newTestCase = testSpecificationService.createTestCase(topicCluster);
		EditorHelper.openModelElement(newTestCase);
	}
...

}


Then there might be other non-ui bundles, where I want to access these instances via @Inject, ContextInjectionFactory.inject() or ContextInjectionFactory.make(TestSpecificationService.class, context).

I guessed that this is only possible if I register these instances at the IEcpliseContext and to get access to the context I should implement it using ContextFunction. So if I get you right, in org.example.services I just could add more component*.xml files under OSGI-INF to make these service classes injectable. Would just adding @Creatable to the service classes without using ContextFunction at all have done the trick, too?

Nevertheless, I have to dig deeper into ServiceRegistry, declarative services and obviously ContextFunctions, I guess.

Thanks again for your support, very appreciated!

[Updated on: Tue, 11 October 2016 13:33]

Report message to a moderator

Re: Provide multiple service implementations via ContextFunction? [message #1745488 is a reply to message #1745486] Tue, 11 October 2016 13:36 Go to previous messageGo to next message
Dirk Fauth is currently offline Dirk FauthFriend
Messages: 2902
Registered: July 2012
Senior Member
Before you are moving into the wrong direction you could have a look at my blog post about Declarative Services: http://blog.vogella.com/2016/06/21/getting-started-with-osgi-declarative-services/

But in combination with e4 DI the issue you will face is that you will only get the first registered service from the OSGi IEclipseContext. ATM there is no way to distinguish which service you will get via injection. But you could for example implement a ContextFunction that references all your registered services, and based on context informations it returns the corresponding service.
Re: Provide multiple service implementations via ContextFunction? [message #1745491 is a reply to message #1745488] Tue, 11 October 2016 13:59 Go to previous messageGo to next message
Roman Zimmer is currently offline Roman ZimmerFriend
Messages: 27
Registered: November 2010
Junior Member
Thanks a lot for your blog post, which I obviously missed while collecting more information about this topic. I will make my way through it and in combination with your input, I'm positive to come to a good and clean solution for my project. Thank you!
Re: Provide multiple service implementations via ContextFunction? [message #1782874 is a reply to message #1745491] Fri, 02 March 2018 18:56 Go to previous message
Darrel Karisch is currently offline Darrel KarischFriend
Messages: 14
Registered: July 2012
Junior Member
One should be able to define a IContextFunction Component with multiple service.context.key values:

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="com.multi.service.context.function">
   <implementation class="com.multi.service.MultiServiceContextFunction"/>
   <service>
      <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
   </service>
   <property name="service.context.key">
   	com.multi.service1
   	com.multi.service2
   </property>
</scr:component>


It appears that simple changes to EclipseContextOSGi where it references SERVICE_CONTEXT_KEY could make this work. As it is, the code assumes there is only one service.context.key value.

It should not be too difficult to imagine a use case where this is desirable, if only for convenience.
Previous Topic:Unable to install local updates
Next Topic:DirectMenuItem corresponding class is initializing twice
Goto Forum:
  


Current Time: Wed Apr 24 21:17:34 GMT 2024

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

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

Back to the top