The Eclipse context can supply not only services but also dynamically calculated values. These are supplied via an interface IContextFunction
. 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.ContextFunction; import org.eclipse.e4.core.contexts.IEclipseContext; public final class RandomFunction extends ContextFunction { @Override public Object compute(final IEclipseContext context) { return Math.random(); } }
Activator
, currently a service ordering 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. Declarative services are discussed in more detail in Appendix A, Using OSGi Service to Dynamically Wire Applications.
The implementation class should extend ContextFunction
, as the interface IContextFunction
is marked as @NoImplement
. This allows additional methods to be added; for example, in Eclipse 4.3, a new method was added to the interface compute(IEclipseContext, String)
which was also added to the ContextFunction
parent class. Java 8 adds default methods, which means this pattern is less likely to occur in future.
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 declarative services, 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 declarative services implementation notices this header, reads the service document and then creates the class. This class then becomes available through the E4 context for inclusion in injection of parts.
Note that the value of the 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.
18.222.184.162