Friday, January 23, 2009

/usr/bin/ld: cannot find -lperl

I was trying to install pp, the Perl PAR Packager:
$ sudo cpan pp
I got this error:
/usr/bin/ld: cannot find -lperl
collect2: ld returned 1 exit status
make[1]: *** [par] Error 1
make[1]: Leaving directory `/home/prystasj/.cpan/build/PAR-Packer-0.982-zX8GIO/myldr'
make: *** [subdirs] Error 2
SMUELLER/PAR-Packer-0.982.tar.gz
/usr/bin/make -- NOT OK
Running make test
Can't test without successful make
Running make install
Make had returned bad status, install seems impossible
I saw a suggestion to install libperl-dev, but I had that package already up-to-date.
By changing this symlink in /usr/lib from:
lrwxrwxrwx 1 root root 15 2009-01-23 15:28 /usr/lib/libperl.so -> libperl.so.5.10
To:
lrwxrwxrwx 1 root root 15 2009-01-23 15:28 /usr/lib/libperl.so -> libperl.so.5.10.0
I was able to install pp:
$ which pp
/usr/local/bin/pp

Wednesday, January 7, 2009

JPA: Retrieving ID of Recently Persisted Object

Using JPA with an orm.xml, I was having trouble retrieving the primary key (id) of a recently persisted object. The entity in my orm.xml:

<entity class="Foo" name="Foo" access="FIELD">
<table name="Foo"/>
<attributes>
<id name="id">
<column name="ID" nullable="false"/>
<generated-value strategy="SEQUENCE"/>
</id>
...
</table>
</entity>
The relevant MySQL for the table:
CREATE TABLE FOO
(
ID INT NOT NULL AUTO_INCREMENT,
...
PRIMARY KEY(ID)
)
Regardless of whether or not the id property was null or not, it was not updated after the following call to persist():
Foo foo = new Foo();
getJpaTemplate().persist(foo);
if (logger.isDebugEnabled())
logger.debug(foo.getId()) // null

Adding a call to flush() however ended up giving me the id:
Foo foo = new Foo();
getJpaTemplate().persist(foo);
getJpaTemplate().flush();
if (logger.isDebugEnabled())
logger.debug(foo.getId()) // outputs the assigned id
I'm not sure why the flush() was necessary. A similar issue is also discussed here: Spring Forums Post.

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.