Spring Mobile inside AuthenticationFailureHandler not found - spring

I am development success and failure handlers in Spring Security.
Depends device type I must show one html view or send one json response. To this purpose I use Spring Mobile, but when I create Device object with HtttpServletRequest not found. Some idea?
web.xml
<filter>
<filter-name>deviceResolverRequestFilter</filter-name>
<filter-class>org.springframework.mobile.device.DeviceResolverRequestFilter</filter-class>
</filter>
ApplicationContext.xml
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="org.springframework.mobile.device.DeviceWebArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
Class
public class AuthFailureHandler implements AuthenticationFailureHandler{
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException ae) throws IOException, ServletException {
Device device = DeviceUtils.getCurrentDevice(request);
if(device.isNormal()){
response.sendRedirect(response.encodeRedirectURL("./userNoAuth"));
} else {
response.sendRedirect(response.encodeRedirectURL("./rest/userNoAuth"));
}
}
}
Error
java.lang.NullPointerException at com.myapp.security.handler.AuthFailureHandler.onAuthenticationFailure(AuthFailureHandler.java:19)
UPDATE:
I am change .getCurrentDevice(HttpServletRequest) method to getRequiredCurrentDevice(HttpServletRequest).
Now I get this error.
java.lang.IllegalStateException: No currenet device is set in this request and one is required - have you configured a DeviceResolvingHandlerInterceptor?

Verify your web.xml contains a filter-mapping for the deviceResolverRequestFilter. The following is a working example from the Spring Mobile Samples repository. Hope that helps!
https://github.com/SpringSource/spring-mobile-samples/tree/master/lite-device-resolver-xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Use the DeviceResolverRequestFilter OR the DeviceResolverHandlerInterceptor in the servlet-context.xml -->
<filter>
<filter-name>deviceResolverRequestFilter</filter-name>
<filter-class>org.springframework.mobile.device.DeviceResolverRequestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>deviceResolverRequestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

Related

How to setup uploaded file's path in Spring MVC

I want to have uploaded file to be stored in my specified folder like this:
/SpringMVC/tmp
but it is stored into this folder:
C:\Users\zhanzhex\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\SpringMVC\tmp\spittr\uploads
this is my controller method for processing uploading:
#RequestMapping(value="/register", method=RequestMethod.POST)
public String processRegistration(
#RequestPart(name="profilePicture",required=false) Part profilePicture,
#Valid Spitter spitter, Errors errors) throws IOException
{
if (errors.hasErrors())
{
System.out.println("find errors");
return "registerForm";
}
profilePicture.write(spitter.getId() + "_profile." + profilePicture.getSubmittedFileName().substring(profilePicture.getSubmittedFileName().indexOf(".") + 1));
spitterRespository.saveSpitter(spitter);
return "redirect:/spitter/"+spitter.getId();
}
I just configure the temp folder for file upload (/tmp/spittr/uploads) in my web.xml, but I want to change the folder while calling write method within controller method, seems I can't. if I calling the write method like this:
profilePicture.write("/tmp/spittr/uploads/" + spitter.getId() + "_profile.jpg");
it will throw IOException to indicate that the folder is not existing:
C:\Users\zhanzhex\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\localhost\SpringMVC\tmp\spittr\uploads\tmp\spittr\uploads
so, I have to remove prefix "/tmp/spittr/uploads" when I calling profilePicture.write method.
see my web.xml below:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>SpringMVCs</display-name>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>spittr.config.RootConfig</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>spittrAppServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>spittr.config.WebConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<multipart-config>
<location>/tmp/spittr/uploads</location>
<max-file-size>2097152</max-file-size>
<max-request-size>4194304</max-request-size>
</multipart-config>
</servlet>
<servlet-mapping>
<servlet-name>spittrAppServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
I don't know why, can I change the destination folder setting? How to do that?
Instead of Part you can use MultipartFile or FilePart interfaces
#RequestPart(name="profilePicture",required=false) MultipartFile profilePicture
These interfaces expose .transferTo() function to copy data to file that you can use like
profilePicture.transferTo(new File("/path/to/file"));

Spring Filter not getting invoked

I added a CORS filter to my application, but it does not seem to be executed (no prints).
The filter is this:
#Component
public class SimpleCORSFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest req,
HttpServletResponse res, FilterChain filterChain)
throws ServletException, IOException {
System.out.println("EXECUTING");
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods",
"POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"X-Requested-With,Content-Type");
filterChain.doFilter(req, res);
}
}
Then I added the filter in the web.xml, which is the following:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>rest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>simpleCORSFilter</filter-name>
<filter-class>org.lh.gestorepazienti.web.SimpleCORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>simpleCORSFilter</filter-name>
<servlet-name>rest</servlet-name>
</filter-mapping>
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Where could it be possibly wrong?
First, it is uncommon to name the Root Spring Container xml file servlet-context.xml. This name is normally used for the DispatcherServlet configuration when using spring-mvc. You'd better use applicationContext.xml.
But anyway, you should use a DelegatingProxyFilter to allow proper initialization of the spring filter :
<filter>
<filter-name>simpleCORSFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
The DelegatingProxyFilter will search in root context a bean named simpleCORSFilter and will delegate the doFilter method to it.
You can use URLMapping as well

Custom HTTP Error 404 - Annotation based setting Spring 3.2

Is it possible to implement annotation based custom HTTP 404 error page using Spring 3.2.1?
I looked for ways in various forums but couldn't find any clear answer.
I also tried configuring using web.xml but it is not working when I access unmapped URL.
Any help please?
Log output
7259 [DEBUG] org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'spring-test' processing GET request for [/spring-test/ss]
7261 [DEBUG] org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /ss
7262 [DEBUG] org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Did not find handler method for [/ss]
7262 [WARN ] org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/spring-test/ss] in DispatcherServlet with name 'spring-test'
7262 [DEBUG] org.springframework.web.servlet.DispatcherServlet - Successfully completed request
web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="rest" version="3.0" metadata-complete="true">
<!-- The definition of the Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>main.java.net.bornil.config</param-value>
</context-param>
<!-- Processes application requests -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>main.java.net.bornil.config</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file />
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/errors/404</location>
</error-page>
</web-app>
Controller
#Controller
#RequestMapping(value = "/errors")
public class CommonExceptionHandler {
private static Logger log = Logger.getLogger(CommonExceptionHandler.class.getName());
#RequestMapping(method = RequestMethod.GET, value = "/{code}")
public ModelAndView handleException(#PathVariable int code) {
if (log.isDebugEnabled()) {
log.debug("ERROR CODE IS: " + code);
}
return new ModelAndView("errors/404");
}
}
I had the same issue. I've a simple webapp, single page and, after spending a morning on the Spring forum (so nice you cannot search '404' there because it's just 3 chars long) and Google this is the best solution I found.
Assuming you have a index.jsp and a 404.jsp, my #Configuration' has:
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
registry.addViewController("/*").setViewName("404");
}

Request Mapping in Spring MVC - back to previous URL

I have a problem with redirect in Spring MVC. I have a controller with few methods:
//PRINT ALL WORKERS
#RequestMapping("/print")
public String listWorkers(Model model)
{
model.addAttribute("workerList", workerService.getAllWorkers());
return "print";
}
//EDIT WORKER DATA
#RequestMapping("/edit")
public String redirectWorker(HttpServletRequest request)
{
String parameter = request.getParameter("workers");
String path = "redirect:/edit/" + parameter;
return path;
}
#RequestMapping("/edit/{worker}")
public String editWorker(#PathVariable("worker")
String login, Model model)
{
model.addAttribute("worker", workerService.getWorker(login));
return "edition";
}
When I'm using in my program for example method with "print" in request mapping, my URL is:
http://localhost:8080/WWP/print
But when I'm using my method with "edit/{worker}" in request mapping and after that I used method with "print" I got an URL:
http://localhost:8080/WWP/edit/print
Cause my "print" was added after "edit" which isn't necessary. How to return to previous URL:
http://localhost:8080/WWP/print
I suppose that I have to change my RequestMapping annotation. But I don't know how to do this.
EDIT:
Ok, here is my web.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml, /WEB-INF/spring/appServlet/security.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Filtry -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
I used the "c:url" in the JSP and it worked.
For example:
It will be remember the previous URL (It's wrong):
My Events
It will be good:
<c:url var="myEventsUrl" value="/events/my" />
My Events
URL is always link to: _http://localhost:8080/WWP/events/my

Does the new Spring MVC Test Framework released in Spring 3.2 test the web.xml configuration?

I've read the docs ( http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/testing.html#spring-mvc-test-framework ) several times and I can't confirm if the WebApplicationContext context that gets injected when you use the #WebApplicationContext annotation is actually looking at the web.xml.
In other words, I want to test my web.xml configuration. The filters and servlet path specifically. But when I configure my test it ignores the web.xml. (e.g. I try a get request on a URL like this /myServletPath/foo and it fails with a 404.)
My test:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration({
"classpath*:WEB-INF/config/application-context.xml",
"classpath*:WEB-INF/oms-servlet.xml",
"classpath*:persistence-context.xml"
})
public class OrderSummaryControllerIntegrationTests {
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
this.mockMvc = webAppContextSetup(this.wac).build();
}
#Test
public void testFindOrderSummariesExpectsSuccess() throws Exception {
mockMvc.perform(get("/oms/orders?user=1234&catalog=bcs"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON));
}
}
And my web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>OMS REST Services</display-name>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
<filter>
<filter-name>webappMetricsFilter</filter-name>
<filter-class>com.yammer.metrics.web.DefaultWebappMetricsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>webappMetricsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/application-context.xml, classpath*:persistence-context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>oms</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>oms</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
You are right, Spring-mvc-test does not read the web.xml file, but you can configure the filters this way:
webAppContextSetup(this.wac).addFilter(new DefaultWebappMetricsFilter(), "/*").build()

Resources