November 5th, 2008 at 11:43 am

Java2Uml – generating UML2 class diagrams from existing code

The Eclipse UML2 project provides models and diagram editors for creating and editing UML models in Eclipse. The problem is that these models are not tied to code in any way, and in particular, if you want to visualize existing Java code in class diagrams, you have no option but to create the class diagram manually. More »

August 12th, 2008 at 4:14 pm

Advanced features in Eclipse popup menus – Take 2: The new API

Following Robin’s comment on my earlier post I found the new API (Extension point description of org.eclipse.ui.menus) which unifies all command contributions to Eclipse menus, views, objects, toolbars etc. More »

August 8th, 2008 at 1:19 pm

Adding EOperation body to model

This is just a short notice for an EMF code generator feature which is mostly unknown and not really documented (well, it will be in the EMF 2nd Edition book, but this won’t be out until December or later).

To add a custom body (replacing the usual throw new UnsupportedOperationException body generated by default), follow this step-by-step howto.

July 24th, 2008 at 2:57 pm

Using advanced features in Eclipse popup menus

One of the first Hello World examples when dealing with contributions to Eclipse extension points is adding an objectContribution or a viewerContribution to a popup menu. However, if one wants to add a more flexible contribution which is hided or disabled in certain circumstances, documentation gets rare.

This article describes how to implement these advanced featues by example. Let’s assume we have an EMF model of objects MyObject which implement a property called type. EMF can generate item and label providers for tree editors. Let’s assume we have implemented such an editor and we want to contribute an action which is only visible for a particular type value.

Update: This article uses the old API of contributing actions to views’ and objects’ popup menus. There is a new API which is described in another post.

More »

July 2nd, 2008 at 11:26 am

How to make an Eclipse Plugin Scriptable with Groovy

Say, you want to implement a quick and flexible automation enhancement to one of your eclipse RCP plugins – for example, because you are writing some sort of business application in which you always have to create a few standard structures manually in order to play with it and test it.

Here’s how you can do it the groovy way:

  • create a new plugin project that depends on all plug-ins you want the automation script to be able to access.
  • download groovy-all-x.y.z.jar from the Groovy homepage and put it into your plug-in’s runtime classpath.
  • create an objectContribution like this:
  •       <objectContribution
                adaptable="false"
                id="myproject.groovyRunner"
                nameFilter="*.groovy"
                objectClass="org.eclipse.core.resources.IFile">
             <action
                   class="myproject.automate.RunGroovyAction"
                   enablesFor="1"
                   id="myproject.groovyRunnerAction"
                   label="Execute as Automation Script"
                   menubarPath="additions">
             </action>
          </objectContribution>
  • implement the action like this
  • package myproject.automate;
    
    import java.io.PrintWriter;
    import java.io.StringWriter;
    
    import groovy.lang.GroovyClassLoader;
    
    import org.codehaus.groovy.control.ErrorCollector;
    import org.codehaus.groovy.control.MultipleCompilationErrorsException;
    import org.codehaus.groovy.control.messages.Message;
    import org.eclipse.core.resources.IFile;
    import org.eclipse.core.runtime.Assert;
    import org.eclipse.core.runtime.IStatus;
    import org.eclipse.core.runtime.Status;
    import org.eclipse.jface.action.IAction;
    import org.eclipse.jface.dialogs.ErrorDialog;
    import org.eclipse.jface.viewers.ISelection;
    import org.eclipse.jface.viewers.IStructuredSelection;
    import org.eclipse.swt.widgets.Shell;
    import org.eclipse.ui.IObjectActionDelegate;
    import org.eclipse.ui.IWorkbenchPart;
    
    import myproject.MyPlugin;
    
    public class RunGroovyAction implements IObjectActionDelegate {
    
    	/** store the parent shell */
    	private Shell shell = null;
    
    	/** store the selected file */
    	private IFile file;
    
    	@Override
    	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
    		shell = targetPart.getSite().getShell();
    	}
    
    	@Override
    	public void selectionChanged(IAction action, ISelection selection) {
    		file = (IFile) ((IStructuredSelection)selection).getFirstElement();
    	}
    
    	@Override
    	public void run(IAction action) {
    		Assert.isNotNull(shell);
    		Assert.isNotNull(file);
    
    		try {
    			/* initialize the GroovyClassLoader with the Eclipse class loader */
    			GroovyClassLoader loader = new GroovyClassLoader(getClass().getClassLoader());
    
    			/* parse the groovy file */
    			Class<?> parsed = loader.parseClass(file.getContents());
    
    			/* cast it to runnable (or whatever you like to implement */
    			Class<? extends Runnable> clazz = parsed.asSubclass(Runnable.class);
    
    			/* instantiate and rum */
    			Runnable r = clazz.newInstance();
    			r.run();
    		}
    		catch(MultipleCompilationErrorsException e) {
    			/* report compilation errors in an error dialog */
    
    			StringWriter messages = new StringWriter();
    			PrintWriter printWriter = new PrintWriter(messages);
    
    			ErrorCollector ec = e.getErrorCollector();
    			if(ec.hasErrors()) {
    				for(Object o : ec.getErrors()) {
    					((Message) o).write(printWriter);
    					printWriter.append('\n');
    				}
    			}
    
    			Status status = new Status(IStatus.ERROR, MyPlugin.PLUGIN_ID,
    					messages.toString(), e);
    
    			ErrorDialog.openError(shell, "Compilation errors", messages.toString(), status);
    		} catch(Exception e) {
    			/* report all other errors here */
    
    			Status status = new Status(IStatus.ERROR, MyPlugin.PLUGIN_ID,
    					"Execution error", e.getCause() == null ? e : e
    							.getCause());
    
    			ErrorDialog.openError(shell, "Error", "Execution error", status);
    		}
    	}
    }

Now you can run your Eclipse application, create a .groovy class (implementing Runnable in the case above) in a file and run it from within your runtime workspace.

Happy scripting …

May 9th, 2008 at 4:22 pm

Extract BibTeX-Entries used in LaTeX source

I manage all of my references in a single big BibTeX database (BTW, I do this using JabRef – a really nice Java tool to manage BibTeX files). Now if I am writing a paper, I first use the big file just because it is easy and I have everything in one place.

But when the paper is finished, I want to throw away all unused references, to optimize the bibtex file and to edit all of the references used in one place (like abbreviating booktitles, because my paper is too long …). So how to extract all entries needed and throwing away the rest?

To do this, I found this perl script from Michael Zhang which does exactly what I need. Thanks Mike! Nice work!

April 30th, 2008 at 3:21 pm

Eclipse ClassLoading Hell

I like Eclipse. It is a really useful tool. It does a lot of magic behind the scenes and after a bit of getting familiar with its API you are able to write quite powerful plug-ins.

The bad thing is, that if something bad happens deep inside that magical box, it is quite challenging to analyze and understand what exactly is going on.

My problem had to do with such a case. I am using the Eclipse Modeling Framework (EMF) and my plan is to persist my models using the CDO-Teneo-Hibernate-MySQL bridge. CDO and Teneo are a bit experimental, but they are well supported in the eclipse.technology.emft Newsgroup.

The database persistence uses an approach of mapping arbitrary EMF models to database tables automatically including the dynamic creation of proxies. But as you might guess, all of this requires two sets of plug-ins (CDO and Teneo) as well as the hibernate library (which has further dependencies, e.g. the CGLib to dynamically create proxies) and the database driver library.

So, last week I ran into massive class loading problems, because the different plugins in the CDO and Teneo projects make use of the Hibernate libraries and manage access to them through a rather heterogeneous collection of exporting and importing packages and making use of the Eclipse-BuddyPolicy tag. Using this tag, for example, a user-contributed plugin can contribute the database driver class to the classpath of an existing plug-in.

However, one of the problems was caused by the fact, that the CGLib Java Bytecode generator was going to build a proxy for a class defined in another bundle (let’s say A) but at the same time also needed to incorporate the HibernateProxy interface (which was in the hibernate library in bundle B). And there is no dependency between A and B, because hibernate is a strategy add-on to CDO. Consequently, the class generation went awfully wrong because CGLib would take the classloader associated with its input class (so classloader of bundle A) which of course did not find the HibernateProxy interface from bundle B.

Back then I did not know all that. I only got an exception with a stack trace like this:

net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
   at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:237)
   at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
   at net.sf.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
   at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.getProxyFactory(CGLIBLazyInitializer.java:127)
   at org.hibernate.proxy.pojo.cglib.CGLIBProxyFactory.postInstantiate(CGLIBProxyFactory.java:43)
   at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PojoEntityTuplizer.java:162)
   at org.hibernate.tuple.entity.AbstractEntityTuplizer.(AbstractEntityTuplizer.java:135)
   at org.hibernate.tuple.entity.PojoEntityTuplizer.(PojoEntityTuplizer.java:55)
   at org.hibernate.tuple.entity.EntityEntityModeToTuplizerMapping.(EntityEntityModeToTuplizerMapping.java:56)
   at org.hibernate.tuple.entity.EntityMetamodel.(EntityMetamodel.java:302)
   at org.hibernate.persister.entity.AbstractEntityPersister.(AbstractEntityPersister.java:434)
   at org.hibernate.persister.entity.JoinedSubclassEntityPersister.(JoinedSubclassEntityPersister.java:91)
   at org.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:58)
   at org.hibernate.impl.SessionFactoryImpl.(SessionFactoryImpl.java:226)
   at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1300)
   at org.eclipse.emf.cdo.server.internal.hibernate.HibernatePackageHandler.getSessionFactory(HibernatePackageHandler.java:273)
   ... some more
Caused by: java.lang.reflect.InvocationTargetException
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at java.lang.reflect.Method.invoke(Unknown Source)
   at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:384)
   at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219)
   ... 74 more
Caused by: java.lang.NoClassDefFoundError: org/hibernate/proxy/HibernateProxy
   at java.lang.ClassLoader.defineClass1(Native Method)
   at java.lang.ClassLoader.defineClass(Unknown Source)
   ... 80 more
Caused by: java.lang.ClassNotFoundException: org.hibernate.proxy.HibernateProxy
   at org.eclipse.osgi.framework.internal.core.BundleLoader.findClassInternal(BundleLoader.java:481)
   at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:397)
   at org.eclipse.osgi.framework.internal.core.BundleLoader.findClass(BundleLoader.java:385)
   at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:87)
   at java.lang.ClassLoader.loadClass(Unknown Source)
   at java.lang.ClassLoader.loadClassInternal(Unknown Source)
   ... 82 more

What …? I thought. CDO calls Hibernate calls CGLib and CGLib can not locate a Hibernate class? So I went digging through the internet tried to understand class loading in Eclipse I found a good article and this Eclipsepedia Entry which provide some insight.

However, this did not really help. If you are stuck somewhere with a ClassNotFoundException, because you don’t know, which class loader was being used to load the class (and failed), you have a problem. Both setting an exception breakpoint and stepping through the execution using the debugger is a bad idea, because there are so many class loads – and also many failing class loads – in Eclipse, that both methods are cumbersome.

A better way to gain information is enabling tracing and activating the class loader trace in org.eclipse.osgi:

Enabling OSGi ClassLoader tracing

This leads to output like this:

BundleClassLoader[org.eclipse.emf.teneo_0.8.0.qualifier].loadClass(org.eclipse.emf.teneo.annotations.pannotation.DiscriminatorValue)
BundleLoader[org.eclipse.emf.teneo_0.8.0.qualifier].loadBundleClass(org.eclipse.emf.teneo.annotations.pannotation.DiscriminatorValue)
BundleLoader[org.eclipse.emf.teneo.annotations_0.8.0.qualifier].findLocalClass(org.eclipse.emf.teneo.annotations.pannotation.DiscriminatorValue)
BundleLoader[org.eclipse.emf.teneo.annotations_0.8.0.qualifier] found local class org.eclipse.emf.teneo.annotations.pannotation.DiscriminatorValue

So you can see in which bundle (in sqare brackets) the classloader looks for your class. This helped me find out, what was going on (described above). To solve my problem, I had to patch the two of the CDO manifests to make the classloader find the additional classes.

One way or another, all that classpath magic is hard to see through, when it comes to dynamic code generation and third party libraries in eclipse.

As a final note: I came over another article (in German), which does not directly address my issues, but could be helpful when you have several plug-ins which have to load different classes from different bundles.

April 24th, 2008 at 11:54 am

Useful Eclipse Java Editor Templates: EasyMock

EasyMock is a really useful tool for unit testing. If you want to test a class which is usually contained in a web of collaboration with other classes, you can easily simulate the other classes’ behaviour using a rather simple and powerful mocking mechanism.

And in order to save typing time, you can use this template to create your mock with one keystroke:

${staticImport:importStatic('org.easymock.EasyMock.*')}
${testType:newName} ${cursor} ${mock:newName} = createMock("${mock}", ${testType}.class);

And, as usual, you can directly import the template using this XML.

April 24th, 2008 at 11:48 am

Useful Eclipse Java Editor Templates: Error handling

So you are writing Eclipse Plugin code and have to catch exceptions? Ok, but what to do with them?

e.printStackTrace() is not very nice. And in order to report it to the user or to log it in the plugin’s log, you have to create an instance of Status first.

Here is a template you can use in your exception hander to save typing time:

Status ${status:newName(org.eclipse.core.runtime.Status)} = new Status(
	IStatus.ERROR, ${plugin:link(Activator)}.PLUGIN_ID,
	"Error while ${cause:link(evaluating)}",
	${exception_variable_name}.getCause() == null ? ${exception_variable_name} : ${exception_variable_name}.getCause());

${plugin}.getDefault().getLog().log(${status});
ErrorDialog.openError(getShell(), "Error", "Error while ${cause}", ${status});

Again, you can use this XML to import the template directly.

April 24th, 2008 at 3:56 am

Useful Eclipse Java Editor Templates: Tracing

In this blog I’ll collect some nice Eclipse Java code templates which I use.

I did not find any site collecting those, so there is no place I know of, where one can commit his favourite templates. So here we go:

Adding a trace boolean in order to switch on or off tracing of a plugin:

This inserts a static boolean which can be used to turn tracing on or off using the Tracing tab in the launch configuration dialog. In order to use this, you also have to create a file called .options in your project root. In this file add the line <project name>/<type name>/debug=false.

And here comes the template. Use it at class level:

	private static boolean trace = false;

	static {
		String value = Platform
				.getDebugOption("${enclosing_project}/${enclosing_type}/debug");
		if (value != null && value.equalsIgnoreCase("true")) {
			trace = true;
		}
	}

Quickly insert a method trace:

If the trace infrastructure is set up, a method call can be logged very quickly using

if(trace) {
	System.out.println("${enclosing_type}.${enclosing_method}()");
}

at the beginning of the method.

Generic trace output:

In the middle of a method, use this:

if(trace) {
    System.out.println("  ${cursor}");
}

In order to import these templates, go to the Eclipse preferences dialog, navigate to Java > Editor > Templates and import this XML.