View Javadoc

1   /***
2    * 
3    * Copyright 2005 LogicBlaze, Inc.
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License"); 
6    * you may not use this file except in compliance with the License. 
7    * You may obtain a copy of the License at 
8    * 
9    * http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License. 
16   * 
17   **/
18  package org.jencks;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  
23  import javax.jms.Message;
24  import javax.jms.MessageListener;
25  import javax.resource.ResourceException;
26  import javax.resource.spi.endpoint.MessageEndpoint;
27  import javax.transaction.HeuristicMixedException;
28  import javax.transaction.HeuristicRollbackException;
29  import javax.transaction.NotSupportedException;
30  import javax.transaction.RollbackException;
31  import javax.transaction.SystemException;
32  import javax.transaction.Transaction;
33  import javax.transaction.TransactionManager;
34  import javax.transaction.xa.XAResource;
35  import java.lang.reflect.Method;
36  
37  /***
38   * An XA based Endpoint which uses an XA transaction per message delivery.
39   *
40   * @version $Revision: 1.1.1.1 $
41   */
42  public class XAEndpoint implements MessageEndpoint, MessageListener {
43      private static final Log log = LogFactory.getLog(XAEndpoint.class);
44  
45      private MessageListener messageListener;
46      private XAResource xaResource;
47      private TransactionManager transactionManager;
48      private Transaction transaction;
49      private boolean beforeDeliveryCompleted;
50      private boolean messageDelivered;
51  
52      public XAEndpoint(MessageListener messageListener, XAResource xaResource, TransactionManager transactionManager) {
53          this.messageListener = messageListener;
54          this.xaResource = xaResource;
55          this.transactionManager = transactionManager;
56      }
57  
58      public void beforeDelivery(Method method) throws NoSuchMethodException, ResourceException {
59          if (transaction != null) {
60              throw new IllegalStateException("Transaction still in progress");
61          }
62          beforeDeliveryCompleted = false;
63          try {
64              transactionManager.begin();
65              transaction = transactionManager.getTransaction();
66  
67              transaction.enlistResource(xaResource);
68              beforeDeliveryCompleted = true;
69  
70              log.trace("Transaction started and resource enlisted");
71          }
72          catch (NotSupportedException e) {
73              System.out.println("Caught: " + e);
74              throw new ResourceException(e);
75          }
76          catch (SystemException e) {
77              System.out.println("Caught: " + e);
78              throw new ResourceException(e);
79          }
80          catch (RollbackException e) {
81              System.out.println("Caught: " + e);
82              throw new ResourceException(e);
83          }
84          catch (Throwable e) {
85              System.out.println("Caught: " + e);
86              e.printStackTrace();
87              throw new ResourceException(e);
88          }
89      }
90  
91      public void afterDelivery() throws ResourceException {
92          if (transaction == null) {
93              throw new IllegalStateException("Transaction not in progress");
94          }
95          if (beforeDeliveryCompleted && messageDelivered) {
96              try {
97                  transaction.delistResource(xaResource, XAResource.TMSUSPEND);
98              }
99              catch (SystemException e) {
100                 throw new ResourceException(e);
101             }
102             try {
103                 transaction.commit();
104                 log.trace("Transaction committed");
105             }
106             catch (RollbackException e) {
107                 throw new ResourceException(e);
108             }
109             catch (HeuristicMixedException e) {
110                 doRollback(e);
111             }
112             catch (HeuristicRollbackException e) {
113                 doRollback(e);
114             }
115             catch (SystemException e) {
116                 doRollback(e);
117             }
118             finally {
119                 transaction = null;
120             }
121         }
122     }
123 
124     public void onMessage(Message message) {
125         messageDelivered = false;
126         messageListener.onMessage(message);
127         messageDelivered = true;
128     }
129 
130     public void release() {
131         if (transaction != null) {
132             try {
133                 transaction.rollback();
134             }
135             catch (SystemException e) {
136                 log.warn("Failed to rollback transaction: " + e, e);
137             }
138         }
139     }
140 
141     protected void doRollback(Exception e) throws ResourceException {
142         try {
143             transaction.rollback();
144             log.trace("Transaction rolled back");
145         }
146         catch (SystemException e1) {
147             log.warn("Caught exception while rolling back: " + e1, e1);
148         }
149         transaction = null;
150         throw new ResourceException(e);
151     }
152 }