Velocity Based Spring MVC in Sakai

29 09 2006

Well it is possible, but you have to rewrite the Spring MVC view resolver and the Velocity Configurer so that neither extend any Spring framework classes, otherwise they will want to drag Velocity into shared. Once you have done that, it works like a dream, except that you cant easily get the templates onto the filesystem.

They work just fine in the classpath, but to get a ResourceLocator to know about the filesystem it has to have a ServletContext. In a normal environment this would be easy, just do it from the request.getSession().getServletContext()…. but in Sakai, thats a Wrapped request and you cant get the servlet context that way. So the robust, but slightly complex way of doing this is to. Put a Spring bean into applicationContext.xml that can hold a ServletContext, then have a ServletContextListener that starts after the Spring ContenxtLoaderListener and injects the ServletContext into the holder. Then the holder itself can be injected into the springapp-servlet.xml as a dependency, so when the VelocityConfigurer starts up it can set the ServletContext in the instance of the Velocity Engine bound to the web app. You cant use a singleton Velocity engine, since it would be the only one in the JVM…… then…… the standard WebappResourceLoader can get gold of the ServletContext, via rsvc in ResourceLocader and hence the real path to a template on the filesystem….. lost yet :)

Perhaps I’ll make a jar of this as the same applies to any tightly bound SpringMVC view technology.





Spring MVC in sakai

28 09 2006

There is an unfortunate side effect of using Spring MVC based apps in Sakai. Sakai has the Springframework libraries in shared, it also has a number of utility classes that make spring MVC much easier, but if those classes are expected to load the selecte view technology, that view technology must also be placed in the shared classloader. As it stands, you cant use the Spring provided VelocityViewResolver as it will pull the Velocity jars into the shared classloader, and break every Velocity app in Sakai…. but you can write your own view resolver which will sit in your own webapp classloader.





Skinable Charon

18 09 2006

After becoming closely acquainted with with Charon at integration week, (thats the current Sakai portal and not a typo :) … more’s the pity ), I’ve had a look at making it a bit more skinnable. After a quick round of templating engines, and considering string properties for good measure, I notices that some including velocity allowed you to render without binding dependencies. So I’ve extracted all the inline html from Charon, created vm templates and put the Velocity binding behind an API. It should now be possible to have per site portal templates that go beyond what can be done with css… and plug in any other templating engine.

A nice side effect is that it was possible to write a unit test case that would render all the templates and validate them for accessibility.

Since we are after a code freeze, this is not going into trunk and 2.3.





To 1.5 or not

13 09 2006

Pandora’s box is open. We may not realize it, but there are a whole load of things in 1.5 that may trip us up. This is more about not moving to 1.5 that moving to it.

Developers who develop on 1.5 will, by mistake, use methods only in 1.5 (Boolean.parseBoolean etc)

Autoboxing and Unautoboxing will compile on 1.5 as 1.4 source, but unless the target 1.4, it wont run in 1.4 as the java.lang.Object is different.

And the real gotya for me is, libraries with generics in wont run under 1.4….. so all those Apache dependencies wont work and we will be stuck, with bugs back at Lucene 1.9.1, pluto 1.0 etc etc etc. Eventually everyone has to move, this is no longer a unidirectional problem, its become bidirectional…. so when do we move to 1.6 :)





Alfresco

8 09 2006

Looks like Alfresco is starting to pursue JSR-170 for its 1.2 release. The positive side is it clusters, the negative side is that at the moment it doesn’t pass all the Level 2 170 tests. I could be plugged in under the new CHS service with a small adapter, but, if its not solid through the JSR-170 API, then it will be a pain to run, even in a cluster.

One to watch and put under the Content Hosting Service when its ready, if Jackrabbit doesn’t get there first.





In Tomcat Unit Testing

7 09 2006

Although the Test Harness is great and enables Unit tests to work for components, there is a ‘dirty hackers’ alternative.

Write a class that operates as a unit test, inject it into Spring, start the test in the init method, and call you pack project 0000-sakai-myproject-pack

Your project will load first and then execute your unit test, pulling in all the necessary dependencies. It may not have the full JUnit environment, but it will test your code.

Just remember to turn the test bean off in production :)





Hierachy Service

7 09 2006

I’ve started to think about the hierarchy service. Im thinking about a Hibernate Managed (with lazy connections) object tree, on the basis that access is read mostly. This greatly simplifies the API and usage. To avoid issues with Entity names, the path, which will be stored in the object will he SHA1 hashed to generate the Unique node id. So we can have node paths upto 4K long.

There permissions will be handled by mapping the path to realms in the security service, but to avoid problems with performance the inherit property of the node will be defined in the node itself. This will make it quick and easy to locate the node.

see https://source.sakaiproject.org/contrib/tfd/trunk/hierarchy

Here’s the api. When the details of the Hierarchy and HierachyProperties have crystallized, I’ll
push them to contrib or post them here.





Log4J and Chainsaw

5 09 2006

After years of using tail -f or less on log4j log files, and then trying to do cleaver things in XL with the output, I realize there is this thing called Chainsaw, which accepts a feed of Log4j over IP.

So you can turn off most of the output in the log files and use Chansaw to drill into the log stats, turning on and off DEBUG on selected classes at runtime.

As with all log4j its a pain to setup. Im using a Simple Receiver on port 4445 and so my log4.properties file looks like this:

log4j.rootLogger=INFO, stdout, Chainsaw

log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{hh:mm:ss.SSS} %-5p[%-20c] %m%n log4j.appender.stdout.Threshold=WARN

log4j.appender.Chainsaw=org.apache.log4j.net.SocketAppender log4j.appender.Chainsaw.remoteHost=localhost log4j.appender.Chainsaw.port=4445 log4j.appender.Chainsaw.locationInfo=true

log4j.logger.org.sakaiproject=WARN log4j.logger.org.sakaiproject.content=DEBUG log4j.logger.org.sakaiproject.dav=DEBUG log4j.logger.org.apache=ERROR log4j.logger.org.springframework=ERROR log4j.logger.org.hibernate=ERROR log4j.logger.vm.none=FATAL log4j.logger.com.sun.faces=FATAL

The trick is the Threshold setting to reduce the level in the stdout.

If I drop this into the webapps/dav/WEB-INF/classes/log4j.properties it gets loaded in the base loader and changes the whole of Sakai.





JCR Session Startup

4 09 2006

Is good, and quick,





JCR Sessions.

4 09 2006

I had thought with the structure of JCR that it would be a good ideal to open and attach one session to each request thread, avoiding the session creation mechanism. Before you think that this is totally daft, remember that the JCR persistence manager in Jackrabbit manages persistence for the entire JVM. So a managed session attached to the request thread is not so dumb…. well, perhaps, except that if anything goes wrong with the session, that state persists with the session to the next request. The interesting bit is that the error hangs around until and eden GC collection cycle takes place…. at which point any objects that were left uncommitted in in the session are finalized. If the finalization ‘rollsback’ the JCR object transaction, the session recovers, but a it looks like everything that was ‘committed’ after the error state is also rolled back.

In retrospect, creating sessions per request is going to be a better approach. However, its going to need some sort of hook into the request cycle to ensure that the Session is created and destroyed. Lazy construction is ok, but there is no unbind hook at the component level.








Follow

Get every new post delivered to your Inbox.

Join 114 other followers