Spring resolve view name dynamically at runtime based on language - spring

I have a web application where page is displayed in English language. There is a button on header section, clicking on it will change the page to Dutch language. (I will store it in cookie). For this I have to load different JSP, CSS, IMAGE folder. Like, I have below files in folder:
helloPortal.jsp
helloPortal_DU.jsp
I don't want to change each and every Controller class to check for language and set ModelView name accordingly. Instead I will say ModelAndView("helloPortal") and want Spring to do it from InternalResourceViewResolver or some other mechanism.
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean> here
I need another ViewResolver where based on language it Suffix _DU.jsp to file name
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value="_DU.jsp" />
</beans:bean>
I googled for this kind of solution but can't find precise solution. InternalResourceViewResolver is for properties file I believe. Is there a way based on cookie/locale change viewName dynamically.
Please let me know if I haven't explained my issue properly.

You could create custom view resolver. The resolver could check the cookies to figure out it needs to resolve to a Dutch version of the view, modify the view name appropriately and then delegate to normal view resolver that you are currently using.
Implementation could look something like this (I haven't tested it, but it should work):
public class DelegatingLocalizedViewResolver implements ViewResolver {
#Autowired
private HttpServletRequest httpServletRequest;
private ViewResolver delegateViewResolver;
#Override
public View resolveViewName(String viewName, Locale locale) throws Exception {
if (isDutchLanguage()) {
return delegateViewResolver.resolveViewName(viewName + "_DU", locale);
}
return delegateViewResolver.resolveViewName(viewName, locale);
}
private boolean isDutchLanguage() {
Cookie[] cookies = httpServletRequest.getCookies();
// ... do cookie logic to figure out if the request is dutch
return true;
}
public void setDelegateViewResolver(ViewResolver delegateViewResolver) {
this.delegateViewResolver = delegateViewResolver;
}
}
XML config would then look something like this:
<beans:bean id="internalResourceViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<beans:bean class="org.example.DelegatingLocalizedViewResolver">
<beans:property name="delegateViewResolver" ref="internalResourceViewResolver" />
</beans:bean>
PS. You might look into Spring's internationalization / localization support and leverage it instead of storing language in the cookie yourself (especially if you plan to support more languages in the future). Once Spring's localization support is enabled, you will get the country/language information in Locale object in the ViewResolver.

Related

JasperReportsViewResolver and Spring MVC - Set filename

I need help with JasperReports and Spring MVC. I can export everything, but I can't set the filename in the output PDF/Excel that my software exports.
In my dispatcher-servlet I have this bean :
<!-- ViewResolver JasperReports -->
<bean id="jasperViewResolver" class="org.springframework.web.servlet.view.jasperreports.JasperReportsViewResolver">
<property name="prefix" value="classpath:/jasper/" />
<property name="reportDataKey" value="dataSource" />
<property name="suffix" value=".jrxml" />
<property name="viewNames" value="Report_*" />
<property name="viewClass">
<value>org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView</value>
</property>
<property name="order" value="1" />
</bean>
That is the ViewResolver provided by Spring MVC.
I have a function in my BaseController ( abstract controller extended by all the #Controller ) :
protected String exportReport(String reportName, String formatoReport, Model model, JRDataSource dataSource) {
model.addAttribute("dataSource", dataSource);
model.addAttribute("format", formatoReport);
return reportName;
}
So, what I do is simply returning this view name from all my #RequestMapping :
#RequestMapping(..something)
public String functionName(...something else) {
.. do some stuff
return exportReport("Report_docIngresso", EFormatoReport.XLS, model, jrDataSource);
}
This works. The export is perfect, but I didn't find the way to set the filename of the exported pdf/excel, that comes out like the latest part of the URL I called before exporting the report.
I already tried to set in the HttpServletResponse the content-disposition with the filename, but it didn't work.
Thanks a lot,
Marco
Try setting the Content-Disposition HTTP response header:
#RequestMapping(..something)
public String functionName(HttpServletResponse response, ...something else) {
.. do some stuff
String header = "inline; filename=myfile.xls";
response.setHeader("Content-Disposition", header);
return exportReport("Report_docIngresso", EFormatoReport.XLS, model, jrDataSource);
}
(Note I saw just now your concluding comment that you tried without success to set the content disposition header. Well.. I can only say it worked for me in a similar setup.)

default view resolution in spring

I am a spring newbie and have a question about view resolution. I am changing a webapp that I downloaded online and it uses the simple view resolver strategy:
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
and I keep getting 404 errors for view resolution and I am suspecting that it uses some sort of rewriting / filtering mechanism. Is there a log that I can view in tomcat / Spring class that I can override in order to understand what file is Spring trying to look for when resolving an incoming request?
I understand the operation of InternalResourceViewResolver which strips file name extensions. But what if the request does not have an extension? For instance:
#RequestMapping("/foo")
protected ModelMap render() { return new ModelMap(); }
Then what is the view name that will be resolved to in this case?
See this link for log4j integration
Spring-mvc doesn't use any file for request handling, it uses controllers and requestmapping to map the request to a controller and respective method if any.
The InternalResourceViewResolver that you have written Resolves “view name” that is returned from the controller class to a JSP page residing in /WEB-INF/view/ directory.
an example
#Controller
public class SimpleController{
#RequestMapping("/home")
public String homeMapper(Model model) {
return "home";
}
}
here homeMapper method will be called if you try to access "home" and as it returns home the relative jsp to be rendered is "home.jsp" should be present in /WEB-INF/view/
For more information see spring mvc reference or any tutorial.

Mapping jsp for a url in Spring 3 without using controller

How to map a jsp for a url in spring 3 without requestmapping to any controller.
eg. /login to login.jsp without having any userdefined controller in between
Like URLFILENAMECONTROLLER in spring2.5, similarly in spring 3
You can use this paragraph from Spring docs for reference. In short, you can do in several ways one of them with view-controller annotation. The other way when using Java Config:
#EnableWebMvc
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
Where the code maps request for /login to /WEB-INF/views/login.jsp view if the view resolver is defined as in the previous answer.
You can do this:
<mvc:view-controller path="/login" view-name="login"/>
Assuming that you have defined a ViewResolver, something like this:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
This will resolve a request to /login to a /WEB-INF/views/login.jsp page

spring security : how to apply #PreAuthorize to SwitchUserFilter

I have to check whether the user has the permission to switch user, on the basis of his userId. In my security xml, inside the <http> element, I am specifying a custom filter :
<custom-filter after="FILTER_SECURITY_INTERCEPTOR" ref="switchUserProcessingFilter"/>
<beans:bean id="switchUserProcessingFilter" class="com.something.MySwitchUserFilter">
<beans:property name="userDetailsService" ref="userServices" />
<beans:property name="switchUserUrl" value="/admin/switchUser" />
<beans:property name="exitUserUrl" value="/exitUser" />
<beans:property name="successHandler" ref="userSwitchSuccessHandler"></beans:property>
</beans:bean>
In MySwitchUserFilter, I override only a single method :
#Override
#PreAuthorize("canISwitchToThisUser(#{request.getAttribute('userId')}")
protected Authentication attemptSwitchUser(HttpServletRequest request) throws AuthenticationException {
return super.attemptSwitchUser(request);
}
#PreAuthorize is working at other locations, but i wonder why its not working here. Note that I am also passing an request parameter 'userId' along with the customary 'j_username'. Note that I am able to switch user, just that the annotation is not being processed.

spring 3 my converter is not used

...but registered
Using Spring 3
I have two converters registered as follows:
<beans:bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<beans:property name="converters">
<beans:list>
<beans:bean class="mypackage.CalendarToStringConverter" />
<beans:bean class="mypackage.StringToCalendarConverter" />
</beans:list>
</beans:property>
</beans:bean>
The converters look like this:
public class StringToCalendarConverter implements Converter< String, Calendar > {
public Calendar convert( String value ) {
return Calendar.getInstance();
}
}
public class CalendarToStringConverter implements Converter< Calendar, String > {
public String convert( Calendar arg0 ) {
return "23.10.1985";
}
}
The problem is that they are not used during conversion in post and get requests.
What am I doing wrong?
What do I havt to do to get this working?
THX!
Are you using <mvc:annotation-driven> and if so, are you pointing to conversionService in the conversion-service attribute?
Here's the converters configuration that works for me. The differences you might try changing:
I pass in a set instead of a list. (setConverters takes a Set parameter)
I use FormattingConversionServiceFactoryBean instead of ConversionServiceFactoryBean. (Should not matter)
My converters are defined as top level beans and referenced. (Also should not matter)
Hopefully one of this will fix your problem.
<util:set id="converters" >
<ref bean="userDao" />
<ref bean="orderDao" />
<util:set>
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters" ref="converters"/>
</bean>

Resources