Now in Los Angeles

I got a gig in Los Angeles thanks to Rick Hightower,
so I’m staying in Santa Monica for the next 6 months aprox. It’s a
pretty cool place to live and the job is great, working with latest
technology: JSF, Hibernate, Spring, …
So if you live near or have any suggestions about what to see and what to do, please let me know.
I’m starting a weblog in spanish
for my friends and other people who wants to  read it about the
differencies between Spain and USA, it’ll be kind of funny.

Using Java 1.5 in real world app

It’s almost sure that the current app we’re developing right
now will use Java 5. That’s the first option and will be used
unless some problem arises. So it was time to remember the Taming the Tiger presentation from Joshua Bloch and Neal Gafter in JavaHispano II. The slides are available from the Denver Java Users Group Archives, and it’s a pity that the link to the video of the session seems broken.

As Joshua and Neal advised the only trouble porting pre 1.5 code to 1.5 is that enum can’t
be used as variable name because it’s a reserved word. And of course
the old code does, so it’s time to refactor that variable names. Seems
that appart from that there won’t be any problem.

BTW I’ve also enjoyed the Still More Java Puzzlers slides.

Hibernate 3 + Annotations + Spring 1.2 + Maven

Today I upgraded a prototype working with Hibernate 2 + Spring 1.1
to the latest Hibernate 3.0.1 + Spring 1.2rc2 + Hibernate annotations
3.0beta1 to avoid writing mapping files and use annotations under Java 5.

To use annotation under Maven you need to add the following properties to project.properties

maven.compile.source=1.5
maven.compile.target=1.5

and these all the dependencies you will need. Note that some of them
are not available at ibiblio yet due to a problem of space that will be
solved soon.

        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.0.4</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.8</version>
        </dependency>
        <dependency>
            <groupId>springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>1.2-rc2</version>
        </dependency>
        <dependency>
            <groupId>springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>1.2-rc2</version>
        </dependency>
        <dependency>
            <groupId>springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>1.2-rc2</version>
        </dependency>
        <dependency>
            <groupId>springframework</groupId>
            <artifactId>spring-hibernate</artifactId>
            <version>1.2-rc2</version>
        </dependency>
        <dependency>
            <groupId>springframework</groupId>
            <artifactId>spring-dao</artifactId>
            <version>1.2-rc2</version>
        </dependency>
        <dependency>
            <groupId>springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>1.2-rc2</version>
        </dependency>
        <dependency>
            <groupId>springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>1.2-rc2</version>
        </dependency>
        <dependency>
            <groupId>springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>1.2-rc2</version>
        </dependency>
        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.0</version>
            <url>http://jakarta.apache.org/commons/collections</url>
        </dependency>
        <dependency>
            <groupId>commons-pool</groupId>
            <artifactId>commons-pool</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
            <groupId>hibernate</groupId>
            <artifactId>hibernate</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6</version>
        </dependency>
        <dependency>
            <groupId>ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>ejb</groupId>
            <artifactId>ejb</artifactId>
            <version>3.0-edr2</version>
        </dependency>
        <dependency>
            <groupId>hibernate</groupId>
            <artifactId>hibernate-annotations</artifactId>
            <version>3.0beta1</version>
        </dependency>
        <dependency>
            <groupId>jta</groupId>
            <artifactId>jta</artifactId>
            <version>1.0.1B</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.1</version>
        </dependency>
        <dependency>
            <groupId>asm</groupId>
            <artifactId>asm</artifactId>
            <version>1.5.3</version>
        </dependency>
        <dependency>
            <groupId>hibernate</groupId>
            <artifactId>antlr</artifactId>
            <version>2.7.5H3</version>
        </dependency>

Soon with Maven 2 you won’t need all this stuff 😉

As far as the Hibernate 2 to 3 migration as many people have already
said it’s just a matter of renaming the net.sf.hibernate imports to
org.hibernate. About the Hibernate annotations I should give Rick the credit as he has already posted the sample code.

To use Spring with the new Hibernate 3 you need to upgrade to Spring
1.2 (1.2rc2 is the latest version currently available) and change org.springframework.orm.hibernate.LocalSessionFactoryBean to org.springframework.orm.hibernate3.LocalSessionFactoryBean in you applicatin context.

To use Java5 annotations instead of mapping files you need to create a hibernate config file (say hibernate.cfg.xml)
with the classes you want to map (or add them to the one you already
have). The reason you need this file is so the Spring framework doesn’t
depend on JDK 5.

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <mapping class="your.domain.class"/>
        <mapping class="another.domain.class"/>
    </session-factory>
</hibernate-configuration>

And then add to your Spring LocalSessionFactoryBean two properties

<property name="configLocation">
    <value>hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
    <value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>

And that’s all for the moment.

Maven 2.0 Alpha 2 Released

Brett has released the Maven 2.0 Alpha 2 version, thanks!

Download

Maven 2 site

Maven 2 and Continuum slides

Brett Porter has posted a set of very interesting slides about Maven 2.0 and Continuum

https://sydneyjug.dev.java.net/files/documents/922/15554/sjug20050601.pdf

Back from JavaHispano

After many busy days I’m able to post this entry.

Two weeks ago I spent two great days at JavaHispano 2004 (Madrid), where I talked about Acegi Security System for Spring.

There I met many nice guys,

Miguel Valdes-Faura

(ObjectWeb), Alexandre Vasseur (AspectWerkz), Santiago Gala (Apache), Hugo Pinto,

Jes�s Perez (Agile-Spain), and people from the JavaHispano JUG as

Abraham Otero.

There
was very interesting talks. What I liked most were “Taming the Tiger”
by Joshua Bloch and Neal Gafter, and Annotation driven AOP by Alexandre
Vasseur. Other interesting ones were from Sun evangelist Angela Caicedo
about JSF, Miguel Valdes about Middleware and the round table about
Java future, with Reggie Hutcherson, another Sun evangelist.

My presentation was about Acegi Security System for Spring and the
features it provides. I used ONess as example of using it in an
enterprise class application. I didn’t expect too much interest from
the public as it’s a very specific thing, but there were questions, and
nobody fell asleep! 😉

I also talked a lot about Maven and saw that everyone is planning to check it for next projects.

It’s worth to say that the conferences were free, and the room was
always under 200 people, wich made it very familiar and a good place to
meet interesting people working in Java. There’s a fact: the more it
costs the more it’s estimated by people.

What are the ideas I got after these two days: AspectWerkz rocks,
JOnAS (the first open source application server, don’t believe JBoss!),
Java 5 and JSF worth trying. And of course Spring Framework community
is growing faster and faster 😉

Maven vs. Ant + Ivy

There was some interesting discussion lately about Ivy. It started with Colin’s blog entry about Ivy and transitive dependencies.

I think that if you decide to use Ant you’d better use something like Ivy to manage the dependencies in a painless way. If you choose maven just for handling dependencies you may prefer using Ant + Ivy, maven is not about just handling jars, I’d like to think that it’s more than that. As Dion I have to stand up for Maven too. It provides me more productivity than Ant.

You may agree or not but something I find really annoying is people trying to reinvent the wheel. Ivy uses the Maven repository at iBiblio and that’s great, we can collaborate to get a better repository BUT Brett is right about the new Ivy repository with dependency metadata, maven project info is already available under the groupId/poms dir and can be used from Ivy, better improve it than starting from scratch, isn’t it?

I’d like to say that some problem I usually find with that dependency metadata is that projects don’t spend a bit of its time to provide it, I don’t force them to do so just to please me, but many people rant about maven because it doesn’t handle dependency information and they should complain to each project developers, not maven.

N.B. A good idea would be an XSL to pretty print the info from the POM.

I expect that the new maven book written by Vincent Massol will proselytize more users 😉 and more importantly developers!

More than 7000 jars in Maven repository

Today the official Maven repository at iBiblio has reached the 7000 jars. Thanks to everybody who helped to make this happen!

I hope that non maven users also benefit from it, remember that there’s a searching engine at maven.ozacc.com

Tracing an application using AspectJ

Almost a year ago I developed a logging aspect so I could trace the program flow without writting to the log in each method call. Also it can be disabled a compile time, improving the performance. I think it’s worth remember it now:

/*
 * Copyright 2004 Carlos Sanchez.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.sf.oness.common.all.logging;

import org.aspectj.lang.*;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Aspect that logs method calling and exception throwing
 * using the apache commons logging package with the TRACE
 * facility.
 * Logs every method, avoiding recursion into the aspect and
 * into toString calls, which may lead to infinite recursion
 * and StackOverflowError exceptions
 *
 * @author Carlos Sanchez
 * @version $Revision: 1.4 $
 */
public aspect LoggingAspect {

    /**
     * The logging aspects should have the highest precedence.
     * This	way, the logging aspects before advice executes
     * before any of the other aspects before advice, and the
     * logging aspects after advice executes after the other
     * aspects after advice.
     * This makes the logging aspects dominate all other aspects
     */
    declare precedence : LoggingAspect, *;

    /**
     * Log every method avoiding recursion into the aspect and
     * into toString calls, which may lead to infinite recursion
     * and StackOverflowError exceptions
     */
    protected pointcut traceMethods() : (
        !cflow(execution(String *.toString()))
            && !cflow(within(LoggingAspect))
            && (execution(* *.* (..)))
            || execution(*.new (..)));

    /**
     * This advice logs method entries
     */
    before() : traceMethods() {
        Signature sig = thisJoinPointStaticPart.getSignature();
        Log log = getLog(sig);
        if (log.isTraceEnabled()) {
            log.trace(
                "Entering "
                    + fullName(sig)
                    + createParameterMessage(thisJoinPoint));
        }
    }

    /**
     * This advice logs method leavings
     */
    after() returning : traceMethods() {
        Signature sig = thisJoinPointStaticPart.getSignature();
        Log log = getLog(sig);
        if (log.isTraceEnabled()) {
            log.trace("Leaving " + fullName(sig));
        }
    }

    /**
     * This advice logs exception throwing
     */
    after() throwing(Throwable ex) : traceMethods() {
        Signature sig = thisJoinPointStaticPart.getSignature();
        Log log = getLog(sig);
        if (log.isTraceEnabled()) {
            log.trace("Thrown " + fullName(sig) + "\n\t" + ex);
        }
    }

    /**
     * Find log for current class
     */
    private Log getLog(Signature sig) {
        return LogFactory.getLog(sig.getDeclaringType());
    }

    /**
     * @return String with class name + method name
     */
    private String fullName(Signature sig) {
        return "["
            + sig.getDeclaringType().getName()
            + "."
            + sig.getName()
            + "]";
    }

    /**
     * @return String with current object + arguments
     */
    private String createParameterMessage(JoinPoint joinPoint) {
        StringBuffer paramBuffer = new StringBuffer();

        /*
         * Log the current object except if the method is a getter, setter or
         * constructor
         */
        if (joinPoint.getThis() != null) {
            String name = joinPoint.getStaticPart().getSignature().getName();

            if (!(name.startsWith("get"))
                && !(name.startsWith("set"))
                && !(name.equals("<init>"))) {

                paramBuffer.append("\n\t[This: ");
                paramBuffer.append(joinPoint.getThis());
                paramBuffer.append("]");
            }
        }

        Object[] arguments = joinPoint.getArgs();
        if (arguments.length > 0) {
            paramBuffer.append("\n\t[Args: (");
            for (int length = arguments.length, i = 0; i < length; ++i) {
                Object argument = arguments[i];
                paramBuffer.append(argument);
                if (i != length - 1) {
                    paramBuffer.append(",");
                }
            }
            paramBuffer.append(")]");
        }
        return paramBuffer.toString();
    }
}
  • very important to avoid infinite recursion!
  • avoid logging of getters, setters and constructors (it’d be better to disable it in the traceMethods pointcut)

This aspect will print a line to the log when you enter a method (with all the parameters), when you leave or when an exception is thrown. This is useful when you need to debug an application in an environment where you can’t use a debugger or it’s too complex to get it working.

Configuration can be done in commons-logging.properties file in the classpath to use Log4J for example:

org.apache.commons.logging.LogFactory=org.apache.commons.logging.impl.LogFactoryImpl
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

and log4j.properties:

# Global logging configuration
log4j.rootLogger=ERROR, stdout
log4j.logger.net.sf.oness=DEBUG, stdout

# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

With this aspect debugging info can be added to classes not developed by you without needing the sources. Just use the AspectJ ability to weave jars and you’ll get it!

You can also check the Cactus LogAspect which does something similar.

Acegi Security System for Spring 0.8.1 released

The 0.8.1 version of the Acegi Security System for Spring has been released, thanks Ben!

This release fixes a number of non-critical bugs, updates JAR
dependencies to match Spring 1.1.5, and introduces X509
(certificate-based) authentication support.

For Maven users, Acegi Security’s latest JARs are now available from
http://acegisecurity.sourceforge.net/maven/acegisecurity/jars and iBiblio.