There’s one thing that is easy to miss when setting up a Portlet using Spring MVC and Annotation configuration, and that is the correct placement of the <context:annotation-config /> elements. In the examples that I found, the element is only located in the applicationContext.xml file, unfortunately this doesn’t always work as you might expect.
In Spring MVC Portlets, the applicationContext file is used to define beans that should be available to all the portlets in that portlet application (or WAR). Similarly it also makes these beans available to any servlets that are defined in the WAR. So far so good, this is working correctly, and is exactly how you would expect it to work.
The problem arises when using Annotation Configuration, and it can be difficult to trace back to exactly what might be causing it. If you define <context:annotation-config /> in just the applicationContext.xml file, then the annotation configuration will appear to work (portlet initialization will work, and they should start up appearing to be fully wired). However when the portlets are used, they will start to throw NullPointerExceptions due to beans not being wired. It appears that @Autowired and @Resource are not being interogated when the portlet is running, but worked fine when it was being initialized.
Attempting to diagnoise this issue will have you looking at classpaths, ensuring that there are no duplicated JARs loaded by parent and child classloaders, tracing the spring logs for wiring errors, validating the presence of spring-aspects.jar, etc, etc, etc. While these are all valid approachs, and can be a good way to clean up an application, in all likelyhood what is wrong is that the <context:annotation-config /> element is missing from the individual portlet’s configuration file. Leaving this element out means that the spring autowiring won’t be enabled when the portlet is using the portal server’s classloader, but was enabled when the portlet was initialially loaded by the application server’s classloader. At least, this appears to be what’s happening in JBoss Portal Server, your miliage may vary with other servers.
How do you ensure that your annotated portlet will be wired correctly? Simple, add these to both your applicationContext.xml and xxx-Portlet.xml files:
<context:annotation-config />
<context:spring-configured />
<aop:aspectj-autoproxy/>
Note: In the case of the xxx-Portlet.xml files, its a good idea to create a common.xml file, then import that in each of the individual portlet files. This allows for commonality between all the portlets, even though they will get their own instance of any beans defined in it.
<import resource=”classpath:/com/foo/bar/context/common.xml”/>
0 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.