Wednesday, May 18, 2016

Eclipse and progress monitors - the old and the new story

Eclipse Progress Monitors - the old and the new story

For a long time, there was an solid article about how to use progress monitors which was what you got when you googled for info about the topic. Now, the old article is replace by a new version. We can argue about whether one is better than the other, but IMHO the key issue is that they describe different approaches, in where the older article can actually help you where your maintaining older code. So, here's both (thanks to the web archive):

Old article:  How to Correctly and Uniformly Use Progress Monitors

New article: Using Progress Monitors

Happy coding - keep up the progress - maybe there's someone monitoring it...

--Fredrik



Friday, January 30, 2015

Xtext and SVN - recovering from missing files when Xtext regenerates the src-gen folder

During the last 6 months I've been involved in a prototyping project using Xtext to express a DSL. This has been a really great learning experience exploring the world of Xtext. But some things are not that great. The site I'm working at uses Subversion and Xtext doesn't play perfectly with it. The key problem is that when running the "Generate Xtext artifacts" from your Xtext grammar, this regenerates the src-gen folders, i.e. deletes them and then regenerates the content. So if you've changed your grammar by renaming or removing a rule, the classes corresponding to the old rules will not be generated, which makes SVN nuts. The reason is that SVN will treat the deleted and no longer regenerated files as "missing" and thus Subversive refuses to commit them as a "Deleted file".

To recover, we can do some "magic" on the command line:
  1. Open a (cygwin) terminal (on Linux/OSX just a terminal)
  2. cd to the checked out SVN repository folder (or Eclipse project)
  3. run "svn status | grep '^! ' to list the "missing" files
  4. Now, we will revert all those files and then delete them using proper svn commands
  5. svn status | grep '^! ' | awk '{print $2}' | sed 's-\\-/-g' > MISSING.txt
    • The 'sed' expression is only necessary on Windows, since the "backslashing" will break the following commands
  6. cat MISSING.txt | xargs svn revert
  7. cat MISSING.txt | xargs svn delete
  8. Try committing again - those "missing" files should now be marked as deleted
  9. Clean up -> rm MISSING.txt
  10. Close the terminal and carry on :-)
Happy Xtext:ing!

PS: Update - created a script to automate this: https://github.com/fredrikattebrant/shell-scripts/blob/master/svn_recover_from_missing_files.sh

Thursday, October 18, 2012

Enabling UUIDs in an EMF ECore model

Enabling UUIDs in an EMF ECore model

A while back we ran into the need to start using UUIDs in our ECore models. Googling a bit led me to this nice blog on the topic. But still one little piece of the puzzle was missing, so here I go with the full recipe and example code as well.

Update: The above link is broken, try this instead!

Adding UUIDs to your favorite model

We start out using the classic Library example. 
  1. Get started by cloning it from here - checkout the "master" branch.
  2. Open the /emf.uuid.library.example/model/emf.uuid.library.example.genmodel
  3. Generate All code
  4. Run the editor and create an example library model with some elements and save it
  5. Open the save library with Text Editor and note how the references are stored:

<?xml version="1.0" encoding="UTF-8"?>
<emf.uuid.library.example:Library xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:emf.uuid.library.example="https://github.com/fredrikattebrant/emf.uuid.library.example/1.0" name="The library">
  <writers books="//@books.0" name="Fredrik Attebrant"/>
  <books author="//@writers.0" title="Using UUIDs in ECore models"/>
</emf.uuid.library.example:Library>
  1. Now, to add support for using UUIDs instead, open the genmodel and select the Library element
  2. Set the Model > Resource Type property to XMI (btw, this was the missing piece in the recipe...)
  3. Regenerate the Model code
  4. Add org.eclipse.emf.ecore.xmi to the plug-in dependencies
  5. Follow the steps described in the blog:
    1. Create a LibraryResourceImpl class (Override the useUUIDs() method)
    2. Create a LibraryResourceFactory
    3. Hook into the org.eclipse.emf.ecore.extension_parser extension point
  6. Generate All code
  7. Run the Library Editor again
  8. Open the previously save library model
  9. Make a change and save the model
  10. Open it with Text Editor again and note how all elements now have UUIDs
  11. Note how references are now stored using the UUID of the referenced elements:
<?xml version="1.0" encoding="UTF-8"?>
<emf.uuid.library.example:Library xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:emf.uuid.library.example="https://github.com/fredrikattebrant/emf.uuid.library.example/1.0" xmi:id="_sQQSEBj-EeKqFILuf-WxiA" name="The UUID library">
  <writers xmi:id="_sQQSERj-EeKqFILuf-WxiA" books="_sQQSEhj-EeKqFILuf-WxiA" name="Fredrik Attebrant"/>
  <books xmi:id="_sQQSEhj-EeKqFILuf-WxiA" author="_sQQSERj-EeKqFILuf-WxiA" title="Using UUIDs in ECore models"/>
</emf.uuid.library.example:Library>

You'll find the example library models in the "librarytests" project and in the uuid branch, you'll find the completed example with UUIDs enabled.

Happy UUID-based modeling!

References


Monday, April 2, 2012

EclipseCon 2012

EclipseCon2012 Cover

This year's EclipseCon was especially exciting because my colleague Anders and I had a talk accepted and was one of a few highlighted sessions.

Our talk was about sharing our experiences of migrating one of FindOut's tools to the new Rich Client Platform "RCP 2.0" in Eclipse 4.2:



Here are the highlights from the conference:

Monday:

The conference started out with an excellent tutorial on writing rich client applications with Eclipse RCP 4.x by Kai Toedter. He also showed that the default SWT rendering engine in the platform can be replaced with Swing. He used the Napkin theme for his contacts demo. Very impressive!


Tuesday:

Tom Schindl explained the new application platform and showed how to easily pool resources and a locale support service that he connected to google translate. The audience was asked for a language to translate to, and without restarting the application "Hello World" was switched to "Hallo Verden" (Norwegian). Impressive!

Brian de Alwis showed how to style your 4.x application with CSS. He also demoed the nifty CSS Spy and editors. For us who had little knowledge of CSS this tool came in real handy.

Alexander Ny├čen gave a comprehensive overview and history of GEF. He also explained GEF4 and the main priorities to introduce there. We were especially glad that one of the bullets was to migrate GEF to use the new 4.x application platform.

Wednesday:

e4 compatibility layer sketch
Figuring out the compat layer
Tom Schindl talked about e(fx)clipse which is a distribution of Eclipse for creating JavaFX applications. He also showed that the default SWT rendering engine in can be replaced with JavaFX.

After lunch it was time for us to present.  We were happy to see that we had about 60-70 attendees in the room. The presentation and demo went very well and we had a very good discussion with the audience during the Q/A.
Eclipse 4 BOF signup
In the evening we attended the e4 BOF which was well attended with all the key people from development and a number of users. One interesting topic was how the solve the problem of having multiple dependency injection frameworks. One example is that Xtext uses Guice. It was also noted that 4.2 is lacking a documented API, something that will be addressed in 4.3. Many of the common UI components such as the Properties view, the Project Explorer and the Preference dialog need to be migrated to the new platform services.




Thursday:

Eclipse 4 meets CDO - inspiring demo of what you can do with the modeled application. Since the application model is implemented using EMF, CDO can be used to share it between multiple users. Think instant content sharing and collaboration using the application model.

Wrap-up session
In the closing session it was revealed that the conference had 650 attendees with 360 of them first-timers. 36 countries and 41 US states were represented. There were 2972 complaints on the WiFi according to Mike Milinkovic. All of this was washed down with almost 7000 beers.

One valuable thing for us was meeting and mingling with everyone including other swedes from companies such as Ericsson, Sandvik, IAR and Oracle...

It was also great to meet the e4 team face to face. We would especially like to thank Remy Suen for fixing a bug that we ran into when migrating our application.

Finally, a special thanks to the Eclipse Foundation for yet another great Eclipse conference!

References


Wednesday, November 16, 2011

Model to model mapping transformations with RSA


During the last year, I've been working on a project developing a transformation between UML models and custom XML. The platform of choice was IBM Rational Software Architect (RSA) which provides very good support for creating model to model transformations. Although there is a pretty a good tutorial in the RSA Help, there are quite a few things that are tricky. Thus I thought that sharing some of the experience I made might help others facing similar challenges. So let's get down to business, here's what I'll cover in the blog:
  1. Getting setup and getting help
  2. Tips for structuring model-to-model mapping projects
  3. How to write custom mapping rules
  4. Pattern for managing the transformation execution lifecycle
  5. Aborting an executing transformation
  6. Pattern for reporting transformation problems
  7. Model markers and decorators
1. Getting setup and getting help

Before you get started on extending RSA, you should make sure to install the extensibility components. Tricky enough, this does not get installed by default, so fire up IBM Installation Manager, hit Modify and make sure to check the "Extensibility" feature. When this is done, you'll have access to "everything" you need to extend this already incredibly capable tool. One funny(?) quirk is that most of the RSA help is available online from IBM's InfoCenters for the various flavors of RSA. However, the help for the extensibility - including APIs, programmers reference etc is only available from the local installed help. I would suspect that this is due to the on-line help being generated from the features installed by default...

No matter what, it is convenient to use the on-line help for everything else. So here's a couple of links:

Rational Software Architect v8 on-line help
Rational Software Architect RealTime Edition v8 on-line help

Now that you have the help figured out, start out by working through the tutorial on model to model mapping transformations. This will save you a lot of time. Also, when working with the mapping model editor, make sure that you have the Outline view open - otherwise you'll have a tough time navigating through your mapping model...

2. Tips for structuring model-to-model mapping projects


The source the for the model to model mapping project is the mapping model. Typically, this is kept in a "model" folder in your model-to-model mapping project. From it, you then generate the transformation source code. In addition to this, you will typically need to write custom code. Here's where the structuring comes in handy - using a simple but clever Java package scheme, you can easily separate custom (handwritten) code from the generated code. This will allow you to simply delete all generated code to ensure that it is completely regenerated. Typical cases when this is useful, is when you remove map levels in the mapping model. Here's an example of a package structure:


mymappingdemo            - Core classes for the transformation plug-in 
mymappingdemo.custom     - Here's your handwritten custom code
mymappingdemo.conditions - You may want to keep your conditions separate
mymappingdemo.l10n       - Generated message strings
mymappingdemo.transforms - Generated transformation source code


In this example, you can safely delete all classes in the mymappingdemo.transforms package, except... Yes there is an exception. If you have modified the generated code, you will need to be careful and make sure to preserve any modified classes. In this case, you must avoid deleting any classes containing "@generated NOT" tags.


3. How to write custom mapping rules
There's two ways of writing custom rules for mapping a model element from the input model to the output model:
  1. Using the inline editor
  2. Creating a custom rule in an external Java class
Use the second alternative. The inline editor is just no good. It is really worse than a regular text editor. Instead create an external Java class and you'll have access to everything you expect when coding and debugging Java with Eclipse.

4. Pattern for managing the transformation execution lifecycle
In many cases it is useful to be able to perform operations before and after the actual transformation. In order to do this I came up with the following approach:

In the generated transformation code, there's a class MainTransform in which you can modify the constructor:


public MainTransform() { 
    super(TRANSFORM, Umlrt2ifmMessages.mainTransform);
    LifecycleManager.register();
    ...
}

Here I've added a call to register my "LifeCycleManager", a class which allows operations for controlling the lifecycle of "things". "Things" can be various caches etc which needs to be cleared before invoking the transformation.

The key reason for introducing this type of "life cycle management" was when I realized that the transformation is only instantiated once - it is a plugin! This if you depend on things being performed at invokation or at the end of a transformation, you need a way to trigger them.

Here's how my LifeCycleManager looks like:

package mymappingdemo.custom;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;

import com.ibm.xtools.transform.core.IRunTransformationListener;
import com.ibm.xtools.transform.core.ITransformContext;
import com.ibm.xtools.transform.core.RunTransformationEventManager;
import com.ibm.xtools.transform.core.extension.AbstractTransformExtensionHelper;
import com.ibm.xtools.transform.core.internal.engine.TransformRunHelper; 
/**
 * Implements lifecycle management for the transformation<br>
 * The transformation is instantiated once per RSA session, thus classes that 
 * persist objects which should not be cached/reused between invocations of 
 * the transformation must be reset (cleared). This can be done by invoking 
 * reset code in the {@link #onTransformationStart(ITransformContext)} method.
 * 
 */
public class LifecycleManager extends AbstractTransformExtensionHelper implements IRunTransformationListener {

     // singleton
     private static LifecycleManager instance;
 
     private ITransformContext transformContext;

    private LifecycleManager() {
    }

     public static LifecycleManager getDefault() {
           if (instance == null) {
                instance = new LifecycleManager();
                RunTransformationEventManager.getInstance().addListener(instance); 
           }
           return instance;
     }


     @Override
     public void onTransformationStart(ITransformContext itransformcontext) {
         this.transformContext = itransformcontext;
         //TODO: add things to perform at the start of a transformation here:
     } 

     @Override
     public void onTransformationEnd(ITransformContext itransformcontext, IStatus istatus) {
            this.transformContext = null; // nothing to cancel, transf. done
            //TODO: add things to perform at the end of a transformation here:
     }


     /**
      * Invoke this method to register the manager as a listener 
      * with the transformation framework
      * 
      */
     public static void register() {
         getDefault();
     }

}



5. Aborting an executing transformation
If we for some reason wants to abort the execution of a transformation, we can add a method  cancelTransform() to the class LifecycleManager, which has access to the transformation context and can cancel it. This can be very useful if you detect problems during the execution of a transformation. To implement this we need to modify the class LifecycleManager. First we need to add a method to support cancellation:

      /**
        * Cancels the transformation execution
        * 
        */
      public void cancelTransform() {
           if (this.transformContext == null) {
                return; // nothing to cancel
           }
           IProgressMonitor monitor = 
              TransformRunHelper.getProgressMonitor(this.transformContext);
           monitor.setCanceled(true);
      }

Unfortunately this will warn you about access restrictions, so you may want to suppress them:


@SuppressWarnings(&quot;restriction&quot;) // Necessary because of: {@link LifecycleManager#cancelTransform()}
public class LifecycleManager extends AbstractTransformExtensionHelper implements IRunTransformationListener {
    ...


Now you are ready to cancel the execution when you've detected a problem with:

LifecycleManager.getDefault().cancelTransform();

6. Pattern for reporting transformation problems


Typically, you're transformation will detect various problems when processing the input and generating the output. This can be of the typical severities info, warning and error and thus it fits right into creating problem markers. More on that in the next sections.

However, we need to deal with the fact that transformation may often be executed in headless mode and thus we do not have access to the marker framework. For this, we can use a trick described by Chris Aniszczyk (ref #1):


 
 /**
  * Detects whether running headless or not
  * @return
  */
 private static boolean isHeadless() {
  // source: http://aniszczyk.org/2007/07/24/am-i-headless/
  boolean headless = false;
  Bundle b = Platform.getBundle("org.eclipse.ui");
  if (b==null || b.getState() != Bundle.ACTIVE) {
     headless = true;
  } 
  return headless;
 }



Next we wrap this up so that we can report problems without having to think about whether we're headless or not ;-)
Here's a sniplet of code that just uses regular "syserr" to print out a message in headless mode, while it calls the problem marker utility when the UI is available:



public class ProblemReporter {
 private static boolean isHeadless() {} 
    ...
    return headless;
 }

 /**
  * Reports an error message for the given model element<br>
  * Prints to stderr in headless mode, else logs to the platform log
  * 
  * @param modelElement
  * @param message
  */
 public static void reportError(NamedElement modelElement, String message) {
   String location = modelElement.getQualifiedName();
   if (isHeadless()) {
       System.err.println("ERROR: location=" + location + ", message=" + message);
   } else {
       TransformationMarkerHelper.getDefault()
                .createErrorMarker(modelElement, message);
   }
 }




7. Model markers and decorators
In order to give the user feedback on problems detected during the transformation, we can use the IMarker framework. There's a good starting point in the article on "Mark My Words" (ref #2). However, a short entry here will not give this justice, so I'll followup with a separate post on the topic.

Happy transforming!




References:

Thursday, April 14, 2011

Hidden features in IBM Rational Software Architect (RSA)


Being a very large tool, there's also an enormous amount of "hidden features" in RSA. Here I'm going to list a few of my favorites. Starting out with:


Controlling the order of model elements in Project Explorer (PE)

By default, model elements are listed alphabetically in PE. Often good, but sometimes you just want to be able to control the order they are listed in - but how?

Well, as with some many other things, bring up the Preferences dialog (Window > Preferences) and browse to Modeling > Views > Project Explorer.
There you'll find a section on "Project Explorer settings" in which you can modify the "Sort by" settings. Setting it to "Storage Order" gives you full control over the order of elements in PE.

Next, you very likely will want to to reorder the elements. With "Storage Order" you'll notice that they appear in the order that they were added to the model.

Reording is done by one of the more hidden features. Here's some examples:

Reordering contents of a UML Package:
  1. Right click on the package in PE and select "Properties"
  2. Switch from "General" to "Advanced"
  3. Click in the value part of the entry for "PackagedElement" and a button marked "..." appears
  4. Click this button
  5. A new Property dialog is opened - use this to move the elements up/down to suit your needs
  6. Close all dialogs and enjoy
If you need to rearrange attributes in a class, perform the same steps, but instead of locating "PackagedElement" locate "OwnedAttribute" and perform your reordining there.

As this is dependent on having the "Sort by" preference set, other users will need to set the same "Sort by" as you to enjoy your model order. You may want to consider sharing of preferences to address this issue.

Monday, March 28, 2011

Controlling Eclipse Preferences


Ever struggled with preference settings in Eclipse?
A typical case is where you have to over and over again reapply the same preferences in to new workspaces and projects. Quite tiresome.

This problem was addressed during this years EclipseCon in the talk Getting Eclipse Preferences Under Control in Teams. Here we learned of three parallel projects addressing in different ways the same issue:

Full presentation is available here.

Shortly after the session, I also stumbled across a post on the e4-dev list announcing yet another initiative e4preferences.

Given that there is a fair number of attempts to address various aspects of the "preference problem", I now hope that we can work together to, if not once and for all solve, but at least improve the preference sharing support for end users.

Except for Bug 334016, there's wikis describing what they do, so I'll have a go at explaining it.

The name of this feature is "Common Preferences" and was developed for Ericsson in order to address the problem of sharing "common preferences" between users and teams in the larger enterprise.

It has been deployed and successfully used for about 4 years now.
For the end user, the typical case could be that he/she never notices that Common Preferences is there to help out. This is accomplished by installing the feature along with everything else in the Eclipse based product and having it preconfigured to set key preferences (such as network proxies etc) upon creating a workspace.

In addition to this, the users can then add their own preferences to the list of what is to be managed. There's a neat export wizard allowing the user to identify what preferences are modified (i.e. changed from their default values) and thus helping the user to compile a Eclipse preference file which later can be imported by others in the team (including the user him/herself). It also allows the comparison of applied preferences with those defined by the Common Preferences.

As of writing, I'm waiting for this bug to progress further through the submission process. Ideally, it could result in an improved preference sharing support in the platform, possibly by merging the key features from the various initiatives addressing this gaping hole.

Why don't you go ahead and vote on bug 334016 ...