Help

Out of the box, seam-gen copies all the dependencies of Seam (and then some) into the lib directory of the generated project. The JAR files in that directory are then placed on the project's build path. While this approach gets you up and running quickly, it's probably not the best long-term strategy. It's difficult to determine which libraries your project actually depends on and which versions of those libraries are present. What you need is some sort of formal dependency management.

One way of managing dependencies is to use Maven 2 as the build tool, which several people have requested for seam-gen to support. However, shifting to Maven 2 is quite a large departure from the current build, which is based on Ant. In this article, I will explain how you can introduce Ivy into the Ant build to track which dependencies and versions of those dependencies your project uses and to have them fetched from a remote repository. Ivy is a sub-project of Ant and provides a collection of Ant tasks focused specifically on providing a dependency manager for Java libraries.

About this solution

What makes the setup I present in this article unique is that it separates fetching the dependencies from the build itself, so once the JARs are in place, the build can work just as it always has. That means the use of Ivy does not affect the efficiency of development that a seam-gen project provides. You also have the ability to create a distribution of the project which includes all the dependent JAR files, a key aspect of ensuring reproducibility. But there is something else that sets this solution apart.

Somewhere along the line folks seemed to have coupled shared repositories with transitive dependencies. You'll discover that it's possible to pull artifacts from the remote repositories without having to use the transitive dependency mechanism common to all Maven 2 projects (and an optional feature in Ivy).

Making way for Ivy

The first step to integrating Ivy into the project is to create a separate Ant build file, which we'll name ivy.build.xml, to host the Ivy-related tasks. Isolating these tasks in a separate file makes them more reusable and keeps the main build file clean. The Ivy build file is imported near the top of the main build file using the Ant import task:

<import file="${basedir}/ivy.build.xml"/>

In the Ivy build file, the first tasks you'll create are ones that fetch Ivy itself, in a sort of self-updating way. We'll store the Ivy JAR file in the build-lib directory at the project root to keep it isolated from the application's dependencies. To be efficient, we'll also check to see if the Ivy JAR has already been downloaded before attempting to fetch it. Here are the contents of ivy.build.xml we have talked about so far:

<?xml version="1.0"?>
<project basedir="." xmlns:ivy="antlib:org.apache.ivy.ant" name="myproject-ivy">
    <property name="ivy.install.version" value="2.0.0-beta2"/>
    <property name="ivy.jar.dir" value="${basedir}/build-lib"/>
    <property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar"/>
    <property name="central.repo" value="http://repo1.maven.org/maven2"/>
    <property name="jboss.repo" value="http://repository.jboss.org/maven2"/>

    <target name="init-ivy">
        <available property="ivy.installed" value="true" file="${ivy.jar.file}" type="file"/>
    </target>

    <target name="download-ivy" depends="init-ivy" unless="ivy.installed">
        <mkdir dir="${ivy.jar.dir}"/>
        <echo message="Installing Ivy..."/>
        <get src="${central.repo}/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
            dest="${ivy.jar.file}"/>
    </target>
<project>
NOTE I'm using Ivy 2.0.0-beta2 because there is a bug in 2.0.0-rc2 (the latest version at the time of this writing).

Before you can use Ivy, you need to have the Ivy configuration files in place. The first configuration file we will look at is the main settings file, which hosts the definitions for the artifact resolvers.

Chaining together a set of resolvers

Ivy works by mooching off of the Maven 2 repositories. However, unlike Maven, it can accommodate any hosted structure. So we need to tell Ivy where to look to find artifacts (i.e., dependencies) and what pattern it should use to locate an artifact in the remote repository as well as in the local cache. This configuration is defined in an Ivy settings file, which we will name ivy.settings.xml. We'll define three resolvers: local, central, and jboss, which we'll string together as a resolver chain and make it the default strategy.

<?xml version="1.0" encoding="UTF-8"?>
<ivysettings>
    <settings defaultResolver="default"/>
    <caches artifactPattern="[organisation]/[module]/[type]s/[artifact]-[revision](-[classifier]).[ext]" 
        checkUpToDate="true"/>
    <resolvers>
        <filesystem name="local">
            <ivy pattern="${ivy.cache.dir}/[module]/ivy-[revision].xml"/>
            <artifact pattern="${ivy.cache.dir}/[module]/[artifact]-[revision](-[classifier]).[ext]"/>
        </filesystem>
        <ibiblio name="central" m2compatible="true" usepoms="false" root="${central.repo}"
            pattern="[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"/>
        <ibiblio name="jboss" m2compatible="true" usepoms="false" root="${jboss.repo}"
            pattern="[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"/>
        <chain name="default" returnFirst="true">
            <resolver ref="local"/>
            <resolver ref="central"/>
            <resolver ref="jboss"/>
        </chain>
    </resolvers>
</ivysettings>

As I mentioned earlier, Ivy can grab JARs from almost any repository, but that also means that you have to tell it what type of repository it is dealing with. The <ibiblio> tag in the Ivy settings file applies a built-in pattern that allows Ivy to treat the repository as a standard Maven 2 repository. However, there is a bug in that pattern that makes it unable to handle non-binary artifacts, so we have to define the pattern explicitly.

You'll notice in this XML configuration two different styles of placeholder variables. The first are regular Ant property references. You can use any property you define in your Ant build prior to calling an Ivy task or any implicit property that Ivy defines (these are not well documented). As you can see here, we are using the built-in ivy.cache.dir property reference to define where the JAR files get cached locally, which happens to resolve to ${user.home}/.ivy2/cache.

The second type of placeholder variables, which are anchored by square brackets, are special Ivy replacement tokens that resolve to the segments of the artifact. The following table shows how these tokens map to Maven 2 terminology:

IvyMaven 2
organisationgroup ID
module, artifactartifact ID
revisionversion
exttype
classifierclassifier

The classifier took me a long time to discover and it requires a special setup to use in Ivy. More on that later.

Once Ivy resolves a dependency, it copies the artifact into the local cache directory, similar to how Maven 2 works. However, you have more control at the configuration level with regard to how Ivy handles updates. You also have the ability to segment the cache by project, which is done by adjusting the patterns in the <filesystem> node. This allows you to keep unrelated projects from interfering with one another. On top of this flexibility, the Ivy cache is already easier to manage than the Maven 2 local repository since it doesn't pollute the cache with its own plugins.

With this configuration in place, Ivy will search the local cache, then the central repository, and finally the JBoss repository to locate an artifact. Now the question becomes, how do you define what Ivy needs to fetch? That's where the Ivy module file comes in.

Telling Ivy about your dependencies

The ivy module file, typically named ivy.xml (though its location can be changed using the ivy.dep.file configuration property), is akin to the dependencies section of a Maven 2 POM file. It's where you define the libraries on which your project depends. Fortunately, the Ivy team does believe in XML attributes, unlike the Maven 2 radicals, so you have a lot less typing to do to define a dependency. But the most absolutely vital feature of Ivy, and what makes it infinitely more useful than Maven 2, is the fact that you can disable transitive dependencies.

I'm outspoken about my position on transitive dependencies. I see them as both evil and a silly device designed for novices (and people with way too much time on their hands). It makes your build non-reproducible and unstable and in the end causes you more work than the work you were attempting to eliminate by moving to Maven 2. This feature really is Maven's boat anchor. Trust me on this one, it's trivial to define which libraries your application depends on. There really aren't that many! And you can put all the worrying aside about exclusions. Okay, enough ranting and time to get back to the task at hand. I could go on about this topic all day!

Below is an Ivy module file for a vanilla seam-gen 2.0.3.CR1 WAR project with a couple of extras thrown in (for now I have removed the dependencies for Drools). Although Ivy has the awareness of dependency scopes (e.g., compile, runtime, test), we aren't concerned about that feature because all we are looking to do is inflate the project lib directory with the JARs we need to use the Ant build as-is.

<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="1.0">
    <info organisation="org.example" module="myproject"/>
    <configurations>
        <conf name="default" transitive="false"/>
    </configurations>
    <dependencies defaultconf="default">
        <dependency org="com.sun.facelets" name="jsf-facelets" rev="1.1.15.B1"/>
        <dependency org="commons-beanutils" name="commons-beanutils" rev="1.7.0"/>
        <dependency org="commons-digester" name="commons-digester" rev="1.7"/>
        <dependency org="javax.el" name="el-api" rev="1.0"/>
        <dependency org="javax.faces" name="jsf-api" rev="1.2_04-p02"/>
        <dependency org="javax.faces" name="jsf-impl" rev="1.2_04-p02"/>
        <dependency org="javax.persistence" name="persistence-api" rev="1.0"/>
        <dependency org="javax.servlet" name="servlet-api" rev="2.5"/>
        <dependency org="javax.transaction" name="jta" rev="1.0.1B"/>
        <dependency org="org.codehaus.groovy" name="groovy-all" rev="1.5.4"/>
        <dependency org="org.hibernate" name="hibernate-validator" rev="3.0.0.GA"/>
        <dependency org="org.jboss.el" name="jboss-el" rev="1.0_02.CR2"/>
        <dependency org="org.jboss.seam" name="jboss-seam" rev="2.0.3.CR1"/>
        <dependency org="org.jboss.seam" name="jboss-seam-debug" rev="2.0.3.CR1"/>
        <dependency org="org.jboss.seam" name="jboss-seam-ioc" rev="2.0.3.CR1"/>
        <dependency org="org.jboss.seam" name="jboss-seam-mail" rev="2.0.3.CR1"/>
        <dependency org="org.jboss.seam" name="jboss-seam-pdf" rev="2.0.3.CR1"/>
        <dependency org="org.jboss.seam" name="jboss-seam-remoting" rev="2.0.3.CR1"/>
        <dependency org="org.jboss.seam" name="jboss-seam-ui" rev="2.0.3.CR1"/>
        <dependency org="org.jbpm" name="jbpm-jpdl" rev="3.2.2"/>
        <dependency org="org.richfaces.framework" name="richfaces-api" rev="3.2.2.GA"/>
        <dependency org="org.richfaces.framework" name="richfaces-impl" rev="3.2.2.GA"/>
        <dependency org="org.richfaces.ui" name="richfaces-ui" rev="3.2.2.GA"/>
        <dependency org="org.testng" name="testng" rev="5.6"/>
    </dependencies>
</ivy-module>

You may be wondering if it's possible to eliminate the duplication in version numbers for the Seam, JSF, and RichFaces libraries (and perhaps others). I have good news for you. An Ivy module file understands Ant property references. So you can declare those versions in the ivy.build.xml file and thus have once central location to control them.

<property name="seam.version" value="2.0.3.CR1"/>
<property name="jsf.version" value="1.2_04-p02"/>
<property name="richfaces.version" value="3.2.2.GA"/>

You can now update your Ivy module file to use these property references. Here's the main Seam artifact now using an Ant property reference to manage the version:

<dependency org="org.jboss.seam" name="jboss-seam" rev="${seam.version}"/>

All we have to do now is tell Ivy to fetch the dependencies and copy them to the lib directory. For that, we switch back to our Ant build file with the Ivy-related targets.

Inflating the project

We'll create a task for inflating the lib file with the artifacts defined in the Ivy module file. This task needs to depend on a task that loads the Ivy Ant tasks and that task has to in turn depend on a task that fetches Ivy. Here are the targets:

<target name="load-ivy" depends="init-ivy,download-ivy">
    <path id="ivy.lib.path">
        <fileset dir="${ivy.jar.dir}" includes="*.jar"/>
    </path>
    <taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant"
        classpathref="ivy.lib.path"/>
    <ivy:settings file="${basedir}/ivy.settings.xml"/>
</target>

<target name="inflate-core" depends="load-ivy">
    <ivy:retrieve pattern="${lib.dir}/[artifact].[ext]" type="jar"/>
</target>

The load-ivy target first defines the Ant tasks Ivy provides using the <taskdef> element. The Ivy tasks are available under the namespace ivy. Finally, the <ivy:settings> task bootstraps the Ivy configuration. In the inflate-core target, the <ivy:retrieve> task resolves the artifacts from the chain of repositories and copies them into the project lib directory (the lib.dir property is defined in the main Ant build file).

Again, there is a mix of Ant property references and Ivy replacement tokens to define where the JAR file is going to end up. We are mirroring the standard seam-gen setup by putting the JAR files needed for compilation into the lib directory and named without their version numbers. You can of course keep the version number by referencing the [revision] token in the pattern, but then you have to update the deployed-jars.war file to ensure that the build includes the artifacts in the deployable archive. Here's a portion of the output when the inflate-core task is run:

Buildfile: build.xml

init-ivy:

download-ivy:

load-ivy:
[ivy:settings] :: Ivy 2.0.0-beta2 - 20080225093827 :: http://ant.apache.org/ivy/ ::
[ivy:settings] :: loading settings :: file = /home/dallen/projects/myproject/ivy.settings.xml

inflate-core:
[ivy:retrieve] :: resolving dependencies :: org.example#myproject;working@sandstone
[ivy:retrieve]  confs: [default]
[ivy:retrieve]  found com.sun.facelets#jsf-facelets;1.1.15.B1 in jboss
[ivy:retrieve]  found commons-beanutils#commons-beanutils;1.7.0 in central
...
[ivy:retrieve] :: resolution report :: resolve 1622ms :: artifacts dl 121ms
        ---------------------------------------------------------------------
        |                  |            modules            ||   artifacts   |
        |       conf       | number| search|dwnlded|evicted|| number|dwnlded|
        ---------------------------------------------------------------------
        |      default     |   24  |   0   |   0   |   0   ||   24  |   0   |
        ---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: org.example#myproject
[ivy:retrieve]  confs: [default]
[ivy:retrieve]  0 artifacts copied, 24 already retrieved (0kB/34ms)

BUILD SUCCESSFUL
Total time: 3 seconds

So far, so good, but currently we are running a bit short functionality that was present before we introduced Ivy. For one, we need the JBoss Embedded JAR files and dependencies in order to be able to run tests. The project build is expecting these artifacts to be in the lib/test directory. Additionally, seam-gen includes the source artifacts for Seam in the lib/src directory, so we will want to pull down those down from the repository as well (and any other sources you want to grab). The question is, where do these artifacts fit in?

Fetching auxiliary artifacts

It's time for us to expand our dependency list to itemize the different types of dependencies. We just identified three types:

  • jar
  • source
  • test-jar

However, the <dependency> element itself has no way to make these distinctions. That is the purpose of the nested <artifact> element. This element lets us define one or more types for a dependency. In addition, we can take on a couple of additional attributes. The most vital of those attributes is the classifier.

The classifier attribute ties back into a discussion I left off with earlier. In the Maven 2 repository, sources are named by appending the suffix -sources to the end of the file name, but before the file extension. The trouble is that this introduces a new segment to the pattern. (It would have been nice if binary artifacts in the Maven 2 repository used the suffix -binary, but that's just wishful thinking).

Fortunately, Ivy understands the concept of an optional segment. (I sure hope this tip saves you time because it took me the better part of a day to track down). An optional segment is defined in an Ivy pattern by surrounding it with parenthesis. Any other text which is between the parenthesis will be ignored if the token has no value. Going back to earlier, you might recall using the following pattern in ivy.settings.xml:

[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]

As you can see, the classifier will be appended to the URL if defined. What we need to do now is define what the classifier is for a given dependency. We'll unfold the <dependency> elements in the Ivy module file and insert one or more <artifact> elements, one of which will host the classifier attribute. Here, again, is the dependency declaration for the main Seam artifact, now paired with its sources:

<dependency org="org.jboss.seam" name="jboss-seam" rev="${seam.version}">
    <artifact name="jboss-seam" type="jar"/>
    <artifact name="jboss-seam" type="source" ext="jar" m:classifier="sources"/>
</dependency>

As you can see, the classifier attribute is defined in its own namespace. In order to prevent Ivy from complaining about the use of invalid XML syntax, you need to declare this namespace in the root element of the Ivy module file:

<ivy-module version="1.0" xmlns:m="http://ant.apache.org/ivy/maven">
    ...
</ivy-module>

When Ivy resolves the dependencies, it grabs all the artifacts, regardless of type. But what the type discriminator allows us to do is copy the artifacts to different locations according to type. We'll introduce a new target in our Ant build that copies the source artifacts to lib/src, using the type in the file name to be consist with how seam-gen lays down the project files:

<target name="inflate-source" depends="load-ivy">
    <ivy:retrieve pattern="${lib.dir}/src/[artifact]-[type]s.[ext]" type="source"/>
</target>

All that we have left to do is grab the runtime test JARs. I'll admit to you that there may be a more elegant way to accomplish this task using Ivy dependency configurations, but I couldn't make sense of that feature and the approach I am about to suggest works perfectly (sometimes we forget that something that works is better than something that is supposed to work). Here are the dependency definitions for those test JARs:

<dependency org="org.jboss.seam.embedded" name="hibernate-all" rev="${jboss-embedded.version}">
    <artifact name="hibernate-all" type="test-jar" ext="jar"/>
</dependency>
<dependency org="org.jboss.seam.embedded" name="thirdparty-all" rev="${jboss-embedded.version}">
    <artifact name="thirdparty-all" type="test-jar" ext="jar"/>
</dependency>
<dependency org="org.jboss.seam.embedded" name="jboss-embedded-all" rev="${jboss-embedded.version}">
    <artifact name="jboss-embedded-all" type="test-jar" ext="jar"/>
</dependency>

Finally, here is the Ant target that retrieves the test JARs and another Ant target to retrieve all three types in a single commmand:

<target name="inflate-test" depends="load-ivy">
    <ivy:retrieve pattern="${lib.dir}/test/[artifact].[ext]" type="test-jar"/>
</target>

<target name="inflate" depends="inflate-core,inflate-source,inflate-test"/>

Though not shown here, you might also want to create a target to purge the lib folder and another to generate a dependency report using the <ivy:report> task.

Once you have all of the Ivy configurations in place described in this article, you can wipe our your lib directory and build your project in these two steps:

ant inflate
ant explode

You are now Ivy-enabled and you're lib folder is no longer bursting at the seams.

Summary

What we set out to do is reign in the chaos of the lib folder in seam-gen projects and setup a system for managing the dependencies. Having a dependency management solution in place makes it easy to add new libraries and upgrade existing ones. The approach taken in this article was to use Ivy to define the dependencies and retrieve them from a remote repository without having to change the project build in any way (other than to import the Ivy-related build file). I purposely did not attempt to integrate Ivy into the build process because there is really no need to constantly retrieve the artifacts while developing your application. Instead, what you want is a set it and forget it approach. This strategy has the side effect of making your build reproducible and stable.

If I get around to writing another article, the next step is to eliminate the deployed-jars.list file and figure out how to instead pull this information from the Ivy module file. But that will require understanding Ivy dependency configurations better on my part.

And in case you are wondering, yes, I am considering integrating Ivy support into the seam-gen core. It just seems like a no-brainer to me. I still have hope for Maven 2, but at this point I am seeing better productivity gains from using this Ivy configuration.

Get the complete Ivy configuration and build file[1] and start using Ivy to manage your application's dependencies today!

Update: Grab the updated Ivy configuration and build file[1] to get a more concise version of the ivy.settings.xml file.

18 comments:
04. Oct 2008, 05:39 CET | Link

I want to clarify my position on transitive dependencies. I am not opposed to projects making dependency information available in the repository as metadata. That, in itself, is useful. But transitive dependencies should be just that, metadata, not an actionable part of the build.

On another note, I mention in the article that I am not using the RC of Ivy because it has a bug, but I don't explain what the bug is. The problem appears to be that as of Ivy 2.0 RC2, the built-in properties are not being setup when Ivy first loads (i.e., <ivy:settings>) so that when Ivy reads in the settings file, it does not resolve ${ivy.cache.dir}. As a result, it complains that the cache directory is not valid. I'm not sure what is going on there, exactly, but clearly something changed between beta 2 and the RC. Just grab my files and attempt to use them with the RC and you will see what I am talking about.

One final note. In the configuration I put the central repository before the JBoss repository. The reason I use this order is because the JBoss repository doesn't always have the sources jars for an artifact, whereas they are present in central if they exist anywhere. However, if Ivy finds a binary artifact in one repository, it will only attempt to find the sources in that same repository. Thus, you can see where the conflict comes into play. Again, I'm not sure what is going inside of Ivy, but to me it appears to be a bug.

ReplyQuote
 
06. Oct 2008, 17:34 CET | Link
Erik-Berndt Scheper

Hi,

Did you file an issue for this in the IVY jira? It looks similar to http://issues.apache.org/jira/browse/IVY-907, for which there is a work-around.

 
06. Oct 2008, 18:30 CET | Link

Hi,

Great article! For a while I have wondered how a tool like seam-gen and seam development in general would interact with a fully package-managed environment (which is what I hope the linux distros will achieve).

Do you have any thoughts on this? Would it seem reasonable to have ivy check /usr/share/java for updated packages on each build?

Best Anders

 
07. Oct 2008, 02:27 CET | Link

Yes, that does appear to be the exact problem I was experiencing. I kind of followed what the workaround was, but I am hoping that in the next release of Ivy I won't have to change anything because it appears that I am doing what I am supposed to do. The fault appears to be Ivy, not my own.

 
07. Oct 2008, 02:31 CET | Link

Yikes, I have a pretty strong opinion that an enterprise application should never be bound to the operating system it is running on (only perhaps the JVM and the application server). That being said, you could certainly have a local repository that Ivy uses, perhaps internal to the company or even on a shared NFS drive. But I would shy away from any references to /usr/share/java. At my last company, we had a pretty serious Perl application and we didn't even use the Perl that came with the Linux distribution.

 
07. Oct 2008, 16:50 CET | Link

Hi,

thank you for your very usefull article. I've got one question. I've made exactly what's said (expect I change seam version to 2.1.0.CR1) and I get a dependency problem :

package javax.ejb does not exist.

Thank you for your reply

 
08. Oct 2008, 00:08 CET | Link

Hmm, what I am trying to think about is how to use the wonderful work that the linux-distribution packagers do. So that when the java packages - JBossAS, richfaces, SEAM etc. are automatically updated that I get the full benefit. I really think the Microsoft way of everyone each being responsible for keeping their software updated (or not!) is not optimal.

 
09. Oct 2008, 02:53 CET | Link

You might need the EJB API dependency. Try this out.

<dependency org="javax.ejb" name="ejb-api" rev="3.0">
    <artifact name="ejb-api" type="jar"/>
</dependency>

I left it out to emphasize that Seam does not rely on EJB, though your application might be using a class from that API (such as an annotation).

 
14. Oct 2008, 14:34 CET | Link

Thanks for an interesting article.

I tried using this with a seam 2.1 snapshot, but Ivy doesn't seem to play very nice with maven snapshots (snapshots.jboss.org).

For example, I'm having trouble resolving: http://snapshots.jboss.org/maven2/org/jboss/seam/jboss-seam/2.1.0-SNAPSHOT/jboss-seam-2.1.0-20081014.042746-297.jar

Here, the directory uses a 'SNAPSHOT' qualifier, while the jar uses a build-number.

19. Oct 2008, 18:58 CET | Link
Wolfgang Schwendt

Hi Dan, given your comment that you are considering integrating Ivy support into the seam-gen core, I have one question: Have you thought about using the Ant Tasks for Maven as an alternative to Ivy? What are the benefits of using Ivy rather than the Ant tasks for Maven? What would be the drawbacks of using the Ant Tasks for Maven?

http://maven.apache.org/ant-tasks.html http://maven.apache.org/ant-tasks/reference.html

In order to reduce complexity for developers, it would be good if Seam-gen used the same tool for dependency management as it is used for the Seam build files itself. I would avoid using two different technologies (Ant Tasks for Seam build files, Ivy for Seam-gen).

19. Oct 2008, 19:02 CET | Link
Wolfgang Schwendt

Maybe also the following blog entry is helpful:

Thursday, September 25, 2008 Using Maven-Ant-Tasks instead of Ivy. by Josh Suereth http://suereth.blogspot.com/2008/09/using-maven-ant-tasks-instead-of-ivy.html

21. Oct 2008, 03:22 CET | Link
Joris Wijlens | joris.wijlens(AT)gmail.com
In order to reduce complexity for developers, it would be good if Seam-gen used the same tool for dependency management as it is used for the Seam build files itself. I would avoid using two different technologies (Ant Tasks for Seam build files, Ivy for Seam-gen).

I agree with Wolfgang about avoiding two technologies. Kick maven out, only use Ivy :).

And thanks for the article.

23. Oct 2008, 09:04 CET | Link
Wolfgang Schwendt

After posting my comments, I experimented a little with the Maven Ant Tasks. Several helpful macros for using them are already in the Seam build files (see build/common.build.xml) and can be easily modified to be used in a build file for Seam-gen. If the objective is just to download all needed libraries and sources for a Seam-gen project, the Maven ant Tasks can accomplish the same as the Ivy-based solution. For a Maven-Ant-Tasks based upgrade of Seam-gen, my approach would be to write a Maven POM that just declares the needed dependencies of a Seam-gen project (but not any build process logic), similar to your file ivy.xml.

I see the following advantages for using the Maven Ant Tasks:

- it's the same technology for dependency management as in the Seam build files

- the POM that declares all dependencies (needed libraries) of a Seam-gen project can inherit from the POMs for Seam (reduces the need to duplicate the declaration of dependencies)

- Maven repositories are the de facto standard for repositories in the Java world nowadays, they don't contain just the JAR files of libraries, but for every JAR also meta-information in form of the POM file. This makes it easy to see what dependencies an included library requires.

- A Maven-Ant-Tasks based Seam-gen would leave the door for easy migration to a 100% Maven based Seam-gen (the POM that declares the dependencies of Seam-gen project could be extended to declare also the build process)

23. Oct 2008, 09:08 CET | Link
Wolfgang Schwendt
- A Maven-Ant-Tasks based Seam-gen would leave the door for easy migration to a 100% Maven based Seam-gen

correction, it should read:

- A Maven-Ant-Tasks based Seam-gen would leave the door open for easy migration to a 100% Maven based Seam-gen

 
09. Mar 2009, 04:32 CET | Link

I don't agree that disabling transitive dependencies is a good thing and I have responded in a blog post here:

http://ptrthomas.wordpress.com/2009/03/08/why-you-should-use-the-maven-ant-tasks-instead-of-maven-or-ivy/

 
16. Apr 2009, 23:31 CET | Link

You can see a slightly different way of accomplishing this while still keeping the transitive deps and avoiding some of the headaches Dan ran into at http://lightguard-jp.blogspot.com/2009/04/ivy-configurations-when-pulling-from.html. I have also submitted a patch to Dan's Ivy support in seam-gen, we may see it in 2.2.0.

 
23. Jul 2009, 04:45 CET | Link
Arbi Sookazian
So what is the status of seam-gen project builds? DAllen has a new post from April 2009 here: https://jira.jboss.org/jira/browse/JBSEAM-2026

Is it going to be Ant + Ivy or Maven 2 (with official Seam archetype) for Seam 3 projects?
 
11. Aug 2009, 06:01 CET | Link

Likely Maven 2, since the Seam 3 build is based on Maven 2 and the m2eclipse plugin is finally usable. It's next to impossible to get this into Seam 2 because the build is so eclectic.

Post Comment