Announcement Announcement Module
Collapse
No announcement yet.
rolling back transactions for a mock client to a remote EJB Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • rolling back transactions for a mock client to a remote EJB

    I have successfuly tested independent objects embedded within an EJB, using Springs org.springframework.test package. These tests were written so that any changes made to the database were rolled back at the end of each test case. I achieved this by making each test class extend the AbstractTransactionalDataSourceSpringContextTests Spring class.

    However I'm having a problem trying to rollback tests I perform on a client object that accesses this remote EJB. As the client shouldn't live in an application container, I've got the test cases to fetch a UserTransaction object from the remote container using a JNDI lookup.
    The UserTransaction object returned is then used to begin and rollback the transaction in the setup and teardown method of the client test class.
    Unfortunately the rollback call doesn't actually do anything as the database keeps the changes made. I have this feeling that the transaction started on the client side is not picked up by the application container, or that the container has created a nested transaction thus preventing the clients rollback propagating to the database.

    I've added the spring context xml file referring to the resources used and have addded the test class below. I've also added the method that retrieves the UserTransaction Object. I would be gratefull if anybody could be helpful here, as I've done a fair bit of reading on the internet trying to figure out where I'm going wrong.

    <beans>

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.Pr opertyPlaceholderConfigurer">
    <property name="location">
    <value>com/convergys/rating/service/properties/JDBC.properties</value>
    </property>
    </bean>

    <!-- The DrivingManagerDataSource will create a conection each time a call is made to the Database. Used for testing purposes and
    developement. For production purposes Spring suggests using JndiObjectFactoryBean-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverM anagerDataSource">
    <property name="driverClassName">
    <value>${DataSource.DriverClassName}</value>
    </property>
    <property name="url">
    <value>${DataSource.URL}</value>
    </property>
    <property name="username">
    <value>${DataSource.Password}</value>
    </property>
    <property name="password">
    <value>${DataSource.Username}</value>
    </property>
    </bean>

    <!-- Transaction manager for a single JDBC DataSource (alternative to JTA) -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSou rceTransactionManager">
    <property name="dataSource"><ref bean="dataSource"/></property>
    </bean>

    <!--<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTran sactionManager">
    <property name="transactionManagerName">
    <value>java:/UserTransaction </value>
    </property>
    </bean>-->

    </beans>



    ************************************************** ********



    public class CostCodeClientTest extends TestCase {

    // static variable memebers when using no security
    private static EJBconnectionHandler EJBconnection = null;
    private static CostCodeService costCodeService = null;

    // static constants
    private final static String jndi_CostCodeBeanEntry = "Convergys/RB/CostCode";
    private final static String environmentLocation = "t3://10.28.32.69:7005";
    private final static String webLogicInitialContextFactory = "weblogic.jndi.WLInitialContextFactory";

    /**
    * JUnit creates an instance of this class for each test method defined below.
    * Therefore it would make sense to define a static initializer to retrieve the costCode
    * service object as the static initializer is only ever invoked by the classloader once.
    */
    static {
    try {
    EJBconnection = new EJBconnectionHandler();
    EJBconnection.generateInitCntxtWithoutSecurity(web LogicInitialContextFactory, environmentLocation);
    EJBconnection.generateEjbObjectStub(jndi_CostCodeB eanEntry);
    costCodeService = EJBconnection.getCostCodeService();
    }
    catch(Exception ex){
    System.out.println("Error on retrieving the static bean member costCodeService");
    }
    }

    private UserTransaction transaction = null;

    /**
    * <b> Method Name </b> setUp <br><br>
    * <b> description </b> sets up the required resources for each test case,
    * such retrieving a new transaction object with which to start a new transaction
    *
    * @throws Exception
    * @author rdb
    * @since 2.3
    */
    public void setUp() throws Exception{
    EJBconnection.generateTransactionObjectStub();
    transaction = EJBconnection.getUserTransaction();
    transaction.begin();
    }

    /**
    * <b> Method Name </b> tearDown <br><br>
    * <b> description </b> removes all tied in resources such as rolling back
    * an active transaction and removing the transaction object
    *
    * @throws Exception
    * @author rdb
    * @since 2.3
    */
    public void tearDown() throws Exception{
    transaction.rollback();
    transaction = null;
    } transaction.rollback();
    transaction = null;
    }

    /**
    * <b> Method Name </b> testCreateCostCode_2_3 <br><br>
    * <b> description </b> tests the cost code creation advertised on
    * the Cost Code service
    *
    * @author rdb
    * @since 2.3
    */
    public void testCreateCostCode_2_3() {
    String testName = "testCreateCostCode_2_3 ";
    int testNo = 0;
    CostCodeData costCodeDataIML = null;

    try {
    // valid test case
    testNo += 1;
    costCodeDataIML = new CostCodeData();
    populateEntity(costCodeDataIML, t_Create);
    costCodeService.createCostCode_2_3(costCodeDataIML );
    passWithNoExceptionRaised(testName, Integer.toString(testNo));
    }
    catch(Exception ex) {
    failWithExceptionRaised(testName, Integer.toString(testNo), ex);
    }
    }


    public void generateTransactionObjectStub() throws Exception, NamingException{
    if (ejbContext == null) {
    throw new Exception("No successful JNDI lookup was made prior to retrieving an EJB home object");
    }
    else {
    transaction = (UserTransaction) ejbContext.lookup("javax.transaction.UserTransacti on");
    }
    }

  • #2
    I guess that you need to use JndiObjectFactoryBean datasource for this to work. Creating your own connection directly from the driver does not allow transaction propagation I think.

    Comment


    • #3
      Is there an example of what DataSource types one can use with the JndiObjectFactoryBean in Spring?? Or is it better to leave Spring out of the equation?? I was thinking of doing a JNDI lookup from my test client module to get a datasource connection and UserTransaction objects to start a transaction on the connection, for each test case I perform in JUnit??? THe Spring in action book is not very informative on this scenario.

      Comment


      • #4
        If you want to use any of the JTA features you need to use JTA enabled datasource/transaction manager. Client->Server and ServerA->ServerB transaction propagation through EJB calls and 2 phase commit are such features.

        Comment

        Working...
        X