Channels ▼
RSS

Design

Customizing Xtext


Using Dependency Injection

As an image helper may keep some sort of cache, it is likely a singleton. Furthermore, there may be different implementations of the image helper; for example, one using the plug-in's image registry when run within Eclipse. So the question is: How do I get the currently valid implementation of the image helper?

Eclipse 3.x usually uses static methods or global singletons for these kinds of components. The disadvantages of this approach have been discussed often. You cannot easily provide another implementation of that service, as the default is hard wired. It is also impossible to have separate implementations for different usage scenarios (e.g., multiple Xtext languages within the same Eclipse workbench).

In Xtext, we use Dependency Injection (DI) to wire up all the components of the runtime infrastructure of a language. From the client's side, DI means that instead of instantiating or resolving a needed component yourself, you simply declare a dependency to its interface and leave the rest of the work to the framework.

How does that help us with the image helper? Xtext's DI is based on Google Guice. A dependency is declared by means of an @com.google.inject.Inject annotation. We just declare a field and annotate it. Then we use this injected instance in the usual way:

public class DomainmodelOutlineTreeProvider 
	extends DefaultOutlineTreeProvider {

	...

	@Inject 
	private IImageHelper imageHelper;
	
	protected Image _image(Entity e) {
		return imageHelper.getImage("Entity.gif");
	}
	protected Image _image(DataType d) {
		return imageHelper.getImage("DataType.gif");
	}
	protected Image _image(PackageDeclaration p) {
		return imageHelper.getImage("PackageDeclaration.gif");
	}
	protected Image _image(Feature f) {
		return imageHelper.getImage("Feature.gif");
	}
}

With some additional EMF magic, our outline tree provider reads as:

public class DomainmodelOutlineTreeProvider 
	extends DefaultOutlineTreeProvider {
	
	protected void _createChildren(DocumentRootNode parentNode,
			Domainmodel domainmodel) {
		for(AbstractElement element: domainmodel.getElements()) {
			createNode(parentNode, element);
		}
	}
	
	protected void _createNode(IOutlineNode parentNode, 
			Import modelElement) {
	}
	
	@Inject 
	private IImageHelper imageHelper;
	
	protected Image _image(EObject e) {
		return imageHelper.getImage(e.eClass().getName() + ".gif");
	}
}

If you run this code, you'll see that it produces the desired outline view.

Dependency Injection Configuration

Now that we've seen how simple DI looks from the client's side, let's have a look at how it is configured. In Guice, the component in charge of managing DI is called the Injector. Almost all objects in the Xtext runtime are created by an Injector, and thus are automatically wired. Rather than accessing the Injector directly, you should have the needed dependencies injected and make sure your own components are instantiated by the Injector only. Think twice before calling a constructor.

The Injector is configured with a Module, which defines the bindings of interfaces to implementing classes. Xtext puts a thin layer on top of the Guice modules to allow overriding bindings using the Generation Gap Pattern. As Xtext languages are also usable in non-Eclipse scenarios, we have two modules for each language: One for a for plain Java environments and another for Eclipse (Figure 2). Only the latter binds all the editor-related components.

Figure 2: The module hierarchy with regular POJOs and Eclipse modules.

Have a look at code of the DomainmodelUiModule: It is where you define your own custom bindings or override the generated or the default bindings. The class is generated once and will not be touched by further runs of the code generator. It inherits from the generated AbstractDomainmodelUiModule, which contains all the bindings that are regenerated when you run Xtext's code generator. Here, you will find a method:

// contributed by OutlineTreeProviderFragment
public Class<? extends IOutlineTreeProvider> bindIOutlineTreeProvider() {
	return DomainmodelOutlineTreeProvider.class;
}

The OutlineTreeProviderFragment — defined in your MWE2 workflow — created the above binding and the skeleton of the DomainmodelOutlineTreeProvider we have just brought to life.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video