|
From: Steven D. <ste...@gm...> - 2005-01-01 18:48:37
|
Hi, Right now Spring doesn't offer support for dynamic languages. This leads to at least one critical issue and a few minor others one that can be resolved. The issues: + De-serialization of dynamic classes (critical): Say you have a setup with a client and server talking to each other. The client and server both share the same set of .groovy files containing a number of classes. These classes implement java.io.Serializable, have a serial version UID yet cannot be de-serialized. Http invoker uses java.io.ObjectInputStream which implements java de-serialization. ObjectInputStream uses it's own scheme to detect which class loader should be used to create a new instance from the serialized format and doesn't allow you to specify your own class loader. This means ObjectInputStream cannot resolve and http invoker cannot transport dynamic classes. + Instantiation of dynamic classes in the bean factory (nice-to-have): I've looked in the Spring sand box and I'm not sure if there's an implementation in there for creating dynamic classes from the bean factory. Currently you would be able to load for example Groovy classes using the bean factory if you would set a Groovy class loader as the context class loader before creating the Spring bean factory. This approach is not very usable as you would only be able to overwrite the context class loader in a simple java application while it would probably be (a lot) harder to do this in say a servlet container. + Temporarily changing the context class loader (nice-to-have): For some method calls you need to temporarily change the context class loader in order to let for example Hibernate load dynamic classes. Hibernate uses the context class loader to load classes. Temporarily changing the context class loader is required when you want to use dynamic classes as persistent objects. Restoring the original context class loader when the method exits - either on a normal exit or by throwing an exception - is required to not cause class loading problems elsewhere in the application (server). If we are talking about dao's we could easily do this using AOP. If we're talking about LocalSessionFactoryBean we need to do the context class loader switch only for the method afterPropertiesSet. We could also do this using AOP but that's a bit clumsy. Also, using AOP everyone would need to write the method interceptor that does the context class loader switch themselves. The proposed solution: Before I discuss the proposed solution I would like to mention that Groovy and Janino both offer a class loader while Jython and BeanShell (apparently) don't. I say apparently because I don't know Jython and BeanShell that well. The first part of the proposed solution is to create factory beans for Groovy, Janino, ... that load scripts either from the file system or from a string. These factory bean would have as object type java.lang.ClassLoader and are there to declaratively load Groovy or Janino classes. Both the Groovy and Janino take a parent class loader. My experiments using Jetty show that the context class loader retrieved in the scope of the context loader listener can be safely used as a parent class loader while handing requests. The second part of the proposed solution addresses the de-serialization issue. Subclassing ObjectInputStream allows you to overwrite the resolveClass method. This would allow you to use a custom class loader. If Spring would offer such a subclass it would be peanuts to subclass SimpleHttpInvokerRequestExecutor, add a classloader property and overwrite the readRemoteInvocationResult method. The third part of the proposed solution addresses the instantiation of dynamic classes by the bean factory. By adding a classloader attribute to the xml bean definition one would be able to refer to the factories discussed above to specify which classloader Spring should use to load the defined class. I'm not sure how this should be implemented in Spring. In DefaultXmlBeanDefinitionParser the context class loader is passed to the bean definition so this looks like the hook. The custom class loader should be retrieved from the factory, I'm not sure how and where this should be implemented. The fourth part of the proposed solution addresses the temporary switch of context class loaders. It would be nice if Spring would offer a method interceptor that implements this. It would also be nice if a classloader property could be added to a subclass of LocalSessionFactoryBean so that the context class loader could be switched in the afterPropertiesSet method. If we can agree on the importance of dynamic language support in Spring I would be happy to implements parts 1, 2 and 4. Steven |