How to upload file using spring mvc3? [duplicate] - java

This question already has answers here:
File Upload to Server Directory Using Spring MVC
(2 answers)
Closed 8 years ago.
I want to upload file and do process by using Spring MVC3. i tried with
#RequestMapping(value = "uploadAction.do")
public ModelAndView upload(
#RequestParam("file") CommonsMultiPartFile file
)
{
System.out.println(file);
ModelAndView view = new ModelAndView();
return view;
}
but it is not working and i have confused with #RequestParam and #ModelAttribute so please help me

The upload functionality depends on several factors factors. As by the docs, following are the things you must ensure
Make a POST request. File upload should be a POST request
#RequestMapping(value = "uploadAction.do", method=RequestMethod.POST)
Enable Spring multipart handling by adding a multipart resolver to the web application’s context
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="100000"/>
</bean>
Ensure commons-fileupload.jar is on your classpath, if you're using maven the following should cover you
<!-- File Upload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.0.1</version>
</dependency>
with all this in place, your mapping should work well, providing that your form is OK, here is an example
<form id="fileuploadForm" action="/uploadAction.do" method="POST" enctype="multipart/form-data" class="cleanform">
<input id="file" type="file" name="file" />
<p><button type="submit">Upload</button></p>
</form>
note also that its always better to program against an interface, by changing the argument type to
public ModelAndView upload(#RequestParam("file") MultipartFile file) {
you'll delegate injecting the implementation to the framework. The benefit is that you can write file upload test using spring mvc test framework, in which case the framework will insert the mocked implementation for the MultipartFile interface

Something like this:
#RequestMapping(value="/upload", method=RequestMethod.POST)
public String upload( #RequestParam("upload")
MultipartFile multipartFile
...
){
....
}
and in the form enctype is required:
<form id="command" name="command" method="POST" action="/upload" enctype="multipart/form-data">
....
<input id="upload" type="file" name="photo">
....
</form>

Related

FileUpload, Struts2, no file in FileUploaderInterceptor

Have a working Struts2 portlet environment where I cannot make Struts fileUpload work, in portlet mode.
I can see that
A file is uploaded to the server, created in temp space.
A multipart request is present on the original request, with the filename
and file contents, where it enters Struts classes.
I can trigger the maximum size response, the default value set in Struts.
The FileUploadInterceptor is triggered but in the Jakarta
MultipartRequest there is no file. Somewhere between the original
request and the Jakarta wrapper the file is lost.
I have tried the same approach in a stripped down Spring boot 2 application, the same problem occurs as in the main project.
Followed the code at
https://struts.apache.org/core-developers/file-upload.html
for the JSP and action classes. The portlet is created, the flow works, but no file in the action.
Standard Sping Boot 2 with extra in pom:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.5.20</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
Struts.xml
<package name="uploadtest" extends="struts-portlet-default" namespace="/uploadtest">
<action name="uploadtestPrepare" class="bouvet.no.fileuploadtest.action.FileUploadSubmitAction">
<result name="success">/WEB-INF/struts2/test/fileUpload.jsp</result>
</action>
<action name="uploadTestSubmit" class="bouvet.no.fileuploadtest.action.FileUploadSubmitAction">
<result name="success">/WEB-INF/struts2/test/fileUpload.jsp</result>
</action>
</package>
and the form
<s:form action="uploadTestSubmit" method="post" enctype="multipart/form-data">
FileName: <s:property value="%{filename}"/>
<s:file name="upload" label="File" />
<s:submit/>
</s:form>
a setter
public void setUploadFileName(String filename) {
this.filename = filename;
}
Is this a bug in portlet mode or am I missing a key dependency, a component, version? Alternative method?
In the image, a breakpoint in the JSR168 dispatcher, the file is present. First code to run after the server.
breakpoint in JSR168 dispatcher
The solution in this case was to step back a step and look at what was present in the request.
The CMS the portlet is running in is in fact taking care of the upload before the upload reach the portlet environment. The jakarta wrapper I found was created by the CMS but it is outside of the portlet scope.
Solution:
public String intercept(ActionInvocation invocation) throws Exception {
final ActionContext context = invocation.getInvocationContext();
Object action = invocation.getAction();
try {
if (action instanceof FileUploadAware) {
HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);
// if (request instanceof MultipartRequestWrapper) {
File file = (File) request.getAttribute("upload");
((FileUploadAware) action).setFile(file);
// }
}
}catch (Exception e){
LOG.error("Exception? {}", e);
}finally {
return invocation.invoke();
}
Not a final solution but the concept, an interceptor that finds an upload attribute on the request and puts it on a FileUploadAware action. The attribute is a local temp file the CMS has intercepted and created.
This works for me, a special solution for this CMS or a general for portlets? Do not know.

Spring boot ModelAndView value is not displayed

I can't get the values added to the model in jsp dispalyed. I have tried with everything and and checked all answers on stackoverflow, but nothing helps.
To save your time, I paste a part of code:
My pom.xml :
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
<relativePath/>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
and my java config code is :
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
and
#EnableWebMvc
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public InternalResourceViewResolver getViewResolver(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
my controller is :
#Controller
#RequestMapping(value = "workorder")
public class WorkOrderController {
#RequestMapping(value = "/toProviewPage", method = RequestMethod.GET)
public ModelAndView toPreview(){
WorkOrderVo workOrderVo = new WorkOrderVo();
workOrderVo.setId(1);
workOrderVo.setName("xxx");
workOrderVo.setPriority(1);
workOrderVo.setDetail("xxxx");
return new ModelAndView("workOrderPreview", "workOrderVo", workOrderVo);
}
}
my jsp file is :
<%# page language="java" contentType="text/html; charset=UTF-8" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<div class="form-group">
<label for="detail" class="col-sm-2 control-label">Detail</label>
<div class="col-sm-10">
<textarea class="form-control" rows="5" id="detail" name="detail" value="${workOrderVo.dreadonly="true"></textarea>
</div>
</div>
but spring boot doesn't resloved is as a jsp file, and display all the html code is the Browser.
Where I write errors?
You can't run the main() method directly for the application when you are using "embedded Tomcat". If you look at your POM it is indicating that the Jasper dependency is provided meaning that it expects your artifact to be put inside a Tomcat container. Running the main() method in your application does not actually load up Jasper which is why you are not seeing the pages processed as JSP. For IntelliJ you need to set up a Maven run configuration (not an application) and use spring-boot:run which apparently sets up Tomcat for you. Here is a picture of how to set it up.
I did it with your application and it appears that the JSPs are being processed. I don't see the exact code you are referencing above in GitHub but I noticed that the preview page had a JSP tag that was processed. There was no value in it but the tag was replaced. Its not clear to me that this is documented so I got a hint from this question. If anyone finds official Spring Boot documentation that makes it clear let me know and I will update this.
I'll summarize the current two feasible solutions:
first :
modify pom dependency, change:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
to
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
The second:
use spring-boot:run command to start application.

Spring Security with XML configuration does not authenticate user

I have a website section (everything under /secure URL) that I'm trying to secure with Spring Security 3.2.5. I'm using the following XML configuration:
<http use-expressions="true">
<intercept-url pattern="/secure/login" access="permitAll" />
<intercept-url pattern="/secure/**" access="isAuthenticated()" />
<form-login default-target-url="/secure/home" always-use-default-target="true" login-page="/secure/login" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user" password="password" authorities="ROLE_SECURE" />
</user-service>
</authentication-provider>
</authentication-manager>
I'm trying to use a custom login form for which I have this controller:
#Controller
#RequestMapping(value = "/secure")
public class LoginController {
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String getLogin() {
return "secure/login";
}
#RequestMapping(value = "/home", method = RequestMethod.GET)
public String getHome() {
return "secure/home";
}
}
and this code inside the login page:
<form method="POST" action="<c:url value="/secure/login" />">
username: <input type="text" name="username" /><br/>
password: <input type="password" name="password" /><br/>
<input type="submit" value="Login" />
</form>
I have the security context loaded in the web.xml using ContextLoaderListener and the
springSecurityFilterChain delegating proxy filter is also setup.
When I try to access the /secure URL I get redirected to /secure/login, my controller is called in the getLogin method and I see my login page. That's all OK.
Now my problem: whatever I submit in the login form gets sent directly to the LoginController and I get an exception saying that POST is not a supported
method, which makes sense because there is no POST handler in the controller.
If I add a method like this in the controller:
#RequestMapping(value = "/login", method = RequestMethod.POST)
public String postLogin() {
return "redirect:/secure/home";
}
I no longer get the error but my postLogin method is invoked wich sends me to /secure/home unauthenticated which then redirects me to /secure/login and I'm back to square one.
I don't know what I'm doing wrong. All examples I see online are Java configured which I prefer not to use and all workflows hapen in the context of the application not under some extra URL path (in my case /secure).
What am I missing?
Form the docs(http://docs.spring.io/spring-security/site/docs/3.0.x/reference/appendix-namespace.html):
default-target-url:
Maps to the defaultTargetUrl property of UsernamePasswordAuthenticationFilter. If not set, the default value is "/" (the application root). A user will be taken to this URL after logging in, provided they were not asked to login while attempting to access a secured resource, when they will be taken to the originally requested URL.
You have to submit the form to j_spring_security_check
<form name='loginForm'
action="<c:url value='j_spring_security_check' />" method='POST'>
This will be handled by Spring Security and will check the user and pass depending on your config.
See this example http://www.mkyong.com/spring-security/spring-security-form-login-example/
Edit: j_security_check should also be supported.
This post helped me get the correct result: http://codehustler.org/blog/spring-security-tutorial-form-login/

JSP not Evaluating with Spring MVC

I am trying to render JSP in a Spring 3.2 using annotation driven configuration, but the JSP renders as a string and is not evaluated.
I am using the maven jetty plugin to run the webapp in development. So it seems as if everything should "just work".
The dependencies I am including to use JSP are
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
The bean to configure JSP is
#Configuration
public class WebAppConfiguration {
#Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
The controller is pretty straight forward
#Controller
public class RootController {
#RequestMapping(value = "/login")
public String login() {
return "login";
}
and the JSP is also pretty easy
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head></head>
<body>
<%= "Hello World" %>
${ "Hello World" }
<form name="auth" action="<c:url value='j_spring_security_check' />" method="POST">
<label>Username: <input type="text" name="j_username"></label>
<label>Password: <input type="password" name="j_password"></label>
<input type="submit" value="Submit"/>
</form>
</body>
</html>
As you can see from the image the JSP is not being evaluated. Is there anything I need to do to tell JSP to be evaluated when rendered.
Edit 1
So just for a little extra information I used the Resthub archetype resthub-mongodb-backbonejs-archetype to bootstrap this project, which uses a WebAppInitializer rather than the older web.xml, and it uses new annotation driven beans rather than the xml beans.
EDIT 2
I have been smashing my head on this for all to long so I put the project on github https://github.com/austinbv/calendar/. Since I do not know what is important and what is not.
Thanks for the help
#austinbv Please use the SPRING LINK to check the setup. (As #Rohit has pointed you above - the missing piece)
I had the same problem when using spring boot. Adding these dependencies to the project pom.xml resolved the issue:
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-compiler</artifactId>
<version>5.5.23</version>
</dependency>
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-runtime</artifactId>
<version>5.5.23</version>
</dependency>
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-compiler-jdt</artifactId>
<version>5.5.23</version>
</dependency>
The above given issue fixed for me after making following change in the "web.xml"
The spring servlet needs to be the default servlet. ie mapped to / and not /*.
Ref link: https://code-examples.net/en/q/b49ce1
You need to specify the appropriate view class
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
resolver.setPrefix("/views/");
resolver.setSuffix(".jsp");
return resolver;
}
I do not know how much actual will be my answer, but I had exactly the same issue (Spring + boot + maven + tomcat).
I solved it by removing the scope-provided from tomcat.embed dependence. So, my dependence now looks like this:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
Because JSP does not obey MVC pattern :P

Spring REST XML service not accepting XML as "accept" header

I have several REST services defined that are currently returning JSON formatted objects as service response bodies. I'm trying to make this service also accept XML as a new requirement though it does not accept this.
I'm following the spring-mvc-showcase sample project and have setup my pom.xml dependencies almost identically, my service definitions likewise are very simple.
#Controller
#RequestMapping(value = "api/sales/*")
public class SalesController {
#RequestMapping(value = "/countries", method = RequestMethod.GET)
#ResponseBody
public List<NamedEntity> getCountries() {
NamedEntity has the appropriate #XmlRootElement annotation.
Could somebody explain the most basic requirements that I would need to get XML as a ResponseBody that the spring-mvc-showcase sample project is using.
EDIT: Added spring MVC sample.
The sample from the spring-mvc-showcase is as follows:
package org.springframework.samples.mvc.messageconverters;
#Controller
#RequestMapping("messageconverters/*")
public class MessageConvertersController {
#RequestMapping(value="/xml", method=RequestMethod.GET)
public #ResponseBody JavaBean writeXml() {
return new JavaBean("bar", "fruit");
Check the request header, client needs to have "application/xml" in the header, rather than "application/json "
Having said this make sure you have registered appropriate message converter for your object. If you are using Java 6 then Spring will auto detect JAXB in your classpath or else you can manually add the converter.
Add #Produces("application/xml") to getCountries()
You need to send "application/xml", not "application/application+xml". Also consider using:
#RequestMapping(value = "/countries", method = RequestMethod.GET, produces={"application/json", "application/xml"})
This ensures your method responds to those media types only and rejects others with 406 HTTP status code.
try this dispatcher servlet config.
<mvc:annotation-driven
content-negotiation-manager="contentManager" />
<bean id="contentManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="ignoreAcceptHeader" value="false" />
<property name="defaultContentType" value="application/json" />
<property name="useJaf" value="false" />
</bean>
and some dependency
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.4.3</version>
</dependency>

Categories