Announcement Announcement Module
Collapse
No announcement yet.
Help on xml:xpath-router Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Help on xml:xpath-router

    Hi all,

    I've just started using spring integration and I'm trying to implement below scenario:

    1. JMS message-driven-channel-adapter for retrieving a text message (that contains an xml)
    2. using xml:xpath-router for routing to channel1 / channel2 / etc. according to a given xml tag value

    No issue about step 1. but I'm facing some troubles for defining properly the xml:xpath-router.

    Below my applicationContext.xml file:

    Code:
    <beans:beans ...>
    
        <!-- Channels definition -->
        <int:channel id="jmsListenerInChannel"/>
        <int:channel id="bpListMessageTypeChannel"/>
        <int:channel id="personListMessageTypeChannel"/>
    
        <!-- A default JMS message listener -->
        <jms:message-driven-channel-adapter id="jmsMessageChannelAdapter"
                     connection-factory="myConnectionFactory"
                     destination="myQueue"
                     channel="jmsListenerInChannel"/>
    
        <!-- Message type routing -->
        <si-xml:xpath-router id="messageTypeRouter" input-channel="jmsListenerInChannel" resolution-required="true">
            <si-xml:xpath-expression expression="/message/header/applicationMessageType/text()"/>
            <si-xml:mapping value="bp_list" channel="bpListMessageTypeChannel"/>
            <si-xml:mapping value="person_list" channel="personListMessageTypeChannel"/>
        </si-xml:xpath-router>
    
        <!--  Dispatch message -->
        <int:outbound-channel-adapter method="dispatch" channel="bpListMessageTypeChannel">
            <beans:bean class="my.integration.jms.BPListMessageTypeDispatch"/>
        </int:outbound-channel-adapter>
        <int:outbound-channel-adapter method="dispatch" channel="personListMessageTypeChannel">
            <bean class="my.integration.jms.PersonListMessageTypeDispatch" />
        </int:outbound-channel-adapter>
    
        <!-- JMS stuff resolution -->
        <jee:jndi-lookup id="myConnectionFactory" jndi-name="${myConnectionFactory.jndiName}">
            <jee:environment>...</jee:environment>
        </jee:jndi-lookup>
        <jee:jndi-lookup id="myQueue" jndi-name="${myQueue.jndiName}">
            <jee:environment>...</jee:environment>
        </jee:jndi-lookup>
    
    </beans:beans>
    I think xml:xpath-router is not defined properly.
    Should I need to "link" my jmsMessageChannelAdapter to an output channel C1 and then defing xml:xpath-router with input-channel="C1" ?

    Could anyone give me some hints ?

    Thanks a lot and regards
    nuvola

  • #2
    It looks fine; what difficulties are you having?

    Comment


    • #3
      Hi Gary,

      from logs I see that

      1. I'm able "to catch" the message from jmsMessageChannelAdapter --> LINE ... converted JMS Message ...
      2. but it seems that the channel messageTypeRouter is not triggered:

      Code:
      Running my.integration.jms.MyListenerTest
      26.apr.2012 13:40:12,016 - (MY LISTENER SERVICE) [INFO  ]-[DefaultConfiguringBeanFactoryPostProcessor(120 )] - No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.
      26.apr.2012 13:40:12,031 - (MY LISTENER SERVICE) [INFO  ]-[DefaultConfiguringBeanFactoryPostProcessor(146 )] - No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created.
      26.apr.2012 13:40:13,703 - (MY LISTENER SERVICE) [INFO  ]-[EventDrivenConsumer                (75  )] - Adding {xml:xpath-router:messageTypeRouter} as a subscriber to the 'jmsListenerInChannel' channel
      26.apr.2012 13:40:13,703 - (MY LISTENER SERVICE) [INFO  ]-[AbstractSubscribableChannel        (46  )] - Channel 'jmsListenerInChannel' has 1 subscriber(s).
      26.apr.2012 13:40:13,703 - (MY LISTENER SERVICE) [INFO  ]-[AbstractEndpoint                   (87  )] - started messageTypeRouter
      26.apr.2012 13:40:13,703 - (MY LISTENER SERVICE) [INFO  ]-[EventDrivenConsumer                (75  )] - Adding {outbound-channel-adapter} as a subscriber to the 'bpListMessageTypeChannel' channel
      26.apr.2012 13:40:13,703 - (MY LISTENER SERVICE) [INFO  ]-[AbstractSubscribableChannel        (46  )] - Channel 'bpListMessageTypeChannel' has 1 subscriber(s).
      26.apr.2012 13:40:13,703 - (MY LISTENER SERVICE) [INFO  ]-[AbstractEndpoint                   (87  )] - started org.springframework.integration.config.ConsumerEndpointFactoryBean#0
      26.apr.2012 13:40:13,703 - (MY LISTENER SERVICE) [INFO  ]-[EventDrivenConsumer                (75  )] - Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
      26.apr.2012 13:40:13,719 - (MY LISTENER SERVICE) [INFO  ]-[AbstractSubscribableChannel        (46  )] - Channel 'errorChannel' has 1 subscriber(s).
      26.apr.2012 13:40:13,719 - (MY LISTENER SERVICE) [INFO  ]-[AbstractEndpoint                   (87  )] - started _org.springframework.integration.errorLogger
      26.apr.2012 13:40:13,719 - (MY LISTENER SERVICE) [INFO  ]-[AbstractEndpoint                   (87  )] - started org.springframework.integration.jms.ChannelPublishingJmsMessageListener$GatewayDelegate@1b88122
      26.apr.2012 13:40:14,016 - (MY LISTENER SERVICE) [INFO  ]-[AbstractEndpoint                   (87  )] - started jmsMessageChannelAdapter
      26.apr.2012 13:40:14,047 - (MY LISTENER SERVICE) [INFO  ]-[MyListenerTest                     (26  )] - Ready to retrieve messages ...
      26.apr.2012 13:40:14,156 - (MY LISTENER SERVICE) [DEBUG ]-[ChannelPublishingJmsMessageListener(268 )] - converted JMS Message [TextMessage[ID:<121840.1335444217532.0>, <?xml version="1.0" encodi
      ng="...]] to integration Message payload [<?xml version="1.0" encoding="ISO-8859-1"?>
      <message>
        <header>
          <type>Extract_bp</type>
          <instituteId>BU.CH</instituteId>
          <application>APP</application>
          <applicationMessageType>bp_list</applicationMessageType>
          <remoteUser>adv</remoteUser>
          <version>00.01.00</version>
          <properties>
            <property>
              <name>Triggering Order</name>
              <value>123456</value>
            </property>
          </properties>
        </header>
        <body>
          <bp>
            <bp_name>BP_0001</bp_name>
          </bp>
        </body>
      </message>]
      26.apr.2012 13:40:19,110 - (MY LISTENER SERVICE) [INFO  ]-[AbstractEndpoint                   (103 )] - stopped org.springframework.integration.jms.ChannelPublishingJmsMessageListener$GatewayDelegate@1b88122
      26.apr.2012 13:40:19,110 - (MY LISTENER SERVICE) [INFO  ]-[AbstractEndpoint                   (103 )] - stopped jmsMessageChannelAdapter
      26.apr.2012 13:40:19,110 - (MY LISTENER SERVICE) [INFO  ]-[EventDrivenConsumer                (75  )] - Removing {xml:xpath-router:messageTypeRouter} as a subscriber to the 'jmsListenerInChannel' channel
      26.apr.2012 13:40:19,110 - (MY LISTENER SERVICE) [INFO  ]-[AbstractEndpoint                   (103 )] - stopped messageTypeRouter
      26.apr.2012 13:40:19,110 - (MY LISTENER SERVICE) [INFO  ]-[EventDrivenConsumer                (75  )] - Removing {outbound-channel-adapter} as a subscriber to the 'bpListMessageTypeChannel' channel
      26.apr.2012 13:40:19,125 - (MY LISTENER SERVICE) [INFO  ]-[AbstractEndpoint                   (103 )] - stopped org.springframework.integration.config.ConsumerEndpointFactoryBean#0
      26.apr.2012 13:40:19,125 - (MY LISTENER SERVICE) [INFO  ]-[EventDrivenConsumer                (75  )] - Removing {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
      26.apr.2012 13:40:19,125 - (MY LISTENER SERVICE) [INFO  ]-[AbstractEndpoint                   (103 )] - stopped _org.springframework.integration.errorLogger
      Thanks for your help and regards
      nuvola

      Comment


      • #4
        Are you saying the message does not appear in the output queue?

        Do you have DEBUG logging set for all of 'org.springframework.integration?

        Can you run again with

        1. The thread name in the log (%t if log4j)
        2. TRACE level for org.springframework.jms
        3. DEBUG level for org.springframework.integration

        Comment


        • #5
          Hi Gary,

          thanks a lot for your feedback, enabling the trace allowed me to find out an error on my BPListMessageTypeDispatch class:

          Code:
          26.apr.2012 15:28:30,463 - (MY LISTENER SERVICE) (org.springframework.jms.listener.DefaultMessageListenerContainer#0-1) [WARN  ]-[AbstractMessageListenerContainer   (695 )] - Execution of JMS message listener failed, and no ErrorHandler has been set.
          org.springframework.integration.MessageHandlingException: org.springframework.expression.spel.SpelEvaluationException: EL1004E:(pos 8): Method call: Method dispatch(java.lang.String) cannot be found on my.integration.jms.BPListMessageTypeDispatch type
          It was defined as
          Code:
          public void dispatch(Document doc)
          now
          Code:
          public void dispatch(String message)
          And from logs now
          Code:
          26.apr.2012 15:35:04,264 - (MY LISTENER SERVICE) (org.springframework.jms.listener.DefaultMessageListenerContainer#0-1) [INFO  ]-[BPListMessageTypeDispatch          (23  )] - BPListMessageTypeDispatch:
          <?xml version="1.0" encoding="ISO-8859-1"?>
          <message>...
          An additional question on xml:xpath-router: currently I'm checking that my xpath expression returns
          - value="bp_list"
          - or value="person_list",

          Code:
              <!-- Message type routing -->
              <si-xml:xpath-router id="messageTypeRouter" input-channel="jmsListenerInChannel" resolution-required="true">
                  <si-xml:xpath-expression expression="/message/header/applicationMessageType/text()"/>
                  <si-xml:mapping value="bp_list" channel="bpListMessageTypeChannel"/>
                  <si-xml:mapping value="person_list" channel="personListMessageTypeChannel"/>
              </si-xml:xpath-router>
          how could I define an entry for other values ? So I can dispatch NOT bp_list/person_list message type to an ERROR channel ... that in turn it could store into file messages that don't match above criteria.

          Thanks a lot again again :-)

          Regards
          nuvola

          Comment


          • #6
            Code:
                <!-- Message type routing -->
                <si-xml:xpath-router id="messageTypeRouter" input-channel="jmsListenerInChannel" default-output-channel="errors">
                    <si-xml:xpath-expression expression="/message/header/applicationMessageType/text()"/>
                    <si-xml:mapping value="bp_list" channel="bpListMessageTypeChannel"/>
                    <si-xml:mapping value="person_list" channel="personListMessageTypeChannel"/>
                </si-xml:xpath-router>

            Comment


            • #7
              Hi Gary,

              thanks again :-)

              So I defined my unknownMessageTypeChannel as below:

              Code:
                  <!-- Message type routing -->
                  <si-xml:xpath-router id="messageTypeRouter" input-channel="jmsListenerInChannel" resolution-required="true" default-output-channel="unknownMessageTypeChannel">
                      <si-xml:xpath-expression expression="/messageNs:message/messageNs:header/messageNs:applicationMessageType/text()" namespace-map="messageNamespaceMap"/>
                      <si-xml:mapping value="bp_list" channel="bpListMessageTypeChannel"/>
                      <si-xml:mapping value="person_list" channel="personListMessageTypeChannel"/>
                  </si-xml:xpath-router>
              
                  <file:outbound-channel-adapter id="unknownMessageTypeChannel" directory="file:${unknownMessageType.directory}"/>
              and I published into my weblogic a "wrong message type" in order to test this use case:

              Code:
              my "wrong message type"
              
              <message xmlns="...">
                <header>
                  <type>AdvExtract_bp</type>
                  <instituteId>BU.CH</instituteId>
                  <application>APP</application>
                  <applicationMessageType>bp_list_wrong</applicationMessageType>
              and from logs I see an exception:

              Code:
              26.apr.2012 16:44:22,617 - (MY LISTENER SERVICE) (main) [INFO  ]-[MyListenerTest               (26  )] - Ready to retrieve messages ...
              26.apr.2012 16:44:22,820 - (MY LISTENER SERVICE) (org.springframework.jms.listener.DefaultMessageListenerContainer#0-1) [WARN  ]-[AbstractMessageListenerContainer   (695 )] - Execution of JMS message listener failed, and no ErrorHandler has been set.
              org.springframework.integration.MessagingException: failed to resolve channel name 'bp_list_bp_list_wrong'
                      at org.springframework.integration.router.AbstractMappingMessageRouter.resolveChannelForName(AbstractMappingMessageRouter.java:168)
                      at org.springframework.integration.router.AbstractMappingMessageRouter.addChannelFromString(AbstractMappingMessageRouter.java:197)
                      at org.springframework.integration.router.AbstractMappingMessageRouter.addToCollection(AbstractMappingMessageRouter.java:218)
              I'm trying to find out where I'm wrong ...

              Thanks and regards
              nuvola

              Comment


              • #8
                Ahh... change resolution-required to "false". That's what triggers sending messages for unresolved channels to the default-output-channel.

                Forgot to mention that.

                Comment


                • #9
                  Obviously you're right !

                  I see messages are stored into files with file name chosen by the framework:

                  9b32a1d1-666c-4793-b7bf-db3e1fa133df.msg
                  acbe90c1-4ceb-413f-80bf-129c1b3d406f.msg

                  How could I change the file:outbound-channel-adapter in order to override the file name ? It should fine if I could store into the file name the timestamp and some info taken from the JMS message (for example the message ID:<121840.1335444217532.0>)

                  Code:
                      <file:outbound-channel-adapter id="unknownMessageTypeChannel" directory="file:${unknownMessageType.directory}"/>
                  ... I'm trying to find out an example abou that ...

                  I've to tell you again thanks thanks thanks ... you helped me a lot!

                  Thanks and regards
                  nuvola

                  Comment


                  • #10
                    You can configure a filename-generator on the adapter. It's a single method strategy interface.

                    Comment


                    • #11
                      There's also

                      Code:
                      filename-generator-expression="headers['jms_messageId'].replace('<','').replace('>','') + '.bad'"

                      Comment


                      • #12
                        Hi Gary,

                        thanks for the provided example !

                        I'm checking the syntax because I got an error:

                        Code:
                        Offending resource: class path resource [applicationContext.xml]; nested exception is org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 62 in XML document from file [C:\projects\maven\workspace\myListener\target\test-classes\myListener-context.xml] is invalid; nested exception is org.xml.sax.SAXParseException: The value of attribute "filename-generator-expression" associated with an element type "null" must not contain the '<' character.
                        Thanks and regards
                        nuvola

                        Comment


                        • #13
                          Try '&lt;' and '&gt;' for '<' and '>'

                          Comment


                          • #14
                            ciao Gary,

                            Your hint is perfect!

                            ... I'm also trying to add a timestamp in the filename ...

                            Code:
                                <file:outbound-channel-adapter id="unknownMessageTypeChannel" directory="file:${unknownMessageType.directory}"
                                   filename-generator-expression="'${myQueue.jndiName}' + '_' + headers['jms_messageId'].replace('&lt;','').replace('&gt;','').replace(':','_') + '_' + new SimpleDateFormat('ddMMyyyy_HHmmss').format(new Date()) + '.xml'"/>
                            The error is:

                            Code:
                            Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1003E:(pos 104): A problem occurred whilst attempting to construct an object of type 'SimpleDateFormat' using arguments '(java.lang.String)'
                            I think it's wrong using ' instead of " within --> new SimpleDateFormat('ddMMyyyy...
                            I'm trying different tries ...

                            Thanks and regards
                            nuvola

                            Comment


                            • #15
                              You need to fully qualify 'java.text.SimpleDateFormat' and 'java.util.Date' so SpEL can find the classes.
                              Last edited by Gary Russell; Apr 26th, 2012, 07:19 PM.

                              Comment

                              Working...
                              X