Thursday, November 29, 2007

Onward to Eclipse Europa ... and then right back

Ok, so after Eclipse Europa (3.3) has been out for quite some time, I decided to give it a try. I was shocked to discover a lot of the changes that had happend :
it seems that the Eclipse foundation has become Red Hat's bitch. There's a ton of new Red Hat sponsored / produced editors (none of which are very good.) There's a ton of useless JBoss integration. The editor overall is slower. All my hotkeys (save one or two, literally) were standard with installation in Eclipse 3.2, and are now broken in Eclipse 3.3. I'm severely disapponted after using Europa for three weeks. The only good part about it is that access to my SVN repository was considerably faster. And it seems I'm not the only one who feels this way about Europa. Get it together Eclipse.

Oh, and the thing that brought me to writing this post in the first place : the XML schema editor is flat out broken. What the fuck ?!

Thursday, November 15, 2007

Spring, Tomcat and memory

As my application has been growing more and more in functionality, it has also been growing in its memory footprint. To that end, I've started getting OutOfMemoryErrors because the heap has started overflowing. That's really not a problem if you have access to the external Tomcat server, you can just increase the heap size using "-Xms128M -Xmx512M" (or other applicable sizes) on the command line, or do this via the GUI if you're running Tomcat in Windows. However, it's not as obvious if you're using Tomcat for debugging within the Web Tools Platform plugins for Eclipse. I started running into this problem recently and it ground my development to a halt until I was able to fix the problem for WTP in Eclipse. WTP passes its arguments to the Tomcat server via the Launch Configuration. To get to it, right click on the Tomcat server in the Servers view -> 'Open' -> 'Open launch configuration' -> 'Arguments' tab -> 'VM arguments:' text box, then add the "-Xms128M -Xmx512M" segment to the end of the parameter list.

Saturday, November 03, 2007

Actual plugin development for Maven 2

Ok, so after Googling around and hours of patient command line testing (yeah, I know, it's horrible, you don't have to tell me) I managed to complete my ToLDya plugin for generating TLD files. Hopefully this plugin will be a great aid to people developing JSP tag libraries other than myself. But along the way, I learned a lot about plugin development in Maven, and I'm quite certain that I've got a shitload more to learn.


  1. Starting out with a barebones Mojo from the Maven provided archetype literally doesn't get you much. It gets you just enough to plug into the Maven framework so that maven can actually run your Mojo, but that's about it.

  2. The AbstractMojo provided by Maven is pathetic. It gives you a logger, and that's about it. By default, it does not give you many of the things a plugin is quite likely to want (more about that later)

  3. Despite the fact that Maven 2 was supposed to be the "lessons learned" version of Maven, I don't think that the Maven developers learned much at all. Maven is grossly behind the times, still relying on XDoclet annotations and pre-JDK 5.0 compatibility. Yes, there is something to be said for keeping things backward compatible (especially in a corporate environment, I know), but at some point you have to move on and do better, in this case : getting up to date with the latest JDK (1.6.03 at the time of this writing).

  4. If you need anything (ie from Maven) while writing a Maven plugin, you have to specifically request that it be injected for you. (See the Maven documentation, this is the one area where they're actually good about documenting things and helping out developers)

  5. If your plugin needs to access any of the classes in the project on which it's run, you need to load them yourself with your own classloader. Maven will not give you one (which is pretty ridiculous to my mind).



Here are some important bits of knowledge for doing anything with a Maven plugin:

  • If you need access to anything from the project (ie any information stored in the POM), you'll need to include the following dependency :


    <dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-project</artifactId>
    <version>${maven.version}</version>
    </dependency>

    In my current POM, the property 'maven.version' is set to 2.0.7. You'll then need to have a property in your plugin Mojo called 'property' (or whatever else you find suitable) and annotate it like so (from within a Javadoc comment of course):



    * @parameter expression="${project}"
    * @required


  • As mentioned previously, if you want to load any of the classes that are in the project on which your plugin is to execute, you have to load them yourself. The same goes for any of the project's dependencies. In order to do this, you'll have to get the list of dependencies (compile, test, runtime) from the MavenProject object ('property', remember?) The MavenProject object has a property called 'runtimeClasspathElements'. This gives you a list of strings that are fully qualified file system paths to the classes in the ${project.build.outputDirectory} as well as all of the dependency JARs on which the client project depends. You'll then have to load them yourself. I did so with a URLClassLoader (part of the JDK). I used the following function for creating the classloader :


    private static URLClassLoader getDependencyClassloader(List dependencies) throws MalformedURLException {
    List classpathUrls = new Vector();

    URL url = null;
    for(int index = dependencies.size() - 1; index >= 0; index--) {
    url = new File(dependencies.get(index)).toURI().toURL();

    classpathUrls.add(
    url.toExternalForm().endsWith(".jar") ?
    url :
    new URL(url.getProtocol(),url.getHost(),url.getPort(),url.getFile() + "/") //add the '/' o indicate a directory );
    }
    URLClassLoader ucl = new URLClassLoader(classpathUrls.toArray(new RL[] {}), Thread.currentThread().getContextClassLoader());

    return ucl;
    }

    Once you have this class loader, you can use it in the long version of Class.forName() to load any classes you may need, as well as perform any loading logic you need with the .getResources() functions on the classloader.





I'll be doing more plugin development in the coming months I'm sure, so I'll try to post what I learn here, but that's about it for now.

Thursday, November 01, 2007

Plugin development with Maven, obsessed

Ok, I let my obsessions get the better of me and I couldn't drop it : I kept searching the interwebs until I had found a solution for my problem. Surprise, surprise, the maven-plugin-testing-harness is a broken ass piece of shit. Enough editorializing though, here's how things went :

1) I had to make sure all of this sh*t was in my POM :
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-descriptor</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>

2) I then had to change from using 'lookupMojo' to instantiating my own mojo and using 'configureMojo' on the test harness. With the former, you'd have to put the /META-INF/maven/plugin.xml file somewhere on the classpath so that the MavenPluginDiscoverer module can detected it.

Why didn't they just tell you helpful things like these on the wikis for the plugins ? God dammit, I'm quickly hating Maven more and more. And to boot, it doesn't properly evaluate the required expressions and inject stubs for them, but maybe I've just missed something (easy, given how poor the documentation for the project is).

The anniversary

I didn't even notice it until today that it's the one year anniversary of this blog. Actually, the anniversary was two days ago, but close enough. Considering my general dislike of (non-development) blogs, that's actually quite impressive. I didn't think it'd last this long. Yay blog.

Maven ... OMG

My recent foray into developing Maven plugins has led me to a horrible discovery : the Maven developers ... suck. They're just not professional. There's no javadoc for the core classes. There's no javadoc for the base plugin classes and interfaces. And the AbstractMojo class which is supposed to be a good starting base class for all other plugins is, to say the least, horribly designed : it doesn't contain access to the MavenProject that's currently being operated on, you have to add it in manually Ironically (or appropriately, take your pick) they made that a plugin too. The supposed "tutorial" on the Maven main site doesn't show any mention of this. The plugin "cookbook" on the site has been "coming soon" for so long that you have to wonder if it's ever going to get written. And, on top of all this, there's no generics and no direct support for JDK 5 annotations and enums. (See previous post). I've now reached a point of severe disappointment with the Maven project, and I'm fast approaching the point where I'm genuinely sorry that I've made this much of a time investment in it.