Friday, July 13, 2007

Maven projects with NetBeans IDE (Part 1)

(This article is on google docs too).

Introduction

I'll present here how to use Maven projects with NetBeans IDE via the MevenIDE project. Since the emphasis is on Maven and Maven-support, I'll just play the devil's advocate and try to focus on most of Maven's features while also underlining ant's flaws.


As always, the answer is somewhere in the middle. There are cases where ant is preferred to Maven and some when it's the other way around.


The build system

All NetBeans projects are ant-based. Ant is a very useful tool due to the cross-platform and usually easy to write build-scripts. But these scripts to compile, generate, build and deploy the projects usually endup being quite complex.


They are so complex sometimes that they represent basically another part of the project. They are also non-standard for each project (especially legacy free-form projects).


Now, using the IDE, we have some pre-cooked scripts and special ant-tasks. But your build-system is rather tied now to the IDE (not actually to the IDE, but to those ant-tasks). Everything is open-source, true, but you can't actually just take the official ant distribution and build your system... You need to tweak it a little. (In NetBeans' defense, at least you have a ready-made ant build system. With other IDEs, you just have some metadata but nothing usable outside the IDE.)


Is it a bird, is it a plane ? It's Maven

Maven isn't an ant replacement. It includes a build-system component, but it's something else. It provides a consistent view on any project with a standardized project definition and plugins for reports and website generation. Think of it as a general project management tool that includes a build tool.


Basically with Maven you don't write any scripts ! Maven provides you a standardized way to structure your project and you just configure various build / reports / site plugins. Therefore you don't have any build scripts anymore -- you have a declarative description of your project, called POM (Project Object Model).


Maven also introduces the concept of repository. That is, a place where all the build artifacts (the resulting JARs or WAR/EAR files) are saved and retrieved from. For example it's easy to imagine a setup where the whole team uses a read-only repository with the 3rd party artifacts. Thus, they don't need to sit in the VCS !


I really can't sum it up better than that so I recommend using the Maven website to learn some more.


MevenIDE

The Maven-NetBeans IDE integration is provided by (part of) the MevenIDE project (install it from here).


All my examples are based on NetBeans 5.5. Sadly, with the NetBeans 6.0 release approaching, most of the Maven-integration work is being put there. That is, for the NetBeans 5.5 version MevenIDE is somewhat beta quality and you're supposed to have more luck with NetBeans 6.0 (now at milestone 10).


You might stumble onto some bugs for the 5.5 integration but it's a very dynamic project with people still working on it and it's quite easy to find workarounds or help in the mailing lists (Milos Kleint is usually there to help).


So, if you don't actually like living on the bleeding-edge by either using the current Maven integration for NetBeans 5.5 or by switching to NetBeans 6.0 M10, you're out of luck. But my advice it to take a chance ! It will be worth it.


Java Application Project

Let's see how you could use a Maven project instead of a normal Java Application Project.


After you created a new Java Application project with the NetBeans wizard, you should have in the Files view something like:


/src

/test

/nbproject

build.xml

manifest.mf


(The Files tab should be next to the Projects tab).


Now we select File->New Project and then Maven2->Archetypes project with the Quickstart Project template. Artifact Id is a public name for your project (for example: maven-javaapp) while Group Id is usually your company (com.example). Please note the “version” parameter. You'll find this useful with dependencies:




Both wizards create some files and some example classes. The NetBeans-default Java Application creates a Main.java file but no test. There are also a lot of semi-exotic files in nbproject/ .


The Maven wizard creates a pom.xml file and a src/ folder. The pom.xml file is the project-metadata for Maven. It basically replaces the build.xml and nbproject/ . It is not the only metadata file Maven uses, but it's the only one that's mandatory (and the one you usually see).


The project name

After you've created the Maven project, you'll see that the name is something like "Maven Quick Start Archetype (jar)". Of course we need to change that to match the default IDE style (which I'm trying to duplicate so far). So, we open the Project POM file in "Project files" and look for the <name> element. Just editing that to "Java Application" and saving the POM should be enough, the Maven Project from the "Projects" tab will refresh and you'll see the new name. Pretty nice, no ?




Please note the extra "Project profiles" file in there. As I told you, there may be some other metadata files, but for most actions, the POM is king.


That was a forced introduction in hand-editing the pom.xml file. You might as well have used the Project properties window to edit the project name. This will automatically change the POM file.



You will notice that the MevenIDE plugin has some pretty nice support for the metadata files. You have auto-completion in the POM file not only for the XML schema but also for plugins from the local repository. There's also hyperlink support (just hold the Control key pressed) that not only opens a browser for real URLs but is able to jump into modules and parent projects (this is a feature of Maven we're not going to talk in this article, but it's good to keep in mind).


Running

Since we already have the Source and Test folder, the main action we'll be doing is running a main-class.


First, if you select Run via Run->Run Main Project menu or the F6 key you'll see this warning message:


It basically tells us the the NetBeans-Maven bridge isn't configured yet, so it doesn't know what to run. As the message says, right-click the project and go to Properties.


We configure the Run->Main Class to something like "com.example.App" (or whatever your package is).


Now, if you open the POM again you'll see that a whole lot of data was automatically added under some <profiles> element.


Again, you select to Run this project (right-click on the Project -> Run or just press F6 if it's the main project). After some messages in the output window, you'll see something like this:


BUILD ERROR (Badly configured, need existing jar at ...)


Huh? What was that ??


Well, as I've said, bugs do exist and you've just stumbled upon MEVENIDE bug 485 . Luckily, there is a workaround: just open the POM and look for

<plugin>

<artifactid>maven-assembly-plugin</artifactid>

then add

<version>2.1</version>


What does this do ? Well, Maven uses various plugins to run everything from building to creating the JARs, to generating reports. Each plugin has a version so we can still have old projects working. Now, where do you expect all these plugins to sit ? Of course -- in the Maven repository.


Whenever a plugin isn't found, Maven tries each repository in order to download it (by default there's only one repository, the official Maven repository).


So, in our case, MevenIDE was using the latest maven-assembly-plugin from the repository which is in beta and has some issues. By forcing the version on 2.1, everything works.


Take note that I've said "download it" above. You should expect something like "Downloading maven-assembly-plugin" with a progress bar in the lower-right corner.


Testing

If you like writing tests (don't you ?), just use right-click on the Project -> Test . You'll see the details in the output window. If everything is ok you should see a BUILD SUCCESSFUL. If some tests fail, you have a BUILD FAILURE and you may click on the failed tests in the output window to see the stacktrace:


MevenIDE also has nice support for the output with marked stacktraces just like the standard projects.

Debugging

In order to debug a project, right-click it in the “Projects” tab and click Debug or just select Run->Debug Main Project (the F5 key). It should look the same as the IDE-project.

Are your tests failing ?

Maven is really in love with tests and these are so important that they break the whole build. That is, you cannot run or debug a project if one of your test fails. This does make sense in theory, but in practice you always have some tests that fail (at least I do ;-) ).


The workaround is to skip tests. From the IDE, you just go to the project properties -> Action Mappings and tick “Skip tests” for the action you want (Run project, Debug project or both).


If you run Maven from the terminal, you must add “-Dmaven.test.skip=true”.


If you feel really in shape, you can configure in your POM the plugin that's in charge for tests and just exclude the tests you are still working on. Just add something like this and you're done:


<project>
<!-- .... -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/TestBroken1.java</exclude>
<exclude>**/TestStillFailing2.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<!-- ... -->
</project>

Note the already familiar artifactId and groupId for the plugin configuration.


This is the end of part 1. Stay tuned for the next articles about how to use dependencies, how to configure your own repository, how to make EJB/EAR artifacts and even NetBeans Platform modules.

4 comments:

DJ said...

Hi,

I dont have Maven/ Netbeans integration issues with M10 versions, but the real plbm is memory consumption of Netbeans when using Maven.


Regards,
DJ

Emilian Bold said...

I suppose you could need more RAM with Maven since it might not be integrated in such a manner as ant but I'm using this on a 1GB RAM system and it feels snappy enough (with the SUN Application Server and JavaDB running too; plus firefox/mail client,etc).

2.718 said...

Thanks for the article -- interesting and useful.

Here are some additional points as I see them:

1. I run Netbeans 6.7 and the integration with Maven is less than perfect. In particular, on the Windows platform, command line arguments with file paths get mangled.

2. If you project auto-generates files, Ant is completely useless but Maven handles it fine.

3. XML, for any non-trivial purpose, is not a human readable format. But even Maven seems to expect users to hand-edit XML files (e.g. to set up a proxy).

4. Maven relies too much on being on-line. To ensure future maintainability, I need to be able to put an entire project, including all tools, under SCM.

5. When you have some time run a search and replace: meven --> maven.

Emilian Bold said...

Hy 2.718,

Thanks for the feedback, although my article might not be so up to date (it's over 2 years old).

#1 is probably a bug you should report. Might be fixed with 6.8 (I use the beta, works nicely).

#3 is debatable. If you are using maven you are probably a developer and shouldn't be worried of XMLs. The IDE has some nice GUI for the proxy though -- I think those settings might be inherited by Maven if you are using the embedded one.

#4 is probably possible. There are some projects that do this (allow you to build a maven 'proxy' of some kind and store the dependencies in a centralized place -- SCM might be too disk intensive though)

#5: MevenIDE is "Maven ide integration project" available on mevenide.codehaus.org