Vita Rara: A Life Uncommon

Groovy Struts Update


Categories: | | | | |

(NB: For the latest on the subject see: Groovy Works.

I worked with using Spring to instantiate the action beans today, and that didn't go too far. I started getting an exception from AspectJ. (See thread on the Spring forum.)

So, I got to thinking. What if I created the GroovyClassLoader in Struts 2 prior to initializing the Spring context, and make the GroovyClassLoader the parent of the Spring context. This works! Finally something that works. It's not really enough though, and it's very cludgy. I would have to have two source trees, one of Groovy files that need to be compiled ahead of time, and one of others that are compiled and loaded at run time. That would make for a messy project in my eyes.

It's back to the drawing board. I'm not sure that my idea is going to work. I have a feeling that inside the Spring context the classloaders are configured as follows:

                   Spring Class Loader
                      |            |
     AspectJ Class Loader        GroovyClassLoader per Groovy bean

The AspectJ class loader and the Groovy class loader are siblings and therefore can not see the classes the other loads. AspectJ needs to have visibility to the Groovy classes otherwise you can't use declarative transactions, or other aspect oriented powered features with Groovy beans. This is a serious, I would say, fatal flaw in Spring's scripting support.

It almost seems like when an application context is started the class loaders for the various scripting languages need to be created and used as the parents of the main Spring class loader for the context. They should also be stored as beans in the application context so they can be injected into the beans that actually load their respective scripts and house the RootBeanDefinition information, etc. The question is which class loader goes first?

Alternatively Spring needs a custom class loader that would consult the various script class loaders when the AspectJ class loader asks it if it knows about a class. All of this is very messy though.

Workaround the AOP and Groovy classloader

Dear Mark

I have same similar problem like you in my current company project. I have tried a workaround method which "SEEM" to work in my case. But I am not sure that it works in other case. I have created 2 application xml files in my application. The first application xml file contains all the beans and Groovy script definition. The second application xml file contains only the pointcut definition like:

<aop:config>
 <aop:pointcut id="PersonServiceOperation" expression="execution(* org.test.PersonService.*(..))"/>
 <aop:advisor advice-ref="txAdvice" pointcut-ref="PersonServiceOperation"/>
</aop:config>

In my java program, I need to create 2 ApplicationContext like:

ApplicationContext context1 = new ClassPathXmlApplicationContext(
  new String[] {"applicaionContext1.xml"});
ApplicationContext context2 = new ClassPathXmlApplicationContext(
  new String[] {"applicaionContext2.xml"}, context1);

It seems that if I pass the context1 to create context2, the AspectJ classloader and GroovyClassloader are not sibiling any more and AspectJ classloader can see the Groovy Class implementation interface. I have already posted my workaround to the spring forum. But I am not sure that my workaround will have any problem in other cases. If you find any problems with my workaround, please let me know so that I can avoid the problem in my project. My email is ctam@xeniumhk.com Thanks a lot for your help.

Thanks
chris tam
xenium