Time for action – calculating values on demand

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.

  1. Create a class called 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();
      }
    }
  2. To allow E4 to recognize the function, register an instance with the OSGi runtime. Although this could be done within the 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>
  3. Add the OSGI-INF folder to the build.properties, to ensure that it gets added when the bundle is built:
    bin.includes = OSGI-INF/,
                   META-INF/,
  4. To allow declarative services to load and create the component, add this header into META-INF/MANIFEST.MF:
    Service-Component: OSGI-INF/*.xml
  5. Finally, inject this value into the application. In the 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);
    }
  6. Run the application, and this time, the Hello tab starts out with a random value appended to the window's title text. Each time the application is started, a different value is calculated.

What just happened?

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

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.184.162