Tuesday, September 30, 2008

Ubuntu: Unable to Resolve Host and /etc/hosts.

Ran into an interesting problem on my laptop running Ubuntu 8.04. After starting her up, there was a huge delay everytime I tried to run a command from a terminal or a simple app. Turns out I needed to edit my /etc/hosts as it was inadvertently changed.

Trying to sudo produced:
$ sudo -s -H
sudo: unable to resolve host prystasj-laptop
[sudo] password for prystasj:
root@prystasj-laptop:/home/prystasj/tmp# whoami
root
My /etc/hosts file at this point:
$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 dell-desktop.example.com dell-desktop

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts
I needed to add my hostname to the file at the end of the first line.
Afterwhich, everything went back to normal:
127.0.0.1 localhost prystasj-laptop
127.0.1.1 dell-desktop.example.com dell-desktop
Would be curious to know why this would have an affect when trying to run apps like gvim that wouldn't seem to require internet access.

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">  
<transformers>
<transformer name="HttpRequestToSoapRequest"
className="org.mule.providers.soap.transformers.HttpRequestToSoapRequest"/>
</transformers>
<model name="echoAuth">
<mule-descriptor name="EchoAuth" implementation="EchoAuth">
<inbound-router>
<endpoint address="axis:http://localhost:65081/services"
transformers="HttpRequestToSoapRequest" />
</inbound-router>
<interceptor className="EchoInterceptor"/>
</mule-descriptor>
</model>
</mule-configuration>

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:
http://localhost:65081/services/EchoAuth?method=echo&user=Costanza&password=bosco

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());

@Override
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={
http.version=HTTP/1.1
method=public abstract java.lang.String AuthService.echo(java.lang.String,java.lang.String)
MULE_ORIGINATING_ENDPOINT=endpoint.http.localhost.65081.services
http.method=GET
http.request=/services/EchoAuth?method=echo&user=Costanza&password=bosco
}}
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:
...
http.request=/services/EchoAuth?method=echo&user=Costanza&password=bosco
http.method=GET
...
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 10.4.1.3 binary distribution:
$ tar xzf db-derby-10.4.1.3-bin.tar.gz -C /opt
$ export DERBY_HOME=/opt/db-derby-10.4.1.3-bin
$ java -jar $DERBY_HOME/lib/derbyrun.jar server start &
Security manager installed using the Basic server security policy.
Apache Derby Network Server - 10.4.1.3 - (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 10.4.1.3 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:
Missing:
----------
1) org.apache.maven.wagon:wagon-webdav:jar:RELEASE
Added the Mule repositories:
<repository>
<id>muleforge</id>
<url>http://repository.muleforge.org</url>
<name>MuleForge Repository</name>
</repository>
<repository>
<id>mule.dependencies</id>
<url>http://dist.codehaus.org/mule/dependencies/maven2/</url>
<name>Mule Dependencies Repository</name>
</repository>
<!-- For the Abdera dependencies -->
<repository>
<id>apache-incubating</id>
<name>Apache Incubating Repository</name>
<url>http://people.apache.org/repo/m2-incubating-repository/</url>
</repository>
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] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Cannot get the revision information from the scm repository :
Error!
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:
<requireJavaVersion>
<!-- minimum version is 1.4.2, Java 5 and higher not allowed -->
<!-- <version>[1.4.2,1.5.0)</version> -->
<version>[1.4.2,1.6.0]</version>
</requireJavaVersion>
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:
org.mule.test.config.MuleClasspathConfigBuilderTestCase.txt:org.mule.config.ConfigurationException:
Failed to parse configuration resource
"file:/home/prystasj/workspace/mule-1.4.x/tests/functional/target/test-classes/test-xml-mule-config.xml"
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"/>
</spring-property>
</bean>

<bean id="upperCaserProxy"
class="org.springframework.aop.framework.ProxyFactoryBean"
singleton="false">
<spring-property name="target">
<ref local="targetUpperCaser"/>
</spring-property>
<spring-property name="interceptorNames">
<spring-list>
<value>upperCaserAdvisor</value>
</spring-list>
</spring-property>
</bean>

<bean id="upperCaserAdvisor"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"
singleton="false">
<spring-property name="advice">
<ref local="upperCaserAdvice"/>
</spring-property>
<spring-property name="mappedNames">
<spring-list>
<value>convert</value>
</spring-list>
</spring-property>
</bean>
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" 
class="org.springframework.aop.framework.ProxyFactoryBean"
singleton="false">
<!-- added after adding Converter interface -->
<spring-property name="proxyInterfaces">
<spring-list>
<value>Converter</value>
</spring-list>
</spring-property>
<spring-property name="target">
<ref local="targetUpperCaser"/>
</spring-property>
<spring-property name="interceptorNames">
<spring-list>
<value>upperCaserAdvisor</value>
</spring-list>
</spring-property>
</bean>
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:
hello

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}

OLLEH
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.

Thursday, July 31, 2008

Snag Installing Ganymede on Hardy w/ Firefox 3

I had an issue installing Eclipse 3.4 Ganymede on Ubuntu Hardy. Eclipse would start to load until I was greeted with a blank error window.

I found this post that guided me in the right direction:

Eclipse just crashed so I’m going to file a bug now…

I was getting the following error mentioned in the above post:
  org.eclipse.swt.SWTError: XPCOM error -2147467262
Accompanying the error was another error "Widget closed too soon!", which turned out to be related to the Welcome screen, which was being displayed since I had a fresh installation.

The bug post for this issue had a couple of suggestions.

First, since I am using Firefox 3, I tried moved /usr/lib/xulrunner-1.9b5 as a few kind people suggested. Ganyemede came up just fine, but Firefox would no longer work.

An alternative workaround mentioned first creating your workspace with Eclipse 3.x, closing the Welcome screen, and the running Ganyemede. I installed Eurpoa 3.3.2, restored xulrunner-1.9b5, ran Eurpoa, and then was able to bring Firefox and Ganyemede up with no problems.

Wednesday, July 30, 2008

XML Unit Testing with Groovy and XMLUnit

A while back I needed to compare XML documents during my unit testing. The documents, or snippets actually, were small enough and I had enough control over how they were created, that simple comparisons of the expected and actual results were enough. After a while as the snippets grew larger I ran into a few problems. For one, if I didn't use StreamingMarkupBuilder to create the XML, whitespace became an issue. And more importantly, "equivalent" XML would compare differently if the order of the elements of a node were not in the same order.

Eventually, I found a few lines of code in the Groovy user guide that turned me onto XMLUnit, at the bottom of the first example:
Groovy Example

The following line quickly took care of the whitespace issue.
import org.custommonkey.xmlunit.*
XMLUnit.setIgnoreWhitespace(true)
For testing equivalent XML, XMLUnit allows to expect child elements in a exact order (identical) or not (similar):
def photoguy = new StreamingMarkupBuilder().bind {
person {
firstname('Larry')
lastname('Appleton')
}
}

// equivalent, but different ordered child elements
def balkisCousin = new StreamingMarkupBuilder().bind {
person {
lastname('Appleton')
firstname('Larry')
}
}

def xmlDiff = new Diff(photographer, balkisCousin)
assert ! XmlDiff.identical()
assert xmlDiff.similar()
Down the road, I ran into the situation where I wanted to allow a difference in a particular element. The element contents were quite large and subject to change and I didn't really need to cover the results in this part of my project. Furthermore, I didn't want to store the actual result as it was that particular day in my test resources I used for the expected results. Naively, I could make an assertion about every other element in the snippet I cared about and ignore the one that might produce a difference, but that wouldn't be good for my mental health.

Luckily, XMLUnit gave me what I needed, in this case I'm allowing one difference:
String expectedXml = getClass().getClassLoader().getResourceAsStream(testFile).getText()
def xmlDiff = new Diff(personAsXml, expectedXml)
assert !xmlDiff.similar()
assert !xmlDiff.identical()

def detailedDiff = new DetailedDiff(xmlDiff)
def differences = detailedDiff.getAllDifferences()
assertEquals detailedDiff.toString(), 1, differences.size()

def location = differences.pop().getTestNodeDetail().getXpathLocation()
// a regex may be better for this?
def expectedLocation = '/person[1]/employment[1]/company[1]/text()[1]'
assertEquals expectedLocation, location
XMLUnit has a whole bunch of other features that I have not gone back to check out yet. Maybe somebody else has and would be kind enough to drop a comment. A new version, 1.2, came out in June.