Category Archives: maven

CXF WS-Security using JSR 181 + Interceptor Annotations (XFire Migration)

I had blogged about how to setup XFire with WS-Security a while ago and since then the XFire 1.x series as we know it is dead, instead Apache’s CXF can be considered XFire 2.0. CXF improves over XFire in many areas including better architecture and more importantly easier message handling and manipulation. In this entry, we’ll setup a CXF application that secures its services using CXF’s WS-Security features.

Before I get to the example I want to mention some of the major changes that I noticed in CXF:

  • Interceptors instead of handlers: Handlers are out and are replaced with a much more common concept of interceptors (if you’re from the Struts2/Webwork world you know what they are). Interceptors are created by extending the AbstractPhaseInterceptor class which forces you to implement handleMessage(Message). Note that you must specify the phase where you want each interceptor executed.
  • Access to MessageContext: In XFire, the MessageContext was always available in your handlers. In CXF you don’t have access to it in the interceptor but you can get contextual properties using the message.getContextualProperty(String) methods. Access to the MessageContext is also available using the @Resource annotation as described here but this only works in service implementations.
  • JAXWS Endpoints: Spring service classes must be exposed using the <jaxws:endpoint> tag. You can also do this programmatically but why would you.
  • Message and Exchange: The Message and Exchange objects have changed dramatically from XFire. CXF’s Message and Exchange objects are devoid of all those helpful methods that were present in XFire but they make up for it by having get(Class) and get(String) methods which can be used to retrieve valuable information. It’s probably a good idea to look through Exchange.keySet() and Message.keySet() and see whats available to you in your interceptors. For example when a Fault occurs, the message.get(Exception.class) returns the exception that was thrown to cause the fault. Also note that the information present in these maps varies depending on what Phase you’re in.

Now to the WS-Security example. CXF just added support for configuring interceptors using annotations which means configuring WS-Security for our web services just got easier.

Here’s the service interface and implementation.

@WebService
public interface SportsService {
    public String getTeam();
        return "Arsenal";
    }
}

@WebService(
    serviceName="SportsService",
    endpointInterface="ca.utoronto.sis.cxfapp.SportsService")
@InInterceptors(interceptors={
        "com.arsenalist.cxfapp.WSSecurityInterceptor"
})
public class SportsServiceImpl implements SportsService {

    public String getTeam() {
        return "Arsenal";
    }
}

I’ve added a single in interceptor called WSSecurityInterceptor which is a class that we’ll write. In XFire we also needed a DomInHandler and a DomOutHandler for each service implementation, none of that is required here. WSSecurityInterceptor will just wrap the WSS4JInInterceptor class, the reason we can’t just specify WSS4JInInterceptor as an annotation is because we need to set custom properties on it such as using UsernameToken authentication.

The other thing WSSecurityInterceptor does is add a ValidateUserTokenInterceptor which is similar to ValidateUserTokenHandler in the XFire examples. Since WSS4J validates a UsernameToken only if it finds a security header we need to cover the case where no security header is specified. ValidateUserTokenInterceptor just makes sure the username, password, nonce and timestamp are specified before even considering it a valid request. Here’s the WSSecurityInterceptor and the PasswordHandler class:

public class WSSecurityInterceptor extends AbstractPhaseInterceptor {

    public WSSecurityInterceptor() {
        super(Phase.PRE_PROTOCOL);
    }
    public WSSecurityInterceptor(String s) {
        super(Phase.PRE_PROTOCOL);
    }

    public void handleMessage(SoapMessage message) throws Fault {

        Map props = new HashMap();
        props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
        props.put(WSHandlerConstants.PW_CALLBACK_REF, new PasswordHandler());

        WSS4JInInterceptor wss4jInHandler = new WSS4JInInterceptor(props);
        ValidateUserTokenInterceptor userTokenInterceptor = new ValidateUserTokenInterceptor(Phase.POST_PROTOCOL);

        message.getInterceptorChain().add(wss4jInHandler);
        message.getInterceptorChain().add(new SAAJInInterceptor());
        message.getInterceptorChain().add(userTokenInterceptor);
    }
}

public class PasswordHandler implements CallbackHandler {
    public void handle(Callback[] callbacks) throws IOException,
            UnsupportedCallbackException {
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
        if (pc.getIdentifer().equals("arsenal")) {
            pc.setPassword("gunners");
        }
    }
}

Note that the ValidateUserTokenInterceptor is invoked in a later phase than WSS4JInterceptor. Here’s the ValidateUsertokenInterceptor class:

public class ValidateUserTokenInterceptor extends AbstractPhaseInterceptor {

    public ValidateUserTokenInterceptor(String s) {
        super(s);
    }

    public void handleMessage(SoapMessage message) throws Fault {
        boolean userTokenValidated = false;
        Vector result = (Vector) message.getContextualProperty(WSHandlerConstants.RECV_RESULTS);
        for (int i = 0; i &lt; result.size(); i++) {
            WSHandlerResult res = (WSHandlerResult) result.get(i);
            for (int j = 0; j &lt; res.getResults().size(); j++) {
                   WSSecurityEngineResult secRes = (WSSecurityEngineResult) res.getResults().get(j);
                    WSUsernameTokenPrincipal principal = (WSUsernameTokenPrincipal) secRes
                            .getPrincipal();

                    if (!principal.isPasswordDigest() ||
                            principal.getNonce() == null ||
                            principal.getPassword() == null ||
                            principal.getCreatedTime() == null) {
                        throw new RuntimeException("Invalid Security Header");
                    } else {
                        userTokenValidated = true;
                    }
                }
            }
        }
        if (!userTokenValidated) {
            throw new RuntimeException("Security processing failed");
        }
    }
}

Now we have a service implementation annotated in a way where it is WS-Security enabled and is also registered as a web service. The final step remaining is to expose it as a consumable endpoint. That can be achieved by either of the following ways:

Using the fully qualified class name:

<jaxws:endpoint
   id="helloWorld"
   implementor="com.arsenalist.cfxapp.SportsServiceImpl"
   address="/SportsService" />

Or by referring to a Spring bean corresponding to the @WebService annotated class. This would be more prudent if you’re using Dependency Injection in your service implementations.

<bean id="sportsServiceImpl" class="com.arsenalist.cfxapp.SportsServiceImpl"/>

<jaxws:endpoint
   id="sportsService"
   implementor="#sportsServiceImpl"
   address="/SportsService" />

Finally you could also just use good ‘ol fashioned Spring beans. This comes in handy if you wan to specify a different binding like Aegis:

<bean id="aegisBean" class="org.apache.cxf.aegis.databinding.AegisDatabinding"/>
<bean class="org.apache.cxf.frontend.ServerFactoryBean" init-method="create">
	<property name="serviceBean" ref="registrationSoapService"/>
	<property name="address" value="/services/1_0_0/Registration"/>
	<property name="dataBinding" ref="aegisBean"/>
</bean>

The CXF documentation which shows how to configure the web.xml is pretty straightforward.

If you’re using Maven, the dependencies section of the pom.xml might look something like this. Remember that support for configuring interceptors via annotations was just added so you have to access the SNAPSHOT repositories instead of the main one.

<repositories>
    <repository>
        <id>apache-snapshots</id>
        <name>Apache SNAPSHOT Repository</name>
        <url>http://people.apache.org/repo/m2-snapshot-repository/</url>
        <snapshots>
        <enabled>true</enabled>
        </snapshots>
    </repository>
    <repository>
        <id>apache-incubating</id>
        <name>Apache Incubating Repository</name>
        <url>http://people.apache.org/repo/m2-incubating-repository/</url>
    </repository>
</repositories>
<dependencies>
    ...
    <!-- spring beans, core, context, web 2.0.6 -->
    ...
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-transports-http</artifactId>
        <version>2.1-incubator-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-core</artifactId>
        <version>2.1-incubator-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-frontend-jaxws</artifactId>
        <version>2.1-incubator-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-ws-security</artifactId>
        <version>2.1-incubator-SNAPSHOT</version>
    </dependency>
    ...
<dependencies>

Thanks for reading.

Spring’s AOP support can’t be ignored

You see I’ve never actually written many (any?) AOP classes but there’s enough talk about it splashed all over the internet that even though it might be a worthless concept that you’ve never used or cared about, you’re bound to encounter it at some point. A fellow GO Train rider once told me it was the thing to know if you want to have a Java job in five years. That made me read the AspectJ in Action book which makes you feel guilty about not using AOP. I don’t talk to that guy anymore. Then there’s Adrian Colyer who will have you believe that AOP is the glue that ties every enterprise application together and without it you might be writing code that is hanging on by threads.

Now I realize for some of you this might bring flashbacks to 2004 but bear with me. A few days ago I had to catch an Exception in the DAO layer and translate it to something else, now normally this very simple problem is solved by 95% of the monkeys by using a try/catch on the Exception and throwing something more worthy of being bubbled up. But if the same DAO method is being executed in different places in your application you might have to do separate try/catch blocks for each, something which is totally acceptable, clear, concise and happening for ages. There’s nothing wrong with it.

But there is an AOP way of doing this outlined pretty clearly in the docs where you write a pointcut and provide advice on the execution of the event. No try/catch blocks, the client code is devoid of any knowledge about exceptions. Spring’s AOP support makes doing this the AOP way very easy, but is it overkill? I don’t know, I guess it depends on your style of development.

So to replace the generic try/catch mechanism with the AOP way, first declare a pointcut:

package com.arsenalist.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class SystemArchitecture {

    @Pointcut("execution(* com.arsenalist.dao.*.*(..))")
    public void daoOperation() {}
}

Once we’ve specified what methods to monitor using pointcuts, give advice on what should happen when the pointcut is executed.

package com.arsenalist.aop;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class DaoExceptionTranslator {

    @AfterThrowing(
      pointcut="com.arsenalist.aop.SystemArchitecture.daoOperation()",
      throwing="ex")
    public void translateException(Exception ex) {
        throw new RuntimeException("Generic message");
    }
}

With the above setup any method executed in the com.arsenalist.dao.*.* packages will be translated into a RuntimeException. I’m assuming that the interfaces reside in com.arsenalist.dao package and the implementations in a package underneath that. Here’s the Spring configuration needed:

<bean id="daoExceptionTranslator" class="com.arsenalist.aop.DaoExceptionTranslator"/>
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" />

Most importanly the Maven POM should look something like this:

<dependency>
    <groupId>aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.5.3</version>
</dependency>
<dependency>
    <groupId>aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.5.3</version>
</dependency>
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib-nodep</artifactId>
    <version>2.1_3</version>
</dependency>
<dependency>
    <groupId>asm</groupId>
    <artifactId>asm-all</artifactId>
    <version>2.2</version>
</dependency>

Although there is a newer version of ASM available, it doesn’t seem to be compatible with Spring AOP.

There can be many arguments against this setup, the main one being that you’re unable to handle the same Exception differently depending on where it’s being called from. To do that you’d have to specify another pointcut and another advice on how to handle it. You also lose all call-context information because you’re assuming that everthing you need to handle the exception is in the Exception object.

But in the general sense it does seem to be an improved method of executing baseline operations when a particular event occurs. The docs get you thinking about other places where you can use AOP proxies instead of the “normal” way of doing things and it’s pretty easy to get sucked into “convert everything to AOP mode”.

If you’re afraid of proxies, this is not for you. Every call to the DAO layer happens via a proxy which is necessary to achieve the intended effect. I’m not sure what the performance penalites of using proxys on every single call to the DAO layer are but if you go this route, CGLIB proxies are apparently much faster than their JDK counterparts. Either way, if you haven’t tried out AOP but are sick of hearing the sound of it, give Spring AOP a shot. It’s probably worth it.

Maven Properties Plugin Download

Update: As of June 6th, 2007, this is now in the Codehaus Sandbox repository.

I get an email once a week asking the whereabouts of the properties plugin for Maven so I thought I’d put it up somewhere.

If you think this is useful, vote in favor of it – Codehaus JIRA MOJO-535.

It has three goals (for now):

  1. read-project-properties: Given a set of property files in name=value format, it reads them and stores them as project properties. This would be nice for those of us that store environment specific information in different property files.
  2. write-project-properties: Writes project properties to a given file. Helpful when some properties need to be available at runtime e.g.: Spring’s PropertyPlaceholderConfigurer)
  3. write-active-profile-properties: Writes the properties of any active profiles to a file.

Here’s some sample usage of the read-project-properties goal which reads property files as project properties:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>properties-maven-plugin</artifactId>
  <version>1.0-SNAPSHOT</version>
  <executions>
    <execution>
      <phase>initialize</phase>
      <goals>
        <goal>read-project-properties</goal>
      </goals>
      <configuration>
        <files>
          <file>etc/config/dev.properties</file>
        </files>
      </configuration>
    </execution>
  </executions>
</plugin>

The write-project-properties goal writes project properties to a file:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>properties-maven-plugin</artifactId>
  <version>1.0-SNAPSHOT</version>
  <executions>
    <execution>
    <phase>generate-resources</phase>
    <goals>
      <goal>write-project-properties</goal>
    </goals>
    <configuration>
      <outputFile>
        target/classes/app.properties
      </outputFile>
    </configuration>
    </execution>
  </executions>
</plugin>

The write-active-profile-properties goal writes all properties of active profiles to a file:

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>properties-maven-plugin</artifactId>
  <version>1.0-SNAPSHOT</version>
  <executions>
    <execution>
      <phase>generate-resources</phase>
      <goals>
        <goal>write-active-profile-properties</goal>
      </goals>
      <configuration>
        <outputFile>
          target/classes/app.properties
        </outputFile>
      </configuration>
    </execution>
  </executions>
</plugin>

Hope this helps someone.