Reputation: 397
I want to add cache-control directive (set both public and max-age seconds) for a couple of URLs in Spring MVC and I want to do those changes via applicationContext.xml only.
I am trying to set the map property cacheControlMappings
of org.springframework.web.servlet.mvc.WebContentInterceptor
, but the only problem is the design of the class which has no setter method for the property. As a workaround, I am invoking the addCacheMapping
method using the org.springframework.beans.factory.config.MethodInvokingBean
.
My configuration in spring-mvc-config.xml is as follows -
I am creating a CacheControl
bean as follows, and I verified by debugging that this bean gets created successfully with appropriate values populated in the application context.
<bean id="cacheControlFactory" class="org.springframework.http.CacheControl" factory-method="maxAge">
<constructor-arg index="0" value="3600"/>
<constructor-arg index="1">
<value type="java.util.concurrent.TimeUnit">SECONDS</value>
</constructor-arg>
</bean>
<bean id="myCacheControl" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref bean="cacheControlFactory"/>
</property>
<property name="targetMethod">
<value>cachePublic</value>
</property>
</bean>
Then I wish to invoke this method - public void addCacheMapping(CacheControl cacheControl, String... paths)
of WebContentInterceptor
which will add entries to the map cacheControlMappings
.
I verified that calling this method programmatically works great, so it should work fine if I invoke it from the XML right? But I am trying to do the same, as shown below, but this does not work for me, and I get zero entries added to the final map.
<bean class="org.springframework.beans.factory.config.MethodInvokingBean">
<property name="targetObject">
<ref bean="webContentInterceptor"/>
</property>
<property name="targetMethod">
<value>addCacheMapping</value>
</property>
<property name="arguments">
<list>
<ref bean="myCacheControl" />
<value>/home</value>
<value>/dp/**</value>
<value>/**/b/*</value>
</list>
</property>
</bean>
Why does the above invocation with MethodInvokingBean
not work? Am I setting the arguments wrong in any way? Do the varargs need a different handling? I don't see any errors thrown either during server startup.
Also, I am aware of this SO thread (How to set Cache-control: private with applicationContext.xml in Spring 4.2 or later ) where the accepted answer mentions there is no way to do this in the XML itself. I wanted to re-confirm if that is correct by trying to implement above solution but it is not working, but I don't see why.
Upvotes: 0
Views: 737
Reputation: 397
As I had suspected, there was an issue in the way the arguments were getting populated. The varargs in a spring injection need to be given as an explicit list instead of an overload of arguments (like it's done in Java).
So the correct way to invoke such a method -
public void addCacheMapping(CacheControl cacheControl, String... paths)
in spring applicationContext.xml is as follows -
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject">
<ref bean="webContentInterceptor"/>
</property>
<property name="targetMethod">
<value>addCacheMapping</value>
</property>
<property name="arguments">
<list>
<ref bean="myCacheControl" />
<list>
<value>/home</value>
<value>/dp/**</value>
<value>/**/b/*</value>
</list>
</list>
</property>
</bean>
As you can see I have now used MethodInvokingFactoryBean
. Somehow MethodInvokingBean
did not work for me.
Upvotes: 1