Spring CommonsMultipartResolver always return null for the MultipartFile - spring

If I use StandardServletMultipartResolver, I get the file properly, but if I use CommonsMultipartResolver I get null for the file. Even without any additional configuration, just replacing new StandardServletMultipartResolver(); with new CommonsMultipartResolver(); the files are not received. I wanted to enforce maxUploadSizePerFile and hence used CommonsMultipartResolver.
In my WebContext Configuration file, I have the following:
#Override
#Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
Long maxFileSize = environment.getRequiredProperty(PropertyConstants.MAX_FILE_UPLOAD_SIZE, Long.class);
multipartResolver.setMaxUploadSizePerFile(maxFileSize);
return multipartResolver;
}
If I just replace the CommonsMultipartResolver with StandardServletMultipartResolver, things start to work. I have commons-fileupload in mvn dependency and the application gets launched without any error.
I am using Tomcat 9.0.0.M1 and Spring 4.2.2.
Is there some configuration I am missing for CommonsMultipartResolver to work?

I have encountered the same issue, but I note that it only occurs when CommonsFileUploadSupport stores the file in memory. As a workaround I found setting maxInMemorySize to 0 works e.g.
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- max upload size in bytes -->
<property name="maxUploadSize" value="20971520" /> <!-- 20MB -->
<!-- max size of file in memory (in bytes) -->
<!-- oddly, the MultipartFile passed as a RequestParam gets set to null if I allow it to use memory
rather than disk! -->
<property name="maxInMemorySize" value="0" />
</bean>

Go to the Servers repertory and Try to add allowCasualMultipartParsing="true" in the context.xml of Tomcat Server in your workspace project.

Related

Change configuration on demand without restarting container

Spring MVC + Java 8 + Tomcat 8 stack
I am maintaining my configuration in yaml and flattening the properties using Spring's PropertyPlaceholderConfigurer and maintaining the configuration in a bean.
Today, it has a inherent problem as I am required to restart the server whenever there is a change to the YML files.
I believe there are ways to refresh the bean without restart, but my main concern is how to do in fail safe manner.
Lets assume, there was a request and that time the config was A, and then we refresh the configuration so now its B, but if any subsequent user request was dependent on the configuration, then it will blow up.
Add this configuration to your servlet-context.xml to catch property changes on the fly:
<context:property-placeholder
location="file:${A_CONFIG_LOCATION}/configuration.properties" />
<beans:bean id="propertiesLoader"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="cacheSeconds" value="1" />
<beans:property name="basenames">
<beans:list>
<beans:value>file:${A_CONFIG_LOCATION}/configuration
</beans:value>
</beans:list>
</beans:property>
</beans:bean>
And then you can read property values like this:
#Component
public class PropertiesReader {
private String value = "some_default_value";
#Autowired
MessageSource propertiesLoader;
public String getValue() {
value = propertiesLoader.getMessage("configuration.value", null, null);
return value;
}
}

Spring ReloadableResourceBundleMessageSource bean unable to find external properties

I've tried to use the Mkyong's guide to access external properties file, without any success.
This is my bean definition in web-osgi-context.xml file located in WEB-INF:
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:bundles/resource</value>
<value>classpath:bundles/override</value>
<value>file:c:/test/messages</value>
</list>
</property>
<property name="cacheSeconds" value="10"/>
</bean>
Accessing the bean:
#SpringBean
private ReloadableResourceBundleMessageSource messageSource;
Trying to extract the message like this:
String name = messageSource.getMessage("customer.name",
new Object[] { 28,"http://www.mkyong.com" }, Locale.US);
System.out.println("Customer name (English) : " + name);
I have messages_en_US.properties files in both C:/test/messages and C:/test folders. They contain following line:
customer.name=Test, age : {0}, URL : {1}
That's all I have, am I missing something? The message I get is:
org.springframework.context.NoSuchMessageException: No message found under code 'customer.name' for locale 'en_US'.
at org.springframework.context.support.AbstractMessageSource.getMessage(AbstractMessageSource.java:155)
Btw, I also tried internal properties, also without success. I deploy my .war in my local servicemix(6.1.1), I also use wicket (6.24.0) and spring (3.2.14). Running mkyong's application(which is not a web application) locally (without deploying it on my local servicemix works).
Sooo I somewhat found the problem and got a workaroud..
This didn't work:
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename">
<value>classpath:messages</value>
</property>
</bean>
And in Code:
#SpringBean
private ReloadableResourceBundleMessageSource messageSource;
By running getClass() on this source I get
class WICKET_org.springframework.context.support.ReloadableResourceBundleMessageSource$$EnhancerByCGLIB$$852b0c02
But this is working:
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
return messageSource;
}
By running getClass() on this source I get
class org.springframework.context.support.ReloadableResourceBundleMessageSource
Is it possible that Cglib enhancer is messing thigs up here? Any way I can make first option working knowing that?

Spring 4 (no boot) with custom jackson ObjectMapper

Secton 65.3 of the spring boot manual indicates that I can replace the default ObjectMapper by providing my own. I am not using boot, just a spring WebMVC application that builds to a .war and runs in tomcat.
It instantiates my ObjectMapper but doesn't use it. I used the debugger to trace through why timestamps still come out as numeric and found that it was using a different instance of ObjectMapper. It's not clear to me where it came from, or why this doesn't cause it to only use mine:
#Primary
#Bean
public ObjectMapper localObjectMapper() {
JodaMapper mapper = new JodaMapper();
mapper.setWriteDatesAsTimestamps(false);
mapper.getSerializationConfig().with(SerializationFeature.INDENT_OUTPUT)
.without(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS)
.without(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)
.without(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return mapper;
}
The above is in a #Configure bean that's definitely getting loaded.
The approach I took above worked fine in Spring 3, just not when I ugpraded to 4.2.2. I have read Jackson Integration Improvements as well, and tried approaches listed there, to the same effect.
--Chris
The way I always did it was:
#Configuration
#EnableWebMvc
public class MyWebMvcConfigurer extends WebMvcConfigurerAdapter {
#Bean
public ObjectMapper localObjectMapper() {
JodaMapper mapper = new JodaMapper();
// ...
return mapper;
}
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter (localObjectMapper())); // use your own ObjectMapper
}
}
One warning, to quote the JavaDoc of WebMvcConfigurer.html#configureMessageConverters:
Note that adding converters to the list, turns off default converter registration. To simply add a converter without impacting default registration, consider using the method extendMessageConverters(java.util.List) instead.
In Spring 4 I've solved with the following xml-configuration
<bean name="jacksonObjectMapper"
class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="featuresToDisable">
<array>
<util:constant
static-field="com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS" />
</array>
</property>
</bean>
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
putting it in the Servlet configuration file, usually under
/WEB-INF/spring/appServlet/*.xml

Reading message from properties file in spring4

I am facing an issue in reading the properties file in spring mvc4. To read messages I have added following in spring-servlet.xml file located under WEB-INF folder.
<context:component-scan base-package="com.test.restful.producer" />
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="location">
<value>classpath:application.properties</value>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
In my controller class,
#Value("${MSG}")
private String msg;
i am getting msg as null. Please helpout me how to load properties file. My appilcation.properties file is available in classpath only.
I am using Spring-4.0.5
Thank you
You can try this xml for creating properties bean.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:propertyFile.properties" name="propertiesBean"/>
Or go for non xml version as below
#PropertySource("classpath:propertyFile.properties")
public class AppConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}

Database connections not being closed with jpaFlowExecutionListener

I'm using Spring Web Flow to build an application. I am making use of the Flow Managed Persistence Context so the entity manager is 'kept open' during the execution of my flow and I can access lazy loaded properties (similar to OpenEntityManagerInViewFilter or OpenSessionInViewFilter for Spring MVC). When I use this, every time I submit a form, the number of active database connections increases, if I don't use the FMPC, I have no problems with the number of open connections).
I'm working with the following setup.
TransactionManager:
#Bean
#Autowired
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
DataSource:
#Bean
public DataSource dataSource() {
final BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(environment.getRequiredProperty(PROPERTY_DATABASE_DRIVER));
dataSource.setUrl(environment.getRequiredProperty(PROPERTY_DATABASE_URL));
dataSource.setUsername(environment.getProperty(PROPERTY_DATABASE_USERNAME, ""));
dataSource.setPassword(environment.getProperty(PROPERTY_DATABASE_PASSWORD, ""));
return dataSource;
}
EntityManagerFactory:
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setPackagesToScan(environment.getRequiredProperty(PROPERTY_ENTITYMANAGER_PACKAGES_TO_SCAN));
final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter() {
{
setDatabase(Database.valueOf(environment.getRequiredProperty(PROPERTY_DATABASE_TYPE)));
setDatabasePlatform(environment.getRequiredProperty(PROPERTY_HIBERNATE_DIALECT));
}
};
factoryBean.setJpaVendorAdapter(vendorAdapter);
final Properties jpaProperties = new Properties();
jpaProperties.put(PROPERTY_HIBERNATE_FORMAT_SQL, environment.getRequiredProperty(PROPERTY_HIBERNATE_FORMAT_SQL));
jpaProperties.put(PROPERTY_HIBERNATE_NAMING_STRATEGY, environment.getRequiredProperty(PROPERTY_HIBERNATE_NAMING_STRATEGY));
jpaProperties.put(PROPERTY_HIBERNATE_SHOW_SQL, environment.getRequiredProperty(PROPERTY_HIBERNATE_SHOW_SQL));
jpaProperties.put(PROPERTY_HIBERNATE_HB2DDL_SQL, environment.getRequiredProperty(PROPERTY_HIBERNATE_HB2DDL_SQL));
factoryBean.setJpaProperties(jpaProperties);
return factoryBean;
}
JpaFlowExecutionListener:
#Bean
#Autowired
public JpaFlowExecutionListener jpaFlowExecutionListener(EntityManagerFactory entityManagerFactory, JpaTransactionManager transactionManager) {
return new JpaFlowExecutionListener(entityManagerFactory, transactionManager);
}
The BasicDataSource has maxActive set to 8 by default and when I reach 8 active connections, the page just hangs. Why are the connections not being closed after the request is complete? I have used the Chrome debugging tools (the network pane) to make sure there are not AJAX requests running or anything, my page submit (an HTTP POST) triggers a 301 redirect which then gives me a new HTTP GET and that results in a status 200, so all good.
When going from one page to the next, a service layer is called but as you can see from my beans, I am using the JpaTransactionManager and the SWF documentation says the following:
Note: All data access except for the final commit will, by default, be non-transactional. However, a flow may call into a transactional service layer to fetch objects during the conversation in the context of a read-only system transaction if the underlying JPA Transaction Manager supports this. Spring's JPA TransactionManager does support this when working with a Hibernate JPA provider, for example. In that case, Spring will handle setting the FlushMode to MANUAL to ensure any in-progress changes to managed persistent entities are not flushed, while reads of new objects occur transactionally.
For the sake of completeness, my spring-web-flow config:
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config.xsd">
<!-- Flow executor, repsonsible for creating and executing flows -->
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
<webflow:flow-execution-listeners>
<webflow:listener ref="jpaFlowExecutionListener"/>
</webflow:flow-execution-listeners>
</webflow:flow-executor>
<!-- Flow registry, responsible for loading all flows so executor can execute them -->
<webflow:flow-registry id="flowRegistry" base-path="/WEB-INF/webflow/flows" flow-builder-services="flowBuilderServices">
<webflow:flow-location-pattern value="/**/*-flow.xml"/>
</webflow:flow-registry>
<!-- Flow builder services -->
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator"/>
<!-- MvcViewFactoryCreator -->
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers">
<list>
<ref bean="viewResolver"/>
</list>
</property>
</bean>
<!-- Flow handler adapter, responsible for answering request for a flow -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor"/>
</bean>
<!-- Flow handler mapping, lets Spring MVCs DispatcherServlet know to send flow request to SWF -->
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry"/>
<property name="order" value="0"/>
<property name="interceptors">
<list>
<ref bean="localeChangeInterceptor" />
</list>
</property>
</bean>
</beans>
My flow has <persistence-context /> defined at the top.
I have the following end-state (which restarts the flow), even when I invoke this and the URL params change to e2s1, the number of active connections is not reset:
<end-state id="restart" commit="true" view="redirect:/main"/>
So it seems that the default hibernate property for hibernate.connection.release_mode is on_close. Considering the EntityManager is kept open during the whole flow, it never closes and a new connection is fetched from the pool for every request within the flow.
Changing the property to after_transaction solves this issue. However, in the case of fetching lazily loaded collections, it still doesn't work, each lazy property will fetch a new connection from the pool. In order to solve this I extended the JpaFlowExecutionListener with this:
public class AvoidLeakJpaFlowExecutionListener extends JpaFlowExecutionListener {
public AvoidLeakJpaFlowExecutionListener(EntityManagerFactory entityManagerFactory, PlatformTransactionManager transactionManager) {
super(entityManagerFactory, transactionManager);
}
#Override
public void paused(RequestContext context) {
super.paused(context);
EntityManager entityManager = (EntityManager) context.getFlowScope().get(PERSISTENCE_CONTEXT_ATTRIBUTE);
if (entityManager != null && entityManager instanceof HibernateEntityManager) {
HibernateEntityManager hibernateEntityManager = (HibernateEntityManager) entityManager;
hibernateEntityManager.getSession().disconnect();
}
}
}
This approach solves the lazily loaded collections problem but will still leak connections when loading of lazy-initialized entities is done using WebFlow's persistence context and this loading is performed during the transition to subflow that does not have configured. as described in in this bug report (where I found this solution as well).

Resources