/** Vote using phase-1 of the 2-phase commit. */ public int prepare(Xid xid) throws XAException { if (_endFlags != -1) { int endFlags = _endFlags; _endFlags = -1; if (_isXATransaction) endResource(xid, endFlags); } if (_isXATransaction) { try { if (log.isLoggable(Level.FINER)) log.finer("prepare-XA: " + xid + " " + _xaResource); int result = _xaResource.prepare(xid); if (result == XA_RDONLY) { if (_xaResource != null) _isXATransaction = true; clearXid(); } return result; } catch (XAException e) { if (log.isLoggable(Level.FINER)) log.finer("failed prepare-XA: " + xid + " " + _xaResource + " " + e); throw e; } } else return XA_OK; }
private boolean runXaResourcePrepare() throws SystemException { Collection<XAResource> resources = getEnlistedResources(); for (XAResource res : resources) { try { res.prepare(xid); } catch (XAException e) { log.trace("The resource wants to rollback!", e); return false; } catch (Throwable th) { log.error("Unexpected error from resource manager!", th); throw new SystemException(th.getMessage()); } } return true; }
@Override public int prepare(Xid xid) throws XAException { prepareResult = xaResource.prepare(xid); return prepareResult; }
private void checkXAHoldability() { System.out.println("START XA HOLDABILITY TEST"); try { EmbeddedXADataSource dscsx = new EmbeddedXADataSource(); dscsx.setDatabaseName("wombat"); XAConnection xac = dscsx.getXAConnection("fred", "wilma"); XAResource xr = xac.getXAResource(); Xid xid = getXid(25, (byte) 21, (byte) 01); Connection conn1 = xac.getConnection(); System.out.println( "By default, autocommit is " + conn1.getAutoCommit() + " for a connection"); System.out.println("Default holdability for a connection is HOLD_CURSORS_OVER_COMMIT"); System.out.println( "CONNECTION(not in xa transaction yet) HOLDABILITY " + (conn1.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); // start a global transaction and default holdability and autocommit will be switched to match // Derby XA restrictions xr.start(xid, XAResource.TMNOFLAGS); System.out.println( "Notice that autocommit now is " + conn1.getAutoCommit() + " for connection because it is part of the global transaction"); System.out.println( "Notice that connection's holdability at this point is CLOSE_CURSORS_AT_COMMIT because it is part of the global transaction"); System.out.println( "CONNECTION(in xa transaction) HOLDABILITY " + (conn1.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); xr.end(xid, XAResource.TMSUCCESS); conn1.commit(); conn1.close(); xid = getXid(27, (byte) 21, (byte) 01); xr.start(xid, XAResource.TMNOFLAGS); conn1 = xac.getConnection(); System.out.println( "CONNECTION(in xa transaction) HOLDABILITY " + (conn1.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "Autocommit on Connection inside global transaction has been set correctly to " + conn1.getAutoCommit()); xr.end(xid, XAResource.TMSUCCESS); conn1.rollback(); Connection conn = xac.getConnection(); conn.setAutoCommit(false); conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); System.out.println( "CONNECTION(non-xa) HOLDABILITY " + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); Statement s = conn.createStatement(); System.out.println( "STATEMENT HOLDABILITY " + (s.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); s.executeUpdate("create table hold_30 (id int not null primary key, b char(30))"); s.executeUpdate("insert into hold_30 values (1,'init2'), (2, 'init3'), (3,'init3')"); s.executeUpdate("insert into hold_30 values (4,'init4'), (5, 'init5'), (6,'init6')"); s.executeUpdate("insert into hold_30 values (7,'init7'), (8, 'init8'), (9,'init9')"); System.out.println( "STATEMENT HOLDABILITY " + (s.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); Statement sh = conn.createStatement( ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); PreparedStatement psh = conn.prepareStatement( "select id from hold_30 for update", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); CallableStatement csh = conn.prepareCall( "select id from hold_30 for update", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); System.out.println( "STATEMENT HOLDABILITY " + (sh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "PREPARED STATEMENT HOLDABILITY " + (psh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "CALLABLE STATEMENT HOLDABILITY " + (csh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); ResultSet rsh = sh.executeQuery("select id from hold_30 for update"); rsh.next(); System.out.println("H@1 id " + rsh.getInt(1)); rsh.next(); System.out.println("H@2 id " + rsh.getInt(1)); conn.commit(); rsh.next(); System.out.println("H@3 id " + rsh.getInt(1)); conn.commit(); xid = getXid(23, (byte) 21, (byte) 01); xr.start(xid, XAResource.TMNOFLAGS); Statement stmtInsideGlobalTransaction = conn.createStatement(); PreparedStatement prepstmtInsideGlobalTransaction = conn.prepareStatement("select id from hold_30"); CallableStatement callablestmtInsideGlobalTransaction = conn.prepareCall("select id from hold_30"); System.out.println( "CONNECTION(xa) HOLDABILITY " + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "STATEMENT(this one was created with holdability false, outside the global transaction. Check it's holdability inside global transaction) HOLDABILITY " + (s.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "STATEMENT(this one was created with holdability true, outside the global transaction. Check it's holdability inside global transaction) HOLDABILITY " + (sh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "STATEMENT(this one was created with default holdability inside this global transaction. Check it's holdability) HOLDABILITY " + (stmtInsideGlobalTransaction.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "PREPAREDSTATEMENT(this one was created with default holdability inside this global transaction. Check it's holdability) HOLDABILITY " + (prepstmtInsideGlobalTransaction.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "CALLABLESTATEMENT(this one was created with default holdability inside this global transaction. Check it's holdability) HOLDABILITY " + (callablestmtInsideGlobalTransaction.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); ResultSet rsx = s.executeQuery("select id from hold_30 for update"); rsx.next(); System.out.println("X@1 id " + rsx.getInt(1)); rsx.next(); System.out.println("X@2 id " + rsx.getInt(1)); xr.end(xid, XAResource.TMSUCCESS); // result set should not be useable, since it is part of a detached // XAConnection try { rsx.next(); System.out.println("FAIL - rsx's connection not active id " + rsx.getInt(1)); } catch (SQLException sqle) { System.out.println("Expected SQLException " + sqle.getMessage()); } // result set should not be useable, it should have been closed by the xa start. try { rsh.next(); System.out.println("FAIL - rsh's should be closed " + rsx.getInt(1)); } catch (SQLException sqle) { System.out.println("Expected SQLException " + sqle.getMessage()); } System.out.println("resume XA transaction and keep using rs"); xr.start(xid, XAResource.TMJOIN); Statement stmtAfterGlobalTransactionResume = conn.createStatement(); PreparedStatement prepstmtAfterGlobalTransactionResume = conn.prepareStatement("select id from hold_30"); CallableStatement callablestmtAfterGlobalTransactionResume = conn.prepareCall("select id from hold_30"); System.out.println("Check holdability of various jdbc objects after resuming XA transaction"); System.out.println( "CONNECTION(xa) HOLDABILITY " + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "STATEMENT(this one was created with holdability false, outside the global transaction. Check it's holdability inside global transaction) HOLDABILITY " + (s.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "STATEMENT(this one was created with holdability true, outside the global transaction. Check it's holdability inside global transaction) HOLDABILITY " + (sh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "STATEMENT(this one was created with default holdability inside the global transaction when it was first started. Check it's holdability) HOLDABILITY " + (stmtInsideGlobalTransaction.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "PREPAREDSTATEMENT(this one was created with default holdability inside the global transaction when it was first started. Check it's holdability) HOLDABILITY " + (prepstmtInsideGlobalTransaction.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "CALLABLESTATEMENT(this one was created with default holdability inside the global transaction when it was first started. Check it's holdability) HOLDABILITY " + (callablestmtInsideGlobalTransaction.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "STATEMENT(this one was created with default holdability after the global transaction was resumed. Check it's holdability) HOLDABILITY " + (stmtAfterGlobalTransactionResume.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "PREPAREDSTATEMENT(this one was created with default holdability after the global transaction was resumed. Check it's holdability) HOLDABILITY " + (prepstmtAfterGlobalTransactionResume.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println( "CALLABLESTATEMENT(this one was created with default holdability after the global transaction was resumed. Check it's holdability) HOLDABILITY " + (callablestmtAfterGlobalTransactionResume.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); rsx.next(); System.out.println("X@3 id " + rsx.getInt(1)); xr.end(xid, XAResource.TMSUCCESS); if (xr.prepare(xid) != XAResource.XA_RDONLY) xr.commit(xid, false); // try again once the xa transaction has been committed. try { rsx.next(); System.out.println("FAIL - rsx's connection not active id (B)" + rsx.getInt(1)); } catch (SQLException sqle) { System.out.println("Expected SQLException " + sqle.getMessage()); } try { rsh.next(); System.out.println("FAIL - rsh's should be closed (B) " + rsx.getInt(1)); } catch (SQLException sqle) { System.out.println("Expected SQLException " + sqle.getMessage()); } System.out.println("Set connection to hold "); conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); System.out.println( "CONNECTION(held) HOLDABILITY " + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); xid = getXid(24, (byte) 21, (byte) 01); xr.start(xid, XAResource.TMNOFLAGS); System.out.println( "CONNECTION(xa) HOLDABILITY " + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); try { conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT); System.out.println("FAIL allowed to set hold mode in xa transaction"); } catch (SQLException sqle) { System.out.println("Expected SQLException(setHoldability) " + sqle.getMessage()); } // try to create a statement with held attributes try { Statement shxa = conn.createStatement( ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); System.out.println( "FAIL opened statement with hold cursor attribute in global transaction"); } catch (SQLException sqle) { System.out.println("Expected SQLException (Statement hold) " + sqle.getMessage()); } try { Statement shxa = conn.prepareStatement( "select id from hold_30", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); System.out.println( "FAIL opened statement with hold cursor attribute in global transaction"); } catch (SQLException sqle) { System.out.println("Expected SQLException (PreparedStatement hold) " + sqle.getMessage()); } try { Statement shxa = conn.prepareCall( "CALL XXX.TTT()", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT); System.out.println( "FAIL opened statement with hold cursor attribute in global transaction"); } catch (SQLException sqle) { System.out.println("Expected SQLException (CallableStatement hold) " + sqle.getMessage()); } // check we cannot use a holdable statement set up in local mode. System.out.println( "STATEMENT HOLDABILITY " + (sh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); try { sh.executeQuery("select id from hold_30"); System.out.println("FAIL used held statement in global transaction"); } catch (SQLException sqle) { System.out.println("Expected SQLException (local Statement hold) " + sqle.getMessage()); } try { sh.execute("select id from hold_30"); System.out.println("FAIL used held statement in global transaction"); } catch (SQLException sqle) { System.out.println("Expected SQLException (local Statement hold) " + sqle.getMessage()); } System.out.println( "PREPARED STATEMENT HOLDABILITY " + (psh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); try { psh.executeQuery(); System.out.println("FAIL used held prepared statement in global transaction"); } catch (SQLException sqle) { System.out.println( "Expected SQLException (local PreparedStatement hold) " + sqle.getMessage()); } try { psh.execute(); System.out.println("FAIL used held prepared statement in global transaction"); } catch (SQLException sqle) { System.out.println( "Expected SQLException (local PreparedStatement hold) " + sqle.getMessage()); } System.out.println( "CALLABLE STATEMENT HOLDABILITY " + (csh.getResultSetHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); try { csh.executeQuery(); System.out.println("FAIL used held callable statement in global transaction"); } catch (SQLException sqle) { System.out.println( "Expected SQLException (local CallableStatement hold) " + sqle.getMessage()); } try { csh.execute(); System.out.println("FAIL used held callable statement in global transaction"); } catch (SQLException sqle) { System.out.println( "Expected SQLException (local CallableStatement hold) " + sqle.getMessage()); } // but an update works sh.executeUpdate("insert into hold_30 values(10, 'init10')"); xr.end(xid, XAResource.TMSUCCESS); System.out.println( "CONNECTION(held) HOLDABILITY " + (conn.getHoldability() == ResultSet.HOLD_CURSORS_OVER_COMMIT)); conn.close(); System.out.println("PASS XA HOLDABILITY TEST"); } catch (XAException xae) { System.out.println("XAException error code " + xae.errorCode); xae.printStackTrace(System.out); Throwable t = xae.getCause(); if (t instanceof SQLException) JDBCDisplayUtil.ShowSQLException(System.out, (SQLException) t); } catch (SQLException sqle) { JDBCDisplayUtil.ShowSQLException(System.out, sqle); } catch (Throwable t) { t.printStackTrace(System.out); } System.out.flush(); }
/** * Tests that simple distributed transaction processing works as expected. * * @throws Exception if the test fails. */ public void testCoordination() throws Exception { if (!versionMeetsMinimum(5, 0)) { return; } createTable("testCoordination", "(field1 int) ENGINE=InnoDB"); Connection conn1 = null; Connection conn2 = null; XAConnection xaConn1 = null; XAConnection xaConn2 = null; try { xaConn1 = getXAConnection(); XAResource xaRes1 = xaConn1.getXAResource(); conn1 = xaConn1.getConnection(); xaConn2 = getXAConnection(); XAResource xaRes2 = xaConn2.getXAResource(); conn2 = xaConn2.getConnection(); Xid xid1 = createXid(); Xid xid2 = createXid(xid1); xaRes1.start(xid1, XAResource.TMNOFLAGS); xaRes2.start(xid2, XAResource.TMNOFLAGS); conn1.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (1)"); conn2.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (2)"); xaRes1.end(xid1, XAResource.TMSUCCESS); xaRes2.end(xid2, XAResource.TMSUCCESS); xaRes1.prepare(xid1); xaRes2.prepare(xid2); xaRes1.commit(xid1, false); xaRes2.commit(xid2, false); this.rs = this.stmt.executeQuery("SELECT field1 FROM testCoordination ORDER BY field1"); assertTrue(this.rs.next()); assertEquals(1, this.rs.getInt(1)); assertTrue(this.rs.next()); assertEquals(2, this.rs.getInt(1)); this.stmt.executeUpdate("TRUNCATE TABLE testCoordination"); // // Now test rollback // xid1 = createXid(); xid2 = createXid(xid1); xaRes1.start(xid1, XAResource.TMNOFLAGS); xaRes2.start(xid2, XAResource.TMNOFLAGS); conn1.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (1)"); // ensure visibility assertEquals( "1", getSingleIndexedValueWithQuery( conn1, 1, "SELECT field1 FROM testCoordination WHERE field1=1") .toString()); conn2.createStatement().executeUpdate("INSERT INTO testCoordination VALUES (2)"); // ensure visibility assertEquals( "2", getSingleIndexedValueWithQuery( conn2, 1, "SELECT field1 FROM testCoordination WHERE field1=2") .toString()); xaRes1.end(xid1, XAResource.TMSUCCESS); xaRes2.end(xid2, XAResource.TMSUCCESS); xaRes1.prepare(xid1); xaRes2.prepare(xid2); xaRes1.rollback(xid1); xaRes2.rollback(xid2); this.rs = this.stmt.executeQuery("SELECT field1 FROM testCoordination ORDER BY field1"); assertTrue(!this.rs.next()); } finally { if (conn1 != null) { conn1.close(); } if (conn2 != null) { conn2.close(); } if (xaConn1 != null) { xaConn1.close(); } if (xaConn2 != null) { xaConn2.close(); } } }
/** * Tests that XA RECOVER works as expected. * * @throws Exception if test fails */ public void testRecover() throws Exception { if (!versionMeetsMinimum(5, 0)) { return; } if (versionMeetsMinimum(5, 7) && !versionMeetsMinimum(5, 7, 5)) { // Test is broken in 5.7.0 - 5.7.4 after server bug#14670465 fix which changed the XA RECOVER // output format. // Fixed in 5.7.5 server version return; } // BUG#14670465 fix broke this functionality in 5.7.1 - 5.7.2 if (versionMeetsMinimum(5, 7, 1) && !versionMeetsMinimum(5, 7, 3)) { return; } XAConnection xaConn = null, recoverConn = null; try { xaConn = getXAConnection(); Connection c = xaConn.getConnection(); Xid xid = createXid(); XAResource xaRes = xaConn.getXAResource(); xaRes.start(xid, XAResource.TMNOFLAGS); c.createStatement().executeQuery("SELECT 1"); xaRes.end(xid, XAResource.TMSUCCESS); xaRes.prepare(xid); // Now try and recover recoverConn = getXAConnection(); XAResource recoverRes = recoverConn.getXAResource(); Xid[] recoveredXids = recoverRes.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN); assertTrue(recoveredXids != null); assertTrue(recoveredXids.length > 0); boolean xidFound = false; for (int i = 0; i < recoveredXids.length; i++) { if (recoveredXids[i] != null && recoveredXids[i].equals(xid)) { xidFound = true; break; } } assertTrue(xidFound); recoverRes = recoverConn.getXAResource(); recoveredXids = recoverRes.recover(XAResource.TMSTARTRSCAN); assertTrue(recoveredXids != null); assertTrue(recoveredXids.length > 0); xidFound = false; for (int i = 0; i < recoveredXids.length; i++) { if (recoveredXids[i] != null && recoveredXids[i].equals(xid)) { xidFound = true; break; } } assertTrue(xidFound); // Test flags recoverRes.recover(XAResource.TMSTARTRSCAN); recoverRes.recover(XAResource.TMENDRSCAN); recoverRes.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN); // This should fail try { recoverRes.recover(XAResource.TMSUCCESS); fail("XAException should have been thrown"); } catch (XAException xaEx) { assertEquals(XAException.XAER_INVAL, xaEx.errorCode); } } finally { if (xaConn != null) { xaConn.close(); } if (recoverConn != null) { recoverConn.close(); } } }
@Override public int prepare(Xid xid) throws XAException { return resource.prepare(xid); }
@Override public boolean runExample() throws Exception { XAConnection connection = null; InitialContext initialContext = null; try { // Step 1. Create an initial context to perform the JNDI lookup. initialContext = getContext(0); // Step 2. Lookup on the queue Queue queue = (Queue) initialContext.lookup("/queue/exampleQueue"); // Step 3. Perform a lookup on the XA Connection Factory XAConnectionFactory cf = (XAConnectionFactory) initialContext.lookup("/XAConnectionFactory"); // Step 4.Create a JMS XAConnection connection = cf.createXAConnection(); // Step 5. Start the connection connection.start(); // Step 6. Create a JMS XASession XASession xaSession = connection.createXASession(); // Step 7. Create a normal session Session normalSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); // Step 8. Create a normal Message Consumer MessageConsumer normalConsumer = normalSession.createConsumer(queue); normalConsumer.setMessageListener(new SimpleMessageListener()); // Step 9. Get the JMS Session Session session = xaSession.getSession(); // Step 10. Create a message producer MessageProducer producer = session.createProducer(queue); // Step 11. Create two Text Messages TextMessage helloMessage = session.createTextMessage("hello"); TextMessage worldMessage = session.createTextMessage("world"); // Step 12. create a transaction Xid xid1 = new DummyXid( "xa-example1".getBytes(CharsetUtil.UTF_8), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes()); // Step 13. Get the JMS XAResource XAResource xaRes = xaSession.getXAResource(); // Step 14. Begin the Transaction work xaRes.start(xid1, XAResource.TMNOFLAGS); // Step 15. do work, sending two messages. producer.send(helloMessage); producer.send(worldMessage); Thread.sleep(2000); // Step 16. Check the result, it should receive none! checkNoMessageReceived(); // Step 17. Stop the work xaRes.end(xid1, XAResource.TMSUCCESS); // Step 18. Prepare xaRes.prepare(xid1); // Step 19. Roll back the transaction xaRes.rollback(xid1); // Step 20. No messages should be received! checkNoMessageReceived(); // Step 21. Create another transaction Xid xid2 = new DummyXid( "xa-example2".getBytes(), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes()); // Step 22. Start the transaction xaRes.start(xid2, XAResource.TMNOFLAGS); // Step 23. Re-send those messages producer.send(helloMessage); producer.send(worldMessage); // Step 24. Stop the work xaRes.end(xid2, XAResource.TMSUCCESS); // Step 25. Prepare xaRes.prepare(xid2); // Step 26. No messages should be received at this moment checkNoMessageReceived(); // Step 27. Commit! xaRes.commit(xid2, false); Thread.sleep(2000); // Step 28. Check the result, all message received checkAllMessageReceived(); return result; } finally { // Step 29. Be sure to close our JMS resources! if (initialContext != null) { initialContext.close(); } if (connection != null) { connection.close(); } } }