1   /*
2    * $Id: AbstractJdbcTransactionalFunctionalTestCase.java 11376 2008-03-16 17:44:10Z dfeist $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.test.integration.transport.jdbc;
12  
13  
14  import org.mule.DefaultExceptionStrategy;
15  import org.mule.api.MuleEventContext;
16  import org.mule.api.context.notification.ServerNotification;
17  import org.mule.api.context.notification.TransactionNotificationListener;
18  import org.mule.api.endpoint.EndpointBuilder;
19  import org.mule.api.endpoint.InboundEndpoint;
20  import org.mule.api.endpoint.OutboundEndpoint;
21  import org.mule.api.service.Service;
22  import org.mule.api.transaction.Transaction;
23  import org.mule.api.transaction.TransactionConfig;
24  import org.mule.api.transaction.TransactionFactory;
25  import org.mule.component.DefaultJavaComponent;
26  import org.mule.context.notification.TransactionNotification;
27  import org.mule.endpoint.EndpointURIEndpointBuilder;
28  import org.mule.model.seda.SedaService;
29  import org.mule.object.PrototypeObjectFactory;
30  import org.mule.routing.inbound.DefaultInboundRouterCollection;
31  import org.mule.routing.outbound.DefaultOutboundRouterCollection;
32  import org.mule.routing.outbound.OutboundPassThroughRouter;
33  import org.mule.tck.functional.EventCallback;
34  import org.mule.transaction.MuleTransactionConfig;
35  
36  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
37  
38  public abstract class AbstractJdbcTransactionalFunctionalTestCase extends AbstractJdbcFunctionalTestCase  implements TransactionNotificationListener
39  {
40  
41      private Transaction currentTx;
42      protected boolean rollbacked = false;
43  
44      protected void doSetUp() throws Exception
45      {
46          super.doSetUp();
47          muleContext.registerListener(this);
48          currentTx = null;
49      }
50  
51      public void testReceiveAndSendWithException() throws Exception
52      {
53          final AtomicBoolean called = new AtomicBoolean(false);
54  
55          EventCallback callback = new EventCallback()
56          {
57              public void eventReceived(MuleEventContext context, Object component) throws Exception
58              {
59                  try
60                  {
61                      called.set(true);
62                      currentTx = context.getCurrentTransaction();
63                      assertNotNull(currentTx);
64                      assertTrue(currentTx.isBegun());
65                      currentTx.setRollbackOnly();
66                  }
67                  finally
68                  {
69                      synchronized (called)
70                      {
71                          called.notifyAll();
72                      }
73                  }
74              }
75          };
76  
77          // Start the server
78          initialiseService(TransactionConfig.ACTION_ALWAYS_BEGIN, callback);
79          muleContext.start();
80  
81          execSqlUpdate("INSERT INTO TEST(TYPE, DATA, ACK, RESULT) VALUES (1, '" + DEFAULT_MESSAGE
82                        + "', NULL, NULL)");
83  
84          synchronized (called)
85          {
86              called.wait(20000);
87          }
88          assertTrue(called.get());
89  
90          Thread.sleep(1000);
91  
92          assertTrue(rollbacked);
93  
94          Object[] obj = execSqlQuery("SELECT COUNT(*) FROM TEST WHERE TYPE = 2");
95          assertNotNull(obj);
96          assertEquals(1, obj.length);
97          assertEquals(new Integer(0), obj[0]);
98          obj = execSqlQuery("SELECT ACK FROM TEST WHERE TYPE = 1");
99          assertNotNull(obj);
100         assertEquals(1, obj.length);
101         assertNull(obj[0]);
102     }
103 
104     public Service initialiseService(byte txBeginAction, EventCallback callback) throws Exception
105     {
106         Service service = new SedaService();
107         service.setExceptionListener(new DefaultExceptionStrategy());
108         service.setName("testComponent");
109         service.setComponent(new DefaultJavaComponent(new PrototypeObjectFactory(JdbcFunctionalTestComponent.class)));
110 
111         TransactionFactory tf = getTransactionFactory();
112         TransactionConfig txConfig = new MuleTransactionConfig();
113         txConfig.setFactory(tf);
114         txConfig.setAction(txBeginAction);
115         
116         EndpointBuilder endpointBuilder = new EndpointURIEndpointBuilder(getInDest(), muleContext);
117         endpointBuilder.setName("testIn");
118         endpointBuilder.setConnector(connector);
119         endpointBuilder.setTransactionConfig(txConfig);
120         InboundEndpoint endpoint = muleContext.getRegistry().lookupEndpointFactory().getInboundEndpoint(
121             endpointBuilder);
122 
123         EndpointBuilder endpointBuilder2 = new EndpointURIEndpointBuilder(getOutDest(), muleContext);
124         endpointBuilder2.setName("testOut");
125         endpointBuilder2.setConnector(connector);
126         OutboundEndpoint outProvider = muleContext.getRegistry().lookupEndpointFactory().getOutboundEndpoint(
127             endpointBuilder2);
128         
129         service.setOutboundRouter(new DefaultOutboundRouterCollection());
130         OutboundPassThroughRouter router = new OutboundPassThroughRouter();
131         router.addEndpoint(outProvider);
132         service.getOutboundRouter().addRouter(router);
133         service.setInboundRouter(new DefaultInboundRouterCollection());
134         service.getInboundRouter().addEndpoint(endpoint);
135 
136         // these tests no longer work - they need replacing with config driven tests
137         // furthemore, nothing is read from service properties any more
138         // (except for axis and xfire related hacks)
139         // so i am removing the code below since it's a pointless call to a deprecated method
140 //        HashMap props = new HashMap();
141 //        props.put("eventCallback", callback);
142 //        service.setProperties(props);
143         service.setModel(model);
144         muleContext.getRegistry().registerService(service);
145         return service;
146     }
147 
148     public void onNotification(ServerNotification notification)
149     {
150         if (notification.getAction() == TransactionNotification.TRANSACTION_ROLLEDBACK)
151         {
152             this.rollbacked = true;
153         }
154     }
155 
156     abstract protected TransactionFactory getTransactionFactory();
157 
158 }