how to quit spring app during startup if certain condition meet? - java

I have a spring app which listens on rabbitmq and processing the message, when the app runs, I will register on a hub database to note that one instance is running, during the registering if another instance is already running, then I need to quit app without init the rabbit connection/queue and listener, otherwise some message could be wrongly consumed. How to do that, I know there are callback when init a bean. So I should create bean and before init it, checking whether another instance is running, but how to make sure this bean will be init before other beans? But I also need to init database source bean before the checking bean, otherwise it can't use the database defined in configuration.
<rabbit:connection-factory id="connectionFactory" host="localhost" username="guest" password="guest" />
<rabbit:admin id="containerAdmin" connection-factory="connectionFactory" />
<rabbit:queue id="ETLQueue" name="ETLQueue" />
<rabbit:direct-exchange id="myExchange" name="ETL">
<rabbit:bindings>
<!--if doens't specifiy key here, the by default the key will be the same as queue name, and then need to send message with the correct key,
otherwise the listener can't receive the mssage-->
<rabbit:binding queue="ETLQueue" key="ETLQueue" />
</rabbit:bindings>
</rabbit:direct-exchange>
<bean id="aListener" class="com.testcom.amqp.listener.ConnectorListener" c:dataSource-ref="dataSource"/>
<!--concurrency will set how many threads running concurrently to consume the messsage, the code need to be thread safe-->
<rabbit:listener-container id="myListenerContainer" connection-factory="connectionFactory" prefetch="1" concurrency="10">
<rabbit:listener ref="aListener" queues="ETLQueue" />
</rabbit:listener-container>

As you are using xml configuration, the attribute depends-on normally helps to say that a bean should not be initialized before the target bean :
<bean id="A" .../>
<bean id="B" ... depends-on="A"/>
Bean B should be initialized after A (unless there are some cyclic dependency in which case spring only does its best ...)

Related

What is the xml equivalent of this bean configuration where an object is being passed for which there is no bean configuration defined?

I need to add OAuth client to a Spring 3 project. I need to use xml based configuration. And I want to know the xml equivalent of the following bean configuration I found in another Spring project. Note that there is an input parameter in the bean definition where an object of type OAuth2ClientContext is being passed (OAuth2ClientContext is an Interface) and is named clientContext. But no bean definition is written anywhere for clientContext. What does this mean? And how would you write this in xml?
#Bean
public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext clientContext){
return new OAuth2RestTemplate(oauth2Resource(), clientContext);
}
The configuration should be like this
<bean id="client" class="package.OAuth2ClientContext" />
<bean id="resource" class="package.Oauth2Resource" />
<bean id="restTemplate" class="package.Oauth2Resource">
<property name="nameOfPropertyResource" ref="resource" />
<property name="nameOfPropertyClient" ref="client" />
</bean>
are you sure that the bean client is not declared? Maybe it’s declared in some jar? If yes you should find it’s name and use the name in the ref

How to configure RabbitMQ in XML file to have 1) listener listening from multiple queues 2) 2 listeners listening to same queue?

I am trying to understand Spring RabbitMQ XML configuration. So far, I never came across xml configuration where a listener is listnening(subscribed) to multiple queues. Like wise, I never found codes wherein 2 listeners are subscribed to the same queue in the same xml file. After going through the XSD documentation where in I found that the attribute- "queue-names" is a comma separated list of queue names. So, I believe xml configuration can also be like -
<rabbit:queue id="springQueue1" name="spring.queue1" auto-delete="true" durable="false"/>
<rabbit:queue id="springQueue2" name="spring.queue1" auto-delete="true" durable="false"/>
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener queues="springQueue1, springQueue2" ref="messageListener"/>
</rabbit:listener-container>
<bean id="messageListener" class="com.ndpar.spring.rabbitmq.MessageHandler"/>
Is this correct? Is the syntax correct in "queues" attribute?? Also, if two listeners are receiving from same queue, then
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener queues="springQueue1" ref="messageListener1"/>
<rabbit:listener queues="springQueue1" ref="messageListener2"/>
</rabbit:listener-container>
<bean id="messageListener1" class="com.ndpar.spring.rabbitmq.MessageHandler1"/>
<bean id="messageListener2" class="com.ndpar.spring.rabbitmq.MessageHandler2"/>
Is this correct?? The "ref" attribute always refers to bean id??? or can it refer to bean name??
Is this valid -
<rabbit:listener queues="springQueue1" ref="messageListener1, messageListener2"/>
Please help.Thanks.
Is this correct? Is the syntax correct in "queues" attribute??
Yes, that is correct; a single consumer consumes from 2 queues.
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener queues="springQueue1" ref="messageListener1"/>
<rabbit:listener queues="springQueue1" ref="messageListener2"/>
</rabbit:listener-container>
It's functionally the same as a single listener with concurrency="2" - in that case, the container will create 2 consumers against the queue. In your case, we'll get 2 containers, each with one consumer.
The ref has to reference a single bean id. For normal <bean/>s, name is a synonym for id.
This is invalid:
<rabbit:listener queues="springQueue1" ref="messageListener1, messageListener2"/>

Using a Service Factory to create an instance of an object that's wired in Blueprint XML

I have a complex object that's wired together in a Blueprint XML config.
<bean id=”complexObject”>
<property name=”subObject1” ref=”subObject1ref” />
<property name=”subObject2” ref=”subObject2ref” />
...
</bean>
I expose like this:
<service ref=“complexObject“ interface=“org.service.IComplexObject“ />
It's consumed like this:
<reference id=“ref_complexObject“ interface=“org.service.IComplexObject“ />
Problem is: It's kinda Singleton, but what I need is always a new instance.
I came across "Service Factory" as described in chapter 5.6 of the OSGi Core Spec. Problem with a Factory is, that I would have to do all the wiring, that's done in Blueprint/Spring at the moment, in Java code again, no?
Is there a way that this Factory can return a new instance of my complexObject that's wired together in the Blueprint XML?

How to perform user-locking in Spring-MVC?

I wanted to know how I can perform user locking (or the best way to perform the same) i.e. if a user is already logged in from a device and tries to login from another device, he/she should be notified that a session is already available for that user and an option to close other session and start a new one.
Framework Used Spring-MVC + hibernate 4.1.
And one more thing: how can I set a list of some user hashmap object in application context?
That can be done with Spring Security and Conncurrent Session Control. You can define how many sessions may exist concurrently and decide what to do if the maximum exceeds.
Their is a simple xml configuration in spring security for the same. First you have to register the SessionRegistry bean. I have used default class of SessionRegistryImpl of spring security for Session registry like :
<bean id="sessionRegistry"
class="org.springframework.security.core.session.SessionRegistryImpl" />
After that we have to register the ConcurrentSessionControlStrategy with container and tell it the maximum session allowed per user.
Example:
<bean id="sessionStrategy"
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<property name="maximumSessions"
value="${security.config.sessionStrategy.maximumSessions.value}" />
<property name="exceptionIfMaximumExceeded" value="true" />
</bean>
security.config.sessionStrategy.maximumSessions.value is the integer value specified in property file. By varying the maximumSessions property value we can define maximum concurrent users easily.

Adding multiple listener-container, with ids, does not seem to work

I have a rabbitMQ configuration where in I need to have two separate listener-containers, each having a set of listeners. Here is a snippet from rabbitmq-context.xml:
<rabbit:listener-container
connection-factory="connectionFactory" message-converter="jsonMessageConverter"
auto-startup="true"
acknowledge="manual"
requeue-rejected="true"
concurrency="5"
task-executor="myTaskExecutor" >
<rabbit:listener queues="Queue1" ref="myQ1Listener" method="onMessage"/>
</rabbit:listener-container>
<rabbit:listener-container
connection-factory="connectionFactory" message-converter="jsonMessageConverter"
auto-startup="true"
acknowledge="manual"
requeue-rejected="false"
concurrency="5"
task-executor="myTaskExecutor" >
<rabbit:listener queues="Queu2" ref="myQ2Listener" method="onMessage"/>
</rabbit:listener-container>
If these are specified without an id all the listeners are started on initialization.
If I go ahead and specify an id to one of them (which I want to reference in another bean), the other listener-container (without the id) does not get initialized.
If I specify ids with both these listener-containers (and do not reference those ids anywhere), still listeners from only one of the listener-containers are initialized.
Can anybody help me understand if there its a configuration issue or is this a bug in RabbitMQ?
This issue has been fixed (https://jira.spring.io/browse/AMQP-332) according to SO question Adding multiple listeners which will listen to different RabbitMQ queue not working.
So, show, please, the wrong config and try to upgrade to te latest Spring AMQP version.
Acutally we have similar test-case. I've just removed the id from nexted <rabbit:listener> elements and the ListenFromAutoDeleteQueueTests passed.
Please, check versions of Spring jars and try to use the latests.

Categories