[ 
https://issues.apache.org/jira/browse/CXF-5293?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13779637#comment-13779637
 ] 

Nan Xu edited comment on CXF-5293 at 9/27/13 4:03 AM:
------------------------------------------------------

I did more debug today. here is what I found and I have a solution for this.

when use jms feature, cxf use some interceptors. all the inbound information 
and process result is put to the inMessage(cxf Message) and outbound process 
result is put to another message. the transaction only check the inbound 
message if it has an exception. the out message status is never checked. 

quick solution is 

write another interceptor to change the inbound message(cxf internal type) when 
outbound message (cxf internal type) has an exception.
code like this

{code:java}
    public class MyInterceptor extends AbstractPhaseInterceptor<Message> {
    public MyInterceptor () {
        super(Phase.Setup);
    }
 
    public void handleMessage(Message message) {
       //this can be empty
    }
 
    // this will be called when exception happen. in the method unwind()
    public void handleFault(Message message) {
          message.getExchange().getInMessage().setContent(Exception.class, 
message.getContent(Exception.class))
    }
}
{code}

and configure this interceptor in the cxf configuration.
{code:xml}
      <bean id="MyInterceptor" class="com.test.MyInterceptor"/>
     <cxf:bus>
        <cxf:inInterceptors>
            
        </cxf:inInterceptors>
        <cxf:outInterceptors>
            <ref bean="MyInterceptor"/>
       </cxf:outInterceptors>
    </cxf:bus>
{code}

though this fix my problem, I would think the jms feature should do this 
automatically. because outbound message sending error should result a message 
rollback.
the interceptor can be put to the outfaultInterceptor but I did not check that.
                
      was (Author: angelfox):
    I did more debug today. here is what I found and I have a solution for this.

when use jms feature, cxf use some interceptors. all the inbound information 
and process result is put to the inMessage(cxf Message) and outbound process 
result is put to another message. the transaction only check the inbound 
message if it has an exception. the out message status is never checked. 

quick solution is 

write another interceptor to change the inbound message(cxf internal type) when 
outbound message (cxf internal type) has an exception.
code like this

{code:java}
    public class MyInterceptor extends AbstractPhaseInterceptor<Message> {
    public MyInterceptor () {
        super(Phase.Setup);
    }
 
    public void handleMessage(Message message) {
       //this can be empty
    }
 
    // this will be called when exception happen. in the method unwind()
    public void handleFault(Message message) {
          message.getExchange().getInMessage().setContent(Exception.class, 
message.getContent(Exception.class))
    }
}
{code}

and configure this interceptor in the cxf configuration.
{code:xml}
      <bean id="MyInterceptor" class="com.test.MyInterceptor"/>
     <cxf:bus>
        <cxf:inInterceptors>
            
        </cxf:inInterceptors>
        <cxf:outInterceptors>
            <ref bean="MyInterceptor"/>
       </cxf:outInterceptors>
    </cxf:bus>
{code}

though this fix my problem, I would think the jms feature should do this 
automatically. because outbound message sending error should result a message 
rollback.
                  
> XA transaction for soap over jms not fully working
> --------------------------------------------------
>
>                 Key: CXF-5293
>                 URL: https://issues.apache.org/jira/browse/CXF-5293
>             Project: CXF
>          Issue Type: Bug
>          Components: Configuration, Integration, Transports
>    Affects Versions: 2.7.6
>         Environment: weblogic 11g with cxf 2.7.6 and spring 3.2.0
>            Reporter: Nan Xu
>
> trying to achieve such a scenario.
> 1. soap message was sent to a inbound queue.
> 2. cxf pick up the soap message from inbound queue, then process it(do a 
> database update)
> 3. response message send to outbound queue.
> expected behavior:
> when the outbound message can not be sent. the database change rollback, and 
> inbound message was send back to the dead letter queue, which is configured 
> at inbound queue failed delivery setting.(based on redelivery time)
> cxf configuration.
> {code:xml}
>     <bean id="dbService" class="com.test.DBActionImpl"/>    <!--update DB-->
>     
>      <jaxws:endpoint id="dbServiceEndPoint" implementor="#dbService" 
> address="jms://">
>               <jaxws:features>
>                       <bean 
> class="org.apache.cxf.transport.jms.JMSConfigFeature" 
> p:jmsConfig-ref="jmsConfig" />
>               </jaxws:features>
>       </jaxws:endpoint>
>  
>       <bean id="jmsConfig" 
> class="org.apache.cxf.transport.jms.JMSConfiguration"
>               p:connectionFactory-ref="connectionFactory" 
>               p:targetDestination="inboundQueue"
>               p:replyDestination="outboundQueue"
>               p:destinationResolver-ref="jmsDestinationResolver"
>               p:transactionManager-ref="transactionManager"
>       /> 
>         <bean id="jmsDestinationResolver" 
> class="org.springframework.jms.support.destination.JndiDestinationResolver" 
> p:resourceRef="true"/>
> {code}
> all the db datasource, jms connection factory and transaction manager are XA.
> I pause the outbound queue production in weblogic to generate the outbound 
> message sending error.
> problem:
> No message was send to Dead Letter Queue and DB change get committed.
> tried with a standard spring jms listener in this way.
> {code:java}
> public class MyMessageListener implements MessageListener {
>       
>       @Autowired
>       private DBAction dbAction;
>       
>       @Autowired
>       private ResponseSender responseSender;  //jms sender use jmsTemplate
>       @Override
>       public void onMessage(Message message) {
>               if (message instanceof TextMessage) {
>                       try {
>                               System.out.println("I get message:  "+ 
> ((TextMessage) message).getText());
>                               
>                               dbAction.updateDb();
>                               
>                               responseSender.sendResponse();
>                               
>                       } catch (JMSException ex) {
>                               throw new RuntimeException(ex);
>                       }
>               } else {
>                       throw new IllegalArgumentException("Message must be of 
> type TextMessage");
>               }
>       }       
> }
> {code}
> everything works fine. means when outbound queue production paused, the 
> message was send to dead letter queue and db change reverted.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

Reply via email to