How to setup uploaded file's path in Spring MVC - spring

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"));

Related

Unable to reach home.jsp

I have an app. Due to some issues, in my web.xml, I had to change the url pattern from "/" to "*.action", and added a welcome-file-list. This is my web.xml now:
<?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>
<!-- 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>
<welcome-file-list>
<welcome-file>home.jsp</welcome-file>
</welcome-file-list>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
Before I did the change, I was able to reach home.jsp by simply typing localhost:8080/myapp in my browser. What should I type now to reach the home page?
Thank you.
NOTE: Im using Spring.
EDIT:
Forgot my HomeController:
#Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
#RequestMapping(value = "/")
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
}
Your request should ends with ".action" try to sent localhost:8080/myapp/some.action
And change mapping in controller to "/some.action"

how to handle url that are not mapped in spring

My dispatcher servlet mapping
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springconfig/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
And the controller has handler like
#RequestMapping("moduleone")
public class ApplicationController {
#RequestMapping(value="Login.html",method=RequestMethod.GET)
public ModelAndView showLoginPage(){
ModelAndView mv=new ModelAndView("../moduleone/Login");
mv.addObject("loginForm", new LoginForm());
return mv;
}
#RequestMapping(value="Home.html", method = RequestMethod.GET)
public ModelAndView showHome(HttpServletRequest request) {
ModelAndView mv=new ModelAndView("Home");
mv.addObject("customerName",appCon.getFirstName() );
return mv;
}
}
Is it possible to handler request that are not mapped in controller
like
http://localhost:8090/Project/moduleone/invalidpage.html
http://localhost:8090/Project/moduleone/invalidurl/invalidpage
I have tried #RequestMapping(value="*",method=RequestMethod.GET) but doest work
As 404 (page not found) actually produces an exception on web container level, containers usually provide an exception handling mechanism, thus you can try exception (or so called error) handling, as shown below;
First create a controller
#Controller
public class PageNotFoundErrorController {
#RequestMapping(value="/pageNotFound.html")
public String handlePageNotFound() {
// do something
return "pageNotFound";
}
}
and configure web.xml in order to map the error to the controller written above;
<error-page>
<error-code>404</error-code>
<location>/pageNotFound.html</location>
</error-page>
you can also extend it by simply adding 403, 500 and other error-codes to web.xml and mapping them to any controller.
What is even more fascinating is that you can also map any exception (even the ones created by your code); here you can find a nice example about it http://www.mkyong.com/spring-mvc/spring-mvc-exception-handling-example/
I try the code block and if change your scenario a bit i can handle it.
//This one is OK
http://localhost:8090/Project/moduleone/invalidpage.html
//add invalid.html not a folder it should be file
http://localhost:8090/Project/moduleone/invalidurl/invalidpage.html
HomeController.java
#RequestMapping(value = {"*/*.html","*.html"}, method = RequestMethod.GET)
public String test(HttpServletResponse response) throws IOException {
return new String("home");
}
dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>TestSpringMVC</display-name>
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>SpringDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springconfig/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringDispatcher</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
</web-app>
I can handle both request with this way.
I think you should define an exception page for your second scenario.
Also you can read this issue

Spring Mobile inside AuthenticationFailureHandler not found

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>

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");
}

Can not connect JAX-RS service to MVC template

I'm attempting to make use of JAX-RS' (Jersey) MVC pattern. Attempts to reach http://localhost:8080/myproject/foos/test result in an error that reads:
java.io.IOException: The template name, /view, could not be resolved to a fully qualified template name
http://localhost:8080/myproject/foos results in the same error.
What am I missing?
Resource:
package resources;
import com.sun.jersey.api.view.Viewable;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("foos")
public class FooResource {
#GET
#Produces(MediaType.TEXT_HTML)
public Viewable get() {
return new Viewable("/index", this);
}
#GET
#Path("{id}")
#Produces(MediaType.TEXT_HTML)
public Viewable get(#PathParam("id") String id) {
return new Viewable("/view", id);
}
}
Views:
WEB-INF / jsp / resources / FooResource
index.jsp
view.jsp
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
<filter>
<filter-name>jersey</filter-name>
<filter-class>com.sun.jersey.spi.container.servlet.ServletContainer</filter-class>
<init-param>
<param-name>com.sun.jersey.config.property.WebPageContentRegex</param-name>
<param-value>/(resources|images|js|styles|(WEB-INF/jsp))/.*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jersey</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>ServletAdaptor</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<description>Set the default, base template path to the WEB-INF folder.</description>
<param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
<param-value>/WEB-INF/jsp</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletAdaptor</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
Made the following changes:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>welcome.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>jersey</filter-name>
<filter-class>com.sun.jersey.spi.container.servlet.ServletContainer</filter-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>controllers</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.WebPageContentRegex</param-name>
<param-value>/((WEB-INF/views))/.*</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
<param-value>/WEB-INF/views/</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.feature.Redirect</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.feature.FilterForwardOn404</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jersey</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Resource:
#Path("foos")
public class FooResource {
#GET
#Produces(MediaType.TEXT_HTML)
public Viewable index() {
return new Viewable("/foos/index", this);
}
#GET
#Path("{id}")
#Produces(MediaType.TEXT_HTML)
public Viewable view(#PathParam("id") String id) {
return new Viewable("/foos/view", id);
}
}
Views:
\welcome.jsp
\WEB-INF\views\foos\
index.jsp
view.jsp
I had this same error running under Jetty 9. The application ran fine using mvn clean jetty:run but had this error when packaged as a war and deployed under Jetty. This is the fix in web.xml that worked for me:
<init-param>
<param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
- <param-value>/WEB-INF/views/</param-value>
+ <param-value>/WEB-INF/views</param-value>
</init-param>
Yep, that's it. So, hopefully this helps someone who stumbles across this. My config is basically the same as craig's, but had the extra slash.
From initial inspection I think you want to put index.jsp and view.jsp directly in WEB-INF/jsp.
The name should be a fully qualified name like /index.jsp or /index.html.

Resources