Spring RabbitMQ SimpleRabbitListenerContainerFactory usage - java

From the docs, I want to use consume from queues by dynamically changing the consumers without restarting the application.
I do see that Spring RabbitMQ latest version supports the same, but no clue/example/explanation to change the same. I couldn't see proper source code for the same or how to pass params like maxConcurrentConsumers
I am using XML based configuration of Spring RabbitMQ along with Spring integration
<bean id="rabbitListenerContainerFactory"
class="org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory">
<property name="connectionFactory" ref="rabbitConnectionFactory"/>
<property name="concurrentConsumers" value="3"/>
<property name="maxConcurrentConsumers" value="10"/>
<property name="acknowledgeMode" value="AUTO" />
</bean>
<int-amqp:inbound-channel-adapter channel="lowInboundChannel" queue-names="lowLoadQueue" advice-chain="retryInterceptor" acknowledge-mode="AUTO" listener-container="rabbitListenerContainerFactory" />
<int-amqp:inbound-channel-adapter channel="highInboundChannel" queue-names="highLoadQueue" advice-chain="retryInterceptor" acknowledge-mode="AUTO" listener-container="rabbitListenerContainerFactory" />
Can anyone guide me how to dynamically configure the consumers?

First of all you shouldn't share the same rabbitListenerContainerFactory for different <int-amqp:inbound-channel-adapter>s, because they do this:
protected void onInit() {
this.messageListenerContainer.setMessageListener(new ChannelAwareMessageListener() {
So, only last adapter wins.
From other side there is even no reason to have several adapters. You can specify queue-names="highLoadQueue,lowLoadQueue" for a single adapter.
Although in case of listener-container you must specify queues on the SimpleRabbitListenerContainerFactory.
If you want to change some rabbitListenerContainerFactory options at runtime, you can just inject it to some service and invoke its setters.
Let me know if I have missed anything.

Related

Mule / Spring transaction is not propagated

I have a problem with database transactions in mule flow. This is the flow that i have defined:
<flow name="createPortinCaseServiceFlow">
<vm:inbound-endpoint path="createPortinCase" exchange-pattern="request-response">
<custom-transaction action="ALWAYS_BEGIN" factory-ref="muleTransactionFactory"/>
</vm:inbound-endpoint>
<component>
<spring-object bean="checkIfExists"/>
</component>
<component>
<spring-object bean="createNewOne"/>
</component>
</flow>
The idea is that in checkIfExists we verify if some data exists (in the database) if it does we throw an exception. If it does not we go to createNewOne and create a new data.
The problem
is that if we run the flow concurrently new objects will be created multiple times in createNewOne and they should not be as we invoke checkIfExists just before it. This means that the transaction is not working properly.
More info:
both createNewOne and checkIfExists have following annotation:
#Transactional(propagation = Propagation.MANDATORY)
Definition of muleTransactionFactory looks as follows
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="dataSource" ref="teleportNpDataSource"/>
<property name="entityManagerFactory" ref="npEntityManagerFactory"/>
<property name="nestedTransactionAllowed" value="true"/>
<property name="defaultTimeout" value="${teleport.np.tm.transactionTimeout}"/>
</bean>
<bean id="muleTransactionFactory" class="org.mule.module.spring.transaction.SpringTransactionFactory">
<property name="manager" ref="transactionManager"/>
</bean>
I have set the TRACE log level (as #Shailendra suggested) and i have discovered that transaction is reused in all of the spring beans:
00:26:32.751 [pool-75-thread-1] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Participating in existing transaction
In the logs transaction is commited at the same time which means that those transactions are created properly but there are executed concurrently which causes an issue.
Issue may be because multi-threading. When you post multiple objects to VM, they will be dispatched to multiple receiving threads and if multi-threading is not properly handled in your components then you might run into the issue you mentioned.
Test making these change - Add VM connector reference and turn off the dispatcher threading profile. That way, VM will process messages one at a time as there is just one dispatcher thread.
<vm:connector name="VM" validateConnections="true" doc:name="VM" >
<dispatcher-threading-profile doThreading="false"/>
</vm:connector>
<flow name="testFlow8">
<vm:inbound-endpoint exchange-pattern="one-way" doc:name="VM" connector-ref="VM">
<custom-transaction action="NONE"/>
</vm:inbound-endpoint>
</flow>
Be aware of the fact that, if the number of incoming messages on VM are very high and time taken to process each message is more, then you may run into SEDA-QUEUE errors due to no thread availability.
If without threading, your flow is behaving correctly then you may need to look how your components should behave in multi-threading.
Hope That helps!

Spring MVC - How can I use different timeouts for my resttemplates?

I am using Spring MVC with Spring 3.1. I have a web application that uses many REST services. One of these REST services takes up to an hour to respond - which I can not change. I have my timeout for the RestTemplate set up like this with the timeout set to 60 minutes:
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate ">
<constructor-arg>
<bean class="org.springframework.http.client.CommonsClientHttpRequestFactory">
<property name="readTimeout" value="3600000" />
<property name="connectTimeout" value="3600000" />
</bean>
</constructor-arg>
</bean>
I would like to be able to set all of my other REST calls to a different set of timeouts. Any ideas on how to do this?
Thanks,
Tim
You can't do this on a method call basis. In other words, all calls on the restTemplate bean will use the same underlying ClientHttpRequestFactory. If you want different requests to use different timeout values, declare multiple RestTemplate beans and inject the appropriate ones in your beans.

How will this connection pooling scenario pan out?

We have a web application that uses C3P0 to pool our connections. We inject C3P0 as a data source into JdbcTemplate. You can see how we do this here:
<bean id="dataSourceDev" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${databasedev.driver}" />
<property name="jdbcUrl" value="${databasedev.url}"/>
<property name="user" value="${databasedev.username}"/>
<property name="password" value="${databasedev.password}"/>
<property name="initialPoolSize" value="5" />
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="1000" />
<property name="acquireIncrement" value="5" />
<property name="maxStatements" value="1000" />
<property name="maxStatementsPerConnection" value="1000"/>
<property name="maxIdleTime" value="10800"/> <!-- 3 hours -->
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg>
<ref bean="dataSourceDev" />
</constructor-arg>
</bean>
<bean id="someDaoBean" class="com.gedi.platform.dao.SomeDaoClass">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<bean id="someResourceClass" class="com.gedi.platform.SomeResourceClass">
<property name="someDao" ref="someDaoBean" />
</bean>
You can see that it's a Java EE web application - it uses Jetty as its application server. My question is, how does Jetty instantiate our beans, and how will that affect connection pooling? If we have dozens of users using the web site at different times, will all of these users be placed in the same connection pool? Or is there only one connection pool per client, in which every HTTP client creates new instances of Resource, DAO, JdbcTemplate and C3P0?
Am I being clear? What I want to have is one connection pool for all HTTP requests, regardless of whether they come from web browsers originating in Boston or New Zealand. That way, the connection pool is exerting its maximum effects. However, if a new connection pool is instantiated for every HTTP client, then the pooling doesn't end up being much of an improvement.
Edit
An important tidbit - We use the Jersey reference implementation of JAX-RS to produce a RESTful interface. So our servlet dispatches requests through Jersey which finds a suitable Resource class/method to handle them. I wonder whether Jersey re-instantiates these classes on every request, or keeps one instance of them at all times.
Neither Jersey nor Jetty are relevant here. Spring is important here. And in Spring every bean (like your dataSourceDev, jdbcTemplate and someDaoBean) are singletons. That means when Spring application context starts, it will creatly exactly one instance of each of them.
That means no matter what uses your DataSource (web request, background job, etc.), the same instance (thus the same connection pool) is used. You are right that if connection pool was created per each request, it would not have been much of an improvement. Actually it would be much, much slower.
But in your case (and this is how 99% of web applications work) all code requiring database access will compete and reuse the same connections (or wait if none available). BTW make sure your database can actually handle 1000 concurrent connections.
Spring creates the beans and caches them, so unless you have specified the beans as prototype scoped(which creates a new bean for each request), all bean are singleton's by default. Jetty doesn't interfere.
When a request comes in, the DispatcherServlet catches the request and hands it off to the appropriate handler. The handler is the same bean if it has not been declared as a prototype bean.
You understood the connection pool correctly. This is exactly why the concept was created. It doesn't matter where the request came from, the maximum number of connections to the database at any point in time will be the one you have defined in the maxPoolSize property.

Spring: how to dynamically create multiple beans from single template definition

I have the following Spring bean for a remote web service defined in xml:
<bean id="authWSTemplate" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean" abstract="true">
<property name="serviceInterface" value="com.example.webservices.Authentication" />
<property name="wsdlDocumentUrl" value="${ws.root}/authentication?wsdl" />
<property name="namespaceUri" value="http://security.webservices.example.com/" />
<property name="serviceName" value="AuthenticationWebService" />
<property name="portName" value="AuthenticationPort" />
<property name="maintainSession" value="true" />
</bean>
How do I obtain this bean template and create a concrete bean (i.e. supply the root property)? Can I then put the concrete bean into the Spring container?
I need numerous concrete beans pointing to different systems, so I have different root values. For this example, say there are 2 systems with roots: http://domain1.com:8001/ws and http://domain2.com:8002/ws.
Therefore I'd want 2 beans called "authWSdom1" and "authWSdom2".
I'm expecting to do this programmatically in an application initialisation block, where I'd retrieve a list of all known system implementations (this info is only known at runtime), and create a bean for each impl, cache the bean name, then my application will retrieve the appropriate bean from the Spring container when required.
Or, is there a better pattern for this? Perhaps by providing the root value in a constructor for the bean?
I'm thinking I cannot have a single bean in Spring as I need to support concurrent access across multiple end points (i.e. multiple users hitting domain1 and domain2 at the same time).
Create custom bean that implements BeanFactoryPostProcessor and InitializingBean.
Use postProcessBeanFactory method to create bean:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
String wsdlDocumentUrl = ....;
// .......
registry.registerBeanDefinition(YOUR_BEAN_NAME, BeanDefinitionBuilder.childBeanDefinition(
getParentNoDomainServicBeanName(authWSTemplate)).addPropertyReference(
"wsdlDocumentUrl", wsdlDocumentUrl).getBeanDefinition());
}
While I believe that Ragnor's answer is suitable if you want to dynamically create the bean in the spring container, I decided to use spring to define my own WSTemplate DTO then use a factory class to use this DTO and programmatically build (root url provided at runtime and DTO suffix value added to it) and cache the resulting JaxWS ProxyBean:
<bean id="authWSTemplate" class="com.example.WSProxyTemplate">
<property name="serviceInterface" value="com.example.webservices.Authentication" />
<property name="wsdlDocumentUrlSuffix" value="/authentication?wsdl" />
<property name="namespaceUri" value="http://security.webservices.example.com/" />
<property name="serviceName" value="AuthenticationWebService" />
<property name="portName" value="AuthenticationPort" />
<property name="maintainSession" value="true" />
</bean>
I like this approach as my spring config is abstracted away from the actual WS bean used. I.e. if I wanted to use something other that JaxWS, then I'd simply write a different factory which used the same DTO beans. Again, this would help if I have to choose the WS implementation at runtime depending upon some system/env criteria.

Spring MVC: disable DefaultAnnotationHandlerMapping

I'm using Spring MVC with <mvc:annotation-driven />
I've implemented my own mapping handler extending DefaultAnnotationHandlerMapping, but I'm not sure how to use it. I've declared it like this:
<bean class="es.kcsolutions.boulevard.DispatcherMappingHandler" />
It works, but, obviously, DefaultAnnotationHandlerMapping works too and always before mine. Is there a way to disable it and use only mine?
Thanks.
My advice would be to remove the <mvc:annotation-driven /> altogether. It doesn't really do anything particularly useful - most of the beans it declares are there already. And in cases where you want to declare your own handler mapping or handler adapter, it just gets in the way.
So take it out, declare your own DefaultAnnotationHandlerMapping bean, and it should work. No need to mess about with ordering in 99.9% of cases.
If you take out any explicit declarations of the DefaultAnnotationHandlerMapping then your custom mapper is supposed to replace it in the dispatcher. (according to javadoc) If you need/want more than one mapping, then you control them by setting their Order property. Lower order numbers execute first.
<bean class="es.kcsolutions.boulevard.DispatcherMappingHandler">
<property name="order" value="0"/>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="1"/>
</bean>

Categories

Resources