Show properties values in views in Spring MVC - spring

I'm struggling to make something veeery simple work. Everything I really need to do is to write a property value in a view, i.e.:
<!DOCTYPE html>
<head>
...
<base href="${properties.config.baseurl}" />
...
</head>
<body>
...
</body>
</html>
My Spring MVC configuration (relevant bit):
<bean id="properties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list><value>/WEB-INF/config.properties</value></list>
</property>
</bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
<property name="exposedContextBeanNames">
<list><value>properties</value></list>
</property>
</bean>
/WEB-INF/config.properties file:
config.baseurl = http://localhost:8080/
The view doesn't display anything at all (i.e. <base href="" />), can anyone explain to me why?
Thank you.

You need to use
${properties['config.baseurl']}
rather than
${properties.config.baseurl}
Otherwise it will try to navigate config.baseurl like a bean path, rather than as a string literal.

Related

Spring MVC dispatcher-servlet returns a 404 Error and not Welcome page

I have searched all the answers to 404 error pages about Spring MVC dispatcher, and I cannot find the answer to my issue.
I am also having an issue with Spring framework 4.1.6 as it no longer has the SimpleForm for forms for log in.
I understand that I need Maven to use the lastest Spring Security log in, which I plan to create a new Spring/Maven project and import this application into.
Just really want to know I have flow control going on before I export it to the Spring/Maven project. So any help with why my Welcome screen is not being found ....is much appreciated.
Heres my web.xml
enter code here<servlet>
<servlet-name>springMVCpizza</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/springMVCpizza-servletConfig.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVCpizza</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>Welcome.jsp</welcome-file>
</welcome-file-list>
Here is my dispatcher-servlet:
<mvc:annotation-driven />
<context:component-scan base-package="com.pizza.controllers" />
<bean id="urlMapping" class="org.springframework.web.servlet.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="Welcome.jsp">welcomePageController</prop>
</props>
</property>
</bean>
<bean id= "welcomePageController" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="LogIn" ref="LoginFormController">
</property>
</bean>
<bean id="loginFormController" class="com.pizza.controllers.loginFormController"></bean>
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang"/></bean>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor"/>
</list>
</property>
<property name="urlMap">
<map>
<entry key="/LogIn.jsp">
<ref bean="loginFormController"/>
</entry>
</map>
</property>
</bean>
<bean id="loginFormController" class="com.pizza.web.LoginFormController">
`enter code here`<property name="commandName"><value>login</value></property>
`enter code here` <property name="commandClass"><value>com.pizza.web.LogIn</value></property>
</bean>
<bean id="loginValidator" class="com.pizza.web.LoginValidator"/>
<bean id="loginFormController" class="com.pizza.controllers.LoginFormController">
<property name="sessionForm"><value>false</value></property>
<property name="commandName"><value>login</value></property>
<property name="commandClass"><value>com.pizza.web.LogIn</value> </property>
<property name="validator"><ref bean="loginValidator"/></property>
<property name="formView"><value>LogIn.jsp</value></property>
<property name="successView"><value>success</value></property>
<property name="urlMap">
<map>
<entry key="/LogIn.jsp">
<ref bean="loginFormController"/>
</entry>
</map>
</property>
</bean>
<bean id="LocaleChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="hl"/>
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"/>
<bean id="ViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" >
<!-- maximum file size in bytes -->
<property name ="maxUploadSize" value="100000"/>
</bean>
Heres the Welcome jsp:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome to the Pizza Store</title>
</head>
<body bgcolor="#EEEEEE">
<center>
<h1>Welcome to the Pizza Store!</h1>
Sign In
<p>Or </p> Create Account
</center>
</body>
</html>

How to apply spring-mobile-device interceptor to welcome-file?

I,m using SpringMVC and i have different design for each device type Desktop/Tablet/Mobile
<!-- START of MOBILE -->
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean
class="org.springframework.mobile.device.site.SitePreferenceWebArgumentResolver" />
<bean class="org.springframework.mobile.device.DeviceWebArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
<mvc:interceptors>
<!-- Resolve the device which has generated the request -->
<bean
class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor" />
<!-- User's site preference -->
<bean
class="org.springframework.mobile.device.site.SitePreferenceHandlerInterceptor" />
<!-- Redirects users to the device specific site -->
<bean
class="org.springframework.mobile.device.switcher.SiteSwitcherHandlerInterceptor"
factory-method="urlPath">
<constructor-arg value="/m" />
<constructor-arg value="/t" />
<constructor-arg value="/" />
</bean>
</mvc:interceptors>
<!-- Device aware view resolving -->
<bean id="liteDeviceDelegatingViewResolver"
class="org.springframework.mobile.device.view.LiteDeviceDelegatingViewResolver">
<constructor-arg>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</constructor-arg>
<property name="mobilePrefix" value="m/" />
<property name="tabletPrefix" value="t/" />
<property name="normalPrefix" value="/" />
<property name="enableFallback" value="true" />
</bean>
<!-- END of MOBILE -->
I have /m /t and / folders views in /WEB-INF/views/ folder for each device and all works fine, but this configuration not applies only to welcome page, ie I open page with phone and see desktop-version of login.jsp (/WEB_INF/views/login.jsp but not /WEB-INF/views/m/login.jsp)
<welcome-file-list>
<welcome-file>/WEB-INF/views/login.jsp</welcome-file>
</welcome-file-list>
What I have to do to change to fix it.
Just don't specify page... and handle 'home' request by controller :)
modify your web.xml to:
<welcome-file-list>
<welcome-file></welcome-file>
</welcome-file-list>
or just remove tag
now, your HomeController should look like this:
#Controller
public class HomeController {
#RequestMapping("/")
public String home(SitePreference sitePreference, Model model) {
return "login";
}
}
hope this helps.

Internationalization with Spring and JSP

I am facing trouble in JSP spring internationalization. My dispatcherServlet.xml contains:
<bean id="localeResolver"
class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="en" />
</bean>
<bean id="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="language" />
</bean>
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" >
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor" />
</list>
</property>
</bean>
<!-- Application Message Bundle -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages/messages" />
<property name="cacheSeconds" value="0" />
<property name="defaultEncoding" value="UTF-8"/>
</bean>
and my jsp contains
<html>
<head>
<title>Admin</title>
</head>
<body>
<a href=<c:url value="/j_spring_security_logout"/>>Logout</a><br/>
Language : English|
Chinese
<h1>
<spring:message code="only.Admin.allowed.here" text="default text" />
</h1>
Current Locale : ${pageContext.response.locale}
</body>
</html>
The default EN language works fine, but I am not able to change the language into Chinese while clicking on Chinese option. The address bar URL changes to /admin?language=en to /admin? language=zh_CN but displays no result.
Thanks in advance.

Access to freemarker variables in html file using FreeMarkerViewResolver

I configured my web application like this link http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch17s04.html
My context
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/" />
<property name="freemarkerSettings">
<props>
<prop key="tag_syntax">square_bracket</prop>
<prop key="auto_import">spring.ftl as spring, echannels.ftl as echannels
</prop>
<prop key="template_update_delay">2147483647</prop>
</props>
</property>
</bean>
<bean id="htmlViewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="contentType" value="text/html;charset=ISO-8859-1" />
<property name="cache" value="${viewResolver.html.cache}" />
<property name="prefix" value="html/" />
<property name="suffix" value=".html" />
</bean>
I use spring-webflow to link all my page html.
In my page html, i can access to conversion scope variables by using ${name_variable}.
My question is: how could i access to FreeMarker variable "foo" in my html if i defined it in my context:
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/" />
<property name="freemarkerVariables">
<map>
<entry key="foo" value="foo" />
</map>
</property>
</bean>
Example of my HTML
<html>
<head>
<title>Welcome</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
</head>
<body>
<h1>Welcome ${issuerId}</h1>
<form action="?execution=${flowExecutionKey}" method="post" name="defineFeeForm">
<input type="submit" name="_eventId_next" value="Next" /> <br/>
</form>
</body>
I can access to ${issuerId} because i have request.setConversationScope("issuerId", "1234") but i want to access also to foo freemarker variable but when i use ${foo}, i got Expression foo is undefined.
Any ideas?
Thanks to #ddekany , it's worked, there're nothing wrong in my configuration. I confused before. :). Yes, foo is visible simply as ${foo}.
Another remark, if i want to add new variables during running of my application, i can use
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("foo2", "foo2");
freeMarkerConfigurer.getConfiguration().setAllSharedVariables(new SimpleHash(variables, freeMarkerConfigurer.getConfiguration().getObjectWrapper()));
and i can access with ${foo2}.
Thanks again. It's done now.

How to use multiple ViewResolvers in Spring?

I am working on a web app where I have most of my pages making use of apache tiles (2.1.2), but a few of them need to just be plain jsps.
I am having a problem in that both an InternalResourceViewResolver and a UrlBasedViewResolver will try to resolve the view no matter what, so that no matter which ordering I use, it will either fail on the plain JSP pages, or on the tiles pages.
Here is the config:
<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
<property name="order" value="0"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
<property name="order" value="1"/>
</bean>
To make it more clear what I am trying to do, I need to be able to have view states like this:
<view-state id="someState" view="/someDir/foo"><!--render foo.jsp -->
<transition on="foo" to="bar"/>
</view-state>
<view-state id="someState" view="something.core"><!--render tile defintion named 'something.core' -->
<transition on="foo" to="bar"/>
</view-state>
Does anyone know how to configure things so that I can get it to render tiles definitions and plain jsps?
As you say, you cannot chain these together. The javadoc for both states clearly that they must both be at the end of the resolver chain.
I suggest that if you really need to use these togather, then you write a simple custom implementation of ViewResolver which takes the view name, and decides which of your two "real" view resolvers to delegate to. This assumes that you can tell which resolver to call based on the view name.
So you'd define a custom ViewResolver like this:
public class MyViewResolver implements ViewResolver {
private ViewResolver tilesResolver;
private ViewResolver jspResolver;
public void setJspResolver(ViewResolver jspResolver) {
this.jspResolver = jspResolver;
}
public void setTilesResolver(ViewResolver tilesResolver) {
this.tilesResolver = tilesResolver;
}
public View resolveViewName(String viewName, Locale locale) throws Exception {
if (isTilesView(viewName)) {
return tilesResolver.resolveViewName(viewName, locale);
} else {
return jspResolver.resolveViewName(viewName, locale);
}
}
private boolean isTilesView(String viewName) {
.....
}
}
You'd need to implement the isTilesView method to decide which resolver to delegate to.
In the XML config, define this new view resolver, and make sure it appears before the other ones.
<bean class="MyViewResolver">
<property name="tilesResolver" ref="tilesViewResolver"/>
<property name="jspResolver" ref="viewResolver"/>
</bean>
I've just solved the same problem by splitting the *-servlet.xml config file in two; in my case the main application uses Tiles, but I want QUnit tests to be simple JSPs.
app-servlet.xml contains only the Tiles view resolver, tests-servlet.xml only contains the JSP view resolver and web.xml mappings are dispatching requests to the correct servlet basing on the URL.
<servlet-mapping>
<servlet-name>app</servlet-name> <!-- will reach app-servlet.xml -->
<url-pattern>/foo</url-pattern> <!-- will use "foo" Tile -->
<url-pattern>/bar</url-pattern> <!-- will use "bar" Tile -->
</servlet-mapping>
<servlet-mapping>
<servlet-name>tests</servlet-name> <!-- will reach tests-servlet.xml -->
<url-pattern>/foo-test</url-pattern> <!-- will use foo-test.jsp -->
<url-pattern>/bar-test</url-pattern> <!-- will use bar-test.jsp -->
</servlet-mapping>
It looks like you're on the right track, but the thing to bear in mind is that some view resolvers behave as if they have always resolved the view. You need to make sure to put such resolvers last in your ordering. I believe the Tiles view is one such.
Edit: whoops... yes, the other poster is correct, both of these resolvers will do 'always match' so you can't use them both in a chain. Another alterative would be to try to extend the TilesView to do a simple JSP render if it cant find a configured tile view.
Yes you can use any number of view resolver in your your project.
So you can use both 'tiles View resolver' and 'Internal view resolver' in same project. .
you have to configure a ContentNegotiatingViewResolver . .
and give order value in your view resolvers.
<property name="order" value="int Value here" />
like I have given tiles view resolver 2 and internalviewresolver 3. .It will first check in tiles definitions if a view is not found in tiles it will be checked in InternaiViewResolver
here is some configurations that works for me.
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="html" value="text/html" />
</map>
</property>
<property name="parameterName" value="accept"></property>
<property name="favorParameter" value="true"></property>
<property name="defaultContentType" value="text/html"></property>
<property name="viewResolvers">
<list>
<ref bean="tilesViewResolver" />
<ref bean="internalViewResolver" />
</list>
</property>
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
<property name="ignoreAcceptHeader" value="true" />
</bean>
<!-- Configures the Tiles layout system -->
<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"
id="tilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/layouts/layouts.xml</value>
<!-- Scan views directory for Tiles configurations -->
<value>/WEB-INF/views/**/views.xml</value>
</list>
</property>
</bean>
<bean id="tilesViewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver"
p:viewClass="org.springframework.web.servlet.view.tiles2.TilesView">
<property name="order" value="3" />
</bean>
<bean id="internalViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="2" />
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
I resolved this issue by simply adding tiles definition for plain jsp's layout, like this:
<definition name="plain-jsp.layout" template="/WEB-INF/layouts/plainJsp.jspx" >
<put-attribute name="content" value=""/>
</definition>
Then you just can use this layout as template for including your simple jsp files.
<definition name="catalog/details" extends="plain-jsp.layout">
<put-attribute name="content" value="/WEB-INF/views/catalog/details.jspx"/>
</definition>
And layout template file:
<html xmlns:tiles="http://tiles.apache.org/tags-tiles"
xmlns:jsp="http://java.sun.com/JSP/Page" version="2.0">
<jsp:output doctype-root-element="HTML"/>
<jsp:directive.page contentType="text/html;charset=UTF-8" />
<jsp:directive.page pageEncoding="UTF-8" />
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=8" />
</head>
<body>
<div id="content">
<tiles:insertAttribute name="content"/>
</div>
</body>
</html>

Resources