With eclipse services we can achieve exactly that with very little overhead. This article is based on the online documentation on services.
Source code for this tutorial is available on github as a single zip archive, as a Team Project Set or you can browse the files online.
Step 1: Creating the service definition
Start with a new Plug-in Project called com.codeandme.customservice. On the Extensions tab of your plugin.xml add a new extension to org.eclipse.ui.services.
Step 2: Creating the service
We want to declare our service through an interface so we could easily exchange the implementation. Therefore create a new interface com.codeandme.customservice.ICustomService. Declaration of specific methods depends of what your service should provide and is not important for this example.
For the implementation create a new class com.codeandme.customservice.CustomServiceImpl with following content:
package com.codeandme.customservice; public class CustomServiceImpl implements ICustomService { private static CustomServiceImpl fInstance = null; public static CustomServiceImpl getInstance() { if (fInstance == null) fInstance = new CustomServiceImpl(); return fInstance; } private CustomServiceImpl() { } }Go back to your plugin.xml and set the serviceClass to com.codeandme.customservice.ICustomService.
Step 3: Creating a service factory
Create a factory class com.codeandme.customservice.CustomServiceFactory:
package com.codeandme.customservice; import org.eclipse.ui.services.AbstractServiceFactory; import org.eclipse.ui.services.IServiceLocator; public class CustomServiceFactory extends AbstractServiceFactory { public CustomServiceFactory() { } @Override public Object create(@SuppressWarnings("rawtypes") Class serviceInterface, IServiceLocator parentLocator, IServiceLocator locator) { if (serviceInterface.equals(ICustomService.class)) return CustomServiceImpl.getInstance(); return null; } }Head back to your plugin.xml and set factoryClass to com.codeandme.customservice.CustomServiceFactory. Our final service declaration looks like this:
<?xml version="1.0" encoding="UTF-8"?> <?eclipse version="3.4"?> <plugin> <extension point="org.eclipse.ui.services"> <serviceFactory factoryClass="com.codeandme.customservice.CustomServiceFactory"> <service serviceClass="com.codeandme.customservice.ICustomService"></service> </serviceFactory> </extension> </plugin>
Step 4: Using the service
When your application needs a service instance it can directly query the service locator with following snippet (from within a view):
ICustomService customService = (ICustomService) getSite().getService(ICustomService.class);Or globally with:
ICustomService customService = (ICustomService) PlatformUI.getWorkbench().getService(ICustomService.class);The source files for this article contain a separate Plug-in using the service.
Final thoughts
At first sight you don't gain a lot with this approach. Real world examples often would separate service definition and implementation into different Plug-ins. When the service is used through its interface and accessed through the ServiceLocator your clients do not have any dependency to the factory or the implementing class. This lets you easily exchange the implementation without altering the clients.
As found in the documentation a service factory might provide different services but for a dedicated serviceClass there may exist only one factory. Such a thing could be done by declaring your own extension points.
It might be a drawback that for services you need a dependency to UI Plug-ins.
No comments:
Post a Comment