I'm utilizing spring for about a year and everything was pretty obvious and simple until I faced spring integration. Ashamed, I can't create Outbound Gateway to send message to remote JMS (ActiveMQ) channel. Before integration I just used JmsTemplates and #JmsListeners directly, there were no problems at all.
What's the difference between request-destination and request-channel?
Here are my configs:
#Configuration
#EnableJms
public class JmsConfig {
...
#Value("${activemq.url}")
private String brokerUrl;
#Bean
public JmsTemplate jmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate(queueConnectionFactory());
jmsTemplate.setDefaultDestinationName(bookingChannelName);
return jmsTemplate;
}
/*
#Bean(name = "bookingChannel")
public Queue activeMQQueue() {
return new ActiveMQQueue(bookingChannelName);
}
*/
#Bean
public JmsListenerContainerFactory jmsListenerContainerFactory() {
SimpleJmsListenerContainerFactory listenerFactory = new SimpleJmsListenerContainerFactory();
listenerFactory.setConnectionFactory(queueConnectionFactory());
return listenerFactory;
}
...
}
and an xml one, where all I've got in root beans element is:
<jms:outbound-gateway request-destination-name="reqDestination" request-channel="bookingChannel" />
Then, there is a gateway code:
#MessagingGateway
public interface BookingGateway<T> {
#Gateway
void bookTicket(T ticket);
}
And finally, here is how I use a gateway:
#Component
public class BookingGatewayImpl<T> {
#Autowired
private BookingGateway bookingGateway;
public <U> void bookTicket(T ticket, BiConsumer<T, U> onStatusReceived) {
bookingGateway.bookTicket(ticket); // second param is not utilized yet
}
}
And when ticket is about to be booked, I get:
send is not supported, because no request channel has been configured
Also, I am not able to uncomment ActiveMQQueue bean from the first listing because spring says it is not compatible with MessageChannel:
Bean named 'bookingChannel' must be of type [org.springframework.messaging.MessageChannel], but was actually of type [org.apache.activemq.command.ActiveMQQueue]
Why oh why should the destination be of MessageChannel type? What exactly am I doing wrong and how to get this ticket message to be sent?
bookingChannel is a MessageChannel between your MessagingGateway and the jms gateway. The destination is the AMQP Queue.
Use
#Gateway(requestChannel="bookingChannel")
#Bean(name = "bookingDestination")
public Queue activeMQQueue() {
return new ActiveMQQueue(bookingChannelName);
}
#Bean(name = "bookingChannel")
public MessageChannel bookingChannel() {
return new DirectChannel();
}
<jms:outbound-gateway request-destination-name="bookingDestination" request-channel="bookingChannel" />
Finally, came up with following configuration. Almost understood the way it's working now:
<?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:int="http://www.springframework.org/schema/integration"
xmlns:jms="http://www.springframework.org/schema/integration/jms"
xmlns:id="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd http://www.springframework.org/schema/integration/jms http://www.springframework.org/schema/integration/jms/spring-integration-jms.xsd">
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="nio://127.0.0.1:61616"/>
</bean>
<bean id="requestQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="bookingChannel"/>
</bean>
<id:channel id="requestChannel"/>
<bean id="channelInterceptor" class="c.e.mentoring.integration.gateway.RequestChannelInterceptor"/>
<jms:outbound-channel-adapter channel="requestChannel" destination="requestQueue"/>
<int:channel-interceptor ref="channelInterceptor"/>
</beans>
Related
Im trying to convert my context xml of hikari db setting to Beans method
<bean id="proxyConfig"
factory-bean="proxyConfigSupport"
factory-method="create"/>
<bean id="proxyConfigSupport" class="net.ttddyy.dsproxy.support.ProxyConfigSpringXmlSupport">
<property name="dataSourceName" value="dataSourceDefaultName"/>
<property name="queryListener" ref="queryListener"/>
</bean>
Im trying to understand how to convert it so I tried this way
#Bean(name = "proxyConfigSupport")
public ProxyConfigSpringXmlSupport proxyDataSource(ChainListener queryListener) {
ProxyConfigSpringXmlSupport proxyConfigSpringXmlSupport = new ProxyConfigSpringXmlSupport();
proxyConfigSpringXmlSupport.setDataSourceName("dataSourceDefaultName");
proxyConfigSpringXmlSupport.setQueryListener(queryListener);
return proxyConfigSpringXmlSupport;
}
But what does it mean "proxyConfig" factory-bean="proxyConfigSupport"
How do i set it the same ?
#Bean(name = "proxyConfig")
public ProxyConfig proxyConfig(ProxyConfigSpringXmlSupport proxyConfigSpringXmlSupport) {
ProxyConfig proxyConfig = new ProxyConfig();
return proxyConfig;
/*
<bean id="proxyConfig"
factory-bean="proxyConfigSupport"
factory-method="create"/>
*/
}
Lets divide the XML up into sections.
<bean id="proxyConfigSupport" class="net.ttddyy.dsproxy.support.ProxyConfigSpringXmlSupport">
<property name="dataSourceName" value="dataSourceDefaultName"/>
<property name="queryListener" ref="queryListener"/>
</bean>
You already got that bean method
#Bean
public ProxyConfigSpringXmlSupport proxyConfigSupport(ChainListener queryListener) {
ProxyConfigSpringXmlSupport proxyConfigSpringXmlSupport = new ProxyConfigSpringXmlSupport();
proxyConfigSpringXmlSupport.setDataSourceName("dataSourceDefaultName");
proxyConfigSpringXmlSupport.setQueryListener(queryListener);
return proxyConfigSpringXmlSupport;
}
Now the second one
<bean id="proxyConfig"
factory-bean="proxyConfigSupport"
factory-method="create"/>
Is nothing more then a description of what should take place. It defines a FactoryBean and specifies it do delegate the getObject() to the proxyConfigSupport bean and call the create() method. This is also explained in the Spring Framework Reference Guide.
As an #Bean method is also, kind of, a factory for beans, you can do something like this.
#Bean
public ProxyConfig proxyConfig(ProxyConfigSpringXmlSupport proxyConfigSupport) {
return proxyConfigSupport.create();
}
Nothing more and nothing less.
I have a Spring Batch job that I am launching from a Spring boot application, like so:
Main:
#SpringBootApplication
#ImportResource("jobApplicationContext.xml")
public class BatchJobRunner {
public static void main(String[] args) {
SpringApplication.run(BatchJobRunner.class, args);
}
}
In my job's application context, I have the following items:
<?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:batch="http://www.springframework.org/schema/batch"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath:*.properties"/>
<bean id="jobRegistry" class="org.springframework.batch.core.configuration.support.MapJobRegistry"/>
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean"/>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
</bean>
<batch:job id="myJob" job-repository="jobRepository">
<batch:split id="main" task-executor="simpleAsyncTaskExecutor" next="step3">
<batch:flow>
<batch:step id="flow1">
<!-- definition -->
</batch:step>
</batch:flow>
<batch:flow>
<batch:step id="flow2">
<!-- definition -->
</batch:step>
</batch:flow>
</batch:split>
<batch:step id="step3">
<batch:tasklet ref="someTasklet"/>
</batch:step>
</batch:job>
</beans>
And finally, I just run it like this:
java -jar my-module.jar
The job starts but:
It does not print out anything. Here is my log4j.properties:
log4j.rootLogger=INFO, stdout
log4j.logger.org.springframework.batch=INFO
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
The job hangs at the end. I put a Sys.out.print in the step3 and it does indeed print, but the spring boot application keeps running and never exits. I also tried to add an #AfterJob with a System.exit(..) and it didn't help either.
I am using Spring f/w 4.1.8, spring boot 1.2.8 and spring batch 3.0.6 (i cannot upgrade my spring-core as some dependencies use that version).
Any idea what I am doing wrong?
Edit:
Looks like beforeJob and afterJob listeners are not firing at all.
ClassCastExeption can be result of Spring different binding (early in xml and late in java). Try configure your batch fully in java. Result can look like this (this is with stored repository in DB, inmemory repository should looks similar):
#Configuration
#EnableBatchProcessing
#ComponentScan("my.batch.*")
#ImportResource("classpath:batch-config.xml")
#PropertySource(value = "classpath:batch.properties")
public class BatchConfiguration implements BatchConfigurer {
#Autowired
private DataSource dataSource;
private PlatformTransactionManager transactionManager;
private JobRepository jobRepository;
private JobLauncher jobLauncher;
private JobExplorer jobExplorer;
#Override
public JobRepository getJobRepository() throws Exception {
return jobRepository;
}
#Override
public PlatformTransactionManager getTransactionManager() throws Exception {
return transactionManager;
}
#Override
public JobLauncher getJobLauncher() throws Exception {
return jobLauncher;
}
#Override
public JobExplorer getJobExplorer() throws Exception {
return jobExplorer;
}
#PostConstruct
public void initialize() {
try {
transactionManager = new DataSourceTransactionManager(dataSource);
jobRepository = createJobRepository();
jobExplorer = createJobExplorer();
jobLauncher = createJobLauncher();
} catch (Exception ex) {
throw new BatchConfigurationException(ex);
}
}
private JobRepository createJobRepository() throws Exception {
JobRepositoryFactoryBean repoFactory = new JobRepositoryFactoryBean();
repoFactory.setDataSource(dataSource);
repoFactory.setTransactionManager(transactionManager);
repoFactory.setTablePrefix(PREFIX);
repoFactory.afterPropertiesSet();
return repoFactory.getObject();
}
private JobExplorer createJobExplorer() throws Exception {
JobExplorerFactoryBean explorerFactory = new JobExplorerFactoryBean();
explorerFactory.setDataSource(dataSource);
explorerFactory.setTablePrefix(PREFIX);
explorerFactory.afterPropertiesSet();
return explorerFactory.getObject();
}
private JobLauncher createJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
}
You miss #EnableBatchProcessing docs.
i'm new to Spring and Spring integration, and i have a simple task to accomplish. Filtering some emails by it's subject though a regex and register some info in the db.
I've set the JavaMailProperties and the test gives me the output of the read emails but the method i'm setting with service-activator is never called and this is actually making me have a strong headache.
The following is the xml configuration file:
<?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:mail="http://www.springframework.org/schema/integration/mail"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/integration/mail
http://www.springframework.org/schema/integration/mail/spring-integration-mail-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<util:properties id="javaMailProperties">
<prop key="mail.store.protocol">pop3</prop>
<prop key="mail.debug">true</prop>
</util:properties>
<mail:inbound-channel-adapter id="pop3Adapter"
store-uri="pop3://username:password#mail..example.com:110/INBOX"
channel="recieveEmailChannel"
should-delete-messages="false"
auto-startup="true"
java-mail-properties="javaMailProperties"
mail-filter-expression="subject matches '(^Presente+\\s([1-9]{1})+(\\s[-]\\s)+([A-Z]{4,})+(\\s[A-Z]{6,})$)'">
<int:poller max-messages-per-poll="10" fixed-delay="10000"/>
</mail:inbound-channel-adapter>
<int:channel id="recieveEmailChannel">
<int:interceptors>
<int:wire-tap channel="logger"/>
</int:interceptors>
</int:channel>
<int:logging-channel-adapter id="logger" level="DEBUG"/>
<int:service-activator input-channel="recieveEmailChannel" ref="leggiMail" method="processa_mail"/>
<bean id="leggiMail" class="it.jenia.ac.mail.rapportini.LeggiMail">
</bean>
</beans>
The LeggiMail class with the processa_mail method is very simple:
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.stereotype.Service;
#Service
public class LeggiMail {
private static Logger logger = Logger.getLogger(LeggiMail.class);
public static int count_get = 0;
#ServiceActivator
public void processa_mail(MimeMessage mimeMessage) {
count_get++;
logger.debug("porcessa_mail working");
}
The test class i'm using this application in:
#ContextConfiguration(locations = { "classpath*:/test-spring-configuration.xml" })
#RunWith(SpringJUnit4ClassRunner.class)
#TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class })
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
public class LeggiMailTest {
private static Logger logger = Logger.getLogger(LeggiMailTest.class);
#Autowired
LeggiMail lm;
#Test
#Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class)
public void test_processa_mail(){
logger.debug("Test started");
}
}
The log Test started appears correctly in the console, but the log porcessa_mail working never shows up..
The first tutorial i found on this subject just spoke about a method that would have been called by default by the context. http://blog.solidcraft.eu/2011/04/read-emails-from-imap-with-spring.html (And it says that the method "processa_mail" should be called by default when the context is loaded, cause it's a service-activator.
Reading this tutorial about service activator didn't help enough: http://docs.spring.io/spring-integration/reference/html/messaging-endpoints-chapter.html
When you try to test some async stuff you some barrier to prevent the main thread to be stopped early, than it is neccessary for entire test-case.
The simples way is add Thread.sleep() before the end of test method.
But better solution is based on some synchonizer, like CountDonwLatch.
From other side there is QueueChannel in the Spring Integration. You can use it as an output-channel for <service-activator>. Inject it to the test class and wait on the output.receive(10000). And assert... the result message to make your test realy unit-test.
Can any one suggest a Redis (NoSQL DB) example for a Collection type?
Generally we use the following (in Spring):
#Cacheable(value = "PRODUCT", key = "#productId" )
public Map<String,Object> findProduct(String productId, String productName)
{ return map; }
which stores the key and value as String, but I need for:
public Map<RestaurantId,Set<Order>>find(String RestaurantId, String productName){ return map; }
Make sure your objects are Serializable, and then simply use the Spring Data Redis cache abstraction (2015 link)
Example copied from the documentation above:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:use-pool="true"/>
<!-- redis template definition -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnectionFactory"/>
<!-- turn on declarative caching -->
<cache:annotation-driven />
<!-- declare Redis Cache Manager -->
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" c:template-ref="redisTemplate"/>
</beans>
You could use Redisson Redis Java client which provides Spring Cache manager as well. It supports both TTL and maxIdleTime parameters.
Code example:
#Configuration
#ComponentScan
#EnableCaching
public static class Application {
#Bean(destroyMethod="shutdown")
RedissonClient redisson() throws IOException {
Config config = new Config();
config.useClusterServers()
.addNodeAddress("redis://127.0.0.1:7004", "redis://127.0.0.1:7001");
return Redisson.create(config);
}
#Bean
CacheManager cacheManager(RedissonClient redissonClient) {
Map<String, CacheConfig> config = new HashMap<String, CacheConfig>();
// create "testMap" cache with ttl = 24 minutes and maxIdleTime = 12 minutes
config.put("testMap", new CacheConfig(24*60*1000, 12*60*1000));
return new RedissonSpringCacheManager(redissonClient, config);
}
}
I am using org.springframework.ws.client.core.WebServiceTemplate for making Web Service calls. How can i configure timeout for the call.
If you are using Spring Webservices 2.1.0 version, You can set timeout using HttpComponentsMessageSender.
CommonsHttpMessageSender are deprecated and not recommended by Spring anymore.
The way I have it implemented, I define my WebServiceTemplate to use HttpComponentsMessageSender.
Values are in Milliseconds
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<property name="defaultUri" value="${endpoint.url}" />
<property name="marshaller" ref="marshaller" />
<property name="unmarshaller" ref="unmarshaller" />
<property name="messageSender">
<bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
<property name="connectionTimeout" value="1200000" />
<property name="readTimeout" value="1200000" />
</bean>
</property>
</bean>
Just Make sure you have in your pom file, you added the following
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.2.1</version>
<scope>compile</scope>
</dependency>
Same as Sathish answer, but programmatically (Spring 4+):
#Component
public class MyWebServiceGatewaySupport extends WebServiceGatewaySupport
{
#Value("${my.ws.readtimeout}")
private String readTimeout;
#Value("${my.ws.connectiontimeout}")
private String connectionTimeout;
Object marshalSendAndReceive(String endpoint, Object requestPayload)
{
WebServiceTemplate wsTemplate = this.getWebServiceTemplate();
WebServiceMessageSender[] senders = wsTemplate.getMessageSenders();
for (WebServiceMessageSender sender: senders)
{
try
{
int readTimeoutMsec = Integer.parseInt(readTimeout);
int connTimeoutMsec = Integer.parseInt(connectionTimeout);
HttpComponentsMessageSender httpSender = (HttpComponentsMessageSender) sender;
httpSender.setReadTimeout(readTimeoutMsec);
httpSender.setConnectionTimeout(connTimeoutMsec);
}
catch (ClassCastException|NumberFormatException cex)
{
logger.warn("Cannot set WS timeout: " + cex.getMessage());
}
}
return wsTemplate.marshalSendAndReceive(endpoint, requestPayload);
}
}
Since Spring Webservices 2.2, you can also use Spring's ClientHttpRequestMessageSender:
#Service
public class CustomWebServiceImpl extends WebServiceGatewaySupport implements CustomWebService {
private static final int CONNECTION_TIMEOUT = (10 * 1000);
private static final int READ_TIMEOUT = (10 * 1000);
public CustomWebServiceImpl() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(CONNECTION_TIMEOUT);
requestFactory.setReadTimeout(READ_TIMEOUT);
setMessageSender(new ClientHttpRequestMessageSender(requestFactory));
}
(...)
}
(no dependency to Apache HTTP Components required)
The below code worked for me.
#Bean
public YourClassImpl yourClassImpl(Jaxb2Marshaller marshaller, HttpComponentsMessageSender httpComponentsMessageSender) {
YourClassImpl client = new YourClassImpl();
client.setDefaultUri(PiiProperties.SOAP_ACTION.getValue());
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
client.setMessageSender(httpComponentsMessageSender);
return client;
}
#Bean
public HttpComponentsMessageSender httpComponentsMessageSender() {
HttpComponentsMessageSender sender = new HttpComponentsMessageSender();
sender.setReadTimeout(1000);
sender.setConnectionTimeout(1000);
return sender;
}
If you want that kind of control, you can
either switch to CommonsHttpMessageSender, which uses the Jakarta Commons
HttpClient
or subclass HttpUrlConnectionMessageSender and in the
prepareConnection(HttpURLConnection) method call
UrlConnection.setReadTimeOut(int)
That's how I did:
#Configuration
public class MunisServiceConfig {
#Value("${service.uri}")
private String soapUri;
#Bean
Jaxb2Marshaller jaxb2Marshaller() {
Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
jaxb2Marshaller.setContextPath(CheckStatePayment.class.getPackage().getName());
return jaxb2Marshaller;
}
#Bean
public WebServiceTemplate munisService() {
WebServiceTemplate template = new WebServiceTemplate();
template.setMarshaller(jaxb2Marshaller());
template.setUnmarshaller(jaxb2Marshaller());
template.setDefaultUri(soapUri);
HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender();
httpComponentsMessageSender.setReadTimeout(3000);
httpComponentsMessageSender.setConnectionTimeout(5000);
template.setMessageSender(httpComponentsMessageSender);
return template;
}
}
This article will probably sort you out:
http://onebyteatatime.wordpress.com/2009/03/19/how-to-set-socket-timeout-using-spring-webservicetemplate/
The way I have it implemented, I define my WebServiceTemplate to use CommonsHttpMessageSender:
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory" />
<property name="messageSender">
<bean
class="org.springframework.ws.transport.http.CommonsHttpMessageSender">
</bean>
</property>
</bean>
Then, in code, I get the messageSender and set the timeout on it. You could equally do this in your xml.
CommonsHttpMessageSender messageSender = (CommonsHttpMessageSender)webServiceTemplate.getMessageSenders()[0];
messageSender.getHttpClient().getParams().setSoTimeout(timeoutMillis);
This code works with Spring Boot (verified on 2.1.5.RELEASE):
#Configuration
public class ExampleServiceClientConfiguration {
#Value("${example-service.uri}")
private String exampleServiceUri;
#Value("${example-service.timeout:120}")
private int exampleServiceTimeout;
#Bean
public ExampleServiceClient exampleServiceClient() {
ExampleServiceClient client = new ExampleServiceClient();
client.setMessageSender(httpUrlConnectionMessageSender());
client.setDefaultUri(exampleServiceUri);
client.setMarshaller(marshaller());
client.setUnmarshaller(marshaller());
return client;
}
#Bean
HttpUrlConnectionMessageSender httpUrlConnectionMessageSender() {
HttpUrlConnectionMessageSender sender = new HttpUrlConnectionMessageSender();
Duration timeout = Duration.ofSeconds(exampleServiceTimeout);
sender.setReadTimeout(timeout);
sender.setConnectionTimeout(timeout);
return sender;
}
#Bean
public Jaxb2Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath(ObjectFactory.class.getPackageName());
return marshaller;
}
}
For the CommonsHttpMessageSender, we can set the timeout in the following way:
<bean id="httpParams" class="org.apache.commons.httpclient.params.HttpClientParams">
<!-- Timeout in milliseconds: in this case 1 minute -->
<property name="soTimeout" value="60000" />
</bean>
<bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
<property name="params" ref="httpParams" />
</bean>
<!-- Define the message sender used by all web service templates -->
<bean id="webServiceMessageSender" class="org.springframework.ws.transport.http.CommonsHttpMessageSender">
<constructor-arg>
<ref bean="httpClient"/>
</constructor-arg>
</bean>
and ref the webServiceMessageSender as below:
<bean id="genericWebServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
<property name="messageSender" ref="webServiceMessageSender"/>
</bean>