× Home Tutorials Training Consulting Products Books Company Donate Contact us









NOW Hiring

Quick links

Share

Eclipse Application Model contributions. This tutorial explains how to define a context function in Eclipse 4 RCP applications.

1. Prerequisites

The following assumes that you have already basic Eclipse RCP development experience. See the http://www.vogella.com/tutorials/Eclipse4RCP/article.html - Eclipse RCP Tutorial for details.

2. Context functions

2.1. What are context functions?

A context function is an OSGi service which has access to the IEclipseContext of the requester. It allows you to lazily create an object for a given key, if this key is not contained in the relevant IEclipseContext.

The context function registers itself for a certain key, for example a class name. Whenever the Eclipse dependency injection does not find an existing object under this key, it calls the compute() method of the context function.

Context function query

In this compute() method the context function can create the requested object. As input you receive the local IEclipseContext in which the injection was invoked and the requested key.

It can also persist the created object into the context, so that successive calls will return the same generated object.

2.2. Creation of a context function

Context functions can be contributed as OSGi services. They extend the ContextFunction class from the org.eclipse.e4.core.contexts package. The Eclipse runtime adds context functions by default to the application context.

They register itself as OSGi service for the IContextFunction interface.

Question: Why should you register your service for the IContextFunction interface but extend the ContextFunction class?

Answer: If the interface gets extended by a new methodyour service continues to work, as the abstract class ContextFunction can provide a default implementation.

You need to specify the key the context function is responsible for. This is done via the service.context.key property in the service definition.

If the key is a class you have to point to the fully qualified class. This key can be used for dependency injection. If you register a key which is not a class name, a consumer of the injection can use the @Named annotation to specify the key.

2.3. Examples for context function registrations

The following example shows the declaration of a context function. This function is available in the application context and responsible for the vogella key.

<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"
        name="com.example.e4.rcp.todo.contextservice.translate">

<implementation class="com.example.e4.rcp.todo.contextservice.Test"/>

 <service>
   <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
 </service>

 <property name="service.context.key" type="String"
   value="vogella"/>

</scr:component>

This key can be used for dependency injection as demonstrated in the following example.

// field injection
@Inject @Named("vogella") Todo todo;

The following example demonstrates a possible implementation of this context function which used OSGi DS annotations.

package com.example.e4.rcp.todo.services.internal;

import org.eclipse.e4.core.contexts.ContextFunction;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IContextFunction;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.model.application.MApplication;
import org.osgi.service.component.annotations.Component;

import com.example.e4.rcp.todo.model.ITodoService;

@Component(name="TodoServiceContextfunction", service=IContextFunction.class,
property="service.context.key=com.example.e4.rcp.todo.model.ITodoService")
public class TodoServiceContextFunction extends ContextFunction {
        @Override
        public Object compute(IEclipseContext context, String contextKey) {
                ITodoService todoService =
                                ContextInjectionFactory.make(MyTodoServiceImpl.class, context);

                MApplication app = context.get(MApplication.class);
                IEclipseContext appCtx = app.getContext();
                appCtx.set(ITodoService.class, todoService);

                return todoService;
        }
}

2.4. When to use context functions?

A context functions can access the IEclipseContext hierarchy. This allows them to lazily create objects using values from the context.

Standard OSGi services have no direct access to the IEclipseContext.

2.5. Publishing to the OSGi service registry from a context function

OSGi services may need to access the objects created by a context function. In this case you can also publish an OSGi service from a context function.

The following example demonstrates how to publish an implementation into the IEclipseContext and to the OSGi service registry.

package com.example.e4.rcp.todo.services.internal;

import org.eclipse.e4.core.contexts.ContextFunction;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.model.application.MApplication;

import com.example.e4.rcp.todo.model.ITodoService;

public class TodoServiceContextFunction extends ContextFunction {
        @Override
        public Object compute(IEclipseContext context, String contextKey) {

                // create instance of ITodoService with dependency injection
                ITodoService todoService =
                                ContextInjectionFactory.make(MyTodoServiceImpl.class, context);

                // add instance of ITodoService to context so that
                // test next caller gets the same instance
                MApplication app = context.get(MApplication.class);
                IEclipseContext appCtx = app.getContext();
                appCtx.set(ITodoService.class, todoService);

                // in case the ITodoService is also needed in the OSGi layer, e.g.
                // by other OSGi services, register the instance also in the OSGi service layer
                Bundle bundle = FrameworkUtil.getBundle(this.getClass());
                BundleContext bundleContext = bundle.getBundleContext();
                bundleContext.registerService(ITodoService.class, service, null);

                // return model for current invocation
                // next invocation uses object from application context
                return todoService;
        }
}

3. Learn more about Eclipse 4 RCP development

I hope you enjoyed this tutorial. You find this tutorial and much more information also in the Eclipse 4 RCP book.

4. About this website

5.2. vogella GmbH training and consulting support

TRAINING SERVICE & SUPPORT

The vogella company provides comprehensive training and education services from experts in the areas of Eclipse RCP, Android, Git, Java, Gradle and Spring. We offer both public and inhouse training. Whichever course you decide to take, you are guaranteed to experience what many before you refer to as “The best IT class I have ever attended”.

The vogella company offers expert consulting services, development support and coaching. Our customers range from Fortune 100 corporations to individual developers.

Copyright © 2012-2016 vogella GmbH. Free use of the software examples is granted under the terms of the EPL License. This tutorial is published under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Germany license.

See Licence.