I have a question on how SimpleMessageListenerContainer handleMesage works? my problem scenario is, I have 1000 messages(m1, m2... m100) in queue then started consumer (5 concurrent consumers) and acknowledgeMode='NONE' in this scenario,
does handleMesage consume 5 messages at a time (m1,m2,m3,m4,m5) then next 5 messages, and so on... ?
Does container creates 5 Receiver instances?
Would like to know end of the handle message where control will goes?
Can you please let me know these.. because we couldn't able to see the messages as soon as Consumer starts in RMQ MNGMT console.... our code inside handleMesage method will take atleast some seconds to process each request.
<bean id="sampleListenerContainer"
class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="queueNames">
<array>
<value>TEST_QUEUE</value>
</array>
</property>
<property name="messageListener" ref="messageListenerAdaptor" />
<property name="acknowledgeMode" value="NONE" />
<property name="concurrentConsumers" value="5" />
</bean>
<!-- message listener -->
<bean id="messageListenerAdaptor"
class="org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter">
<property name="delegate" ref="listenerPojo" />
<property name="messageConverter" ref="messageConverter" />
</bean>
<bean id="listenerPojo"
class="com.amqp.consumer.Receiver" >
</bean>
With version 1.3 and later, each consumer gets prefetch messages at a time (the broker sends them round robin)
Yes but they're called consumers, not receivers
When the listener method exits, the consumer grabs the next message, this frees up the amqp-client thread so it can get another message from the broker.
With ackmode NONE, it depends on which version of Spring AMQP you are using how messages are delivered to the consumer.
With versions prior to 1.3, all 1000 messages would immediately be sent to the container (200 for each consumer).
After version 1.3.0, the number of messages sent to each consumer depends on the prefetchCount property (default 1); there will actually be prefetch+1 messages removed from the broker for each consumer.
Understand that AcknowledgeMode="NONE" means you can lose messages because the broker automatically acks the messages when they are sent to the consumer. Any messages sitting in the consumer (prefetch) will be lost if the server crashes.
Related
I have a use case where when the connectivity to rabbitmq goes down I need to manage the messages in different way.
I have a logic
RabbitTempate template // get template using API call
template.setReplyTimeout(10000);
template.convertAndSend(message);
But the problem is when the rabbitmq server connectivity goes down Spring AMQP automatically waits for connectivity to get resolved for 5 min
But because of that the client thread calling that particular logic waits for 5 min .
Is there any way i can change it , I am using CachingConnectionFactory
<bean id="connectionFactory"
class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory">
<constructor-arg value="rabbit-server-fqdn" />
<property name="virtualHost" value="vhost" />
<property name="username" value="username" />
<property name="password" value="password" />
<property name="cacheMode" value="CONNECTION" />
<property name="channelCacheSize" value="25" />
</bean>
Is there any way I can override these settings from 5 min so that client API does not need to wait for such huge amount of time ?
I have a listener which listens to one queue, I want a listener in such a way that my listener need to consume one message after another message with delay of 1 min. I have seen receiveTimeout property for the listener container but i couldn't able to achieve the delay in message consumption. here is my listener container.
<!-- search message listener container -->
<bean id="listenerContainer" class="org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="queueNames">
<array>
<value>TEST_QUEUE</value>
</array>
</property>
<property name="messageListener" ref="messageListenerAdaptor" />
<property name="acknowledgeMode" value="AUTO" />
<property name="concurrentConsumers" value="1" />
<property name="receiveTimeout" value="60000" />
</bean>
There is no way to do what you want with the listener container configuration; the receiveTimeout is simply how long the container waits for a message before looking to see if, say, the container has been stopped.
You could play some games with an intermediate queue with dead-lettering and time-to live, but that will be complicated.
It would probably be easier to use RabbitTemplate.receive() (or receiveAndConvert()) if you want to get messages on a schedule rather than being event-driven.
There is a new plugin for RabbitMQ which might help you.
I'm trying to set up WebSockets with spring-messaging using stomp, and using redis-backed sessions with spring-session. Our application context is wired via xml, and spring-session is working with the non-websocket portion of the application. The relevant config for websocket is as follows
<websocket:message-broker application-destination-prefix="/streaming" >
<websocket:stomp-endpoint path="/data">
<websocket:sockjs session-cookie-needed="false" />
</websocket:stomp-endpoint>
<websocket:stomp-broker-relay prefix="/topic" relay-host="${jms_hostname}" relay-port="${jms_stomp_port}" />
<websocket:client-inbound-channel>
<websocket:interceptors>
<ref bean="sessionRepoMessageInterceptor"/>
<ref bean="authenticationValidationInterceptor" />
<ref bean="selectorValidationInterceptor" />
<ref bean="selectorQuotingInterceptor" /> <!-- comes after we have validated the selector, we now shim it so JMS understands it -->
</websocket:interceptors>
</websocket:client-inbound-channel>
</websocket:message-broker>
I have defined what I think are the necessary beans for spring-session's integration with web sockets here:
<bean id="redisSessionBackedWebsocketHandler" class="org.springframework.session.web.socket.server.">
</bean>
<bean id="sessionRepoMessageInterceptor" class="org.springframework.session.web.socket.server.SessionRepositoryMessageInterceptor">
</bean>
<bean id="webSocketRegistryListener" class="org.springframework.session.web.socket.handler.WebSocketRegistryListener">
</bean>
but I'm not sure where I would wire them in to the web socket configuration, and have not been able to find any doc on how to do it this way.
Thoughts?
The Spring Session WebSocket contains the config just only for the Java & Annotation variant.
And according to the Spring Session Docs the AbstractSessionWebSocketMessageBrokerConfigurer does the stuff for seamless integration between Spring Session and Spring WebSockets. However there we can see some paragraph, what it does:
To hook in the Spring Session support, we need to ensure ...
To be honest it isn't so easy to configure that stuff from XML.
Feel free to follow with the issue: https://github.com/spring-projects/spring-session/issues/101
Our Webflow (2.3.1) application is claiming a lot of memory for each new flow that we open through the browser.
The screenshot below shows our application's memory use. When the application starts it takes an initial 400 Mb. After that we open 4 individual, identical Webflow TEST pages in the browser which each claim about 90Mb of extra memory..
Each test page is started from its own simple flow definition:
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/webflow"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd" start-state="start">
<view-state id="start" view="test/test1">
</view-state>
<end-state id="end"/>
<bean-import resource="../flow-beans.xml"/>
</flow>
The JSP test pages are also very simple, just empty with one line of text.
When we currently set the JVM memory to 1.5Gb the application eventually crashes on the server with OutOfMemoryExceptions after opening about 15 different flows. 1.5 Gb seems a bit much, regarding the low complexity of our screens..
We are wondering if the amount of memory Webflow seems to claim for these simple flows/pages is expected and if we should therefore just assign more memory to the server JVM. If not, we would like to know how we can decrease this memory usage.
Below is our entire webflow configuration.
We have tried adding a flow-execution-repository tag and played around with the max-executions-snapshots and max-executions values, but even the most conservative settings don't change the memory usage we are seeing.
<?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:webflow="http://www.springframework.org/schema/webflow-config"
xmlns:tx="http://www.springframework.org/schema/tx"
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-2.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- Launches new flow executions and resumes existing executions. -->
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
</webflow:flow-executor>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:our.properties" />
<property name="placeholderPrefix" value="$xxxx"></property>
</bean>
<tx:annotation-driven transaction-manager="$xxxx{txManager}" />
<!-- Creates the registry of flow definitions for this application -->
<webflow:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<webflow:flow-location-pattern value="classpath:flows/**/*-flow.xml" />
</webflow:flow-registry>
<bean id="viewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
<property name="viewResolvers" ref="viewResolver" />
</bean>
<bean id="expressionParser" class="org.springframework.expression.spel.standard.SpelExpressionParser">
<constructor-arg name="configuration">
<bean class="org.springframework.expression.spel.SpelParserConfiguration">
<constructor-arg name="autoGrowCollections" value="true" />
<constructor-arg name="autoGrowNullReferences" value="false" />
</bean>
</constructor-arg>
</bean>
<bean id="webflowExpressionParser" class="org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser">
<constructor-arg name="expressionParser" ref="expressionParser" />
</bean>
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="viewFactoryCreator" validator="validator" expression-parser="webflowExpressionParser"/>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="projectVersion" class="our.company.versions.ProjectVersionUtil">
<property name="xxxxVersion" value="$xxxx{xxxx.version}" />
<property name="systemConfigurationDao">
<ref bean="SystemConfigurationDao"/>
</property>
</bean>
</beans>
When Spring Web Flow starts a new flow it basically constructs a new BeanFactory which loads the xml file and imports any additional xml files. The newly constructed BeanFactory has the context of the DispatcherServlet as its parent.
Now the problem with this is that a the bean factory constructs instances of all the beans even those defined in imported XML files.
<bean-import resource="../flow-beans.xml"/>
If there are a lot of beans in there those will be duplicated for each flow instance. In general you don't want your all of your beans duplicated and stored in the users sessions.
Remove the singleton beans from the flow-beans.xml and put them in the normal application context, they are still referable from within the flow definition. Or you could simply add the flow-beans.xml to the list of files loaded at startup of your application.
I'm trying to implement jpa idempotent repository just as described here http://camel.apache.org/file2.html, but i'm getting a Mbean export error.
On my application-context.xml i've the following section.
<bean id="mvStore" class="org.apache.camel.processor.idempotent.jpa.JpaMessageIdRepository" lazy-init="false">
<!-- Here we refer to the spring jpaTemplate -->
<constructor-arg index="0" ref="jpaTemplate" />
<!-- This 2nd parameter is the name (= a cateogry name). You can have different repositories with different names -->
<constructor-arg index="1" value="FileConsumer" />
</bean>
<context:mbean-server id="mbeanServer" />
<context:mbean-export server="mbeanServer" registration="replaceExisting" default-domain="br.com.touchtec"/>
If I remove the above section than the server (tomcat) starts just fine. Can anybody help me on this?
Here's the stack:
Caused by: org.springframework.jmx.export.UnableToRegisterMBeanException: Unable to register MBean [org.apache.camel.processor.idempotent.jpa.JpaMessageIdRepository#6df960c4] with key 'mvStore'; nested exception is javax.management.MalformedObjectNameException: Key properties cannot be empty
at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:602)
at org.springframework.jmx.export.MBeanExporter.registerBeans(MBeanExporter.java:527)
at org.springframework.jmx.export.MBeanExporter.afterPropertiesSet(MBeanExporter.java:413)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
... 50 more
Caused by: javax.management.MalformedObjectNameException: Key properties cannot be empty
at javax.management.ObjectName.construct(ObjectName.java:467)
at javax.management.ObjectName.<init>(ObjectName.java:1403)
at javax.management.ObjectName.getInstance(ObjectName.java:1285)
at org.springframework.jmx.support.ObjectNameManager.getInstance(ObjectNameManager.java:62)
at org.springframework.jmx.export.naming.MetadataNamingStrategy.getObjectName(MetadataNamingStrategy.java:114)
at org.springframework.jmx.export.MBeanExporter.getObjectName(MBeanExporter.java:728)
at org.springframework.jmx.export.MBeanExporter.registerBeanInstance(MBeanExporter.java:631)
at org.springframework.jmx.export.MBeanExporter.registerBeanNameOrInstance(MBeanExporter.java:592)
... 54 more
First of all, I hope you're clear on the fact the jmx part is not necessary to make the Idempotent Repository work. Your error is a pure JMX/Spring error, not linked to Camel.
If you want to use an MBeanExporter, you should read the official documentation on Spring JMX to have a better understaking of this matter.
Your MBeanExporter definition might look like
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="bean:name=mvStore" value-ref="mvStore"/>
</map>
</property>
<property name="server" ref="mbeanServer"/>
</bean>