Announcement Announcement Module
Collapse
No announcement yet.
Spring, BlazeDS, JMS Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring, BlazeDS, JMS

    Hi,

    I am using Spring-BlazeDS integration alongwith JMS. Till now I could able to send messages to JMS and receive them in Flex using the integration API.
    Now I want to further extend this functionality and here are my requirements
    1. Messages sent from Java will contain a additional property say "user". Messages will be delivered on Topic and not on queue.
    2. A Message subscriber will connect from Flex. Whenever there is any message sent to JMS, in current scenario all the clients who are subscribed to the topic are able to receive message. I want to modify this functionality and client should get messages only when the property supplied by client contains matching "user" property specified by the message producer.
    In simple words if published message contains "user" property value as "a" and if there are two clients - C1, C2. Then if C1 client is logged in as "a" then only client C1 should be able to receive message and not C2. I dont want to use selector as it still gives provision to client to receive all messages.
    It would be good if I can intercept a request sent by client and then add its identification (picked up from session scope bean) to message request.

    In short I want to implement a functionality similar to Private Chat using JMS.

  • #2
    To have a messages received only by a particular Flex client, you need to dynamically create a simple AMF MessageDestination at runtime that is unique to that client. You could trigger the initialization of this destination through a remoting call. The Java side could look something like:

    Code:
    @Service
    @RemotingDestination
    public class DynamicDestinationService {
        
        private final MessageBroker broker;
        
        @Autowired
        public DynamicDestinationService(MessageBroker broker) {
            this.broker = broker;
        }
        
        public void createMessageDestination(String id) {
            MessageService service = (MessageService) broker.getServiceByType(MessageService.class.getName());
            MessageDestination dest = (MessageDestination) service.createDestination(id);
            dest.setAdapter(dest.createAdapter(service.getDefaultAdapter()));
            dest.start();
        }
    }
    On the Flex side, after invoking createMessageDestination, you would then subscribe to the new destination.

    The routing from the Topic to the dynamically created MessageDestination is a pretty good use case for utilizing Spring Integration (http://static.springframework.org/sp...reference.html). You could use the message-driven channel adapter to pull the message off the topic and route it to a handler that then pushes the message to the Flex client.

    The Spring config might look something like:
    Code:
    <jms:message-driven-channel-adapter id="jmsIn" destination="chatTopic" channel="chatMessageChannel"/>
    
    <integration:channel id="chatMessageChannel"/>
    
    <integration:service-activator input-channel="chatMessageChannel" ref="userMessageHandler" />
    and then the userMessageHandler bean could be:

    Code:
    @Component
    public class UserMessageHandler {
        
        private final MessageTemplate messageTemplate;
        
        @Autowired
        public UserMessageHandler(MessageTemplate messageTemplate) {
            this.messageTemplate = messageTemplate;
        }
        
        public void pushChatMessageToUser(ChatMessage message) {
            messageTemplate.send(message.getUserId(), message.getMessageText());
        }
    }

    Comment


    • #3
      Hi Jeremy,

      Thanks for your reply and such detailed explaination. I have a question, whether above implementation requires third party JMS provider like JBOSS MQ or Active MQ.
      Can above listed aproach be completely developed using BlazeDS, Spring, Flex given the fact that there is an external application which want to send messages to Flex Application.

      Comment


      • #4
        Originally posted by curiousmind View Post
        Hi,

        I am using Spring-BlazeDS integration alongwith JMS. Till now I could able to send messages to JMS and receive them in Flex using the integration API.
        Now I want to further extend this functionality and here are my requirements
        1. Messages sent from Java will contain a additional property say "user". Messages will be delivered on Topic and not on queue.
        2. A Message subscriber will connect from Flex. Whenever there is any message sent to JMS, in current scenario all the clients who are subscribed to the topic are able to receive message. I want to modify this functionality and client should get messages only when the property supplied by client contains matching "user" property specified by the message producer.
        In simple words if published message contains "user" property value as "a" and if there are two clients - C1, C2. Then if C1 client is logged in as "a" then only client C1 should be able to receive message and not C2. I dont want to use selector as it still gives provision to client to receive all messages.
        It would be good if I can intercept a request sent by client and then add its identification (picked up from session scope bean) to message request.

        In short I want to implement a functionality similar to Private Chat using JMS.
        Not sure how this will translate to Spring Flex but in POJO I did the following in order to send a message to a single subscriber (I use custom adapter):

        extract subscriber IDs when message arrives (in adapter's invoke() method):

        Code:
        List<MessageClient> messageClients = FlexContext.getFlexClient().getMessageClients();
        and send like:
        Code:
        final MessageService msgService = (MessageService)this.getDestination().getService();
        			    
        // Set of client IDs we want to send the message to
        final Set<Object> _targetClient=new LinkedHashSet<Object>();
        			    
           for (final Iterator<MessageClient> _clientIt = _messageClients.iterator(); _clientIt.hasNext();  ) {
            	_targetClient.add(_clientIt.next().getClientId());
           }
        			    	
            msgService.pushMessageToClients(_targetClient, message, true);
        Obviously you have to have some code that associates user with messaging client(s).

        If you figure out how to make this work in Spring + Flex + JMS drop me a note... I'll be looking to implement similar solution soon.

        Comment


        • #5
          Originally posted by curiousmind View Post
          I have a question, whether above implementation requires third party JMS provider like JBOSS MQ or Active MQ.
          Can above listed aproach be completely developed using BlazeDS, Spring, Flex given the fact that there is an external application which want to send messages to Flex Application.
          No, you don't necessarily even need JMS. Spring Integration offers a number of alternative adapters for sending and receiving messages, and the above approach could be replicated with any of them.

          Comment


          • #6
            Hi jeremy,

            I have implemented an application using the approach you have defined above. But while debugging the code, I noticed that the spring integration project is using "actionscript" adapter. Though this adapter is commented and only "jms" adapter is enabled in messaging-config.xml, the spring MessageTemplate class seems to be using only "actionscript". Hence I am not sure whether the new destinations created using

            MessageDestination dest = (MessageDestination) service.createDestination(id);
            are creating jms destinations or actionscript destination. Could you please tell me how can I force MessageTemplate class to use configuration defined in messaging-config.xml

            Here is the snippet of xml configuraiton file.

            <bean id="messageTemplate" class="org.springframework.flex.messaging.MessageT emplate"/>

            <bean id="userMessageHandler" class="com.majescomastek.cmr.destination.UserMessa geHandler">
            <constructor-arg>
            <ref bean="messageTemplate"/>
            </constructor-arg>
            </bean>
            Configuration of JMS topic is done inside same file using Spring provided classes.

            Comment


            • #7
              Originally posted by curiousmind View Post
              Hi jeremy,

              I have implemented an application using the approach you have defined above. But while debugging the code, I noticed that the spring integration project is using "actionscript" adapter. Though this adapter is commented and only "jms" adapter is enabled in messaging-config.xml, the spring MessageTemplate class seems to be using only "actionscript".
              I'm a little confused by your reference...we don't use messaging-config.xml at all (at least not in the Test Drive examples). What exactly are you looking at?

              Originally posted by curiousmind View Post
              Hence I am not sure whether the new destinations created using
              Code:
              MessageDestination dest = (MessageDestination) service.createDestination(id);
              are creating jms destinations or actionscript destination.
              If you don't explicitly set the adapter, then I believe it uses the default adapter for the MessageService. This is typically the ActionScriptAdapter, but can be overridden.

              Though you wouldn't think it by looking at a typical messaging-config.xml, each destination actually needs a unique adapter instance. The adapter is where most of the specific settings for a destination are actually configured.

              I'm not sure why you would need in the case you described to set anything other than the ActionScriptAdapter for the dynamically created destination.

              The MessageTemplate's purpose is to be able to push messages to any destination. This should work no matter what kind of adapter the destination is using.

              Comment

              Working...
              X