Spring: RestTemplate messageConverters are not registered - spring

I have an issue with the registration of the messageConverters on the org.springframework.web.client.RestTemplate.
I have tried (with no effect) two solutions:
1) Defining a bean of restTemplate in the Spring configuration, with all the converters that I need:
<bean id="restTemplate" name="restTemplate" class="org.springframework.web.client.RestTemplate" autowire-candidate="true">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
<bean class="test.myApp.MyHttpMessageConverter" />
</list>
</property>
</bean>
2) Declaring the messageConverters in the <mvc:annotation-driven> tag:
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
<bean class="test.myApp.MyHttpMessageConverter" />
</mvc:message-converters>
</mvc:annotation-driven>
I also used the attribute register-defaults="true"
With both of these two solutions, the restTemplate instance contains only the same 6 default converters:
ByteArrayHttpMessageConverter
StringHttpMessageConverter
ResourceHttpMessageConverter
SourceHttpMessageConverter
AllEncompassingFormHttpMessageConverter
Jaxb2RootElementHttpMessageConverter
There is no trace of the test.myApp.MyHttpMessageConverter and of the org.springframework.http.converter.FormHttpMessageConverter.
I'm using the 4.3.1.RELEASE version of Spring.
How to make possible the registration of the messageConverters?
Thanks in advance.

I have found the solution.
Since I'm using the Spring Integration <int-http:outbound-gateway> component, I need to add the attribute "rest-template" in the outbound-gateway.
So, the working solution is the (1) that I posted above, together with this configuration:
<int-http:outbound-gateway rest-template="restTemplate" ... />
Otherwise, it will be used a default rest-template (without custom messageConverters).

Related

java spring session how to custom cookie key

I using spring session HttpSession, how can I custom cookie key, I tried this solution: Custom cookie name when using Spring Session. but it does not work, the name is SESSION still.
my config like below:
<context:annotation-config/>
<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
<context:property-placeholder location="classpath:/env/env_test.properties"/>
<bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:port="${spring.redis.port}" p:hostName="${spring.redis.host}"/>
<bean id="mapSessionRepository" class="org.springframework.session.MapSessionRepository" />
<bean id="sessionRepositoryFilter"
class="org.springframework.session.web.http.SessionRepositoryFilter">
<constructor-arg ref="sessionRepository"/>
<property name="httpSessionStrategy">
<bean class="org.springframework.session.web.http.CookieHttpSessionStrategy">
<property name="cookieName" value="_session_id" />
</bean>
</property>
</bean>
You just need to add below bean to create custom cookie.
<bean class ="org.springframework.session.web.http.DefaultCookieSerializer">
<property name="cookieName" value="JSESIONID"></property>
</bean>
JESSIONID - Custom Cookie Name
Please remove below configuration fr`enter code here`om xml file.
<bean id="sessionRepositoryFilter"
class="org.springframework.session.web.http.SessionRepositoryFilter">
<constructor-arg ref="sessionRepository"/>
<property name="httpSessionStrategy">
<bean class="org.springframework.session.web.http.CookieHttpSessionStrategy">
<property name="cookieName" value="_session_id" />
</bean>
</property>
</bean>
You have to create a bean with class
org.springframework.session.web.http.DefaultCookieSerializer
So inside of that bean, you define your custom properties, after you declare that bean as a property of the following:
org.springframework.session.web.http.CookieHttpSessionStrategy
By example:
<bean id="yourCookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer">
<property name="cookieName" value="yourCustomName"/>
<property name="cookiePath" value="yourCustomPath"/>
...
</bean>
<bean id="cookieHttpSessionStrategy" class="org.springframework.session.web.http.CookieHttpSessionStrategy">
<property name="cookieSerializer" ref="yourCookieSerializer"></property>
</bean>

Spring: How to inject a property with a non-setter method?

Is it possible to inject a property bean through a method with a signature doesn't start with set?
Specifically, I'm trying to use Spring to configure an embedded Jetty instance and I need to be able to inject a servlet bean via an addServlet() method.
I am looking at Jetty/Tutorial/Embedding Jetty documentation. I guess you mean calling ServletContextHandler.addServlet(). You have few choices:
#Configuration (since 3.0)
My favourite approach. You can configure everything using Java!
#Configuration
public class Jetty {
#Bean(initMethod = "start")
public Server server() {
Server server = new Server(8080);
server.setHandler(context());
return server;
}
#Bean
public ServletContextHandler context() {
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
context.addServlet(servlet(), "/*");
return context;
}
#Bean
public ServletHolder servletHolder() {
return new ServletHolder(helloServlet());
}
#Bean
public HelloServlet helloServlet() {
return new HelloServlet();
}
}
Inheritance/decorating
You can inherit from or wrap original ServletContextHandler class to follow Java bean naming conventions. Of course it requires an extra class, but makes Jetty class Spring-friendly. You can even publish such wrapper or maybe someone already did that?
MethodInvokingFactoryBean
I don't like this approach as it seems too low level. Basically you create a bean that calls arbitrary method with arbitrary arguments:
<bean id="javaVersion" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="servletContextHandler"/>
<property name="targetMethod" value="addServlet"/>
<property name="arguments">
<list>
<ref bean="yourServlet"/>
</list>
</property>
</bean>
just the spring file adapted to Jetty 7. It's possible to add yours contextHandlers...
<bean id="contexts"
class="org.eclipse.jetty.server.handler.ContextHandlerCollection" />
<context:property-placeholder location="src/main/resources/ws.properties" />
<!-- Manually start server after setting parent context. (init-method="start") -->
<bean id="jettyServer" class="org.eclipse.jetty.server.Server"
destroy-method="stop">
<property name="threadPool">
<bean id="ThreadPool" class="org.eclipse.jetty.util.thread.QueuedThreadPool">
<property name="minThreads" value="10" />
<property name="maxThreads" value="50" />
</bean>
</property>
<property name="connectors">
<list>
<bean id="Connector" class="org.eclipse.jetty.server.nio.SelectChannelConnector">
<property name="port" value="8181" />
</bean>
</list>
</property>
<property name="handler">
<bean id="handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
<property name="handlers">
<list>
<ref bean="contexts" />
<bean id="defaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler" />
<bean class="org.eclipse.jetty.servlet.ServletContextHandler"
p:contextPath="/${ws.context.path}">
<property name="sessionHandler">
<bean class="org.eclipse.jetty.server.session.SessionHandler" />
</property>
<property name="servletHandler">
<bean class="org.eclipse.jetty.servlet.ServletHandler">
<property name="servlets">
<list>
<bean class="org.eclipse.jetty.servlet.ServletHolder"
p:name="spring-ws">
<property name="servlet">
<bean
class="org.springframework.ws.transport.http.MessageDispatcherServlet" />
</property>
<property name="initParameters">
<map>
<entry key="contextConfigLocation" value="classpath:/spring-ws-context.xml" />
</map>
</property>
</bean>
</list>
</property>
<property name="servletMappings">
<list>
<bean class="org.eclipse.jetty.servlet.ServletMapping"
p:servletName="spring-ws" p:pathSpec="/*" />
</list>
</property>
</bean>
</property>
</bean>
<bean class="org.eclipse.jetty.server.handler.RequestLogHandler" />
</list>
</property>
</bean>
</property>
</bean>

Spring resource

Problem: I want to make the below bean definitions (specified in aaplicationContext.xml) optional for "org.springframework.web.context.ContextLoaderListener". If i am not providing the "emsPropLocation" context parameter correctly, tomcat web container is not able to initialized properly and it is obvious reason. Is there any way to make it optional?
appicationContext.xml:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="false"/>
<property name="location" value="file:/#{contextParameters.emsPropLocation}" />
</bean>
<!-- TIBCO Connection Factory Bean -->
<bean id="tibcoConnectionFactory" class="com.tibco.tibjms.TibjmsConnectionFactory">
<constructor-arg value="${emsServerURL}"/>
<property name="userName" value="${emsUserName}"/>
<property name="userPassword" value="${emsPassword}"/>
<property name="connAttemptCount" value="${connAttemptCount}"/>
<property name="connAttemptDelay" value="${connAttemptDelay}"/>
<property name="connAttemptTimeout" value="${connAttemptTimeout}"/>
<property name="reconnAttemptCount" value="${reconnAttemptCount}"/>
<property name="reconnAttemptDelay" value="${reconnAttemptDelay}"/>
<property name="reconnAttemptTimeout" value="${reconnAttemptTimeout}"/>
</bean>
<!-- bean id="tibcoUtil" class="com.nr.ns.upload.TibcoUtil" scope="singleton">
<constructor-arg value="true"/>
</bean-->
<bean id="jmsExceptionListener" class="com.nr.ns.upload.LogMsgExceptionListener"/>
<!-- Spring CachingConnectionFactory Bean -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<constructor-arg ref="tibcoConnectionFactory"/>
<property name="reconnectOnException" value="${reconnectOnException}"/>
<property name="sessionCacheSize" value="${sessionCacheSize}"/>
<property name="exceptionListener" ref="jmsExceptionListener"/>
</bean>
<!-- JMSTemplate Bean -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<constructor-arg ref="connectionFactory"/>
<property name="receiveTimeout" value="${receiveTimeout}"/>
<property name="deliveryMode" value="${deliveryMode}"/>
</bean>
We are keeping WAR file outside tomcat and to make it happen we have "app.xml" file inside TOMCAT_HOME/conf/Catalina/localhost.
app.xml:
<Context path="/app"
docBase="/abc/ccp/app.war"
reloadable="true"
unpackWAR="false">
<Parameter name="emsPropLocation"
value="/xyz/config/EMSServerConf.properties"
override="false"/>
</Context>
have a try to change the ignoreResourceNotFound property of your propertyConfigurer to true.
If contextParameters.emsPropLocation is not set, this will default to what is afer the colon.
<property name="location" value="file:/#{contextParameters.emsPropLocation:/xyz/config/EMSServerConf.properties}" />

How do I set up custom Mongo formatters in Spring?

I've been at this for a few hours and haven't found anyone that's gotten this working yet. I want to persist a BigDecimal object in Mongo, but Mongo doesn't natively support BigDecimal. I followed Spring's docs here but no luck.
From what I can tell Spring isn't injecting my custom converter classes into Mongo when it's writing to the db. Here's what I have done:
My applicationContext-services.xml
...
<!-- Factory bean that creates the Mongo instance -->
<mongo:mongo
host="localhost"
port="1234" />
<mongo:db-factory
dbname="solar"
mongo-ref="mongo"/>
<mongo:mapping-converter>
<mongo:custom-converters>
<mongo:converter>
<bean class="com.mine.BigDecimalReadConverter"/>
</mongo:converter>
<mongo:converter>
<bean class="com.mine..BigDecimalWriteConverter"/>
</mongo:converter>
</mongo:custom-converters>
</mongo:mapping-converter>
<!-- Use this post processor to translate any MongoExceptions thrown in #Repository annotated classes -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="mongoDbTest"
class="com.mine.MongoDbTest">
<property name="mongoTemplate">
<ref local="mongoTemplate" />
</property>
</bean>
The error I'm getting is:
java.lang.IllegalArgumentException: Multiple constructors with arguments found in class java.math.BigDecimal! Annotate one with #PreferedConstructor explicitly to select it to be used in persistence operations.
at org.springframework.data.mapping.PreferredConstructorDiscoverer.<init>(PreferredConstructorDiscoverer.java:81)
Try using this for converter support:
<bean id="mappingContext"
class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" lazy-init="true"/>
<bean id="defaultMongoTypeMapper"
class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper" lazy-init="true">
<constructor-arg name="typeKey"><null/></constructor-arg>
</bean>
<bean id="mappingMongoConverter"
class="org.springframework.data.mongodb.core.convert.MappingMongoConverter" lazy-init="true" >
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<constructor-arg name="mappingContext" ref="mappingContext" />
<property name="typeMapper" ref="defaultMongoTypeMapper" />
</bean>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate" lazy-init="true">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<constructor-arg name="mongoConverter" ref="mappingMongoConverter" />
</bean>
Here is how I solved this. The order in which you define the beans matters. So my app.xml that I got it working with is:
<bean id="mappingContext" class="org.springframework.data.document.mongodb.mapping.MongoMappingContext"/>
<bean id="readConverter" class="com.mine.BigDecimalReadConverter"/>
<bean id="writeConverter" class="com.mine.BigDecimalWriteConverter"/>
<mongo:mapping-converter id="mappingConverter">
<mongo:custom-converters>
<mongo:converter ref="readConverter" />
<mongo:converter ref="writeConverter" />
</mongo:custom-converters>
</mongo:mapping-converter>
<!-- Factory bean that creates the Mongo instance -->
<mongo:mongo
host="${${environment}.mongodb.host}"
port="${${environment}.mongodb.port}" />
<mongo:db-factory
dbname="${${environment}.mongodb.databaseName}"
mongo-ref="mongo"/>
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
<constructor-arg name="mongoConverter" ref="mappingConverter"/>
</bean>
<!-- Use this post processor to translate any MongoExceptions thrown in #Repository annotated classes -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

Spring and Mybatis multiple data sources setup

My applications uses Spring3+MyBatis3. I'm trying to setup multiple data source for it. Setup looks like:
<!-- db1 setup-->
<bean id="db1SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:configLocation="WEB-INF/mybatis/sqlMapConfig.xml"
p:dataSource-ref="db1DataSource" />
<bean id="db1SqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="db1SqlSessionFactory"/>
</bean>
<!-- db2 setup -->
<bean id="db2SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
p:configLocation="WEB-INF/mybatis/sqlMapConfig.xml"
p:dataSource-ref="db2DataSource" />
<bean id="db2SqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="db2SqlSessionFactory"/>
</bean>
In the logs, I've found this message:
No unique bean of type [org.apache.ibatis.session.SqlSessionFactory] is defined: expected single matching bean but found 2: [db1SqlSessionFactory, db2SqlSessionFactory]
I googled and looked into mybatis manuals but couldn't find way how to setup multiple data sources with mybatis.
Any ideas?
also solved ! just reference your factory bean in MapperScannerConfigurer : sqlSessionFactoryBeanName
First data source >>>>>>>
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<bean id="sqlSessionFactory1" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource1"/>
</bean>
<bean id="MapperScannerConfigurer1" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.package.p1"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory1"/>
</bean>
Second data source >>>>>>
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource2"/>
</bean>
<bean id="MapperScannerConfigurer1" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.package.p2"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory2"/>
</bean>
solved, the problem was that I must specify directly reference to sqlSessionFactory
<bean id="myDao" class="org.mybatis.spring.mapper.MapperFactoryBean"
p:sqlSessionTemplate-ref="db1SqlSessionTemplate"
p:mapperInterface="my.project.domain.dao.MyDao"
p:sqlSessionFactory-ref="db1SqlSessionFactory"/>
In a DAO implementation use SqlSessionTemplate instead of SqlSessionDaoSupport. Inject bean db1SqlSessionTemplate or db2SqlSessionTemplate.
#Repository
public class TestDaoImpl implements TestDao{
#Autowired
private SqlSession db1SqlSessionTemplate;
...
db1SqlSessionTemplate.selectList("testSelect");
...
}
When extending SqlSessionDaoSupport the context Spring does not know that you use SqlSession.

Resources