Why Spring and Hibernate cant be seperated

After extracting the spring-core, spring-hibernate3 and all the various parts of Sakai, fixing the classloader issues surrounding IdGenerators etc, I find both Spring and Hibernate use CG Lib for proxies, and if you separate Spring from Hibernate, they fight over CGLib. Either Hibernate cant create proxies because it cant see the hibernate classes from CGLib or Spring cant get to CGLib because its not in shared. Looks like its not going to be possible to separate Spring and Hibernate into separate classloaders without providing some extra level of visibility between the classloaders.

Reloading components in webapps… now :)

All this talk of a requirement for reloading components as a requirement for developers got me thinking. Webapps do load spring context, so why not write a context listener for a webapp that loads that webapp up as a component ? Well at the moment almost nothing. Provided I treat the webapp the same as I would a component. I can change the packaging from component to war in pom.xml, add web.xml to the WEB-INF folder with a modified context listener class that loads the component with a new classloader and the correct context classloader. Start up tomcat and hot deploy. The component comes up. I can then redeploy, and I get a whole bunch or spring Infos about bean overloads. And relaoding works, no tomcat restart required.

So what about dependencies ? Well I am doing a tool and a component. My Tool depends on my component, but nothing depends on my component. Maven builds them in order, and so tomcat deploys them in order. The component first and then the tool. So the load order is correct. Obvously, if you reload the component, you have to reload the tool, and anything else that depends on the component, so this technique is not for all.

Problems: Yes, I am not saying this works 100% but I have only tried 2 reloads so far and at the moment not entirely successful. Im trying Rwiki, which has about 5 spring config files in the component. It depends on Hibernate, and sine I shared the same global Session Factory as the rest of sakai, which has already started long ado, Hibernate doesnt know about my Pojos… but there are other tools that use Hibernate in tools, not great for production, but perhapse Ok for faster development. Annother problem I have encountered so far, but not tried to fix is that some of the properties processing doesnt work. Things like ${aproperty.value} and abc@springId dont work, but only because there apear to be the wrong property conversion mechanisms in place.

If I get it working well, I will commit the code somewhere

Update:

Leaving the orriginal components pack in place loads the Hibernate Pojos. Then when you create the new beans from the webapp, they replace the beans in the component. I can now reload RWiki’s component without restarting tomcat. It is a full Entity component with Hibernate storage

Google Calendar

Everyone keeps on telling me how cool Google Calendar is, and how we should throw away our Enterprise calendar systems. I sort of heard what they said an intended to get round to having a look one day. Finally I did. And it is.

Previously I shared iCal with webdav, and it was Ok, but no one could see when I was busy or not, and its hard to manage. With Google Calendar the interface is Ok, you get control over who can do what, including allowing family members to edit some of your calendars. The best bit is that there is good sync support. I can sync to my iCal with Spanning Sync http://www.spanningsync.com/ which just works in the background all the time, bi directional. And by sending my Blackberry to http://m.google.com/sync I can now have my Blackberry synced online, no more messy bluetooth or USB cables, it even integrated with the Blackberry Calendar and puts a “Sync with Google” menu item inside the blackberry Calendar.

So now I just need an application to generate palusable excuses for missing meetings… integrated with my calendar…. as a post event excuse generation alert. ‘If you have just missed this meeting, you might like to say…..’

OSGI Components

Perhapse this is premature, but a quick look around Apache Felix and Spring OSGI (Sorry I should say Spring Modules…. why the name change ?) gives the impression that its not going to be too hard to make most of Sakai OSGI.

So what is needed?

Well we would have to upgrade to Spring 2.5, we would have to write a service definition for each bundle and convert/move the components.xml file into the right places to make them load properly… and then we would have to deal with all the out of band things that go on in Sakai over the classloader boundaries.

IMHO, this would be a more productive long term aim that trying to write our own re-loadable component manager in competition with the component lifecycle that OSGi provides.

I also notice that there is goos support in eclipse for automating the creation of new bundles as eclipse plugins are just OSGi bundles, but for us the more important thig appears to be that Felix and Spring Modules will work with little or no effort inside Tomcat if we use the top level container concepts.

Spring Proxes that Dont appear to quite work.

Spring Auto Proxies take the hassle out of AOP, but they dont always work. The situation. I have an implementation in a classloader (component classloader) that cant be seen by the classloader that spring lives in (shared classloader). The Service API to the implementation is in the shared classloader. So I can create an Auto Proxy on the Service API and all is Ok. But then there are some configuration settings in the implementation, expressed as getters and setters, that are not present in the API. So in Sakai, sakai.properties does this all over the place with a method@springID where springID is traditionally the API id.

Unfortunately Auto Proxies cant proxy the impl without being able to see it, so they don’t work. Now you could re implement the Auto Proxy and put it in the same classloader as the impl, and then all would be cool, or you could do some AOP in the impl and not bother with the Auto Proxy… but thats not quite as easy as an auto proxy.

Naturally the danger appears when you think you have proxied the impl, and something deep in the code binds to the impl via reflection… but you have only proxied the API.

So…. dont bind to implementations at all… ever…. especially not via reflective methods… or casting… it will catch you out eventually. Unfortunately there is a lot of code out there that has made the assumption that it lives in single classloader….. and binds internally to its impls…. you have been warned :)

How to run Oracle on OSX Intel

You cant, well not on OSX. But you can bring up a Parallels desktop, install debian etch from the network iso make certain you give it 1G of swap to keep oracle happy, dont add any extra packages and then edit /etc/apt/sources.list

deb http://debian.virginmedia.com/ etch contrib main

deb http://security.debian.org/ etch/updates main contrib
deb-src http://security.debian.org/ etch/updates main contrib

deb http://oss.oracle.com/debian unstable main non-free

to include the oracle oss

then you do a

wget http://oss.oracle.com/el4/RPM-GPG-KEY-oracle  -O- | sudo apt-key add -
apt-get update
apt-get install oracle-xe

Once that is all done, and you have been through the oracle db configure step, you should apt-get install ssh so that you can create a TCP tunnel to localhost:8080 from you OSX box. That done you can expose the http://localhost:8080/apex url on your OSX box, login to the Oracle XE web interface and configure.

The nice thing about this is, if you keep the kernel small, its almost like running oracle as a native app in OSX. I did try with Ubuntu, but it was far to clever and made a huge mess of the VGA console and would only run with X enabled…. not very lightweight.

Running Oracle On OSX

Being slightly desperate for a test instance of Oracle on OSX I had a brainwave. Run Linux inside Parallels Desktop and run Oracle inside that VM. Since Parallels uses VT and can go direct to Hardware, looks like an option. However to Ubuntu 7.04 running you have to tell parallels your OS is solaris. Something to do with teh vga setup. Aparently line vga=771 also works on boot.

Timer leaks

If you use Timer and TimerTask you may find some strange with one shot TimerTasks, i.e. ones that run just once after a delay. If you add a lot of them to the Timer, they tend to be held onto by the Timer itself, and hence if there are any references these will also not get GC’d.

The JavaDoc appears to say that if you cancel the task eg TimerTask.cancel(), and then Timer.purge the references should be released, however in tests I have done this does not appear to happen in JDK 1.5.

If you want to delay invocation of events, then a java.util.concurrent.DelayQueue is probably a good alternative. The Queue can be processed periodically by a single TimerTask, resulting in no memory leak.

Running specific Maven Test with JVM Args

I have some long running tests in search, but I wouldnt want anyone to run them as part of the normal build. The tests dont have the word Test in the classname which prevents them from running, but they can be invoked on the command line with -Dtest=classname

mvn -Dtest=SearchSoak test

Also I have found that its necessary sometimes to add jvm args to the unit test, reconfiguring the Surefire plugin makes this possible, in the pom

...
  <properties>
    <deploy.target/>
    <maven.test.jvmargs> </maven.test.jvmargs>
  </properties>
...
<build>
...
 <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <configuration>
          <forkMode>pertest</forkMode>
          <argLine>${maven.test.jvmargs}</argLine>
        </configuration>
      </plugin>
    </plugins>
...
</build>

And then to run with a heap dump and YourKit connection


export DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:/Applications/YourKit Java Profiler 6.0.16.app/bin/mac"

mvn -Dtest=SearchSoak \
   -Dmaven.test.jvmargs='-XX:+HeapDumpOnOutOfMemoryError -agentlib:yjpagent' \
   test

HSQL Unit testing

Dont be fooled by HSQL Unit testing… its transaction isolation may lead you to beleive that your unit tests are working perfectly, but its doesnt support READ_COMMITTED transaction isolation, and its a true transaction monitor when it comes to committing the data, ie the code is single threadded. Since Sakai uses READ_COMMITTED for its transaction isolation in production, rahter than READ_DIRTY, tests that work on HSQL will not work in production, and tests that work in production wont work in HSQL.

update testtable set x = x + 1 where id = 99;
select x from testtable where id = 99;
commit;

If test table contains 1, and you do this in HSQL on multiple threads, there will be collisions on what is selected from testtable, since the sect reads the dirty data direct from the database, and not the data in the transaction. In MySQL and Oracle, each thread will give a unique number since a) the select is taken from the value in the transaction and, b) until the commit fires, the record is locked for update. Most of the time it doesnt matter, but if you are doing any tests that involve more than one thread, beware.

There is an alternative, DerbyDB from apache, that has an Apache license and so can be used in maven poms, however the dialect is not the same as Oracle, MySQL or HSQL. Have a read of this for more details.

← Previous PageNext Page →