Tuesday, August 19, 2008

Intercepting HTTP Parameters on an Axis Endpoint in Mule

I've been trying to write an interceptor for Mule 1.4.3 container to intercept a message that contains a username and password for authentication. The interceptor is to act as a Permission Check interceptor described in the Mule docs.

I was able to come up with an approach that might fit my needs, although there could very well likely be a better approach.

My Mule 1.4.3 configuration is setup to take an HTTP request for an Axis endpoint. The HTTP request has a user and a password parameter. I have an interceptor, EchoInterceptor, that is going to look for the user and password parameters:
<mule-configuration id="Mule_Echo_Parameters_Axis" version="1.0">  
<transformer name="HttpRequestToSoapRequest"
<model name="echoAuth">
<mule-descriptor name="EchoAuth" implementation="EchoAuth">
<endpoint address="axis:http://localhost:65081/services"
transformers="HttpRequestToSoapRequest" />
<interceptor className="EchoInterceptor"/>

The EchoAuth class has an echo method whose invocation I want to intercept. The method simply echos the parameters its given. An HTTP request to the Axis endpoint looks like:

The interceptor class:
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mule.umo.Invocation;
import org.mule.umo.UMOException;
import org.mule.umo.UMOInterceptor;
import org.mule.umo.UMOMessage;
import org.mule.util.PropertiesUtils;

public class EchoInterceptor implements UMOInterceptor {

private final Log logger = LogFactory.getLog(this.getClass());

public UMOMessage intercept(Invocation invocation) throws UMOException {

logger.info("Intercepted method invocation.");

UMOMessage incomingMessage = invocation.getMessage();
logger.info("Incoming message: " + incomingMessage.toString());

String request = incomingMessage.getProperty("http.request").toString();
int i = request.indexOf('?');
String query = request.substring(i + 1);
logger.info("HTTP request query string: " + query);

// following example in Mule's HTTPRequestToSoapRequest class
Properties p = PropertiesUtils.getPropertiesFromQueryString(query);
String user = p.getProperty("user");
String password = p.getProperty("password");
logger.info("Query string parameter 'user': " + user);
logger.info("Query string parameter 'password': " + password);

UMOMessage resultingMessage = invocation.execute();
logger.info("Returning resulting message: " + resultingMessage.toString());

return resultingMessage;
The results in my mule.log, with a lot of the clutter omitted:
EchoInterceptor: Incoming message: org.mule.providers.soap.axis.AxisMessageAdapter
/org.mule.providers.soap.axis.AxisMessageAdapter... properties={
method=public abstract java.lang.String AuthService.echo(java.lang.String,java.lang.String)
EchoInterceptor: HTTP request query string: method=echo&user=Costanza&password=bosco
EchoInterceptor: Query string parameter 'user': Costanza
EchoInterceptor: Query string parameter 'password': bosco
EchoAuth: Received user: Costanza
EchoAuth: Received password: bosco
EchoAuth: Authentication: Costanza/bosco
EchoInterceptor: Returning resulting message:
In my real-world project, I need to send the user and password off to a
service for authentication, and halt processing. The interceptor doc lists a couple of methods for doing so I need to investigate further.

Saturday, August 16, 2008

Getting Groovy with Apache Derby

I'm working my way through the so-far excellent Programming Groovy by Venkat Subramaniam. Since I'm on the database chapter, I decided it was time to install a database server on my machine. The examples in the book are done with MySQL, but I thought I would try the more lightweight Apache Derby.

I downloaded the binary distribution:
$ tar xzf db-derby- -C /opt
$ export DERBY_HOME=/opt/db-derby-
$ java -jar $DERBY_HOME/lib/derbyrun.jar server start &
Security manager installed using the Basic server security policy.
Apache Derby Network Server - - (648739) started and ready to accept connections on port 1527 at 2008-08-16 17:31:37.060 GMT
That was simple enough, I decided to create a couple aliases to make startup and shutdown easier:
alias startderby="java -jar $DERBY_HOME/lib/derbyrun.jar server start &"
alias stopderby="java -jar $DERBY_HOME/lib/derbyrun.jar server shutdown &"
Running Derby's ij tool, I was able to create a database with a script similar to the one in the book, but tailored for Derby:
connect 'jdbc:derby://localhost:1527/peopledb;create=true;';

create table people (
name varchar(100) not null,
age integer not null

insert into people (name, age) values ('John', 26);
insert into people (name, age) values ('Jenny', 23);
insert into people (name, age) values ('Marshall', 6);
I could not find a method for determining whether or not a table exists before trying to create it in Derby. I ran the script with:
$ java -jar $DERBY_HOME/lib/derbyrun.jar ij ~/tmp/people.sql

ij version 10.4
ij> connect 'jdbc:derby://localhost:1527/peopledb;create=true;';
ij> create table people (
name varchar(100) not null,
age integer not null
0 rows inserted/updated/deleted
ij> insert into people (name, age) values ('John', 26);
1 row inserted/updated/deleted
ij> insert into people (name, age) values ('Jenny', 23);
1 row inserted/updated/deleted
ij> insert into people (name, age) values ('Marshall', 6);
1 row inserted/updated/deleted
I was able to query the database with the following Groovy code (again modeled from the book):
import groovy.sql.Sql

def url = 'jdbc:derby://localhost:1527/peopledb'
def driver = 'org.apache.derby.jdbc.ClientDriver'

def sql = Sql.newInstance(url, driver)
// println sql.connection.dump()

sql.eachRow('SELECT * from people') { person ->
printf "%-20s%s\n", person.name, person.age
Command and results:
$ groovy -cp $DERBY_HOME/lib/derbyclient.jar People.groovy
John 26
Pam 24
Marshall 6
Looks like I'm good to continue with the examples..

As an aside, the download page also links for the Eclipse plugins. I've used the plugins for a 10.2 version of Derby for Eclipse 3.3, but not the 10.4 plugins with Eclipse 3.4 which I currently have. I could not get the plugins recognized in Eclipse 3.4, if someone has, if someone has, a comment would be greatly appreciated.

Sunday, August 3, 2008

My Attempt at Bulding Mule 1.4.x

I thought I'd take a crack at building the Mule source, which uses Maven for its builds:
$ svn export http://svn.codehaus.org/mule/branches/mule-1.4.x
$ cd mule-1.4.x
$ mvn validate
I was first presented with the following error:
1) org.apache.maven.wagon:wagon-webdav:jar:RELEASE
Added the Mule repositories:
<name>MuleForge Repository</name>
<name>Mule Dependencies Repository</name>
<!-- For the Abdera dependencies -->
<name>Apache Incubating Repository</name>
Now the version issue for wagon-webdav was resolved. From the mvn validate output:
    WAGON_VERSION: 1.0-beta-2
My next problem was that I did an export and not a checkout:
[INFO] Updating project files from SCM: skipped.
Provider message:
The svn command failed.
Command output:
svn: '.' is not a working copy

[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] Cannot get the revision information from the scm repository :
So I replaced my export with a checkout:
$ svn co http://svn.codehaus.org/mule/branches/mule-1.4.x .
Now a Java version problem:
[WARNING] Rule 1: org.apache.maven.plugin.enforcer.RequireJavaVersion failed with message: Detected JDK Version: 1.6.0
is not in the allowed range [1.4.2,1.5.0).
As I only have Java 6 on my machine:
$ java -version
java version "1.6.0"
OpenJDK Runtime Environment (build 1.6.0-b09)
OpenJDK Server VM (build 1.6.0-b09, mixed mode)
I changed the configuration of the enforcer plugin to allow up to Java 1.6.0:
<!-- minimum version is 1.4.2, Java 5 and higher not allowed -->
<!-- <version>[1.4.2,1.5.0)</version> -->
The Build Guide lists I could of skipped the enforcer with:
$ mvn -DskipEnforcer=true
After running:
$ mvn test
I got a lot farther, but the amount of test errors are kind of scary:
Tests run: 131, Failures: 10, Errors: 46, Skipped: 0
A common error was a found in the output files in tests/functional/target/surefire-reports was:
Failed to parse configuration resource
I was able to read the file with Groovy's XmlSlurper just fine:
#!/usr/bin/env groovy
file = new File(args[0])
def xml = new groovy.util.XmlSlurper().parse(file)
println xml
I tried the build with skipping the tests:
$ mvn -DskipTests package
But I got a compilation error. Maybe someday I'll take the time to figure out whats going wrong. I was still able to generate some Eclipse project files though:
$ mvn eclipse:eclipse
So I can still take a good look at the source, which is good enough.

Friday, August 1, 2008

Declarative Spring AOP and Interfaces

I ran into what seems to be a somewhat frequent user error adding Spring AOP through a container when trying to add advice to a class that implements an interface. The exception:
PropertyAccessException 1: org.springframework.beans.TypeMismatchException:
Failed to convert property value of type [$Proxy0] to required type [UpperCaser] for property
'uppercaser'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of
type [$Proxy0] to required type [UpperCaser] for property 'uppercaser':
no matching editors or conversion strategy found" not found in container
Since I ran into the problem and saw a fair share of related posts on the Spring Forums, I thought I'd document it. In my test project, I have a simple class that converts a String to all upper-case letters. Before implementing an interface, everything worked fine.
public class UpperCaser {
public String convert(String toConvert) {
return toConvert.toUpperCase();
My entry class:
public class UpperCaserUMO  { 
UpperCaser uppercaser;
public String doit(String payload) {
String result = uppercaser.convert(payload);
return result;

// needed so Spring can inject uppercaser, can't say:
// UpperCaser caser = new UpperCaser();
public void setUppercaser(UpperCaser uppercaser) {
this.uppercaser = uppercaser;
And my advice the reverse the upper-cased Sting:
public class UpperCaserAdvice implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
Object response = invocation.proceed();
String reversedResponse = new StringBuffer((String)response).reverse().toString();
return reversedResponse;
Everything worked fine with this configuration (my container is Mule 1.4.3):
<bean id="targetUpperCaser" class="UpperCaser" singleton="false"/>
<bean id="upperCaserAdvice" class="UpperCaserAdvice" singleton="false"/>

<bean id="upperCaserUMO" class="UpperCaserUMO" singleton="false">
<spring-property name="uppercaser">
<ref local="upperCaserProxy"/>

<bean id="upperCaserProxy"
<spring-property name="target">
<ref local="targetUpperCaser"/>
<spring-property name="interceptorNames">

<bean id="upperCaserAdvisor"
<spring-property name="advice">
<ref local="upperCaserAdvice"/>
<spring-property name="mappedNames">
In my "at work" project, the target class, UpperCaser here, implemented an interface, so I added an interface to UpperCaser:
public interface Converter {
public String convert(String toConvert);

public class UpperCaser implements Converter {
I resolved the exception above by changing my entry class to have members of the interface and not the implementation:
public class UpperCaserUMO  { 
Converter uppercaser;
public void setUppercaser(Converter uppercaser) {
this.uppercaser = uppercaser;
And changing my ProxyFactoryBean to acknowledge the interface with the proxyInterfaces property to set things up right took care of the exception:
<bean id="upperCaserProxy" 
<!-- added after adding Converter interface -->
<spring-property name="proxyInterfaces">
<spring-property name="target">
<ref local="targetUpperCaser"/>
<spring-property name="interceptorNames">
And all was well. I based my test project from Mule's Echo example. I also added logging statments which I omitted above so I could track what's going on.
INFO  2008-08-01 12:55:20,063 [WrapperSimpleAppMain] org.mule.MuleServer: Mule Server initialized.
Please enter something:

INFO 2008-08-01 12:55:26,568 [UpperCaserUMO.2] UpperCaserUMO: Inside method doit().
INFO 2008-08-01 12:55:26,575 [UpperCaserUMO.2] UpperCaserAdvice: About to invoke method: convert
INFO 2008-08-01 12:55:26,575 [UpperCaserUMO.2] UpperCaser: Received: hello
INFO 2008-08-01 12:55:26,575 [UpperCaserUMO.2] UpperCaser: Result: HELLO
INFO 2008-08-01 12:55:26,576 [UpperCaserUMO.2] UpperCaserAdvice: Method 'convert' complete.
INFO 2008-08-01 12:55:26,576 [UpperCaserUMO.2] UpperCaserAdvice: Method response: HELLO
INFO 2008-08-01 12:55:26,576 [UpperCaserUMO.2] UpperCaserAdvice: Reversing response...
INFO 2008-08-01 12:55:26,576 [UpperCaserUMO.2] UpperCaserAdvice: Reversed response: OLLEH
INFO 2008-08-01 12:55:26,576 [UpperCaserUMO.2] UpperCaserAdvice: Returning reversed response...
INFO 2008-08-01 12:55:26,576 [UpperCaserUMO.2] UpperCaserUMO: Conversion result: OLLEH
INFO 2008-08-01 12:55:26,576 [UpperCaserUMO.2] UpperCaserUMO: Returning result.
INFO 2008-08-01 12:55:26,593 [SystemStreamConnector.dispatcher.1] org.mule.providers.stream.StreamMessageDispatcher: Connected: StreamMessageDispatcher{this=14fcd9a, endpoint=stream://System.out}

I entered a string in the consloe, UpperCaser upper-cased it, and the advice class reversed it.
Seems a whole lot less complicated to me now. Hopefully this helps someone out in a similar situation.

Pro Spring 2.5
This example was with version 2.0.6 of Spring that comes with Mule 1.4.3. I'm going to assume it works with 2.5.