Monday, November 19, 2012

Xtext tip: How do I get the Guice Injector of my language?

This post is about one of the most frequent mistakes people are making when starting to use Xtext beyond the basic functionality. I stumble across this in our newsgroup about three times a week.

The problem usually starts by the necessity to load a file in your language in the UI, lets say in a custom action. You already know that in Xtext everything is wired up with dependency injection (DI), and that you need a DI configured XtextResourceSet to load a model. So you start looking for an Injector to create your XtextResourceSet and find that one is returned by the generated [DSL]StandaloneSetup.createInjectorAndDoEMFRegistration(). This seems to work fine first, but in the followoing you'll get a lot of strange errors. Things that worked before are suddenly broken.

A variant of the error – more popular among former oAW users – is to run a generator MWE2 workflow containing such a [DSL]StandaloneSetup from the UI.

Never ever use the [DSL]StandaloneSetup for your language within Eclipse!


Why not? Xtext relies on EMF and EMF uses on a bunch of global registries to work. E.g. the EPackage.Registry for the implementation classes for EPackages or the Resource.Factory.Registry for parsers for model files. These are global singletons, and they are usually populated by means of Eclipse extension points, e.g. org.eclipse.emf.ecore.generated_package or org.eclipse.emf.ecore.extension_parser. If you run a standalone Java application – the term standalone means without equinox here – there is no concept of extension points. That means you have to register the DSL to EMF's registries yourself. This is what the [DSL]StandaloneSetup is meant for. If you're using it within Eclipse, you'll overwrite the contributions from the extension points with new instances from the standalone setup. This will crash your application. 

It gets even worse: Xtext has a couple of singletons, too, but they are not global but scoped within the (singleton) Injector of your language. If you just create a new Injector, you'll end up with two instances for all of these singletons. This will likely hit you badly.

Finally, some Xtext components have different implementations for Eclipse and for standalone mode. E.g., Xtext's Java reflection layer (aka JVM model) uses JDT's Java model in Eclipse and Java Reflection in standalone mode. The Injector from the standalone setup will register different implementation classes, thus also breaking functionality.

So how do I use dependency injection in Eclipse properly then?


The Equinox aware Injector you're looking for can be obtained from the Activator of your language (in the UI plug-in). But it would be bad advise to just tell you to go there. You should rather use DI properly. If you think about where to get the Injector you're most often already on the wrong track.

A central aspect of DI is not to care about object creation at all, but just declare dependencies (via @Inject in Guice). Every dependency that is injected will also be created by the Injector so its own dependencies will be created on-demand and injected recursively. As a result, in a well-designed application using DI, there is only one entry class that is explicitly created or populated by the Injector and the rest is automatically DI aware as it is injected somewhere.

IDE components in Eclipse are usually registered by contributing to an extension point with an executable extension, usually an attribute with name class, for example

   <extension point="org.eclipse.ui.editorActions">
      
      <editorContribution targetID="..." id="...">

         <action
 class="[some class extending IActionDelegate]"
  
   ... 

Xtext generates a so called executable extension factory for you that will instantiate the given class using the Injector, so use

  ... class="[DSL]ExecutableExtensionFactory:[some class name]"

and the class will be generated with all its dependencies injected. This is also covered in the documentation.

If there is no such extension point, and your class is not yet instantiated using DI, you might have to access the Injector via the Activator and use it to inject all dependencies, i.e.

   [DSL]Activator.getInstance().getInjector("").injectMembers(this);

Note that you should only have to do this for the entry class, from which all other components are injected. If you have to use the Injector, make sure it is only once.

How do I use DI in tests?


There is a whole section on using DI in tests in the documentation. I am not going to repeat this here. The base configuration requires using JUnit4 and is automatically generated for your language has been created with a recent version of Xtext. If not, make sure to add

   pathTestProject = "[DSL].tests" 

in the section on paths in your MWE2 workflow and

   // generates junit test support classes into Generator#pathTestProject
   fragment = junit.Junit4Fragment {}
 


to the fragments and regenerate. This will create the preconfigured test plug-in. Use the InjectorProvider for standalone tests and the UiInjectorProvider for plug-in tests. Once again, your code should not show any references to an Injector.

And the Injector of another language?


Sometimes, you want to switch to a service implementation from another language, e.g. when your DSL allows cross references to another. Usually, you are in the DI context of one language and have an URI to a resource or element of the other language at hand. In this case use the IResourceServiceProvider.Registry:

   @Inject IResourceServiceProvider.Registry reg;

and use that to get the component, e.g. to get the default ILabelProvider

   ILabelProvider otherLangLabelProvider = 
      reg.getResourceServiceProvider(otherLangURI)
           .get(ILabelProvider.class);

Thursday, July 12, 2012

Seven Languages By Seven Geeks

One of the most powerful new features of Xtext is the capability to build languages for the JVM. In my opinion, these languages are a real breakthrough in domain-specific language design:
  • These DSLs directly interoperate with Java. They compile to Java code and allow to refer to Java artifacts.
  • They not only cover structural aspects but also behavior. DSLs become really powerful with a rich expression language offering today what Java has been missing for years, like type inference, lambda expressions, extension methods etc.
  • Complicated integration patterns like Generation Gap or Protected Regions become obsolete. Everything can be expressed on the same level of abstraction
  • They offer top-notch Eclipse-based tooling and integrate into the Java IDE. Switch between the DSL and the Java code during debugging, refactor across multiple languages, navigate to source etc.
Yet we have the impression that the concept and the benefits of JVM DSLs have not been well understood and adopted. This is why we decided it was time for another example and documentation offensive. The result is the 7 Languages project: Seven example JVM languages highlighting the benefits of this approach in various use cases of Java development:
  1. A scripting language. Write code without any boilerplate.
  2. A build language similar to Gradle but statically typed.
  3. JavaBeans facades for mongoDB objects.
  4. A DSL to define Guice modules.
  5. A language to route HTTP requests with conditions, variables and dependency injection.
  6. A template language
  7. A LOGO-like turtle drawing environment.
Clone or fork the code from github and enjoy the documentation on theXtext website.

Wednesday, March 28, 2012

EclipseCon 2012 - I have had my share

I am at EclipseCon 2012, this year at Reston (VA). I have just finished my parts and can now relax and take it easy for the remainder of the conference.

Yesterday I gave a a tutorial on "DSLs for Xtext Developers" together with Sebastian. Around 50 participants learnded how to wirte their own DSLs that run on the JVM and integrate tightly with Java. Looking at the feedback so far, this was a real success, even thought it was a whole lot of stuff. Have a look at the slides:





Today I talked about "A Fresh Look at graphical Editing". In comparison to the talk at EclipseCon Europe, I changed the focus a bit and spent more time to make clear, why most graphical model editors really suck. This time I seem to have made my point, at least noone has asked me so far to convert the Generic Graph View framework into a model editor. The new features, like multitouch gestures and discovery diagrams went fine, too. Here are the slides



Wednesday, January 18, 2012

Impressions on GEF

For the Generic Graphical View project I've been digging deep into the Graphical Editing Framework (GEF) lately. GEF is the base technology below almost any graphical framework in the Eclipse environment. I wanted to keep the tool stack as low as possible and have the maximum control on everything so I decided to use GEF directly. Here are my impressions.

I really like GEF's base architecture: The separation between Draw2D and GEF, the concepts of Tools, Requests, EditParts and EditPolicies. It helps you to find the component to change in order to implement a new feature quickly. The pictures in the GEF online help really help
understanding this.


Pecularities

In some areas GEF appears to be kind of rusty. A whole bunch of relevant commercial products has been relying on it for years. Long term backward API compatibility has taken its toll. Some things definitely need a serious overhaul and often a better naming. I am very happy to hear that a 3.0 version is planned. Here is my wishlist for improvements:
  • Make coordinates double by default. Integer coordinates often result in rendering glitches due to rounding errors and are not well suited for scaling.
  • Add alpha channel (transparency) support.
  • Revise scaling of fonts: Sometimes a label's bounds don't match its text's extend.
  • Rename methods of the update mechanism. I am often confused about the semantics validate(), invalidate(), invalidateTree() or revalidate().
  • Rectangular bounds are not well suited for round things like ellipses. Similar to that, clipping child figures only makes sense for Viewports but nothing else. The need of an invisible container figure for side affixed children is really an ugly workaround.
  • Diagram layout does not take connection labels into account.
  • Add support for curve connections.
  • The feedback figures - the surrogates when a figure is moved or resized - seem to come from a time where hardware graphics acceleration was pure luxury. If you have nested edit parts you might have to reimplement the nested figure construction twice for nicer feedback.
  • Using a bit less inheritance and more composition would be fine.


Mutable Geometric Primitives

As many other graphics frameworks, GEF code tries to create as little new objects as possible. Geometrical primitives such as points, dimensions and rectangles are therefore mutable and reused often. There are even things as a static Rectangle.SINGLETON for temporary calculation. This pretty much reminds me of good old C++. I am not sure whether such optimization is still necessary. It results in pretty unreadable code:
Point p = figure.getLocation(); 
// p is the location in local coordinates
p.getParent().transformToParent(p);
// now p is in parent coordinates
Point q = p.add(p).scale(2):
// this will also modify p
You see: As the semantics of the variable changes, it is no surprise you cannot find a more expressive name than p. In addition, you have to be very careful if you are dealing with a reference or a copy. Modifying a Translatable (once again bad name, as Dimension also implements this interface) directly can also circumvent an event mechanism. This is really error prone. I'd strongly advise to introduce immutable primitives.


Coordinate Transformations

The way transformation between local, global and parent coordinates are handled is somehow unsuggestive. I've used various 2D and 3D scenegraph-based frameworks but I never got as confused with coordinates as in GEF. For example, if you have a ScalableLayeredPane showing some scaled content, its translateToAbsolute(Point) method will not take the scaling into account while translateToParent(Point) will.


Some Hints

Starting with GEF from zero is hard. You will likely spend a serious amount of time debugging why your diagram doesn't show anything at all. Better copy some basic setup from one of the GEF examples. Here are my favorite pitfalls:
  • missing minimum size on figure - figure does not show up at all in some layouts
  • wrong coordinate system - figures don't appear where they should, somtimes in nirvana
  • wrong layout manager, e.g. a plain XYLayout on a FreeformFigure - results in endless layout loop
  • reusing a geometry element instead of making a copy - completely unpredictable editor behavior
  • the default ChangeBoundsRequest does not take local coordinate systems into account
For better diagram layout algorithms the KIELER project offers a good choice.

Multitouch Gestures in the Generic Graph View

In my previous post, I've already described the discovery mechanisms of the Generic Graphical View project: Starting from one node you can step by step reveal other connected nodes in the same model. The model itself is fixed - it is still a view! - but the user can decide herself which subset of elements should appear in the diagram. That behavor allows to create diagram views focussed on a specific semantic aspect of the model.

The challenge is to find a decent UI for nodes wich have several hidden connections. How should a user select any subset of these?

Since the Helios release SWT supports four multitouch gestures: PAN, ZOOM, SWIPE and ROTATE. On my Mac's touchpad these gestures are actually easier to perform than a conventional drag operation because there is no extra mouse button. So I decided to give it a try and have a look how gestures could be used in the graph view. Here is a screencast showing the results:



SWT's multitouch API is fairly simple (example snippet). The first step was to add multitouch events to GEF, such that the can be handled in the same way as mouse or keyboard events. I had to extend a couple of GEF classes. If you're interested in the details, have a look at the classes in the package org.eclipse.xtext.graphview.behavior.gestures and the GraphViewRootEditPart.

These changes allow to use a ZOOM gesture on a ScalableFreeformRootEditPart.
Note that the PAN gesture is already supported by GEF because the FigureCanvas uses hardware scrolling. Unfortunately, these event is always consumed, such that it will not make it through to other GEF elements.

The ZOOM gesture can also be used to drill down into elements. If the mapping defines an open reference to another diagram, you can drill down by selecting it and performing the ZOOM in gesture. If you‘re inside a drill down diagram, you can ZOOM out into the container diagram.

Any Tool can now handle multitouch gestures by implementing the IViewerGestureHandler interface. For a DragTracker this makes no sense, as it is exited as soon as the mouse key is released and you cannot start a drag and a multitouch gesture simultaneously.

The RevealGestureTool works as follows: Click on the + button to reveal the hidden connected elements, Then use ROTATE or SWIPE to rotate elements, ZOOM to change the distance and right-click to select and pin individual elements. Another click will commit the input.

Discovery Diagrams for the Generic Graphical View

If you've read my previous posts or seen my presentation at EclipseCon Europe 2011, you'll already know the Generic Graphical View framework: Using two Xtext-based DSLs - one for mapping semantic to graphical elements and the other for styling the figures - you can easily create nice looking diagrams for any Java based model.


In its first version the contents of the diagram was entirely defined in the mapping DSL. It was only possible to restrict the visible elements to a subset of the model by adding filtering expressions in the mapping. For bigger models it was hard to focus on a subset that is not structural defined but based on semantics, e.g. all classes that deal with addresses in a CRM application.

Many graphical frameworks handle the selection of the visible elements in a diagram by means of dialogs. The user is then forced to switch between keyboard and mouse which is annoying, and these dialogs are often complicated and unintuitive. The goal for the Generic Graph View project was to build a UI for choosing the diagram contents that uses the mouse or trackpad only and avoid dialogs at all cost. The following screencast demonstrates the basic functionality.



As a first step, actions were introduced that allow to hide existing graphical elements - nodes, labels or connections. If you hover over an element, you'll get an popup button allowing to remove it from the view. So you can start with a big diagram and strip it down to what you want to see. Once an element inside a node has been removed, you can restore the node completely using another popup button. You can define elements as initially hidden using a hidden flag in the mapping definition.

In addition to the subtractive approach, you can step by step extend the diagram contents from an initial node. If you're hovering over a node that has hidden connection, several + buttons will popup. When one of these buttons is triggered, the hidden elements and connections will appear in transparent arranged in a circle around the source element. In the same drag operation you can change the distance and the angle of that circle. This behavior will get really cool with multitouch gestures, which I will cover in a separate post.