Results 1 to 9 of 9

Thread: Help about SpEL expression

  1. #1

    Default Help about SpEL expression

    Hi all,

    in my scenario the header could contain a 'customer attribute' MessageId:

    Code:
    [Headers={timestamp=1339161965407, id=..., JMSXDeliveryCount=1, jms_type=bp_list, jms_timestamp=1339161963190, jms_redelivered=false, MessageId=..., jms_messageId=...}]
    That 'customer attribute' is not mandatory so in some cases is not present.
    I would like to use it around my spring context file when I want to trace the incoming request:

    Code:
    ...
        <!--  Dispatch message -->
        <file:outbound-gateway directory="file:${unmatchedMessageType.directory}"
            request-channel="unmatchedMessageTypeChannel" reply-channel="generatedFileChannel"
            filename-generator-expression="'${queue.jndi.name}' + '_' + headers.MessageId + '.xml'"/>
    ...
    When MessageId is not present I would like to use instead headers.jms_messageId.
    So the logic should be: if headers contains MessageId use it else use jms_messageId.

    I was not able to code that logic directly into a SpEL expression so I wrote a simple bean that exposes a method for doing that (public String retrieveId(MessageHeaders headers)).

    Then I tried to use the bean in my spring context file

    Code:
        <!-- Helper beans -->
        <beans:bean id="messageIdentifier" class="ch.integration.jms.listener.model.MessageIdentifier"/>
    
    ...
        <!--  Dispatch message -->
        <file:outbound-gateway directory="file:${unmatchedMessageType.directory}"
            request-channel="unmatchedMessageTypeChannel" reply-channel="generatedFileChannel"
            filename-generator-expression="'${queue.jndi.name}' + '_' + @messageIdentifier.retrieveId(headers) + '.xml'"/>
    ...
    But I got below error:

    Code:
    Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1057E:(pos 49): No bean resolver registered in the context to resolve access to bean 'messageIdentifier'
            at org.springframework.expression.spel.ast.BeanReference.getValueInternal(BeanReference.java:45)
            at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:52)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:63)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:62)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:62)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:62)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:62)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:62)
            at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:93)
            at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:93)
            at org.springframework.integration.handler.LoggingHandler.handleMessageInternal(LoggingHandler.java:105)
            at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73)
            ... 41 more
    Any help is greatly appreciated.

    Geetings
    nuvola

  2. #2
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    I think you are asking about Ternary operator with SpEL http://static.springsource.org/sprin....html#d0e12040
    Let us know if that helped

  3. #3

    Default

    Thanks for the link about Ternary operator with SpEL.

    I'm trying to use it as below:

    Code:
        <int:logging-channel-adapter channel="bpListMessageTypeResultChannel"
            expression="'#### [Channel=bpListMessageTypeChannel][***' + (headers.MessageId != null) ? headers.MessageId : headers.jms_messageId + '][Headers=' + headers + '][Payload=' + payload + ']'"
          level="INFO"/>
    but I got a type conversion problem so my above syntax is wrong ...

    Code:
    Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1001E:(pos 0): Type conversion problem, cannot convert from java.lang.String to java.lang.Boolean
    An additional question. I need to use the same Ternary operator expression in more places in my spring context file, is there a way to store the result of the expression into a variable and reference it in the spring context file where it is needed ?

    Thanks and regards
    nuvola

  4. #4
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    645

    Default

    Hello

    If you do this:
    Code:
    headers.MessageId != null ? headers.MessageId : headers.jms_messageId
    it's enough to use an "Elvis Operator": http://static.springsource.org/sprin....html#d0e12053

    Code:
    headers.MessageId ?: headers.jms_messageId
    Also try to wrap it with () as it should be done before String concatenation. That's why you've catched SpelEvaluationException

    But what is a problem to use with <logging-channel-adapter> attribute log-full-message="true" ?

    is there a way to store the result of the expression into a variable
    Can you explain a bit more about use-case? If you plan to store result of SpEL around Message properties (payload & headers) it will be bad idea: Spring Integration has stateless programming model and invokes SpEL from 'expression' attributes at runtime for each Message.

    Take care,
    Artem Bilan

  5. #5

    Default

    Hi Artem,

    your suggestion wrapping the expression with () works:

    Code:
        <int:logging-channel-adapter channel="bpListMessageTypeResultChannel"
            expression="'#### [Channel=bpListMessageTypeChannel][' + (headers.MessageId ?: headers.jms_messageId) + '][Headers=' + headers + '][Payload=' + payload + ']'"
            level="INFO"/>
    but it seems it doesn't work in case of stored-proc-outbound-gateway ...
    I used the same expression in the below <int-jdbcarameter name="I_MSG_ID" expression="...":

    Code:
        <int-jdbc:stored-proc-outbound-gateway request-channel="bpListMessageTypeChannel"
                                               reply-channel="bpListMessageTypeResultChannel"
                                               data-source="dataSource"
                                               stored-procedure-name="${stored-procedure-name.bp}"
                                               auto-startup="true"
                                               ignore-column-meta-data="true">
            <int-jdbc:sql-parameter-definition name="I_XML"
                                               direction="IN"
                                               type="VARCHAR"/>
            <int-jdbc:sql-parameter-definition name="I_MSG_ID"
                                               direction="IN"
                                               type="VARCHAR"/>
            <int-jdbc:sql-parameter-definition name="O_ERR_CODE"
                                               direction="OUT"
                                               type="INTEGER"/>
            <int-jdbc:parameter name="I_XML" expression="payload"/>
            <int-jdbc:parameter name="I_MSG_ID" expression="(headers.MessageId ?: headers.jms_messageId)"/>
    but I got

    Code:
    Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: Required input parameter 'I_MSG_ID' is missing
            at org.springframework.jdbc.core.CallableStatementCreatorFactory$CallableStatementCreatorImpl.createCallableStatement(CallableStatementCreatorFactory.java:209)
            at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:947)
            at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1003)
            at org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:388)
            at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:351)
            at org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:181)
            at org.springframework.integration.jdbc.StoredProcExecutor.executeStoredProcedure(StoredProcExecutor.java:276)
            at org.springframework.integration.jdbc.StoredProcExecutor.executeStoredProcedureInternal(StoredProcExecutor.java:267)
            at org.springframework.integration.jdbc.StoredProcExecutor.executeStoredProcedure(StoredProcExecutor.java:247)
            at org.springframework.integration.jdbc.StoredProcOutboundGateway.handleRequestMessage(StoredProcOutboundGateway.java:82)
            at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:97)
            at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73)
            ... 28 more
    Instead it is ok if I use <int-jdbcarameter name="I_MSG_ID" expression="headers.MessageId"/>

    Does the expression syntax change in case of stored-proc-outbound-gateway ?

    Thanks and regards
    nuvola

  6. #6
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    645

    Default

    OK.

    Try this one:
    HTML Code:
    <int-jdbc:parameter name="I_MSG_ID" expression="headers['MessageId'] ?: headers['jms_messageId']"/>

  7. #7

    Default

    This works if the headers contain the property 'MessageId' otherwise I got an error

    Code:
    Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 54): Field or property 'MessageId' cannot be found on object of type 'org.springframework.integration.MessageHeaders'
            at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:208)
            at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:72)
            at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57)
            at org.springframework.expression.spel.ast.Elvis.getValueInternal(Elvis.java:44)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:63)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:62)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:62)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:62)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:62)
            at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:62)
            at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:93)
            at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:93)
            at org.springframework.integration.handler.LoggingHandler.handleMessageInternal(LoggingHandler.java:105)
            at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73)
            ... 41 more
    I'm trying to work around your suggestion ...

  8. #8
    Join Date
    Jan 2009
    Location
    Ukraine, Kharkov
    Posts
    645

    Default

    I still don't understand:
    if you change SpEL from beanPropety style to map style it should work.
    I've tested it before send you suggestion ;-).

    So, I repeat: this should work:
    HTML Code:
    <int-jdbc:parameter name="I_MSG_ID" expression="headers['MessageId'] ?: headers['jms_messageId']"/>
    And in the <logging-channel-adapter> do the same, please

  9. #9

    Default

    If I change from beanPropety style to map style in both stored-proc-outbound-gateway and logging-channel-adapter it works

    Code:
        <int-jdbc:stored-proc-outbound-gateway request-channel="bpListMessageTypeChannel"
    ...
            <int-jdbc:parameter name="I_XML" expression="payload"/>
            <int-jdbc:parameter name="I_MSG_ID" expression="headers['MessageId'] ?: headers['jms_messageId']"/>
        </int-jdbc:stored-proc-outbound-gateway>
    
        <int:channel id="bpListMessageTypeResultChannel"/>
    
        <int:logging-channel-adapter channel="bpListMessageTypeResultChannel"
            expression="'#### [Channel=bpListMessageTypeChannel][' + (headers['MessageId'] ?: headers['jms_messageId']) + '][Headers=' + headers + '][Payload=' + payload + ']'"
            level="INFO"/>
    If I change only in the stored-proc-outbound-gateway I got the error.

    So as you suggested I changed in both :-)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •