Want to catch NullPointerExceptions but not keep stopping on java.net.URL? Use Breakpoint Properties and Restrict to Selected Locations - see how its done in the following 2 screenshots:
About Eclipse, Modeling and other stuff
Here I'm blogging about various topics covering Eclipse, modeling, RCP development etc.
Thursday, December 22, 2016
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:
- Open a (cygwin) terminal (on Linux/OSX just a terminal)
- cd to the checked out SVN repository folder (or Eclipse project)
- run "svn status | grep '^! ' to list the "missing" files
- Now, we will revert all those files and then delete them using proper svn commands
- 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
- cat MISSING.txt | xargs svn revert
- cat MISSING.txt | xargs svn delete
- Try committing again - those "missing" files should now be marked as deleted
- Clean up -> rm MISSING.txt
- 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
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!
Update: The above link is broken, try this instead!
Adding UUIDs to your favorite model
We start out using the classic Library example.
- Get started by cloning it from here - checkout the "master" branch.
- Open the /emf.uuid.library.example/model/emf.uuid.library.example.genmodel
- Generate All code
- Run the editor and create an example library model with some elements and save it
- 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>
- Now, to add support for using UUIDs instead, open the genmodel and select the Library element
- Set the Model > Resource Type property to XMI (btw, this was the missing piece in the recipe...)
- Regenerate the Model code
- Add org.eclipse.emf.ecore.xmi to the plug-in dependencies
- Follow the steps described in the blog:
- Create a LibraryResourceImpl class (Override the useUUIDs() method)
- Create a LibraryResourceFactory
- Hook into the org.eclipse.emf.ecore.extension_parser extension point
- Generate All code
- Run the Library Editor again
- Open the previously save library model
- Make a change and save the model
- Open it with Text Editor again and note how all elements now have UUIDs
- 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
- https://github.com/fredrikattebrant/emf.uuid.library.example
- http://serdom.eu/ser/2007/03/05/how-to-enable-uuid-in-emf-generated-model-to-get-copypaste-working (Update: link is broken - try #3 below instead)
- http://eioki.eu/2007/03/05/how-to-enable-uuid-in-emf-generated-model-to-get-copypaste-working
Monday, April 2, 2012
EclipseCon 2012
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:
Figuring out the compat layer |
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.
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.
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
- We've made some example code available on github.
- Bug 374597 - [Compatibility] ClassCastException when adding pure 4.x view to 3.x perspective running in compatibility mode
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:
- Getting setup and getting help
- Tips for structuring model-to-model mapping projects
- How to write custom mapping rules
- Pattern for managing the transformation execution lifecycle
- Aborting an executing transformation
- Pattern for reporting transformation problems
- Model markers and decorators
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:
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:
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:
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:
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:
Unfortunately this will warn you about access restrictions, so you may want to suppress them:
Now you are ready to cancel the execution when you've detected a problem with:
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):
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:
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!
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:
- Using the inline editor
- Creating a custom rule in an external Java class
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("restriction") // 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); } }
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:
Labels:
eclipse,
model,
rsa,
transformation
Location:
Torshamnsgatan 30A, 164 40 Kista, Sweden
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:
- Right click on the package in PE and select "Properties"
- Switch from "General" to "Advanced"
- Click in the value part of the entry for "PackagedElement" and a button marked "..." appears
- Click this button
- A new Property dialog is opened - use this to move the elements up/down to suit your needs
- Close all dialogs and enjoy
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.
Subscribe to:
Posts (Atom)