Category Archives: java

JaxWs, Spring, and referencing the wsdl in a jar, not via http

Well, this was awkward. Spring provides a quite handy factory class for creating JaxWs clients with JaxWsPortProxyFactoryBean

The config is quite simple really, you just do:

<bean id="partnerProxy" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
        <property name="serviceInterface" value="is.vf.conan.ws.ConanPartnerPortType"/>
        <property name="wsdlDocumentUrl" value="http://localhost:8088/mockConanPartnerBinding?WSDL"/>
        <property name="namespaceUri" value="http://is.vf.conan/1.0/"/>
        <property name="serviceName" value="ConanPartnerService"/>
        <property name="portName" value="ConanPartnerPort"/>
</bean>

The “namespaceUri”, “serviceName” and “portName” are all boiler plate, that you have to extract from the wsdl, and shouldn’t really have to specify, but whatever, it’s boiler plate.  “serviceInterface” has to already exist.  You  have to have generated the types and interfaces before hand. But, if you’re doing wsdl first development, and you’re reading this, you already have all that. (Update 2010-07: If you don’t want to type in all that boiler plate (and who does), see: Spring JaxWS clients with less config)

Here in the office, we have a client jar, which contains the generated types and interfaces, and the wsdls themselves.  This is easy to distribute, and lets you add in support for a new service by simply dropping in a new client jar. (The jar is made with maven, using the jaxws-maven-plugin and it’s wsimport goal)

All well and good. Except. You can’t start this application unless that wsdl is up and available. You can add

        <property name="lookupServiceOnStartup" value="false"/>

Which is certainly a good start, but what if my endpoint doesn’t actually provide the wsdl at runtime? What if the ?wsdl url suffix doesn’t work here.

Well, we have two options:

  1. Have a server running all the time to provide the wsdl, and use the “endpoint” property to specify the final destination. (yuck)
  2. Have the proxy factory reference the WSDL inside that client jar.

You will see in some docs that you can do things like this:

<property name"wsdlDocumentUrl" value="classpath:blah.wsdl"/>

This works, if the wsdl can be found. If you have the wsdl in the same class structure as the rest of your code, this is probably all you need. But if your wsdl is inside a jar in the classpath, well, I tried lots of singing and dancing, but couldn’t work out how to make a url that pointed reliably to the wsdl inside the jar. :( This made me very sad.

I really don’t like having to override things, but well…. Here’s an extended spring factory bean. You now must use the endpoint property, plus the new property “localWsdlName” as well as “lookupServiceOnStartup = false” I was going to be using endpoint properties anyway, to make it nice and easy to switch out the different test environments we use, so that was not a big problem.

“localWsdlName” refers to the path inside the jar. It _should_ be able to be a “classpath:blah” reference as well, but it’s all relative to the jar that provides the service interface.

public class VodafoneJaxWsFactoryBean extends JaxWsPortProxyFactoryBean {
    private String localWsdlName;
 
    @Override
    public void afterPropertiesSet() {
        super.afterPropertiesSet();
        // This will be a looonnng file:// url, reaching into the jar 
        // holding the service interface
        URL url = getServiceInterface().getResource(localWsdlName);
        setWsdlDocumentUrl(url);
    }
 
    public void setLocalWsdlName(String localWsdlName) {
        this.localWsdlName = localWsdlName;
    }
}

And the new config you need to use this…

    <bean id="partnerProxy" class="is.vf.conan.VodafoneJaxWsFactoryBean">
        <property name="serviceInterface" value="is.vf.conan.ws.ConanPartnerPortType"/>
        <property name="endpointAddress" value="http://localhost:8088/mockConanPartnerBinding"/>
        <property name="localWsdlName" value="/conanPartner.wsdl"/>
        <property name="lookupServiceOnStartup" value="false"/>
        <property name="namespaceUri" value="http://is.vf.conan/1.0/"/>
        <property name="serviceName" value="ConanPartnerService"/>
        <property name="portName" value="ConanPartnerPort"/>
    </bean>

There you have it! If you have everything in one big blob project, you don’t need this, just specify the localWsdlName as “classpath:blah” and you’re done.

EHCache, JMX, Hibernate and Spring

We have a spring/hibernate application that we also like being able to use JConsole with, so we expose a few things via jmx.  Spring makes this pretty easy for the most part, you just use @ManagedResource on with the boiler plate config below, you’re good to go!

    <!-- Allow any bean to be exposed as an mbean.  Just use @ManagedResource and @ManagedAttribute -->
    <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
        <property name="assembler" ref="assembler"/>
        <property name="namingStrategy" ref="namingStrategy"/>
        <property name="autodetect" value="true"/>
        <property name="registrationBehaviorName" value="REGISTRATION_IGNORE_EXISTING"/>
    </bean>
    <bean id="attributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
    <bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
        <property name="attributeSource" ref="attributeSource"/>
    </bean>
    <bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
        <property name="attributeSource" ref="attributeSource"/>
    </bean>

But what about exposing beans from libraries?  For hibernate it’s easy, you just make spring create the hibernate provided bean…

    <bean id="hibernateStatistics" class="org.hibernate.jmx.StatisticsService">
        <property name="statisticsEnabled" value="true"/>
        <property name="sessionFactory" ref="nipSessionFactory"/>
    </bean>

and then modify your mbean exporter config to specifically include hibernate stats…

    <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
        <property name="assembler" ref="assembler"/>
        <property name="namingStrategy" ref="namingStrategy"/>
        <property name="autodetect" value="true"/>
        <property name="registrationBehaviorName" value="REGISTRATION_IGNORE_EXISTING"/>
        <property name="beans">
            <map>
                <entry key="Hibernate:name=statistics" value-ref="hibernateStatistics"/>
            </map>
        </property>
    </bean>

Presto, hibernate stats are now available in Jconsole, wherever you specify with the key. Well and good. But what about EHCache? According to http://ehcache.org/documentation/jmx.html there’s mbeans provided here too, so we can just list them in our bean config and add them to the list with hibernate right? MAYBE! You can get the cache manager working like this…

    <bean id="cacheManager" class="net.sf.ehcache.management.CacheManager">
        <constructor-arg ref="innerCacheManager"/>
    </bean>
    <bean id="innerCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="shared" value="true"/>
    </bean>

and then refer to cacheManager in the list of beans to export. But when it comes to the CacheStatistics object, you need to somehow get at the EhCache object itself, and spring bean config doesn’t have any way of getting at that easily.

Instead, you can just ask EhCache to register itself with the mbean server. This is covered at http://forum.springsource.org/showthread.php?t=63453 but I just wanted to cover it with a bit more information…

The extra beans you need for full EhCache jmx management, on top of the hibernate stats config above is:

    <!-- only needed explicitly because ehcache needs it to register itself -->
    <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
      <property name="locateExistingServerIfPossible" value="true"/>
    </bean>
 
    <!-- ehcache needs to register itself, we can't just give the bean to jmx ourselves -->
    <bean id="ehCacheMBeanRegistration" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="staticMethod" value="net.sf.ehcache.management.ManagementService.registerMBeans"/>
        <property name="arguments">
            <list>
                <ref bean="innerCacheManager"/>
                <ref bean="mbeanServer"/>
                <value>true</value>
                <value>true</value>
                <value>true</value>
                <value>true</value>
            </list>
        </property>
    </bean>
    <bean id="innerCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
        <property name="shared" value="true"/>
    </bean>

Adabas D, hibernate and compound primary keys

lastly, My (least) favourite application here at work, that beauty that uses Adabas D as the database server, also makes liberal use of compound keys. However, in our useage, one portion of that key is always fixed, so when I started trying to replace a lot of the raw jdbc with hibernate as I mentioned earlier, I just put the fixed portion as a regular column, and labelled the varying column with the @Id notation. This worked just fine for reads, and for most of the basic writes we were doing at the time. (Where the write simply changed a field in the table) However, when we tried to update an object property, (By object I mean, myObject.complicatedChild = blah, not just myObject.integerField = wop) it all failed.

Error: ASSIGNMENT IMPOSSIBLE, CHAR VALUE TOO LONG
SQLState:  22001
ErrorCode: -2010

Excellent…..

SAP isn’t very helpful on what that means, it seems to just try and say that, well, you tried to put too big a char value into a char column. Like hell I said, but went off to hibernate debugging to see just what exactly was going on. Which led me to discover that the hibernate code simply wasn’t working!

The generated hibernate code:

update TABLE set
FIXED_PART_OF_KEY=3,
ID_OF_OTHER_OBJECT=4
where REGULAR_PART_OF_KEY ='somekey'

This by itself was failing! but if you take out the FIXED_PART_OF_KEY from the update though, it all works just fine! (This was actually a longer process of elimination, with a lot more rows initially) So, even though there is only one row where the regular part of the key matched “somekey” I went ahead and converted to fully using compound keys across the project, suspecting some inanity from within.

And low and behold, it all started working again. Hooray!  I use the @IdClass method, as it seems to fit our code best.

So:

  1. add @IdClass to original entity
  2. remove @Column attributes from the original ID entity, and put them in the new IdClass
  3. put @Id attributes on both columns in the original entity
  4. add equals and hashcode implementations to the IdClass, and mark as @Embeddable
  5. Add a constructor to the IdClass to deal with the “fixed” portion of the key

Lastly, any other object that was referencing this just by the regular part of the key now needs to be updated as well. so @JoinColumn get’s replaced with @JoinColumns, and the dangling property for the unused fixed portion of the key is deleted.

Moral of the story? Don’t use Adabas D, it’s archaic and has a terribly old jdbc driver. Don’t use Compound Keys if you have a choice. It just causes extra pain.

Versions used: hibernate 3.2.6GA and java 6. JDBC driver for adabas provided by SAG.

Adabas D, Cirpack and Hibernate

It’s more possible than you think!

Use org.hibernate.dialect.SAPDBDialect as the hibernate dialect, and it seems to be good to go. I’ve had to use @IdClass and create @Embeddable key classes for all the cirpack compound keys, but for simple read and edit, this has let me use hibernate, instead of raw JDBC. Hooray for that!

I haven’t figured out a pretty way of dealing with Adabas columns specified as “int” that are only ever used as booleans, but I can live with that for now.

Unfortunately, you _do_ have to actually specify the dialect, as hibernate won’t work this one out on it’s own. Tested with a 2001 dated version of adabasd.jar, and hibernate 3.2.6GA

Upgrading jBPM from 3.1.2 to 3.2.3

At work we have a running blob of code that was built by a predecessor on jBPM 3.1. It’s basically concrete and unmaintainable, but I decided to give it a good effort. First port of call was to see about upgrading to the latest, so that I could use the latest tooling for designing or editing the processes, and also to get the jbpm-console operational.

First, simply trying to drop the 3.2 jbpm-console war into the running tomcat fails wonderfully.

So, rather than outline each and every fix I had to make along the way, here’s a list of the notes I took while doing this. It was having to wade through this pile of shit that motivated me to get this blog up, something I’d meant to do for a while, as a way of returning the favour for some of the more useful tech blogs I’ve seen out there.

My Goals

Just so you know what I was trying to achieve, I wanted to upgrade a running 3.1 jbpm app to 3.2, then try and add the jbpm-console web app alongside for some better management.

Database upgrade

The documentation here is terrible. The section of the userguide on database upgrades (for 3.2) still refers to how to upgrade from 3.0 to 3.1. This is bug JBPM-1689 over in the jboss jira. But at least I found out what I was meant to do. (oh, and the script in the release notes doesn’t have ; characters at line ends, so you’ll need to edit it before trying to run it)

Compilation breakages

Where’d my code go? We were using timers extensively, though looking at some of the examples now, I don’t actually know why. Still.

  • scheduler.exe.Timer -> job.Timer
  • SchedulerSession -> JobSession
  • saveTimer -> saveJob
  • deleteTimer ->deleteJob
  • timer.isDue() -> timer.getDueDate().before(new Date()))
  • timer.execute() -> timer.execute(jbpmContext)

Spring and other XML config

We were using spring-modules, and had the jbpm config loaded up at runtime. So, our hibernate context, which included the links to all the jbpm hbm.xml files needed to be updated with the new Job.hbm.xml file, the new locations of the Timer, and remove some of the dead ones.

your web.xml that may have referred to the DeployServlet and UploadServlet need to use the ProcessUploadServlet now.

Your jbpm.cfg.xml needs to be updated to include the tx service (Line 5)

1
2
3
4
5
6
7
8
  <jbpm-context>
    <service name="persistence" factory="org.jbpm.persistence.db.DbPersistenceServiceFactory" />
    <service name="message" factory="org.jbpm.msg.db.DbMessageServiceFactory" />
    <service name="scheduler" factory="org.jbpm.scheduler.db.DbSchedulerServiceFactory" />
    <service name="tx" factory="org.jbpm.tx.TxServiceFactory" />
    <service name="logging" factory="org.jbpm.logging.db.DbLoggingServiceFactory" />
    <service name="authentication" factory="org.jbpm.security.authentication.DefaultAuthenticationServiceFactory" />
  </jbpm-context>

At this point you should have your existing jBPM app running with the 3.2 jars, against a 3.2 db. yay.

Making jbpm-console play with others

At this point you can actually deploy the jbpm-console.war into your container (I’m using tomcat) and it will load up, and give you a login and everything. (Once you sort out jar hell. I had to copy plenty of jars from my webapp to the jbpm-console lib folder, and then add the extra ones that jbpm needed. This is a straightforward, if tedious game of adding jars until you don’t get ClassNotFoundException anymore. (antlr, commons-logging, commons-collections, hibernate, jsf, asm, cglib, bsh, dom4j, jta, and a jdbc driver)

Once it’s unpacked, you need to edit the WEB-INF\classes\hibernate.cfg.xml file to match the connection used in your main webapp.

And now, even more importantly, you need to turn off the job runner that’s included (for god knows what reason) in the console. Edit the web.xml file to remove/comment out the following…

    <!-- Job executor launcher (begin) ==>
Turn this off so that your app doesn't clash with this one picking up Jobs/Timers
    <listener>
        <description>
            Starts the job executor on servlet context initialization and stops it on 
            servlet context destruction.
        </description>
        <listener-class>org.jbpm.web.JobExecutorLauncher</listener-class>
    </listener>
    == Job executor launcher (end) -->

Note: You can still use the console to signal tokens and so forth, this doesn’t stop that, it just stops it from picking up jobs.

Usernames and login

Running on tomcat there were some issues where I couldn’t actually login to the console. http://wiki.jboss.org/wiki/JbpmOnTomcat has some words on this, but what I found was simplest was to edit the jbpm-console.war::web.xml some more. My tomcat app was already using a couple of usernames and passwords, so I just told jbpm-console to use them. The <security-constraint> section needs to use a role (<role-name>) that’s already in your tomcat-users.xml file, and the roles listed in <security-roles> need to match as well. You can also take the approach they recommend and set up the ID tables, and add all sorts of other users and stuff, but some of that seems to be just so that the _examples_ run, whereas I was trying to retrofit the jbpm-console and the 3.2 code to an existing app.

I’m almost certain that this will _still_ not cover all the pain _you_ will go through, but hopefully it helps a bit.

I’ve still not got to actually using the 3.2 designer to make changes to this chunk of legacy yet, but hey, running the latest version sure seems like it should help. And now we have the jbpm-console giving us a bit more control of things when processes go astray.