Multipart file not uploading - spring-mvc

I upload file from JSP but unable to get it in controller #ModelAttribute . File Controller.java
#RequestMapping(method = RequestMethod.POST)
public String createTestConfig(Model model, #Valid #ModelAttribute("myConfig") myConfigDTO myConfig, BindingResult bindingResult, Errors errors, final RedirectAttributes redirectAttributes){
MultipartFile multipartFile = myConfig.getMyFile();
}
In above, multipartFile shows null
File UI.jsp
<input type="file" name="myFile" path="myFile" />
File dispatcher-servlet.xml
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="99999999999"/>
</bean>
Please let me know if any solution.

Related

"HTTP Status 404" and there is an extra "wrong path" in request path

This is my practice Spring project. I can not redirect to the right page in SpringMVC Interceptor.
spring-mvc.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: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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<description>Spring MVC Configuration</description>
<context:property-placeholder ignore-unresolvable="true" location="classpath:myshop.properties"/>
<context:component-scan base-package="com.huahua.my.shop" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="${web.view.prefix}"/>
<property name="suffix" value="${web.view.suffix}"/>
</bean>
<mvc:resources mapping="/**/static/**" location="/static/" cache-period="31536000"/>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/login"/>
<mvc:exclude-mapping path="/static/**"/>
<mvc:exclude-mapping path="/loginOut"/>
<bean class="com.huahua.my.shop.web.admin.web.intercepter.LoginIntercepter" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/login"/>
<bean class="com.huahua.my.shop.web.admin.web.intercepter.PermissionIntercepter" />
</mvc:interceptor>
</mvc:interceptors>
</beans>
this is UserController class
#Controller
#RequestMapping(value = "/user")
public class UserController {
#Autowired
TbUserService tbUserService ;
#RequestMapping(value = "/list" , method = RequestMethod.GET)
public String userList(){
return "user_list" ;
}
}
this is my interceptor
public class LoginIntercepter implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o ) throws Exception {
TbUser tbUser =(TbUser) httpServletRequest.getSession().getAttribute(ConstantUtils.SESSION_USER); //SESSION_USER = user
System.out.println(httpServletRequest.getRequestURL());
if (tbUser == null){
httpServletResponse.sendRedirect("login");
}
return true;
}
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {}
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {}
}
this is LoginController
#Controller
public class LoginController {
#Autowired
private TbUserService tbuserService ;
#RequestMapping(value = {"","login"},method = RequestMethod.GET)
public String login(){
return "login" ;
}
#RequestMapping(value = "login",method = RequestMethod.POST)
public String login(#RequestParam(required = true) String email ,
#RequestParam(required = true ) String password ,
#RequestParam(required = false) String isRemember,
HttpServletRequest request,
Model model){
TbUser user = tbuserService.loginRight(email, password);
isRemember = isRemember == "on" ? "checked" : null ;
if (user != null ){
request.getSession().setAttribute(ConstantUtils.SESSION_USER,user);
request.getSession().setAttribute("remember",isRemember);
return "redirect:/main" ;
}
else {
model.addAttribute("message","username or password is wrong");
return "login" ;
}
}
when I log in and request http://localhost:8080/user/list , I successfully entered user_list.jsp.
after a time, this session is out of time,I refresh this page,
the HTTP of refresh user_list page
I hope it is redirected to http://localhost:8080/login,
but I got this path http://localhost:8080/user/login
wrong with 404
how can I solve this wrong?
why there is extra a '/user' in the path?
and what are the relation between the /user in redirect path and the #RequestMapping(value = "/user") in UserController ?
Thank you very much!!!
As the API docs note for HttpServletResponse#sendRedirect:
Sends a temporary redirect response to the client using the specified
redirect location URL and clears the buffer. The buffer will be
replaced with the data set by this method. Calling this method sets
the status code to SC_FOUND 302 (Found). This method can accept
relative URLs;the servlet container must convert the relative URL to
an absolute URL before sending the response to the client. If the
location is relative without a leading '/' the container interprets it
as relative to the current request URI. If the location is relative
with a leading '/' the container interprets it as relative to the
servlet container root.
So because you have specified a relative URL is resolved relative to the current request URl /users/list
So you need to change it to:
httpServletResponse.sendRedirect("/login");

Mockito doesn't mock in spring mvc controller test

I have controller
#Controller
public class AuthorController {
#Autowired
private AuthorDAO authorDao;
#RequestMapping("/authors")
public String showAuthor(#RequestParam String name, ModelMap model) {
Author author = authorDao.findByName(name);
model.addAttribute("author", author);
return "authors";
}
}
I wrote test for it
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:test-application-context.xml"})
public class AuthorControllerTest {
private static final String JACK_C = "Jack C.";
#Autowired
AuthorController controller;
#Test
public void testShowAuthor() {
Author expectedAuthor = new Author();
AuthorDAO daoMock = mock(AuthorDAO.class);
when(daoMock.findByName(JACK_C)).thenReturn(expectedAuthor);
ModelMap model = new ModelMap();
String view = controller.showAuthor(JACK_C, model);
assertEquals("View name is incorrect","authors", view);
assertSame(expectedAuthor, model.get("author"));
verify(daoMock).findByName(JACK_C);
}
}
test-application-context.xml:
<context:annotation-config />
<context:component-scan base-package="com.github.futu" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property
name="url" value="jdbc:mysql://localhost:3306/blog" /> <property name="username"
value="blogger" /> <property name="password" value="blogger" /> </bean>
<bean id="com.github.futu.dao.AuthorDAO" class="com.github.futu.dao.impl.AuthorDAOXml"/>
<bean id="com.github.futu.dao.PostDAO" class="com.github.futu.dao.impl.PostDAOXml" />
<bean id="validator" class="com.github.futu.validator.PostValidator" />
But real dao is called. What have I missed?
You're creating a mock here
AuthorDAO daoMock = mock(AuthorDAO.class);
that is completely unrelated to your controller injected into your test class
#Autowired
AuthorController controller;
Of course the autowired AuthorDao target is going to come from your XML configuration
#Autowired
private AuthorDAO authorDao;
Ideally you would change your XML configuration only produce a #Controller bean and add a setter to it to set the AuthorDao from within the test, using your mock.

Spring mvc not able to read messages.properties file

I am trying to use custom validation error messages by using properties file. I have placed messages.properties file in web content/web-inf/ folder.
NonEmpty.batchDomain.batchName=Invalid message 2.
My applicationContext file is :
<context:component-scan base-package="com.coaching.controller" />
<!-- Enable annotation driven controllers, validation etc... -->
<mvc:annotation-driven />
<!-- Resolves view names to protected .jsp resources within the /WEB-INF/views
directory -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<mvc:default-servlet-handler />
<mvc:resources mapping="/resources/**" location="/resources/" />
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages" />
</bean>
And my controller is :
#RequestMapping(method = RequestMethod.POST)
public ModelAndView addBatch(
#Valid #ModelAttribute("batchDomain") BatchDomain batchDomain,
BindingResult result, HttpServletRequest request,
HttpServletResponse response) throws Exception {
try {
if (result.hasErrors()) {
ModelAndView modelAndView = new ModelAndView("newBatch");
return modelAndView;
}
}
BatchDomain is :
public class BatchDomain {
#NotNull
#NotEmpty
#Size(min = 1, max = 100)
private String batchName;
#Min(1)
#Max(1000)
private int strength;
}
As far as I have seen in google, I am following the correct approach. So, what can be the reason behind this issue?
You may try to put file "messages.properties" in /src/main/resource directory.

MappingJacksonJsonView return top-level json object

I converted to controller to use ContentNegotiatingViewResolver instead of MessageConverters to support multiple output types. With json, I am using MappingJacksonJsonView:
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<constructor-arg>
<bean class="org.springframework.oxm.xstream.XStreamMarshaller" />
</constructor-arg>
</bean>
</list>
</property>
<property name="ignoreAcceptHeader" value="true" />
<property name="defaultContentType" value="application/json" />
</bean>
With the following controller logic:
#RequestMapping(value = "/id/{id}", method = RequestMethod.GET)
public ModelAndView getById(#PathVariable (value="id") String id) {
MyObject ret = doGetById(id);
ModelAndView modelAndView = new ModelAndView("common/single");
modelAndView.addObject("myObject", ret);
return modelAndView;
}
The json return when I access /id/1234.json is something like:
{
myObject: {
field1:"abc",
field2:"efg"
}
}
Is there a way for my to set myObject as the top level node for the result so it look like this instead:
{
field1:"abc",
field2:"efg"
}
What's happening is Spring MVC is taking the ModelAndView and serializing it to JSON. Since a ModelAndView just looks like a map, and in this case, you only have one entry in the map with a key name of myObject, that's what the JSON response looks at. In order to get just your object, you need to return just your object instead of a ModelAndView and let Jackson serialize your object to JSON.
Rather than returning a ModelAndView, return a MyObject and annotate the method with #ResponseBody, so your controller method becomes
#RequestMapping(value="/id/{id}", method=RequestMethod.GET, produces="application/json")
public #ResponeBody MyObject getById(#PathVariable (value="id") String id) {
return doGetById(id);
}
I faced same issue and following solution works for me.
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="prefixJson" value="true" />
</bean>
You should be able to remove the outer node by using MappingJacksonJsonView.setExtractValueFromSingleKeyModel(true):
Set whether to serialize models containing a single attribute as a map
or whether to extract the single value from the model and serialize it
directly.
The effect of setting this flag is similar to using
MappingJacksonHttpMessageConverter with an #ResponseBody
request-handling method.
For example:
private final MappingJacksonJsonView view = new MappingJacksonJsonView();
public MyController() {
view.setExtractValueFromSingleKeyModel(true);
}
#RequestMapping(value = "/id/{id}", method = RequestMethod.GET)
public ModelAndView getById(#PathVariable (value="id") String id) {
MyObject ret = doGetById(id);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setView(this.view);
modelAndView.addObject("myObject", ret);
return modelAndView;
}
This should also work if you prefer to do it via configuration:
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="extractValueFromSingleKeyModel" value="true" />
</bean>

Insert JSP Form Data in DataBase Using Spring Controller

i am making rest web services using spring.
with the help of rest client-ui i am Easily Insert update and Delete the User.
now i want to do the same things with the User JSP page but now am not able to call user Controller
User.jsp
<form action="adduser" name="user" id="my-form",method="POST"
onsubmit="com.mobile-app.controller"/>
UserController
#RequestMapping(method = RequestMethod.POST, value = "/adduser", headers="Accept=application/xml, application/json")
public void createuser(#RequestBody User user) {
try {
userManager.AddToUser(user);
} catch (Exception e) {
e.printStackTrace();
}
}
Web.Xml
<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>/rest/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>Index.jsp</welcome-file>
</welcome-file-list>
Rest-Servlet.XML
<context:component-scan base-package="controller" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="adduser" class="com.mobileapp.controller.UserController">
<property name="userManager" ref="userManager" />
</bean>
Kindly please Help me To call Controller addUser Via JSP action
I will be very thankful
Create a POJO UserForm.java as
public class UserForm {
private Long id;
#NotEmpty(message = "Please enter name")
private String name;
#NotEmpty(message = "Please enter username")
private String username;
#NotEmpty(message = "Please enter password")
private String password;
private String address;
private String gender;
#Future(message = "Please enter valid DOB")
private Date dob;
private String email;
private String mobile;
//Getter & Setter
}
user.jsp page code will be
<c:url var="saveOrUpdateUrl" value="/app/user/saveOrUpdate" />
<form:form action="${saveOrUpdateUrl}" method="post" modelAttribute="userForm" id="userForm">
<form:input path="name"/>
// Other input fields
<input name="saveBtn" value="Save" type="submit">
</form:form>
In Controller you should have 2 method as
#Controller
#RequestMapping("/user")
public class UserController {
#RequestMapping(value = "/add", method = RequestMethod.GET)
public String add(Model model) {
UserForm userForm = new UserForm();
model.addAttribute("userForm", userForm);
return "user";
}
#RequestMapping(value = "/saveOrUpdate", method = RequestMethod.POST)
public String saveOrUpdate(#RequestParam("id") Long id, #Valid UserForm userForm, BindingResult result, Model model) {
//Logic to save data from userForm
}
}

Resources