The Eclipse context can supply not only services but also dynamically calculated values. These are supplied via an interface IContextFuction
. By registering a service with that class name, and a key name with the service.context.key
it is possible to create a value upon request.
RandomFunction
which extends ContextFunction
and which returns a random value:package com.packtpub.e4.application; import org.eclipse.e4.core.contexts.IContextFunction; import org.eclipse.e4.core.contexts.IEclipseContext; public final class RandomFunction extends ContextFunction { @Override public Object compute(final IEclipseContext context) { return Math.random(); } }
Activator
, but currently a bug prevents this from happening. Instead, register it using declarative services. Create a file called random.xml
in a folder called OSGI-INF
with the following content:<?xml version="1.0" encoding="UTF-8"?> <scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="math.random"> <implementation class="com.packtpub.e4.application.RandomFunction"/> <service> <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/> </service> <property name="service.context.key" type="String" value="math.random"/> </scr:component>
OSGI-INF
folder to the build.properties
, to ensure that it gets added when the bundle is built:bin.includes = OSGI-INF/, META-INF/,
META-INF/MANIFEST.MF
:Service-Component: OSGI-INF/*.xml
Hello
part, add the following:@Inject @Named("math.random") private Object random; @PostConstruct public void create(Composite parent) { label = new Label(parent, SWT.NONE); label.setText(window.getLabel() + " " + random); }
The IEclipseContext
can acquire calculated values as well as values inserted into the runtime. The calculation is done through a function, registered with the IContextFunction
interface—though currently the only way to register it is with the declarative services model, as shown previously.
The implementation class should extend ContextFunction
, as the interface IContextFunction
is marked as @NoImplement
. This allows additional methods to be added. In Eclipse 4.3, a new method was added to the interface compute(IEclipseContext,String)
which was also added to the ContextFunction
parent class.
The OSGi declarative services API allows a service to be created and made available to clients that need to use it. To register a service with DS, a service document is created (in the example this is random.xml
), and it is referred to with the Service-Component
header in the MANIFEST.MF
file. When the plug-in is installed, the DS component notices this header, reads the service document, and then creates the class. This class then becomes available through the E4 context for inclusion in the injection of parts.
Note that the value of the calculated function is cached upon first calculation. So even if the code is changed to inject the value as a method parameter, only the first value calculated will be seen. Although the IEclipseContext
has a method to remove the value, it doesn't necessarily trigger the removal from all contexts. The recommendation is to use an OSGi service for data that must be calculated each time.