The documentation here says:
The framework will, on initialization of a DispatcherPortlet, look for a file named [portlet-name]-portlet.xml in the WEB-INF directory of your web application and create the beans defined there (overriding the definitions of any beans defined with the same name in the global scope).
I do the configuration using annotations if I can, because it feels easier to keep configuration and the actual code in sync. So this [portlet-name]-portlet.xml in my project looks like this (and this file exists maaany time... One for each portlet):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<bean class="some.path.to.a.Class" />
</beans>
That is a lot of XML just for a tiny piece of information: That some.path.to.a.Class should be used to handle requests to [portlet-name]. It would be a lot easier to put a @ForPortlet("[portlet-name]") annotation or something like that on some.path.to.a.Class and forget about this XML file completely. Is anything like that possible? This bug report may hint at a "no"/"not yet"?
SOLUTION
Thanks to the super helpful hints by OlliS (Thanks a lot!) I figured out a way to do it. I dived at the points that OlliS gave me into spring's source and after taking a looooong time to figure out how things work together I wrote the following class:
public class MyPortletContext extends
AbstractRefreshablePortletApplicationContext
{
private static final String PORTLET_PACKAGE = "package.where.my.portlets.are.";
private static final String REMOVE_FROM_NAMESPACE_FOR_PORTLETNAME = "-portlet";
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws BeansException, IOException
{
// The following line does the same thing as specifying
// <context:annotation-config /> in the xml file:
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
// Figure out the portlet name:
final String portletName = StringUtils.removeEnd(getNamespace(),
REMOVE_FROM_NAMESPACE_FOR_PORTLETNAME);
// Derive the controller from the portlet name:
final String beanClassName = PORTLET_PACKAGE + portletName;
// Tell spring about the bean:
final GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName(beanClassName);
final String beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, beanFactory);
final BeanDefinitionHolder bdHolder = new BeanDefinitionHolder(
beanDefinition, beanName, new String[] { beanClassName });
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, beanFactory);
}
}
Then I registered this class as contextClass in the portlet.xml file using an init-param, just like OlliS figured in his answer. And that's it. No *-portlet.xml file needed any more. Just a single class configuring all my portlets.
Of course one could still improve this class, making it more flexible, reading the portlet package from somewhere instead of a constant. Maybe an init-param. Or one could scan for annotations, perhaps the mentioned @ForPortlet annotation, which would create the possibility to register more than one bean. But for now I am happy :-).