Spring MVC UrlBasedViewResolver custom view file - java

I have a view resolver:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
And a Controller:
#RequestMapping(value = "/home", method = RequestMethod.GET)
public String loadPage(HttpServletRequest request,HttpServletResponse response, HttpSession session,ModelMap modelMap ) {
String langlayout = "eng";
UrlBasedViewResolver urlResolver = new UrlBasedViewResolver();
urlResolver.setPrefix("/WEB-INF/views/"+langlayout);
urlResolver.setSuffix(".jsp");
return "home/list.jsp";
}
after clicking in the jsp its still looking in the WEB-INF/views/home/list instead of WEB-INF/views/eng/home/list
How can I define custom view page

Finally got the solution for my question
<!-- Declare a view resolver -->
<bean class="com.project.controller.AppPortalViewResolver">
<property name="viewResolver" ref="viewResolver" />
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
AppPortalViewResolver.class
public class AppPortalViewResolver implements ViewResolver {
private ViewResolver viewResolver;
public void setViewResolver(ViewResolver viewResolver) {
this.viewResolver = viewResolver;
}
#Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
/* do your logic to change the view name */
viewName = "ur_folder_structure";
return viewResolver.resolveViewName(viewName, locale);
}

#RequestMapping(value = "/home", method = RequestMethod.GET)
public String loadPage(HttpServletRequest request,HttpServletResponse response, HttpSession session,ModelMap modelMap ) {
String langlayout = "eng";
return langlayout+"/home/list.jsp";
}

Related

Bean Velocity Config from xml to java

I'd like convert xml bean with velocity to config java class
This is old xml config:
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF/view/"/>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".html"/>
<property name="exposeSpringMacroHelpers" value="true"/>
</bean>
And this is new java class config:
#Bean
public ViewResolver viewResolver()
{
VelocityViewResolver viewResolver= new VelocityViewResolver();
viewResolver.setPrefix("");
viewResolver.setSuffix(".html");
viewResolver.setCache(true);
return viewResolver;
}
#Bean
public VelocityConfigurer velocityConfig()
{
VelocityConfigurer velocityConfig = new VelocityConfigurer();
// ???????????
return velocityConfig;
}
How to do it?
VelocityConfig extends VelocityEngineFactory, so you can use the method setResourceLoaderPath:
velocityConfig.setResourceLoaderPath("/WEB-INF/View/");

Spring Internalization to print country in the right language

When I want to access at the page with address?language=en or language=fr, I use the following controller :
public class AddressController {
private static Logger logger = Logger.getLogger(AddressController.class);
#RequestMapping(value="/address",method=RequestMethod.GET)
public ModelAndView init(HttpServletRequest r){
ApplicationContext context = new FileSystemXmlApplicationContext("/WEB-INF/spring-servlet.xml");
SessionLocaleResolver resolver = (SessionLocaleResolver) context.getBean("localeResolver");
String[] locales = resolver.resolveLocale(r).getISOCountries();
//String[] locales = Locale.getISOCountries();
Map<String,String> countryList = new HashMap<String,String>();
for(String countryCode : locales){
Locale loc = new Locale(resolver.resolveLocale(r).getLanguage(),countryCode);
countryList.put(loc.getDisplayCountry(), loc.getDisplayCountry());
logger.info(loc.getDisplayCountry());
}
Map<String,String> tree = new TreeMap<String,String>(countryList);
ModelAndView modelAndView = new ModelAndView("address");
modelAndView.addObject("address",new Address());
modelAndView.addObject("countriesList", tree);
return modelAndView;
}
}
spring-servlet.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.application.myGoogleAppEngine.controller" />
<!-- <mvc:annotation-driven /> -->
<!-- Register the messageBundle.properties -->
<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource">
<property value="classpath:MessageBundle,classpath:Messages" name="basenames" />
<property value="UTF-8" name="defaultEncoding" />
</bean>
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
<property name="defaultLocale" value="fr" />
</bean>
<bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="language" />
</bean>
<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<ref bean="localeChangeInterceptor" />
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property value="org.springframework.web.servlet.view.JstlView" name="viewClass" />
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
When I access to the controller by calling /address?language=en or /address?language=fr, I notice with the Logger in the loop 'for(String countryCode : locales)' that every country names print in french and not in english.
Do you have any solutions ?
Why don't you use the request parameter 'language' to create the the countries list? The SessionLocaleProvider will always return the same language as long as the session stays alive.
The following code sample takes the parameter to construct a list of localized country names:
#Controller
public class CountriesController {
#RequestMapping(value="/countries", method=RequestMethod.GET)
public ModelAndView getCountries(#RequestParam("language") String language){
List<String> countries = new ArrayList<>();
Locale locale = new Locale(language);
String[] isoCountries = Locale.getISOCountries();
for (String isoCountry : isoCountries) {
Locale countryLoc = new Locale(language, isoCountry);
String name = countryLoc.getDisplayCountry(locale);
if (!"".equals(name)) {
countries.add(name);
}
}
ModelAndView model = new ModelAndView("countries");
model.addObject("model", countries);
return model;
}
}

Spring MVC & Freemarker/Velocity

I've got a problem with Freemarker's and Velocity's view resolver (not running at same moment) - both of them don't see Spring's session beans. Spring's InternalResourceViewResolver works good.
Some code:
<context:component-scan base-package="com.revicostudio.web" />
<mvc:annotation-driven />
<bean id="userSession" class="com.revicostudio.web.session.UserSession" scope="session" />
<bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<property name="resourceLoaderPath" value="/WEB-INF/jsp/" />
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityLayoutViewResolver">
<property name="cache" value="true" />
<property name="prefix" value="" />
<property name="layoutUrl" value="layout.jsp"/>
<property name="suffix" value=".jsp" />
<property name="exposeSessionAttributes" value="true" />
<property name="exposeRequestAttributes" value="true" />
<property name="requestContextAttribute" value="rc" />
</bean>
In jsp:
${userSession}<br /> <!-- Null if Freemarker's view resolver active, session object if Spring's resolver active -->
${error}<br /> <!-- Normal request attribute, put to map, that works good in both resolvers -->
IndexController:
#Controller
#RequestMapping("/index")
public class IndexController {
#RequestMapping(method=RequestMethod.GET)
public String getIndex(Model model) {
return "index";
}
#ModelAttribute("userRegisterCredentials")
public UserRegisterCredentials getUserRegisterCredentials() {
return new UserRegisterCredentials();
}
#ModelAttribute("userLoginCredentials")
public UserLoginCredentials getUserLoginCredentials() {
return new UserLoginCredentials();
}
}
1.You should annotate controller to point out which model attribute should be exposed in a session
2.In freemarker, access to session attrs is done by a freemarker session wrapper.
Short example below, based on Your code:
#Controller
#SessionAttributes("userRegisterCredentials")
#RequestMapping("/index")
public class IndexController {
#RequestMapping(method=RequestMethod.GET)
public String getIndex(Model model) {
return "index";
}
#ModelAttribute("userRegisterCredentials")
public UserRegisterCredentials getUserRegisterCredentials() {
return new UserRegisterCredentials();
}
}
On the ftl side:${Session.userRegisterCredentials.someStringField}

Spring MVC & Freemarker session attribute not exposed

I've got a problem with Freemarker's viewResolver with Spring - session attributes are not exposed to view, as it is in Spring's InternalResourceViewResolver.
Now, important part is: when I change from Spring's resolver to Freemarker's one, session attribute is not passed, it's null. When Spring's resolver is working, session is passed.
My code:
dispatcher-servlet.xml:
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<bean id="userSession" class="com.revicostudio.web.session.UserSession" scope="session">
</bean>
<context:component-scan base-package="com.revicostudio.web" />
<mvc:annotation-driven />
<!--
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/ftl/"/>
<property name="freemarkerVariables">
<map>
<entry key="xml_escape" value-ref="fmXmlEscape"/>
</map>
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".jsp"/>
<property name="exposeSpringMacroHelpers" value="true"/>
<property name="exposeRequestAttributes" value="true"/>
<property name="allowRequestOverride" value="false" />
<property name="exposeSessionAttributes" value="true"/>
<property name="allowSessionOverride" value="false" />
<property name="exposePathVariables" value="true"/>
</bean>
<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape"/>-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/ftl/" />
<property name="suffix" value=".jsp" />
<property name="exposeContextBeansAsAttributes" value="true" />
</bean>
</beans>
LoginController.java:
#Controller
#RequestMapping("/login")
#SessionAttributes("userSession")
public class LoginController {
#Autowired
private UsersDatabaseService usersDatabaseService;
#RequestMapping(method = RequestMethod.POST)
public String login(
#ModelAttribute UserLoginCredentials userLoginCredentials,
UserSession userSession,
final RedirectAttributes redirectAttributes)
{
int failedLoginAttempts = userSession.getFailedLoginAttempts();
if (failedLoginAttempts < LoginConfig.maxLoginTries ||
System.currentTimeMillis()-userSession.getFailedLoginsWaitTimeStart() > LoginConfig.failedLoginsWaitMinutes*60*1000) {
if (usersDatabaseService.isValidPassword(userLoginCredentials.getUsername(), userLoginCredentials.getPassword())) {
userSession.setUser(usersDatabaseService.getUser(userLoginCredentials.getUsername()));
userSession.setFailedLoginsWaitTimeStart(System.currentTimeMillis());
}
else {
failedLoginAttempts++;
if (failedLoginAttempts == LoginConfig.maxLoginTries) {
redirectAttributes.addFlashAttribute("error",
"You've entered invalid username or password more than "
+ LoginConfig.maxLoginTries + " times. Try again in "
+ LoginConfig.failedLoginsWaitMinutes +" minutes.");
}
else {
redirectAttributes.addFlashAttribute("error", "Invalid username or password");
userSession.setFailedLoginAttempts(failedLoginAttempts);
System.out.println(failedLoginAttempts);
}
}
}
else {
redirectAttributes.addFlashAttribute("error",
"You've entered invalid username or password more than "
+ LoginConfig.maxLoginTries + " times. Try again in "
+ LoginConfig.failedLoginsWaitMinutes +" minutes.");
}
return "redirect:/";
}
}
IndexController:
#Controller
#RequestMapping("/index")
public class IndexController {
#RequestMapping(method=RequestMethod.GET)
public String getIndex(Model model) {
return "index";
}
#ModelAttribute("userRegisterCredentials")
public UserRegisterCredentials getUserRegisterCredentials() {
return new UserRegisterCredentials();
}
#ModelAttribute("userLoginCredentials")
public UserLoginCredentials getUserLoginCredentials() {
return new UserLoginCredentials();
}
}
index.jsp:
<body>
<!-- Code for Freemarker -->
<#if error??>
${error}
</#if>
<#if userSession??>
${userSession}
</#if>
<#if !(userSession??)>
b
</#if>
<!-- Code for JSTL -->
${userSession}
You have a session problem because of that redirectAttributes.addFlashAttribute(). which means addFlashAttribute actually stores the attributes in a flashmap (which is internally maintained in the users session and removed once the next redirected request gets fulfilled),
Just try without redirectAttributes.addFlashAttribute() you will get session.
May be this will help you

Spring MVC - marshalling an XML parameter to object (JAXB) in a multipart request

I created a file upload service using Spring MVC with apache commons multipart resolver support which specifies that a file should be attached as part of a multipart HTTP Post request. The request also contains a parameter containing an XML string with meta-data about the object. The XML can be marshalled using JAXB.
Other services that are not multipart handle the marshalling transparently, e.g.:
#RequestMapping(value = "/register", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public ModelAndView createUser(#RequestBody CreateUserDTO createUserDTO) throws Exception {
UserDTO user = userService.createUser(createUserDTO);
return createModelAndView(user);
}
Here CreateUserDTO is a JAXB annotated object which is automatically marshalled.
In the multipart case I'd like to have the same transparency. Ideally I would like to do the following:
RequestMapping(method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public ModelAndView createAttachment(#RequestParam AttachmentDTO attachment,
HttpServletRequest request) throws Exception {
final MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
AttachmentDTO attachment = null;
final MultipartFile dataFile = multipartRequest.getFile("data");
AttachmentDTO createdAttachment = attachmentService.createAttachment(attachment,
dataFile);
return createModelAndView(createdAttachment);
}
Unfortunately this does not work. I am able to bind the attachment parameter as String, but the automatic marshalling does not work. My work around is to manually do the marshalling like the following, but I don't like this approach (especially since the parameter may be specified both in JSON and XML form):
#Autowired
private Jaxb2Marshaller jaxb2Marshaller;
#Autowired
private ObjectMapper jacksonMapper;
#RequestMapping(method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
public ModelAndView createAttachment(#RequestParam(ATTACHMENT_PARAMETER) String attachmentString,
final HttpServletRequest request) throws Exception {
final MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
AttachmentDTO attachment = null;
try {
attachment = (AttachmentDTO)jaxb2Marshaller.unmarshal(new StreamSource(new StringReader(attachmentString)));
} catch (XmlMappingException e) {
//Try JSON
try {
attachment = jacksonMapper.readValue(attachmentString, AttachmentDTO.class);
} catch (IOException e1) {
throw new BadRequestException("Could not interpret attachment parameter, both JSON and XML parsing failed");
}
}
Does anyone have a better suggestion for resolving this issue?
For completeness I also specify the relevant Spring config here:
<bean id="viewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1"/>
<property name="favorPathExtension" value="true"/>
<property name="ignoreAcceptHeader" value="false"/>
<property name="mediaTypes">
<map>
<entry key="xml" value="application/xml"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="modelKey" value="object"/>
<property name="marshaller" ref="jaxbMarshaller"/>
</bean>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="objectMapper" ref="jaxbJacksonObjectMapper"/>
</bean>
</list>
</property>
</bean>
<!--Use JAXB OXM marshaller to marshall/unmarshall following class-->
<bean id="jaxbMarshaller"
class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="com.behindmedia.btfd.model.dto"/>
</bean>
<bean id="jaxbJacksonObjectMapper" class="org.codehaus.jackson.map.ObjectMapper"/>
<!-- allows for integration of file upload functionality -->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
<property name="maxUploadSize" value="100000000"/>
</bean>

Categories