Karsten's Blog

November 21, 2011

Xtext 2.1.1 artifacts available on Eclipse Maven repository

Filed under: Maven, Xtext — kthoms @ 11:42 AM

Until now it was always a struggle to make Xtext (or Eclipse) artifacts available on a public available repository. It seems that this has now finally found a good end.

Today Achim Demelt pointed me to a Google+ posting from Dennis Huebner (our Xtext build manager) where he announced that Xtext artifacts are now automatically available on the Nexus repository at maven.eclipse.org.

The given POMs have all dependencies from their bundle manifests. This is the recommended “Maven way”, but you may face that too many dependencies are pulled transitive, and you may have to cut them down by explicit exclusions. I haven’t tested this with the new repository, but this is what I experienced when doing a similar approach earlier with Xtext 2.0.1, whose artifacts are deployed on the Fornax Repository. Use the dependency:tree plugin, or better M2E, to identify possible exclusions.

November 1, 2011

EclipseCon 2011 warmup

Filed under: Xtext — Tags: , , , , , — kthoms @ 11:07 PM

EclipseCon is just about to start and I am glad that I can make it this year. I have the chance to present Project Spray on thursday (Nov 3rd, 11:30 AM Bürgersaal 2) together with Jos Warmer. Spray aims to provide tooling to facilitate the creation of visual editors based on the Graphiti framework by the use of Xtext based DSL and Xtend code generator. You can basically compare it with what GMF Tools does for GMF, just with a DSL based approach.

EclipseCon Europe 2011

The project was founded at this year’s Code Generation conference, and Jos contributed an initial state of Spray derived from a customer’s project back in August. Since then the project team refactored the code base quite a bit. We are still in an early project phase. Most of the development is done in spare time yet, like Open Source projects often start. That was quite tough besides my full packed work schedule. Many hours on train or evenings in the hotel were spent to push this project.

At the moment I am just about to release version 0.3.0 of the Spray SDK, which I will use for our demo on thursday. Of course we want to gain a large audience. I am honest enough to say that attendees won’t see a production ready tool yet, but of course it is in working state. Jan announced a pie fight for visual tooling, I am ready to open my mouth wide enough to catch the incoming pies.

For our session we don’t want to start any discussion on graphical editing vs. visualization, whether GMF is better than Graphiti, or DSL / code generation vs. framework approach. There is always a niche for everything, and we are confident that Spray fills one of these gaps.

Besides what an end user actually can do with Spray at this moment there are quite some hidden gems in the project. I am using Spray to have also a non-trivial example for Eclipse Modeling tooling. You will find, for example

At EclipseCon I will take the chance to exchange with some experts in the fields of Modeling, especially Xtext and Graphiti. I will lay another focus on Build systems, especially Maven. Besides that there are many other interesting talks, far more than I can attend. And not to forget to meet all the other Eclipse enthusiasts. See you there!

October 6, 2011

Xtext, Maven and Source Control

Filed under: Maven, Xtext — Tags: , , — kthoms @ 6:39 PM

Although I more and more use Git for source control, I face Subversion still frequently in daily life. I follow the rule that I don’t want to check in what can be generated in a headless build, where I usually use Maven. Xtext projects have the source folders src-gen and xtend-gen, where generated sources go to. Further, you will usually have 3 projects: The grammar project, the UI project and a test project.

In this article I will show some guidelines that I follow when checking in Xtext projects into source control.

Handling the src-gen folder

The content of src-gen can be produced during a build, so I do not check in the content of it. What needs to be considered is that is no good idea to ignore the folder completely, since it would be missing when fresh checking out the project. This leads to an incomplete build path, and the MWE2 workflow is not executable from Eclipse until the folder was created. This is because the .mwe2 file needs to be on the project’s classpath, which is not the folder src, but the output folder, bin or target/classes. It will be copied automatically with default workspace settings only when the build path is complete. This behavior can be changed in the workspace / project settings in Java / Compiler / Building.

If you rate down build path problems to warning level or just disable build abortion on errors, the .mwe2 file will be copied anyway to the target folder. If using project specific settings you could even check in these settings and share it in the team.

I prefer to check in the src-gen folder, but avoid that any content gets checked in. To do so, add the folder with svn add, but none of its content! Best you do this immediately after the Xtext project was created. After the folder was scheduled for adding, you can set the svn:ignore property to value “*”.

The xtend-gen folder

At the moment it is not possible to compile .xtend files during a Maven build, so the content of xtend-gen must be checked in and handled like handcrafted sources. To cut this story short: Xtend and Java files depend usually on each other. Xtend files cannot be compiled until Java sources from the same project were compiled, and some Java sources will depend on about-to-be-compiled Xtend sources. So the Java source compilation fails, aborting the build.

I hope to solve this problem soon.

Some ignore patterns

On the root of each of the 3 Xtext projects, set the property svn:ignore to this value:

bin
target
.DS_Store
plugin.xml_gen

Configure Maven clean plugin

When running mvn clean on your project you would like to to clean up all derived resources. The target folder will be removed by default, but this is not enough. The content of the src-gen folders must be cleaned up as well. This can be done by configuring the maven-clean-plugin. One thing to consider is that Xtext has 3 projects. It is not correct to configure the clean plugin for all 3 projects due the lifecycle of a Maven build: The projects will be build after each other, executing all lifecycles per project. If you execute a “mvn clean install” this would have the effect that

  1. clean is called on the grammar project
  2. in phase generate-sources the Xtext implementation classes are produced to all 3 projects
  3. the sources for the grammar project are compiled
  4. now the build continues with the next module, e.g. the UI project
  5. the project will be cleaned, removing the previously generated sources
  6. compilation fails, since the generated sources are missing now

For this reason the clean plugin must be configured only in the grammar project, and it should clean up the sources from all 3 projects. Now comes again a detail related to source control: Since we want to have the src-gen checked in, we have to avoid that the SCM related folders and files are removed. Otherwise this would confuse your SCM system. So these files must be excluded from deletion. This leads to the following configuration:

<plugin>
  <artifactId>maven-clean-plugin</artifactId>
  <configuration>
    <filesets>
      <fileset>
        <directory>src-gen</directory>
        <includes>
          <include>**</include>
        </includes>
        <excludes>
          <exclude>.svn/**</exclude>
          <exclude>.gitignore</exclude>
        </excludes>
      </fileset>
      <fileset>
        <directory>../${project.artifactId}.ui/src-gen</directory>
        <includes>
          <include>**</include>
        </includes>
        <excludes>
          <exclude>.svn/**</exclude>
          <exclude>.gitignore</exclude>
        </excludes>
      </fileset>
      <fileset>
        <directory>../${project.artifactId}.tests/src-gen</directory>
        <includes>
          <include>**</include>
        </includes>
        <excludes>
          <exclude>.svn/**</exclude>
          <exclude>.gitignore</exclude>
        </excludes>
      </fileset>
    </filesets>
  </configuration>
</plugin>

September 28, 2011

Moving an Xtend generator into its own plugin

Filed under: Xtext — Tags: , — kthoms @ 9:23 AM

One of the nice things that you get when starting an Xtext project is an Xtend based generator that is automatically invoked when you save an Xtext model file. The Xtend generator for your language resides in the .generator subpackage of your language. The problem with that is that it is usually no good idea to have the generator bundled with your language. It is a completely seperate feature which is reasonable to put it in an own plugin. Further, the DSL plugins must not depend on the generator plugin, the dependency must be vice versa. This article describes the steps that need to be done for this.

As a reference take the sources from project Spray. There you can find an concrete example where the described steps have been applied.

Create the generator plugins

Create two additional plugins: One for the runtime part of the generator, one for the UI contributions.

Generator runtime plugin

Move everything from the .generator subpackage of your DSL runtime project to the generator plugin. (In Spray this is org.eclipselabs.spray.generator.graphiti). The dependencies are the same as in the DSL runtime project, but add the DSL runtime plugin as additional dependency (see this MANIFEST.MF as reference). Don’t forget to add an xtend-gen source folder to the project.

Guice module for runtime plugin

Create a Module class extending AbstractGenericModule in the runtime plugin. In this module at least the IGenerator implementation class must be bound.

public class GraphitiGeneratorModule extends AbstractGenericModule {
    public Class<? extends org.eclipse.xtext.generator.IGenerator> bindIGenerator() {
        return SprayGenerator.class;
    }
    ...
}

Generator UI plugin

The UI plugin must basically bind the JavaProjectBasedBuilderParticipant in its own module and register it through the org.eclipse.xtext.builder.participant extension point. These steps are required:

UI Guice Module

Create a module class extending AbstractGenericModule and bind JavaProjectBasedBuilderParticipant:

public class GraphitiGeneratorUIModule extends AbstractGenericModule {
    private final AbstractUIPlugin plugin;
    
    public GraphitiGeneratorUIModule (AbstractUIPlugin plugin) {
        this.plugin = plugin;
    }

    @Override
    public void configure(Binder binder) {
        super.configure(binder);
        binder.bind(AbstractUIPlugin.class).toInstance(plugin);
        binder.bind(IDialogSettings.class).toInstance(plugin.getDialogSettings());
    }
    /**
     * Bind the JavaProjectBasedBuilderParticipant in order to invoke the generator during the build.
     */
    public Class<? extends org.eclipse.xtext.builder.IXtextBuilderParticipant> bindIXtextBuilderParticipant() {
        return org.eclipse.xtext.builder.JavaProjectBasedBuilderParticipant.class;
    }

    ...
}

Activator class

Create a class Activator which creates a Guice injector from the modules:

  1. DSL runtime module
  2. org.eclipse.xtext.ui.shared.SharedStateModule
  3. DSL UI module
  4. Generator runtime module
  5. Generator UI module
public class Activator extends AbstractUIPlugin {
	private Injector injector;
	private static Activator INSTANCE;

	public Injector getInjector() {
		return injector;
	}
	
	@Override
	public void start(BundleContext context) throws Exception {
		super.start(context);
		INSTANCE = this;
		try {
		    injector = Guice.createInjector(Modules2.mixin(new SprayRuntimeModule(), new SharedStateModule(), new SprayUiModule(this), new GraphitiRuntimeModule(), new GraphitiGeneratorModule(), new GraphitiGeneratorUIModule(this)));
		} catch (Exception e) {
			Logger.getLogger(getClass()).error(e.getMessage(), e);
			throw e;
		}
	}
	
	@Override
	public void stop(BundleContext context) throws Exception {
		injector = null;
		super.stop(context);
	}
	
	public static Activator getInstance() {
		return INSTANCE;
	}
	
}

Open the manifest editor. On the “Overview” page enter the Activator class name. Also check the options “Activate this plug-in when one of its classes is loaded” and “This plug-in is a singleton”.

ExecutableExtensionFactory

Create a class ExecutableExtensionFactory. Since this class won’t be public API it is a good approach to put it into an internal package.

public class ExecutableExtensionFactory extends AbstractGuiceAwareExecutableExtensionFactory {

	@Override
	protected Bundle getBundle() {
		return Activator.getInstance().getBundle();
	}
	
	@Override
	protected Injector getInjector() {
		return Activator.getInstance().getInjector();
	}
	
}

plugin.xml

Add a plugin.xml with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.4"?>
<plugin>
   <extension
         point="org.eclipse.xtext.builder.participant">
      <participant
            class="org.eclipselabs.spray.generator.graphiti.ui.internal.ExecutableExtensionFactory:org.eclipse.xtext.builder.IXtextBuilderParticipant">
      </participant>
   </extension>
</plugin>

Check that the ExecutableExtensionFactory class name matches yours.

Remove the GeneratorFragment

Open the .mwe2 workflow of your DSL project. Remove the entry for the GeneratorFragment:

// Code generator
fragment = generator.GeneratorFragment {
  generateJavaMain = false 
  generateMwe = false
  generatorStub = true 
}

Now regenerate the DSL.

Add binding for IWorkspaceRoot

The generator fragment contributes a binding for IWorkspaceRoot to the UI Module of your DSL, which is required by the builder participant. Therefore this binding must be added manually to your UI Module.

public class SprayUiModule extends AbstractSprayUiModule {
    ...
    public org.eclipse.core.resources.IWorkspaceRoot bindIWorkspaceRootToInstance() {
        return org.eclipse.core.resources.ResourcesPlugin.getWorkspace().getRoot();
    }
}

Result

As a result your DSL plugins should have no dependencies on your generator plugin. When you save a model file in your Eclipse instance with the deployed plugins the code generator should be invoked. The pattern described here would also allow to create multiple generator plugins for the same DSL which are invoked independently when building the project. Each of them registers its own builder participant and invokes its own generator.

September 13, 2011

Setting template file encoding in Xpand workflow

Filed under: Xpand — kthoms @ 2:14 PM

A typical problem when running Xpand is file encoding of the Xpand templates. Xpand uses guillemot brackets («»), which are not available in all character sets. Often, ISO-8859-1 and UTF-8 are good choices for encoding Xpand templates. However, on Mac the default encoding is MacRoman, and I would recommend to change that for interoperability reason. I would recommend changing the resource encoding setting on the root folder containing Xpand templates, or even the project, and checking in the settings. This way the encoding is shared amongst team members.

When executing the Xpand generator with MWE it is important that the templates are read with the right encoding. Otherwise you will get an error like this:
org.eclipse.internal.xtend.xtend.parser.ParseException: no viable alternative at character '�' on line 159
Xpand’s Generator component has a property fileEncoding, but this is the encoding used by the outlets to write files. If you need to change the behavior for reading files, you need to set the encoding value of the ResourceManager. The configuration is like this:

MWE1:


    ...




MWE2

  component = org.eclipse.xpand2.Generator {
    ...
    resourceManager = org.eclipse.xtend.expression.ResourceManagerDefaultImpl {
     	fileEncoding = "ISO-8859-1"
    }
  }

August 17, 2011

Using Xtext injected types in Xpand

Filed under: Xpand, Xtext — kthoms @ 12:57 PM

During a project migration I stumbled over the need to access the IScopeProvider from an Xtext based language within Xtend(1) extensions that are used from Xpand templates. This is not quite how Xpand would work out-of-the-box, so here is an approach to solve it.

InjectableGenerator

I subclassed org.eclipse.xpand2.Generator and called it InjectableGenerator. The intention is to register a global variable for a configurable set of types (e.g. the IScopeProvider). The name of the variable is the class name that should be get from Guice. To add injectors, instances of ISetup are registered to the component, similar to Xtext’s org.eclipse.xtext.mwe.Reader component.

The hook that is used to register the global variables to Xpand’s execution context is the method getGlobalVars(WorkflowContext ctx), which is overridden here.

package org.eclipselabs.xtext.xpand;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.emf.mwe.core.WorkflowContext;
import org.eclipse.xpand2.Generator;
import org.eclipse.xtend.expression.Variable;
import org.eclipse.xtext.ISetup;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.inject.ConfigurationException;
import com.google.inject.Injector;

/**
 * Allows Xtext based dependency injection. Injected instances are registered as
 * global vars to the Xpand Execution Context.
 */
public class InjectableGenerator extends Generator {
	private List<Injector> injectors = Lists.newArrayList();

	public void addRegister(ISetup setup) {
		injectors.add(setup.createInjectorAndDoEMFRegistration());
	}

	protected List<Injector> getInjectors() {
		return injectors;
	}
	
	private Set<Class<?>> injectedTypes = Sets.newHashSet();

	public void addInjectGlobalVar (String className) {
		try {
			Class<?> clazz = Class.forName(className);
			injectedTypes.add(clazz);
		} catch (Exception e) {
			throw new IllegalArgumentException("Invalid type: "+className);
		}
	}
	
	@Override
	protected Map<String, Variable> getGlobalVars(WorkflowContext ctx) {
		Map<String, Variable> result = super.getGlobalVars(ctx);
		// try to get an instance of each configured type
		for (Class<?> clazz : injectedTypes) {
			boolean configured = false;
			for (Injector injector : injectors) {
				try {
					Object obj = injector.getInstance(clazz);
					result.put(clazz.getName(), new Variable(clazz.getName(), obj));
					configured = true;
				} catch (ConfigurationException e) {
					; // ignore
				}
			}
			if (!configured) {
				throw new IllegalStateException("Could not configure instance of "+clazz.getName());
			}
		}
		return result;
	}
}

Workflow Configuration

In your workflow configuration you would of course now use the specialized Generator component. It could be used like this:

...
component = org.eclipselabs.xtext.xpand.InjectableGenerator {
   register = my.dsl.MyDslStandaloneSetup {}
   injectGlobalVar = "org.eclipse.xtext.scoping.IScopeProvider"
   // injectGlobalVar = ... other types
   
   // further configuration of Xpand Generator
}

Execution context aware Java extensions

It is not possible to directly access the ExecutionContext from within Xpand templates or Xtend functions. We need to delegate to Java extensions. The classes that we delegate to must implement the IExecutionContextAware interface. The setExecutionContext(ExecutionContext ctx) method is the right place to retrieve the IScopeProvider and bind it to an instance variable.

public class MyExtensions implements IExecutionContextAware {
	protected IScopeProvider scopeProvider;

	@Override
	public void setExecutionContext(ExecutionContext ctx) {
		if (ctx.getGlobalVariables().get("scopeProvider")!=null) {
			this.scopeProvider = (IScopeProvider) ctx.getGlobalVariables().get("scopeProvider").getValue();
		} else if (ctx.getGlobalVariables().get(IScopeProvider.class.getName())!=null) {
			this.scopeProvider = (IScopeProvider) ctx.getGlobalVariables().get(IScopeProvider.class.getName()).getValue();
		} else {
			throw new IllegalStateException("No IScopeProvider found as global var in the execution context");
		}
	}

	// add (non-static!) extension methods here!
        public List<EObject> someMethod (org.eclipse.emf.ecore.EObject context) {
          ... do something
        }
}

Note that we also query the global variable named “scopeProvider” here. This is because in another context (i.e. Check based validation) the same extension would be used with another execution context. The InjectableExecutionContext binds the IScopeProvider to that name.

It might be a good idea to have an abstract base class for these Extension classes.

Now you can use the methods defined in the Java extension class and access the required instances from your language configuration within.

// file: MyExtensions.ext
List[emf::EObject] someMethod (emf::EObject ctx) : JAVA MyExtensions.someMethod(org.eclipse.emf.ecore.EObject);

July 12, 2011

Xtend – Generating from multiple input models

Filed under: Xtext — kthoms @ 8:52 PM

Xtext’s integration of Xtend based code generators is nice. If you save changed (or add/remove) DSL model files an incremental build will automatically be triggered and even removes derived artifacts if you remove the source from which it is generated. The IGenerator interface takes a Resource, and you can generate 1 or multiple target artifacts from the model elements within that resource.

However, the API does not allow to create a single artifact from multiple input models. But this is a common use case if you do serious code generation. I will show you how you could extend Xtext’s Domainmodel example to generate a simple text file that lists the name of all Entity instances of all .dmodel files that are reachable in the built project.

Adding an extended generator interface

Create an interface IGenerator2 that extends the IGenerator interface:

public interface IGenerator2 extends IGenerator {
	/**
	 * @param input - the input for which to generate resources
	 * @param fsa - file system access to be used to generate files
	 */
	public void doGenerate(ResourceSet input, IFileSystemAccess fsa);
}

The generator class will later implement this interface and generate a single artifact from all Entity instances in all resources.

Extending the JavaProjectBasedBuilderParticipant

The JavaProjectBasedBuilderParticipant is used by default to invoke the IGenerator implementation that was bound to the runtime module. We will extend this class to add additional logic and inject an IGenerator2 instance that will be invoked once per triggered build.

The builder participant is an UI concept, so create the extended class JavaProjectBasedBuilderParticipant2 in the UI plugin:

package org.eclipse.xtext.builder;

import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.builder.JavaProjectBasedBuilderParticipant;
import org.eclipse.xtext.generator.IFileSystemAccess;
import org.eclipse.xtext.generator.IGenerator2;
import org.eclipse.xtext.resource.IContainer;
import org.eclipse.xtext.resource.IResourceDescription;
import org.eclipse.xtext.resource.IResourceDescription.Delta;
import org.eclipse.xtext.resource.IResourceDescriptions;
import org.eclipse.xtext.resource.impl.ResourceDescriptionsProvider;

import com.google.inject.Inject;

public class JavaProjectBasedBuilderParticipant2 extends JavaProjectBasedBuilderParticipant {
  @Inject
  private ResourceDescriptionsProvider resourceDescriptionsProvider;

  @Inject
  private IContainer.Manager containerManager;

  @Inject (optional=true)
  private IGenerator2 generator;

  protected ThreadLocal<Boolean> buildSemaphor = new ThreadLocal<Boolean>();

  @Override
  public void build(IBuildContext context, IProgressMonitor monitor) throws CoreException {
    buildSemaphor.set(false);
    super.build(context, monitor);
  }

  @Override
  protected void handleChangedContents(Delta delta, IBuildContext context, IFileSystemAccess fileSystemAccess) {
    super.handleChangedContents(delta, context, fileSystemAccess);
    if (!buildSemaphor.get() && generator != null) {
      invokeGenerator(delta, context, fileSystemAccess);
    }
  }

  @Override
  protected void handleDeletion(Delta delta, IBuildContext context, IFileSystemAccess fileSystemAccess) {
    super.handleDeletion(delta, context, fileSystemAccess);
    if (!buildSemaphor.get() && generator != null) {
      invokeGenerator(delta, context, fileSystemAccess);
    }
  }

  private void invokeGenerator (Delta delta, IBuildContext context, IFileSystemAccess fileSystemAccess) {
    buildSemaphor.set(true);
    Resource resource = context.getResourceSet().getResource(delta.getUri(), true);
    if (shouldGenerate(resource, context)) {
      IResourceDescriptions index = resourceDescriptionsProvider.createResourceDescriptions();
      IResourceDescription resDesc = index.getResourceDescription(resource.getURI());
      List<IContainer> visibleContainers = containerManager.getVisibleContainers(resDesc, index);
      for (IContainer c : visibleContainers) {
        for (IResourceDescription rd : c.getResourceDescriptions()) {
          context.getResourceSet().getResource(rd.getURI(), true);
        }
      }

      generator.doGenerate(context.getResourceSet(), fileSystemAccess);
    }
  }
}

Note that IGenerator instance will be invoked once per changed resource, so potentially multiple times. We have to make sure that the IGenerator2 instance will be invoked just once. Therefore a thread local semaphor flag will be queried before the generator is called. In this scenario it does not matter whether a change or deletion should be handled. The generator always processes the whole model once.

The most important thing is to populate the BuildContext’s ResourceSet with all relevant model resources. It is important here collect the resources that are in scope of the built project. The right way to do this is to use the language’s IContainer.Manager to collect the resources that are within the visible containers. Each of them is queried for its contained IResourceDescription instances, from which the Resource instances are created.

Extending the generator class

Now open the generator class DomainmodelGenerator and implement IGenerator2. Add an implementation of the method from the extended interface:

...
// makes allContentsIterable available
import static extension org.eclipse.xtext.xtend2.lib.ResourceExtensions.*
...

class DomainmodelGenerator implements IGenerator2 {
  ...
  override void doGenerate(ResourceSet rs, IFileSystemAccess fsa) {
    val Iterable<Entity> entities = rs.resources.map(r|r.allContentsIterable.filter(typeof(Entity))).flatten

    fsa.generateFile("entities.txt", entities.compile)
  }

  def compile (Iterable<Entity> entities) '''
    «FOR e : entities SEPARATOR ", "»«e.name»«ENDFOR»
  '''

  ...
}

Guice configuration

Now bind the extended builder particpant in the UI module:

public class DomainmodelUiModule extends AbstractDomainmodelUiModule {
	@Override
	public Class<? extends IXtextBuilderParticipant> bindIXtextBuilderParticipant() {
		return JavaProjectBasedBuilderParticipant2.class;
	}
}

… and the generator to the Runtime module:

public class DomainmodelRuntimeModule extends AbstractDomainmodelRuntimeModule {
	public Class<? extends IGenerator2> bindIGenerator2 () {
		return DomainmodelGenerator.class;
	}
}

Result & Conclusion

After restarting your runtime workspace the generator will produce an “entities.txt” file to the src-gen folder of a project with .dmodel files, which will simply list the names of all found Entity instances.

This scenario is quite common, so it would be great if the Xtext framework could provide built-in support for that. I have therefore raised a feature request.

July 7, 2011

Game Development – A whole new area for Eclipse Modeling?

Filed under: Eclipse, MDSD, Uncategorized, Xtext — Tags: , , — kthoms @ 3:15 PM

The Eclipse Modeling Project provides the world’s leading set of tools and frameworks that are used for successfully applying model driven software development techniques in various areas. Successful adoption are known in Enterprise Computing, Embedded System Development, Mobile Development etc. But what about Game Development? I have not heard about Game productions that use Eclipse Modeling or Model Driven Software Development in general so far. I cannot know about all projects in the world, but at least it is an indicator that this development technique is at least not wide adopted in the branch of Game Development.

Game Development is highly complex, developed in multidisciplinary teams under high time pressure and quality requirements. And the complexity is even growing, whilst time pressure also. Time-to-market is everything there. If your game comes too late, you are out. If you don’t use the latest technologies, you are lame. How could such projects ever be successful just by coding and hacking? I could imagine that game developers are just too busy with developing their games in a traditional way to think how they could gain speed and quality by applying software engineering techniques like MDSD.

I would not wonder if they associate MDSD with drawing UML diagrams and wasting time clicking and drawing useless stuff. Model Driven Software Development is everything else than useless. It helps raising the level of abstraction, speeding up development and gaining quality. If applied correctly, of course. Of course they think their kind of software development is special and completely different than other disciplines. But let me say, it’s not the case. Every piece of software has generic parts, schematic parts and parts that don’t fit into one of the previous sections. And for the schematic parts, MDSD can always help. Don’t tell me that a multi-million, mission-critical enterprise project is less challenging than game development.

One of the most promising things for game development can be the usage of Domain Specific Languages (DSLs), especially textual ones. With Xtext 2.0 the development of textual DSLs with tight integration of expression languages and code generators has become easier than ever before. If you don’t ever tried Xtext, do it!

On October 4th there will be an interesting workshop at the 10th International Conference on Entertaining Computing (ICEC 2011) in Vancouver, Canada. The “1st Workshop on Game Development and MDSD” will bring experts from both worlds together. The Call for Position Papers is running now, deadline is July 30th. If you are in one of those businesses, submit a propopsal or attend the workshop. I think both “worlds” can really win a lot from working together. This workshop could be a good start.

July 5, 2011

Xtext 2.0 / Xpand 1.1 plugins available as Maven artifacts

Filed under: Maven, Xpand, Xtext — Tags: , , , , — kthoms @ 5:22 AM

It’s now one week after release of Eclipse Indigo, and with that Xtext 2.0 and Xpand 1.1. For those who use Maven without Tycho to build projects using these frameworks it is of course necessary to have all related plugins available in some Maven repository.

With the help of the osgi-to-maven2 project I was now able with some tweaks to create the necessary POMs and deploy scripts for the plugins. What osgi-to-maven2 basically does is to analyze the plugin manifests and create POMs for them including dependencies. The project is not maintained at the moment and has a problem especially with the parsing of the plugins org.eclipse.ui.views and org.eclipse.ui.workbench, which have some strange directives in the Export-Package section where I could not find documentation about. The underlying manifest parser from Springsource (com.springsource.util.osgi) vomits when parsing those manifests, and also upgrading to the latest release does not help. Time to open a bug.


Export-Package: org.eclipse.ui;mandatory:="ui.workb
ench",org.eclipse.ui.about,org.eclipse.ui.actions;ui.workbench=split;
mandatory:="ui.workbench",org.eclipse.ui.activities,org.eclipse.ui.ap
plication,org.eclipse.ui.branding,org.eclipse.ui.browser;ui.workbench
=split
;mandatory:="ui.workbench",org.eclipse.ui.commands,org.eclipse.

Also the osgi-to-maven2 tool does not handle absent optional libraries so far.

The Xtext 2.0, Xpand 1.1 and dependent plugins are available at the Fornax Platform’s repository http://fornax-platform.org/nexus/content/groups/public/ under the groupId org.eclipse.plugins.

Based on the deployed plugins it should be possible to setup a plain Maven build for Xtext 2 based projects.

May 30, 2011

Spray – a quick way to create Graphiti

Filed under: Eclipse, Uncategorized, Xtext — Tags: , , , — kthoms @ 6:34 AM

Last week was the CodeGeneration 2011 conference in Cambridge/UK, the melting pot for model driven development. It was once again a great conference, even bigger and more inspiring than the recent years. You will find some good summaries of the conference and the Language Workbench Competition workshop in the blogs from Angelo Hulshout, Johan den Haan and Marco Brambini.

At this conference I had an experience report talk together with Bernhard Merkle from Sick (“Graphiti + Xtext: mixing graphical and textual DSLs for sprayers/designers“) on wednesday, where we discussed the integration of Xtext and Graphiti for combining textual and visual DSLs. It is also obvious for us that although Graphiti – more maybe because – has a quite good API the work to actually create Graphiti based editors is repetitive and thus a candidate for code generation and a more abstract description by a DSL. On thursday Marko Boger, former grounder of Gentleware and now professor at the University of Konstanz, showed how they developed exactly such tooling (i.e. textual DSLs with Xtext and code generators with Xpand) to create visual modeling tools. In fact, the newest version of Poseidon for UML was created that way and with the developed tooling visual DSLs can be developed very fast. However, they generate against their own Poseidon runtime and wish to change that to Graphiti in the future. Right after that session, Jos Warmer showed in his talk “Developing an Insurance Product Modeling Workbench” that he already did that for his current customer. Means, he has developed a DSL with Xtext and code generators with Xpand that create Graphiti editors.

There was obviously high interest in this approach, thus we scheduled a Birds-of-a-feather session for thursday evening in the Castle Inn Pub nearby to discuss model-driven development of Graphiti DSLs. About 20 persons crowded the far to small table, and we had a lively discussion.

As a result we decided to join our efforts in an Open Source project. Jos named his DSL “Spray” and I think this is a perfectly fitting name for the project. Further we decided to host that project at Eclipselabs, since parts of it will be potentially contributed to Graphiti or its umbrella project, the Graphical Modeling Project.

The BoF session thus was the birth of project “Spray“. Right after the BoF session was the conference dinner, and I founded the project on my iPhone while waiting for entrance. Maybe this is the first Eclipse related project founded with the iPhone? Jos subtitled it with “a quick way to create Graphiti”, which again perfectly describes what the project will be about. He already uploaded an overview of Spray (extracted from his CG2011 presentation) , and its implementation will be soon contributed as a first version of Spray. We contacted the Graphiti team about our idea and got positive feedback and even one developer who wants to contribute to the project. Also the internal feedback at itemis showed that the project may find some volunteers here.

The overwhealming high interest in contributing to this project is of course good, but now the project must challenge to actually find a concrete vision. Jos’ contribution will be a good start for that, and the experience and requirements of the other interested parties will hopefully be constructive and shape the project. This is a great chance to create something really useful together with real experts on every needed skill. I hope to find enough time myself to contribute and maybe even customers who have a concrete need for it, so that we can provide a working solution in the near future.

Project Spray: http://code.google.com/a/eclipselabs.org/p/spray

« Newer PostsOlder Posts »

The Silver is the New Black Theme Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 375 other followers