web.xml init params more than one param-value - spring

I would like to ask if it is possible to add more than one param-value in
<param-value>
tag?
For example:
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext, org.springframework.web.context.support.XmlWebApplicationContext</param-value>
</init-param>
Thank you!

That depends on the parameter. The code which reads the value can parse it in any way they like. This means there is no way for you to say "I want to pass multiple values" and no standard.
Spring doesn't support more than one class as contextClass. This class is used to build the application context and a Java class can always only have a single concrete type. If you don't specify the parameter, Spring will use XmlWebApplicationContext as default. If you use annotated Java config, then you will want to replace this with org.springframework.web.context.support.AnnotationConfigWebApplicationContext.
The classes which configure Spring need to specified with contextConfigLocation which takes a list (comma and/or space separated) of file or class names.
For details, see the documentation: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-java-instantiating-container-web and http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html

What you done is correct , it should be separated by comma , as the delimeter
<context-param>
<param-name>contextClass</param-name>
<param-value>ex1.com,ex2.com,.....</param-value>
</context-param>
or you can put them like below to make it more readable,
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
org.springframework.web.context.support.XmlWebApplicationContext
</param-value>
</context-param>
should work as expected

you can use several values in <param-value>, but only if method can accept array of values.
example 1:
<init-param>
<param-name>suffixExclusions</param-name>
<param-value>.jsp, .ftl</param-value>
</init-param>
it works fine, because there can be many parameters.
example 2:
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true, false</param-value>
</init-param>
will be an exception:
org.springframework.beans.TypeMismatchException: Failed to convert property value of type 'java.lang.String' to required type 'boolean' for property 'forceEncoding'; nested exception is java.lang.IllegalArgumentException: Invalid boolean value [true, false]
[INFO] [talledLocalContainer] at org.springframework.beans.BeanWrapperImpl.convertIfNecessary(BeanWrapperImpl.java:480)
[INFO] [talledLocalContainer] at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:512)
[INFO] [talledLocalContainer] at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1120)
cause method expect only one boolean value.
UPD
according documentation expected only one class in parameter contextClass

Related

Why filters and filter-mappings (same with Servlets) are defined seperately?

Does defining filter and filter-mapping seperately provide any benefit, while they could be combined in to one space? (Same is true with Servlets)
<filter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
By combining I mean something like below.
<superfilter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<url-pattern>/*</url-pattern>
</superfilter>
It is because by separating <filter> and <filter-mapping> , you can apply the same filter to different URL patterns.
From the comment, you propose why don't just combine them into a single <filter> likes:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<url-patterns>/foo<url-pattern>
<url-patterns>/bar<url-pattern>
<url-patterns>/baz<url-pattern>
</filter>
A filter and url mapping can have more configuration properties such as <dispatcher> (or may be more in the future specification) . Suppose all of above mapping has different settings , your proposed solution may cause a
to have a large structure which look likes:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<url-patterns>
<name>/foo</name>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</url-pattern>
<url-patterns>
<name>/foo</name>
<dispatcher>ERROR</dispatcher>
</url-pattern>
<url-patterns>
<name>/foo</name>
<dispatcher>FORWARD</dispatcher>
</url-pattern>
</filter>
I think it is a matter of preference whether you like flatten or nested structure. I guess that Servlet Spec designer like flatten more and so go for the flatten choice.

Parameters for filter, cleaner way?

I'm writing a filter and want to exclude some directories from that filter.
Right now i've got this:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>filter.aFilter</filter-class>
<init-param>
<param-name>excludePatterns</param-name>
<param-value>/css,/images</param-value>
</init-param>
</filter>
I was wondering if there is a cleaner way than the comma seperated values, which I have to split in my filter. Is there a pure xml way of specifying multiple parameters in the web.xml file for your filter?
Thanks in advance

How to execute 2 related Custom JSP tags with Freemarker without having SimpleSequence incompatible with java.util.List Exception

I am using Freemarker to render my website pages. I have custom Jsp Taglib references in my pages.
I am experiencing "java.lang.ClassCastException: freemarker.template.SimpleSequence incompatible with java.util.List " while executing 2 related tags sequentially.
<#assign mytag=JspTaglibs["/WEB-INF/tld/mytaglib.tld"]/>
<#mytag.query view="home" params="query params">
<#mytag.process maxItems=10 />
</#mytag.query>
The first tag mytag.query calls a query service and puts the item list to the pageContext.
pageContext.setAttribute("items", resultSet.getItems());
The second tag mytag.process reads the list of items from pageContext and processes them.
List allItems = (List)pageContext.getAttribute("items");
I searched a bit on the Internet and saw that Freemarker has the Object Wrapper feature to wrap the objects that are put to pageContext and convert them to SimpleHash, SimpleSequence and SimpleCollection types in order to make them easily accessible by the templating code. This is explained in the http://freemarker.org/docs/pgui_datamodel_objectWrapper.html
I am not allowed to modify the taglib to not to cast "items" to java.util.List.
Is there a way to tell Freemarker not to convert java.util.List to its SimpleSequence object?
Thanks..
Before 2.3.22: Ugh... that's kind of broken really. It should give you back the original object. But looking at the source code, that only works if you are using a pure BeansWrapper as the objectWrapper (or some custom subclass of it that still returns things wrapped into an AdapterTemplateModel or WrapperTemplateModel, so that FreeMarker can extract the original object).
Update (since 2.3.22):
This is fixed in FreeMarker 2.3.22, but as fixing this is not 100% backward compatible (only 99.99% or like...) you have to activate the fix:
<init-param>
<param-name>incompatible_improvements</param-name>
<param-value>2.3.22</param-value>
</init-param>
This works with DefaultObjectWrapper too, so you shouldn't change the object wrapper from its default. DefaultObjectWrapper with 2.3.22 improvements activated pretty much deprecates pure BeansWrapper anyway.
Alternatively, you can activate 2.3.22 fixes only for the object wrapper (as opposed to the whole Configuration above):
<servlet>
...
<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
...
<init-param>
<param-name>object_wrapper</param-name>
<param-value>DefaultObjectWrapper(2.3.22)</param-value>
</init-param>
...
Thanks for the answer.
I think there may be a bug in the FreemarkerServlet because when I tried to set BeansWrapper in the overridden init method like below, it has no effect and it uses the DefaultWrapper.
public void init() throws ServletException {
super.init();
Configuration cfg = getConfiguration();
cfg.setTemplateLoader(new CustomPageTemplateLoader());
cfg.setLocalizedLookup(false);
cfg.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);
}
But when I return the ObjectWrapper in the overridden createObjectWrapper method, it worked.
#Override
protected ObjectWrapper createObjectWrapper() {
return ObjectWrapper.BEANS_WRAPPER;
}

How to use context-param defined in web.xml in dispatcher servlet?

I have a very small concern, to which I couldn't find an answer even after Googling for quite sometime.
How do we use context-param defined in web.xml in the dispatcher servlet?
In my web.xml, I have defined it like this:
<context-param>
<param-name>root.path</param-name>
<param-value>/root</param-value>
</context-param>
I can access it in my Java class using the below lines of code:
String rootPath = sce.getServletContext().getInitParameter("root.path");
However, I don't see a way to use this value in dispatcher servlet. I want to use a variable for /root in the below case than the value itself.
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="file:/root/main.properties" />
Any help is highly appreciated.
Thank you.
Try using
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="file:/#{contextParameters.root.path}/main.properties" />
This will create problem if we give name as "root.path", instead give name as "root_path"

Spring form:select does not render with an option "selected" attribute

I'm stuck in a problem with converters and bindings.
I have a page with a form:select where I bind an list of object with itemValue
<form:select id="id_a" items="${items}" path="builder" itemValue="id" />
I've created 2 converter that convert this bean. One convert from the bean to a string displaying the description the other convert from an id to obtain the bean from the DB.
private Converter<BuilderType, String> getBuilderTypeToStringConverter(){
return new Converter<BuilderType, String>(){
public String convert(BuilderType builder){
return builder.getDescription();
}
};
}
private Converter<String,BuilderType> getStringToBuilderTypeConverter(){
return new Converter<String, BuilderType>(){
public BuilderType convert(String id){
return builderService.findById(new Long(id));
}
};
}
So when I create the bean everything works fine, I see the description in the select field and when submit the form the id gets transformed to to the real bean and put into the model attribute before reaching the controller.
the problems is when I try to update, my select is still correctly populated, but the actual value is not selected. There is no option with the attribute "selected" to initialize correctly the select.
That's really strange because I have an sample application (petclinic) of spring roo that actually with the same type of converters populate correctly the select.
The only way I found to get this working is a bit is to add ".id" to the path :
<form:select id="id_a" items="${items}" path="builder.id" itemValue="id" />
But this way on submit I receive back in the controller a empty "builder" with only the id set, not the comprete object I normaly receive when the correct converter gets invoked.
I really have no idea what could be the difference between the two applications that makes one work and not the other... even the spring library version are the same!
I've found the problem. It seems that in the web.xml of working application there was another filter I was not using, just adding this made everything work fine:
<filter>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
It's really strange because nowhere I've found that this was mandatory or even have little a connection with the spring tags to make them work as expected!
I think you should define equals method for the entity class (BuilderType) and compare the instances by id. Otherwise, form generation is not able to find the current value from the list of items for options.
You can verify this by checking calls to equals when implemented in BuilderType.
I was facing the same problem and was able to solve it with help of this comment and the sample code (AbstractEntity.java) in Spring Data book.

Resources