Simbiosis

Communiques from the wilderness

ZSI -> CXF: Parameters coming in as NULL

Recounting a strange little compatibility issue I had between ZSI 2.0 and CXF 2.0.x. I was using CXF as the server, running from Maven using Jetty, and ZSI as the client. The parameters from the ZSI were arriving at the service implementation as null. With the web services logging turned on I could see that the SOAP packet was arriving OK, and looked good.

A little bit of digging round the web turned up this message.

The issue was that ZSI wasn’t explicitly namespacing the elements, and so CXF was not seeing them. The solution was to add elementFormDefault=”qualified” to my WSDL definition, and rebuild the ZSI stubs.

<wsdl:definitions xmlns:soap=”http://schemas.xmlsoap.org/wsdl/soap/”
    …
    xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
    xsd:elementFormDefault=”qualified”
    xsd:attributeFormDefault=”unqualified”>

November 17, 2008 Posted by Nigel | Work, java, python | | No Comments Yet

Zope3 Component Architecture (CA) style Adapters for Java

After programming for Zope3/Plone for the past year I’ve come to really
admire the flexibility and elegance that their implementation of the
adapter pattern gives us.
And, after Martin Aspeli put the call out almost a year ago, and it has not yet been answered, I thought it was time to give it a go.
How hard could it be.

So, what I’ve developed is a very simple, no dependency, maven available library which should greatly improve the flexibility of your code.

The project page is here
and the repository is at Git Hub.

October 15, 2008 Posted by Nigel | java, plone, programming | | 1 Comment

Some thoughts on a dynamic (lazy) data access layer for web services

The problem I’ve been address in my most recent work block has been to develop an interface to a relational data store which can be used either as a local DB, or via webservices. The concept is quite straight forward, we want CRUD operations on a set of data objects. The schema is fairly straight forward too, with a core hierarchy of elements with a few enumerated lists. As well as a few cuts across the hierarchy.

We want to use this with webservices, as well wanting to be able to serialise to an XML document, so we layed out the schema in XSD, and applied HyperJAXB3 to is using a JAXB annotations document. Other than a few tweaks to the HJ3 code to add in some extra features we needed, everything this far is vanilla.

We then laid out a generic DAO interface, and implemented a JPA and webservices client. The webservices server actually just wraps the JPA client with a security layer.

All is well so far, with the base functionality passing all the unit tests. But, this is a fairly clumsy, class by class CRUD interface. With JPA/Hibernate you can lazily fetch parents and children of an object, and replicating this functionality would be really useful. But the webservices link really kills things.

One approach we tried was to override the getter methods on the beans to allow dynamic retrieval of data if the stored attribute is null. But we needed the webservices client to create these new (extended) beans. This is actually harder than it sounds, as CXF w/ JAXB does not allow you to replace the context factory. (see https://jax-ws.dev.java.net/issues/show_bug.cgi?id=282 )

We also tried writing our own proxies, with some success. But we ran into troubles when proxying single elements (as opposed to lists) as you loose the annotations which CXF and JPA require.

The obvious answer, which I haven’t mentioned yet is to put this logic in the getters proper. This would be nice, but because we are generating the classes from a schema we don’t want to change the generated code. There are many reasons, none less than because the schema is evolving and it hurts to merge changes. We attempted to write our own JAXB plugin to change the methods which were already generated, but XJC/the-java-code-model do not allow you to remove code from a method, only append to it. Similarly, you can’t get the annotations on a method, nor modify existing annotations. This is a huge problem for us, as it would save us having to modify the JAXB plugins which create this code, rather we could simply apply our changes to the produced code.

Perhaps there is a way around this, but it certainly isn’t obvious, or indexed by Google.

The closing remarks are these. With a bit of backfilling JAXB/XJC will be an immensely powerful tool, able to develop a wide range of data models. (I’m working on the tickets now). Dynamic getter access to attributes via web services would be nice, but it is too much hard work really, and if it is required then creating a second set of domain objects is your only real hope, IMHO. When this project wraps up I’ll release the code here so we can all think about how this approach really faired.

April 3, 2008 Posted by Nigel | JPA, Work, java | | 1 Comment

I want the last 2 hours back!

I just spent a few hours writing an Acegi filter to get a certificate from a form post, and put it into a modified User Detail principle. All well and good, except after a redirect back to / I got the error below. Normally this would redirect you back into the application using a JSP page. It turned out that because I’m using Acegi 1.0.5 which has a bug when there is no access denied page handler defined. The reason this occurs only when I was logged in was because I neglected to add ROLE_ANONYMOUS authentication authority list. If only the error meant something debugging wouldn’t have been so hard.

HTTP ERROR: 500

INTERNAL_SERVER_ERROR

RequestURI=/

Caused by:

java.lang.NullPointerException
	at org.acegisecurity.ui.ExceptionTranslationFilter.handleException(ExceptionTranslationFilter.java:229)
	at org.acegisecurity.ui.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:176)
	at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
	at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
	at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
	at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
	at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
	at org.acegisecurity.ui.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
	at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
	at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
	at org.acegisecurity.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:275)
	at org.acegisecurity.util.FilterChainProxy.doFilter(FilterChainProxy.java:149)
	at org.acegisecurity.util.FilterToBeanProxy.doFilter(FilterToBeanProxy.java:98)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1089)
	at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:365)
	at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
	at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
	at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712)
	at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
	at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:211)
	at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
	at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)
	at org.mortbay.jetty.Server.handle(Server.java:295)
	at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:503)
	at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:827)
	at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:511)
	at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:210)
	at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:379)
	at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:361)
	at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:442)

Powered by ScribeFire.

February 15, 2008 Posted by Nigel | Spring, java | | No Comments Yet

Spring and JNDI (Tomcat or Jetty)

Recently I had need to deploy some Spring webapps which required predeploy configuration. Being the first time I had to find a serious answer I looked to the mythical JNDI for an answer. This document is meant to complement other Spring JNDI documents out there.

Essentially the problem is this. We need to deploy a webapp. The webapp needs configurations (database and webservice endpoint locations). Editing properties files or XML config within the webapp isn’t nice, because on a redeploy the config will be lost. Inside containers like Tomcat I am not aware of a way to easily add extra items to the classpath which won’t get nuked unexpectedly, so solutions like PropertyPlaceholderConfigurer don’t really fly as the properties file will end up within the webapp. And I don’t like the idea of setting environment variables for to locate such things.

In steps JNDI. JNDI is the Java answer to namespaced, centralised configuration. Application containers like Tomcat, Jetty, Glassfish, etc all allow you to export objects via JNDI. This may not be a completely correct description, but it is sufficient for this demonstration. The trick is how to use these. I’ll show Jetty configs (which in Maven live in src/main/webapp/WEB-INF/jetty-env.xml) as well as some references to Tomcat (in $CATALINA_HOME/conf/server.xml or better still, in $CATALINA_HOME/conf/Catalina/[engine]/<webapp>.xml) (more on Tomcat here). This means that the config lives OUTSIDE the webapp, and is immune to inadvertant changes, making hot-patching sites easier as War/webapp is independent of the site config.

First, exposing a DB.
This exposes a Postgres DB on the name icatDB. Note, there is a special JDBC namespace. Also note I am not using the normal Postgres connection class, rather I’m using the connection pooling class.
Jetty:
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
"http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
<New id="icatDB" class="org.mortbay.jetty.plus.naming.Resource">
<Arg>jdbc/icatDB</Arg>
<Arg>
<New class="org.postgresql.ds.PGPoolingDataSource">
<Set name="serverName">localhost</Set>
<Set name="databaseName">icat2</Set>
<Set name="user">nigel</Set>
<Set name="password"></Set>
</New>
</Arg>
</New>
</Configure>

Tomcat: Example from a different project:
<Context path="/continuum">
<Resource name="jdbc/users"
auth="Container"
type="javax.sql.DataSource"
username="sa"
password=""
driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
url="jdbc:derby:database/users;create=true" />
</Context>

Spring: I am going to pass this into an entity manager:
...
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="POSTGRESQL" />
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
</bean>
</property>
</bean>

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/icatDB"/>
</bean>

So I cheated here. The data source already has a JNDI entrypoint so Spring isn’t involved. However in this next example I need to pass in a String which is a webservice endpoint address:Passing a String:
These kinds of elements are passed via the env namespace. From the Jetty JNDI page it tells me we can only pass in these types:

  • java.lang.String
  • java.lang.Integer
  • java.lang.Float
  • java.lang.Double
  • java.lang.Long
  • java.lang.Short
  • java.lang.Character
  • java.lang.Byte
  • java.lang.Boolean

This is fine for configuration work, which is all we are doing.
Jetty:
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
"http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
<New class="org.mortbay.jetty.plus.naming.EnvEntry">
<Arg>icatWebservice</Arg>
<Arg type="java.lang.String">http://hostname:8081/ws/ICAT</Arg>
</New>
</Configure>

Tomcat:

<Context path="/icat"
docBase="/var/home/tomcat/icat.war">
<Environment name="mcatextWebservice"
type="java.lang.String"
value="http://localhost:8180/mcatext/ws"/>
</Context>

Now Spring.

First import the jee namespace into your Spring config:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
...
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="...
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
...

Now we can use the jee:jndi-lookup element in place of a value element:
...
<bean id="icatConnectionManagerBase" scope="session"
class="au.edu.archer.services.icat.ICATWsClientImpl">
<constructor-arg index="0">
<jee:jndi-lookup jndi-name="java:comp/env/icatWebservice"/>
</constructor-arg>
</bean>

There has also been discussion of writing a PropertyPlaceholderConfigurer like bean which can bring all the JNDI into the properties scope so we could just use ${env.property} notation.

February 14, 2008 Posted by Nigel | Maven, Spring, java | | 9 Comments

Maven classpath issues at compile time

Here’s a very weird Maven/Java issue. The error message (below) occurs in my build phase where JaxB is called to produce some Java objects from XML. JaxB calls HyperJaxB, and on some systems it crashes.

[ERROR] XJC while compiling schema(s): org.apache.commons.logging.LogConfigurationException: org.apache.commons.logging.LogConfigurationException: org.apache.commons.logging.LogConfigurationException: Class org.apache.commons.logging.impl.Log4JLogger does not implement Log
Caused by: org.apache.commons.logging.LogConfigurationException: org.apache.commons.logging.LogConfigurationException: org.apache.commons.logging.LogConfigurationException: Class org.apache.commons.logging.impl.Log4JLogger does not implement Log
Caused by: org.apache.commons.logging.LogConfigurationException: org.apache.commons.logging.LogConfigurationException: Class org.apache.commons.logging.impl.Log4JLogger does not implement Log
Caused by: org.apache.commons.logging.LogConfigurationException: Class org.apache.commons.logging.impl.Log4JLogger does not implement Log

But not all. My main dev machine works, my deployment machine doesn’t. My other deployment machine also works, but dave’s machine doesn’t. All of us are using the same Maven version (2.0.8), mostly the same Java versions (1.5.0_xx), and some are amd64, other are x86. However, the crash/work divide does not fall on this line. In fact, on the deployment machine both local users can compile OK, but the LDAP users can’t.

On Dave’s machine if we move the local repo to /tmp (-Dmaven.repo.local=/tmp/repository) it starts working. I did capture the class path on a few occasions, and it seems to be in quite a random order. I noticed that commons-logging is far closer to the start of the class path when the compile works, but I don’t have enough samples to confirm this.

Another curiosity I saw was that if your home directory is in a non-standard place, like /var/home/, then maven puts your repository in a directory called ? in the current working directory. Thats right, question mark. Oh dear.

Some machine details below:

Working machine:
Maven version: 2.0.8
Java version: 1.5.0_13
OS name: “linux” version: “2.6.23.9-mactel-ns” arch: “i386″ Family: “unix”

Broken machine:
Maven version: 2.0.8
Java version: 1.5.0_11
OS name: “linux” version: “2.6.18-8.1.3.el5xen” arch: “amd64″

Username: test.user
Maven version: 2.0.8
Java version: 1.5.0_13
OS name: “linux” version: “2.6.23.9-mactel-ns” arch: “i386″ Family: “unix”
Worked

Username: tomcat – LDAP/NFS
Didn’t work

Username: root
Worked

Username: srb
Worked

Powered by ScribeFire.

February 8, 2008 Posted by Nigel | Archer, Maven, java | | 2 Comments

ManyToOne reference loading with JPA/Hibernate

In this example an InvestigationType has many SampleType’s. If I load an InvestigationType via em (entity manager) find it also loads the samples.

1.	InvestigationType inv2 = (InvestigationType) em.find(
2.		InvestigationType.class, inv.getId());
3.	System.out.println("Inv2 ID="+inv2.getId());
4.	System.out.println("Inv2 Title="+inv2.getTitle());
5.	assertTrue(inv2.getSample().size() == 2);

However, if I load a SampleType the investigation field is null, unless I refresh the object.

1.	// Get a sample
2.	SampleType s3 = (SampleType) em.find(
3.		SampleType.class, inv2.getSample().get(0).getId());
4.	em.refresh(s3);
5.	System.out.println(convertDataToXmlString(s3));
6.	InvestigationType inv3 = s3.getInvestigation();
7.	assertNotNull(inv3);

From my understanding I should not have to do this as the fetching should be the same in both instances, ie resolving the parent by default. Similarly, if I query for both objects the references are correctly loaded.

List items = em.createQuery("SELECT i, s FROM au.edu.archer.schemas.datadeposition.SampleType s,
     IN(s.investigation) i WHERE s.id=2").getResultList();

If someone could tell me why this is so, please let me know. Else, at least I have a working example now.

Powered by ScribeFire.

January 8, 2008 Posted by Nigel | Archer, JPA, java | | No Comments Yet

Hibernate, spring, and different jars

The situation is this. I had a working application which used Hibernate annotated classes, and JTA for data bindings, within a spring framework. Then I moved the annotated classes into a Jar file, and the application stopped working. Hibernate knew nothing about the classes because the PersistenceAnnotationBeanPostProcessor does not traverse into the JARS on the classpath. Further neither the entity manager or HibernateJpaVendorAdapter have options to specify the explicit paths to the classes.

So, after heaps of trials and tests I’ve had to abandon the JPA approach and use the direct Spring-Hibernate bindings, as they allow you to specify the path to a mappings file. This is a pain, as all my code is written to use an entityManager and now I have to have duplicate implementation which use the hibernate session factory. Perhaps there is a hibernate implementation of the entity manager, but I could not find it.

I used this blog entry for most of the config code.

Powered by ScribeFire.

November 25, 2007 Posted by Nigel | Spring, java, programming | | No Comments Yet

Spring 2.0.6 and ACEGI

Because ACEGI depends on spring 1.2.6, we need to override a few dependencies if we want to use spring 2.0.6. To do this, we use the following exclusions:

    <dependency>
       <groupId>org.acegisecurity</groupId>
       <artifactId>acegi-security</artifactId>
       <version>1.0.5</version>
       <exclusions>
         <exclusion>
           <artifactId>spring-aop</artifactId>
           <groupId>org.springframework</groupId>
         </exclusion>
         <exclusion>
           <artifactId>spring-beans</artifactId>
           <groupId>org.springframework</groupId>
         </exclusion>
         <exclusion>
           <artifactId>spring-context</artifactId>
           <groupId>org.springframework</groupId>
         </exclusion>
         <exclusion>
           <artifactId>spring-core</artifactId>
           <groupId>org.springframework</groupId>
         </exclusion>
         <exclusion>
           <artifactId>spring-dao</artifactId>
           <groupId>org.springframework</groupId>
         </exclusion>
         <exclusion>
           <artifactId>spring-jdbc</artifactId>
           <groupId>org.springframework</groupId>
         </exclusion>
         <exclusion>
           <artifactId>spring-remoting</artifactId>
           <groupId>org.springframework</groupId>
         </exclusion>
         <exclusion>
           <artifactId>spring-support</artifactId>
           <groupId>org.springframework</groupId>
         </exclusion>
       </exclusions>
     </dependency>

October 1, 2007 Posted by Nigel | java | | 1 Comment

Setting up Tomcat behind Apache 2.2 in a hierarchical path

The situation I want to deal with is this:

Public Web Root
  |-plone
  \-portals
     |-portal1 (server A)
     \-portal2 (server B)

In apache 2.2 they (the writers of the Apache docs) seem to prefer the use of mod_proxy_ajp, which is an AJP/1.3 driver for mod_proxy. At the apache end we just install mod_proxy_ajp and add a line such as the following to the proxy_ajp.conf file:
ProxyPass /portals/portal1 ajp://nigel-dev:8009/portals/portal1

Note that the paths on the proxy host and the application server are the same. This is important, as at the application end it will only know its path name from its context, and unless you want to do some url rewriting, and possible use something called ProxyHTMLURLMap. It, like most potentially useful software, isn’t available in Red Hat, so we can’t investigate this option.

So, the purpose of this post is to explain how to get the application server’s paths to match the proxies. Do the following:

  1. Create the path structure with in the $CATALINA_HOME/webapps directory, ie $CATALINA_HOME/webapps/portals
  2. Install the WAR or webapp install into its place in the hierarchy
  3. Create a context xml file for each application. These go in $CATALINA_HOME/conf/Catalina/localhost, and are named the same as the webapps path, with # in place of /. ie $CATALINA_HOME/conf/Catalina/localhost/portals#portal1.xml and $CATALINA_HOME/conf/Catalina/localhost/portals#portal2.xml.
  4. Inside these files put the following:
<Context docBase="portals/portal1.war" cookies="true">

</Context>

The cookies is important to force the use of cookies as opposed to URL rewriting to preserve the sessions. The docBase is obviously the path to the webapp or WAR file.

September 28, 2007 Posted by Nigel | java | | No Comments Yet