user4567570 user4567570 -4 years ago 143
Java Question

Spring MVC Fileupload - how to setup the MultipartConfigElement in XML based application?

I am developing Spring MVC + JPA + Fileupload XML based application by taking a reference from the http://websystique.com/springmvc/spring-mvc-4-fileupload-download-hibernate-example/. This is purely a annotation based application and in my project we're using XML based configurations. So far I was able to developed application successfully and half of it working fine. The only part I am pending with is the below. I am not sure how/where to configure this in

applicationcontext.xml
or
web.mxl
file.

private MultipartConfigElement getMultipartConfigElement(){
MultipartConfigElement multipartConfigElement = new MultipartConfigElement(LOCATION, MAX_FILE_SIZE, MAX_REQUEST_SIZE, FILE_SIZE_THRESHOLD);
return multipartConfigElement;
}
@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
registration.setMultipartConfig(getMultipartConfigElement());
}
private static final String LOCATION = "C:/mytemp/";
private static final long MAX_FILE_SIZE = 1024 * 1024 * 25;//25MB
private static final long MAX_REQUEST_SIZE = 1024 * 1024 * 30;//30MB
private static final int FILE_SIZE_THRESHOLD = 0;


The original file is:
HelloWorldInitializer.java

public class HelloWorldInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

/*Set these variables for your project needs*/

private static final String LOCATION = "C:/mytemp/";
private static final long MAX_FILE_SIZE = 1024 * 1024 * 25;//25MB
private static final long MAX_REQUEST_SIZE = 1024 * 1024 * 30;//30MB
private static final int FILE_SIZE_THRESHOLD = 0;

@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { HelloWorldConfiguration.class };
}

@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}

@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}

@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
registration.setMultipartConfig(getMultipartConfigElement());
}

private MultipartConfigElement getMultipartConfigElement(){
MultipartConfigElement multipartConfigElement = new MultipartConfigElement(LOCATION, MAX_FILE_SIZE, MAX_REQUEST_SIZE, FILE_SIZE_THRESHOLD);
return multipartConfigElement;
}
}


HelloWorldConfiguration.java

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.websystique.springmvc")
public class HelloWorldConfiguration extends WebMvcConfigurerAdapter{

@Bean(name="multipartResolver")
public StandardServletMultipartResolver resolver(){
return new StandardServletMultipartResolver();
}

@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");

registry.viewResolver(viewResolver);
}


// Configure ResourceHandlers to serve static resources like CSS/ Javascript etc...
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}

//Configure MessageSource to lookup any validation/error message in internationalized property files
@Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}

/**Optional. It's only required when handling '.' in @PathVariables which otherwise ignore everything after last '.' in @PathVaidables argument.
* It's a known bug in Spring [https://jira.spring.io/browse/SPR-6164], still present in Spring 4.1.7.
* This is a workaround for this issue.
*/
@Override
public void configurePathMatch(PathMatchConfigurer matcher) {
matcher.setUseRegisteredSuffixPatternMatch(true);
}
}


HibernateConfiguration.java

Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages={"com.websystique.springmvc.repository"})
@ComponentScan({ "com.websystique.springmvc.configuration" })
@PropertySource(value = { "classpath:application.properties" })
public class HibernateConfiguration {

@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, Environment environment) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();

// dataSource
entityManagerFactoryBean.setDataSource(dataSource);

// Hibernate JPA Vendor Adapter
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());

// package to scan
entityManagerFactoryBean.setPackagesToScan("com.websystique.springmvc.model");

// JPA Properties
entityManagerFactoryBean.setJpaProperties(getProperties(environment));

return entityManagerFactoryBean;
}


public Properties getProperties(Environment environment){
Properties jpaProperties = new Properties();

//Configures the used database dialect. This allows Hibernate to create SQL that is optimized for the used database.
jpaProperties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));

//Specifies the action that is invoked to the database when the Hibernate SessionFactory is created or closed.
jpaProperties.put("hibernate.hbm2ddl.auto", environment.getRequiredProperty("hibernate.hbm2ddl.auto"));

//If the value of this property is true, Hibernate writes all SQL
jpaProperties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));

//If the value of this property is true, Hibernate will format the SQL
jpaProperties.put("hibernate.format_sql", environment.getRequiredProperty("hibernate.format_sql"));

return jpaProperties;
}


@Bean
public DataSource dataSource(Environment environment) {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
dataSource.setUrl(environment.getRequiredProperty("jdbc.url"));
dataSource.setUsername(environment.getRequiredProperty("jdbc.username"));
dataSource.setPassword(environment.getRequiredProperty("jdbc.password"));

return dataSource;
}

@Bean
@Autowired
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory){
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
return jpaTransactionManager;
}
}


These all configurations I mapped it to the XML file:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:repository="http://www.springframework.org/schema/data/repository"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository-1.11.xsd">


<!-- Enables the Spring MVC @Controller programming model -->
<mvc:annotation-driven />
<context:component-scan base-package="com.websystique.springmvc.controller" />

<mvc:resources location="/static/" mapping="/static/**" />

<!-- Load database.properties file -->
<context:property-placeholder location="classpath:application.properties" />

<!-- Enable JPA Repositories -->
<jpa:repositories base-package="com.websystique.springmvc.repository" />

<!-- Enable Transaction Manager -->
<tx:annotation-driven transaction-manager="transactionManager" />

<!-- Necessary to get the entity manager injected into the factory bean -->
<beans:bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />


<!-- ====== MYSQL DataSource ====== -->
<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<beans:property name="driverClassName" value="${jdbc.driverClassName}" />
<beans:property name="url" value="${jdbc.url}" />
<beans:property name="username" value="${jdbc.username}" />
<beans:property name="password" value="${jdbc.password}" />
</beans:bean>

<!-- ====== Hibernate JPA Vendor Adaptor ======= -->
<beans:bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<beans:property name="showSql" value="${hibernate.show_sql}"/>
<beans:property name="generateDdl" value="true"/>
<beans:property name="database" value="MYSQL"/>
</beans:bean>


<!-- Beans -->
<beans:bean id="userDocumentService" class="com.websystique.springmvc.service.UserDocumentServiceImpl" />
<beans:bean id="userService" class="com.websystique.springmvc.service.UserServiceImpl" />
<beans:bean id="fileValidator" class="com.websystique.springmvc.util.FileValidator" />

<!-- ======== Entity Manager factory ======== -->
<beans:bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!-- Data Source -->
<beans:property name="dataSource" ref="dataSource"/>

<!-- JPA Vendor Adaptor -->
<beans:property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>

<!-- spring based scanning for entity classes-->
<beans:property name="packagesToScan" value="com.websystique.springmvc.model" />

<beans:property name="jpaProperties">
<beans:props>
<beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop> <!-- validate | update | create | create-drop -->
<beans:prop key="hibernate.dialect">${hibernate.dialect}</beans:prop>
<!-- <beans:prop key="hibernate.cache.use_query_cache">true</beans:prop> -->
</beans:props>
</beans:property>
</beans:bean>

<!-- ======== Transaction Manager ==== -->
<beans:bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<beans:property name="entityManagerFactory" ref="entityManagerFactory" />
</beans:bean>


<!-- Localization of hibernate messages during validation!-->
<beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basename" value="classpath:messages" />
<beans:property name="defaultEncoding" value="UTF-8" />
</beans:bean>

<beans:bean name="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>


<!-- This is for JSP -->
<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>
</beans:beans>


Now only functionality needs to implement is the
MultipartConfigElement
. How and where to implement it? Because of not having this configuration in place I

see the below error:
Jan 14, 2017 3:20:09 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/spring-mvc-fileupload-xml] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
at com.websystique.springmvc.controller.AppController.saveDocument(AppController.java:199)
at com.websystique.springmvc.controller.AppController.uploadDocument(AppController.java:189)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:111)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:509)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1104)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

Answer Source

The simple solution apart from the questions raised is add the below dependency:

<dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
</dependency>

And the create the following bean in the servlet-context.xml file.

<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />

Done !!!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download