Ruby support on Maven 2

Eric Redmond has developed the Ruby support for developing Maven 2 mojos.

It’s great to see how in few weeks since 2.0 was released a lot of contributions have been made for all kind of tools. For instance there’s already support for C, C++ and C#. Do you want to contribute some COBOL support? 😉

Spring 2.0 M1 released

Spring 2.0 M1 was released last week. As a maven related news, it will make life easier with transitive dependencies because the orm support was splitted in different jars spring-jdo, spring-hibernate2, spring-hibernate3, spring-toplink, spring-ojb.

Jars and poms are already available at ibiblio, so you can start using it right now in your maven 1 / maven 2 projects

Announcement by Juergen Hoeller:

Dear Spring community,

I am pleased to announce that Spring 2.0 M1 has just been released. 2.0 M1
is the first milestone of the next generation of Spring: introducing XML
schema based bean definitions, sophisticated AspectJ support, task executor
abstraction, asynchronous JMS facilities, portlet support, etc.

The main sample application in this release is JPetStore, which already
illustrates some basic usage of schema-based bean definitions and aspects
expressed using AspectJ pointcut language. 2.0 M2 will include further
sample usages and improved documentation of the new configuration style.

Spring 2.0 remains fully backwards-compatible with Spring 1.2. Both the DTD
style and the schema style are supported for XML bean definitions. No
incompatible API changes have been introduced (other than removing
deprecated methods). Furthermore, Spring 2.0 still runs on JDK 1.3+ and J2EE
1.2+.

Note that Spring has been repackaged: spring.jar contains the entire core
plus some small extensions; larger extensions such as support for specific
ORMs have been factored out into separate jar files (spring-hibernate2.jar,
spring-hibernate3.jar, spring-toplink.jar, etc). See the readme for details.

Cheers – and Merry Christmas to everybody celebrating Christmas 🙂

Juergen

ApacheCON San Diego

Next weekend I’ll be in San Diego for ApacheCON hackathon and conference. If you are there don’t miss the two tutorials and one session about Maven! And say hello if you see me 😉

Maven repository, adding sources

Now as part of the upload of your jar to the maven repository at
ibiblio you can include the sources, making them available to all your
users, helping you to find and solve bugs, hopefully ;).

For instance, to generate the eclipse project for a maven 2 project with the sources attached, you can run

mvn eclipse:eclipse -Declipse.downloadSources=true
 

Read the instructions to make an upload bundle, now with sources!

Using transitive dependencies the right way

So we have this cool feature called transitive dependencies in maven 2. For those that don’t know yet that allows me to say:

  • me: I want struts 1.2.8 in my webapp, do it!
  • maven: sure, I add struts-1.2.8, but as I know you’re a bit lazy I’ll add for you commons-beanutils, commons-digester, jakarta oro,… because I know you’ll need them
  • me: cool, I still remember those days when I had to download the jars by hand and put them in a folder in cvs and then create a classpath in ant,…
  • maven: no problem

But then something happens with some of the jars:

  • me: I want to use spring-hibernate 1.2.5
  • maven: you again? I’ll add spring-hibernate-1.2.5, but as it depends in other stuff, I’ll add also spring-orm and its dependencies, hibernate-annotations, hibernate 2, hibernate 3,…
  • me: wait! how is that you’re adding hibernate 2 and 3? I want to use just 3!!
  • maven: well, if you wanna use all the features in spring-hibernate you’ll need both or you may get a ClassNotFoundException. There’s no way I can know what will you use and what not.
  • me: let me think, if I had created a spring-hibernate2 and spring-hibernate3, I could depend on spring-hibernate3 and everything would be automatic
  • maven: yes, but shit happens, and that’s not how it was released
  • me: ok, then let’s tag hibernate 2 and 3 as optional in the spring-hibernate pom in ibiblio, that way I don’t need to exclude hibernate2, although I’ll need to add also hibernate3 to my dependencies.
  • maven: that will be hard for a lazy bastard like you
  • me: stfu!

To sum up this is my advice: the days of downloading jars and adding them to a folder ended time ago, don’t be worried about creating more smaller jars that explicitly define their dependencies with no doubt, meaning that you’ll always know the requirements of a piece of software. Avoid big jars that depend on everything.

(Thanks to all the people that contributed to this entry teaching me the wonders of the english cosswords. You’re more than you think 😉 )

Building Spring with maven2

Probably you already noticed that maven2 beta-1 is out,
and I’m quite sure that you are wondering if it’s ready to be used in a
real world. Well, you can try to build the Spring Framework with it as
a example of a not too simple application, with a lot of dependencies.

What do you need:

  • Spring 1.2.4 distribution
  • Maven 2 beta-1
  • A bunch of non redistributable Sun jars due to its licensing
    schema (hopefully they’re changing that stupid restriction). When maven
    doesn’t find the jars it will show where you can download them, getting
    that information from the poms in the repository. If not you can fill an issue.
    Of course you can get them also from the Spring distribution, geronimo
    open source ones,… Copy them to your local repo, by default under
    $HOME/.m2/repository.
    • javax/transaction/jta/1.0.1B/jta-1.0.1B.jar
    • javax/jdo/jdo/2.0-20050809.1515/jdo-2.0-20050809.1515.jar
    • javax/jms/jms/1.1/jms-1.1.jar
    • javax/ejb/ejb/2.0/ejb-2.0.jar
    • javax/xml/jaxrpc/1.1/jaxrpc-1.1.jar
    • javax/resource/connector/1.0/connector-1.0.jar
    • javax/mail/mail/1.3.2/mail-1.3.2.jar
    • javax/faces/jsf-api/1.1/jsf-api-1.1.jar

Split
the sources in the
different spring subprojects, because they come in the same directory.
You can use this ant target, adding it to the end of spring build.xml
file and run “ant
splitsources”, which will create a “m2” folder with a subfolder for
each subproject.

    <target name="splitsources" description="Split the sources in subprojects">

        <copy todir="m2/all/src/main/java">
            <fileset dir="${src.dir}"/>
        </copy>

        <copy todir="m2/all/src/main/java">
            <fileset dir="tiger/src"/>
        </copy>

        <copy todir="m2/all/src/test/java">
            <fileset dir="${test.dir}"/>
        </copy>

        <copy todir="m2/all/src/test/java">
            <fileset dir="tiger/test"/>
        </copy>

        <copy todir="m2/spring-core/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="org/springframework/core/**"/>
                <include name="org/springframework/util/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-beans/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="org/springframework/beans/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-aop/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="org/springframework/aop/**"/>
                <include name="org/springframework/metadata/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-context/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="org/springframework/context/**"/>
                <include name="org/springframework/jndi/**"/>
                <include name="org/springframework/ui/**"/>
                <include name="org/springframework/validation/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-dao/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="org/springframework/dao/**"/>
                <include name="org/springframework/transaction/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-jdbc/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="org/springframework/jdbc/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-support/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="org/springframework/cache/**"/>
                <include name="org/springframework/jca/**"/>
                <include name="org/springframework/jmx/**"/>
                <include name="org/springframework/mail/**"/>
                <include name="org/springframework/scheduling/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-web/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="org/springframework/web/**"/>
                <exclude name="org/springframework/web/servlet/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-webmvc/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="META-INF/*.tld"/>
                <include name="org/springframework/web/servlet/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-remoting/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="org/springframework/ejb/**"/>
                <include name="org/springframework/jms/**"/>
                <include name="org/springframework/remoting/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-orm/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="org/springframework/orm/**"/>
                <exclude name="org/springframework/orm/hibernate/**"/>
                <exclude name="org/springframework/orm/hibernate3/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-hibernate/src/main/java">
            <fileset dir="m2/all/src/main/java">
                <include name="org/springframework/orm/hibernate/**"/>
                <include name="org/springframework/orm/hibernate3/**"/>
            </fileset>
        </copy>

        <copy todir="m2/spring-mock/src/main/java">
            <fileset dir="${mock.dir}"/>
        </copy>

        <copy todir="m2/spring-test/src/test/java">
            <fileset dir="m2/all/src/test/java"/>
        </copy>

    </target>

Download the poms
and uncompress them in the directory you uncompressed spring. Go to the
m2 directory and run any m2 goal, like “m2 install”, that will copy to
your local repo all the spring jars (remember to remove them so the
official ones get downloaded from ibiblio next time you use maven2 for
any other purpose).

You can take a look at how simple are the poms now, for instance the
spring-hibernate project, that needs a lot of jars in the classpath to
run is as simple as:

<project>
  <parent>
    <artifactId>spring-parent</artifactId>
    <groupId>springframework</groupId>
    <version>1.2.4</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>
  <artifactId>spring-hibernate</artifactId>
  <version>1.2.4</version>
  <dependencies>
    <dependency>
      <groupId>springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>1.2.4</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-annotations</artifactId>
      <version>3.0beta2</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate</artifactId>
      <version>3.0.5</version>
    </dependency>
    <dependency>
      <groupId>net.sf.hibernate</groupId>
      <artifactId>hibernate</artifactId>
      <version>2.1.8</version>
    </dependency>
  </dependencies>
</project>

You’ll notice that tests are not running, the reason is that spring
test sources can’t be splitted in subprojects because they don’t follow
the modular desing and have circular dependencies, eg. a test class in
spring-core uses a class in spring-beans whenspring-beans depends in spring-core. I’ll post an entry about this soon.

Writing file system independent applications with commons-vfs

Lately I’ve been playing with commons virtual file system
(commons-vfs), which is a really cool way to make your application file
system independent. You can write the same code to access files in your
local file system, samba servers, sftp servers, http, webdav,… see the complete list.

        FileSystemManager fileSystemManager = VFS.getManager();
        FileObject from = fileSystemManager.resolveFile(getFrom());
        FileObject to = fileSystemManager.resolveFile(getTo(), getFileSystemOptions());
        to.copyFrom(from, new AllFileSelector());

The application context with Spring would be something like the
following. You can see that setting the file system options it’s a pita
because they don’t follow the beans convention and you need to call
different methods instead of setting bean properties. I hop they change
ths in next versions.

    <bean id="myBean" class="TestBean">
        <property name="from" value="http://www.myserver.com/filename"/>
        <property name="to" value="sftp://username:[email protected]/home/whatever"/>
        <property name="fileSystemOptions" ref="sftpFileSystemOptions"/>
    </bean>

    <bean id="sftpFileSystemConfigBuilder"
          class="org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder"
          factory-method="getInstance"/>

    <bean id="sftpFileSystemOptions" class="org.apache.commons.vfs.FileSystemOptions"/>

    <bean id="sftpFileSystemOptions_disableStrictHostKeyChecking"
          class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="sftpFileSystemConfigBuilder"/>
        <property name="targetMethod" value="setStrictHostKeyChecking"/>
        <property name="arguments">
            <list>
                <ref local="sftpFileSystemOptions"/>
                <value>no</value>
            </list>
        </property>
    </bean>

    <!-- use private key instead of password -->
    <bean id="sftpFileSystemOptions_setIdentities"
          class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject" ref="sftpFileSystemConfigBuilder"/>
        <property name="targetMethod" value="setIdentities"/>
        <property name="arguments">
            <list>
               <ref local="sftpFileSystemOptions"/>
               <list><value>Path to the ssh identity file</value></list>
            </list>
        </property>
    </bean>

Another drawback is that you need to build from sources, no releases are available yet 😦

The risks of funny t-shirts

Here in the company I’m currently working as contractor we usually
play soccer once a week. This week I took my t-shirt with the
inscription “Spanish SEX instructor. First lesson free” (sex in very
big letters). So I put it on in the restrooms of the company,
walked
out of the office, and called the elevator. The surprise was when going
out of the elevator was the CEO of the company, but luckily with my
fast reflexes I turned and was able to hide the message. uffff.

That remembers me other great conversations performed by me or coworkers like:

After the buying of the company I was working for:

  • what do you guys do?
  • we’re contractors, and you, are you in sales team?
  • no, I’m the CEO of xxx (the company that just bought ours)

In the elevator

  • what do you guys do?
  • we are in the xxx project
  • cool, how is it going?
  • it’s going ok (here I paid the price of my not so good english)
  • only ok! here in this company we expect the best!!
  • and what do you do? are you in marketing team?
  • no, I’m the CEO

Maven tips and Tricks: Perforce (round 2)

In relation to my last post about maven and Perforce
this is a better solution that will work with both maven 1.0.x and 1.1.
The previous one doesn’t work under maven 1.1 because the bundled ant
version was updated to 1.6, that doesn’t include the optional perforce
tasks.

This time you’d need:

  • oro and ant-apache-oro as a dependency in your project.xml.
        <dependency>
            <groupId>oro</groupId>
            <artifactId>oro</artifactId>
            <version>2.0.8</version>
            <!-- you don't need the root classloader if
                 only running under maven 1.1 -->
            <properties>
                <classloader>root</classloader>
            </properties>
        </dependency>
        <dependency>
            <groupId>ant</groupId>
            <artifactId>ant-apache-oro</artifactId>
            <version>1.6.4</version>
        </dependency>
  • The actual goal in maven.xml
        <!-- perforce -->
        <goal name="p4sync">
    
            <!--
                 you need Perforce command line client and maybe specify
                 P4CLIENT and P4PASSWD environment variables
            -->
    
            <ant:taskdef name="p4sync"
               classname="org.apache.tools.ant.taskdefs.optional.perforce.P4Sync"
               classpathref="maven.dependency.classpath"/>
    
            <p4sync view="//depot/whatever/..." />
        </goal>

Another option to avoid defining each one of the tasks is creating a properties file in the classpath and load it with

        <ant:taskdef resource="com.whatever.PerforceTasks"
           classpathref="maven.dependency.classpath"/>

And the contents of the properties file is

        # Perforce tasks available
        p4change=org.apache.tools.ant.taskdefs.optional.perforce.P4Change
        p4delete=org.apache.tools.ant.taskdefs.optional.perforce.P4Delete
        p4label=org.apache.tools.ant.taskdefs.optional.perforce.P4Label
        p4labelsync=org.apache.tools.ant.taskdefs.optional.perforce.P4Labelsync
        p4have=org.apache.tools.ant.taskdefs.optional.perforce.P4Have
        p4sync=org.apache.tools.ant.taskdefs.optional.perforce.P4Sync
        p4edit=org.apache.tools.ant.taskdefs.optional.perforce.P4Edit
        p4integrate=org.apache.tools.ant.taskdefs.optional.perforce.P4Integrate
        p4resolve=org.apache.tools.ant.taskdefs.optional.perforce.P4Resolve
        p4submit=org.apache.tools.ant.taskdefs.optional.perforce.P4Submit
        p4counter=org.apache.tools.ant.taskdefs.optional.perforce.P4Counter
        p4revert=org.apache.tools.ant.taskdefs.optional.perforce.P4Revert
        p4reopen=org.apache.tools.ant.taskdefs.optional.perforce.P4Reopen
        p4fstat=org.apache.tools.ant.taskdefs.optional.perforce.P4Fstat

Note that you can’t use the properties file bundled with ant because it includes all optional tasks, wich would force you to include all ant-*.jar files in the classpath.

What Business Can Learn from Open Source

I can list a lot of people I wish they read this essay: What Business Can Learn from Open Source, by Paul Graham.