package com.alibaba.cobar.client.transaction; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertNotNull; import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertTrue; import static org.testng.AssertJUnit.fail; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; import org.testng.annotations.Test; import com.alibaba.cobar.client.AbstractTestNGCobarClientTest; import com.alibaba.cobar.client.entities.Offer; import com.alibaba.cobar.client.test.services.IOfferService; /** * H2 In-Memory Database doesn't support transaction, so in this test case, we * need to turn to non-in-memory database to test the transaction.<br> * * @author fujohnwang */ @Test(sequential=true) public class MultipleDataSourcesTransactionManagerTest extends AbstractTestNGCobarClientTest { String selectSqlActionTwo = "com.alibaba.cobar.client.entities.Offer.findByMemberId"; private Long[] memberIds = new Long[] { 1L, 129L, 257L, 2L, 130L, 258L, 386L }; public MultipleDataSourcesTransactionManagerTest() { super(new String[] { "META-INF/spring/cobar-client-appctx.xml", "META-INF/spring/datasources-appctx.xml", "META-INF/spring/namespace-sqlaction-composed-router-appctx.xml", "META-INF/spring/cobar-client-offer-services-appctx.xml" }); } public void testOfferCreationOnMultipleShardsWithTransactionRollback() { new TransactionTemplate(((PlatformTransactionManager) getApplicationContext() .getBean("transactionManager"))).execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { try { Offer offer = new Offer(); offer.setMemberId(1L); offer.setGmtUpdated(new Date()); offer.setSubject("o1"); getSqlMapClientTemplate().insert( "com.alibaba.cobar.client.entities.Offer.create", offer); offer = new Offer(); offer.setMemberId(2L); offer.setGmtUpdated(new Date()); offer.setSubject("o2"); getSqlMapClientTemplate().insert( "com.alibaba.cobar.client.entities.Offer.create", offer); } finally { status.setRollbackOnly(); } } }); Long[] mids = new Long[] { 1L, 2L }; for (Long mid : mids) { Offer parameter = new Offer(); parameter.setMemberId(mid); assertNull(getSqlMapClientTemplate().queryForObject(selectSqlActionTwo, parameter)); } } public void testOfferCreationOnMultipleShardsWithNormallyOfferService() { String selectSqlActionTwo = "com.alibaba.cobar.client.entities.Offer.findByMemberId"; for (Long mid : memberIds) { Offer parameter = new Offer(); parameter.setMemberId(mid); Offer offer = (Offer) getSqlMapClientTemplate().queryForObject(selectSqlActionTwo, parameter); assertNull(offer); } ((IOfferService) getApplicationContext().getBean("normalOfferService")) .createOffersInBatch(createOffersWithMemberIdsFrom(memberIds)); for (Long mid : memberIds) { Offer parameter = new Offer(); parameter.setMemberId(mid); Offer offer = (Offer) getSqlMapClientTemplate().queryForObject(selectSqlActionTwo, parameter); assertNotNull(offer); assertEquals(mid, offer.getMemberId()); } } /** * need data stores that support transaction to test this behavior. */ public void testOfferCreationOnMultipleShardsWithAbnormalOfferService() { String selectSqlActionTwo = "com.alibaba.cobar.client.entities.Offer.findByMemberId"; for (Long mid : memberIds) { Offer parameter = new Offer(); parameter.setMemberId(mid); Offer offer = (Offer) getSqlMapClientTemplate().queryForObject(selectSqlActionTwo, parameter); assertNull(offer); } try { Object offerService = getApplicationContext().getBean("abnormalOfferService"); assertTrue(offerService instanceof Proxy); ((IOfferService) offerService) .createOffersInBatch(createOffersWithMemberIdsFrom(memberIds)); fail(); } catch (RuntimeException e) { // pass } for (Long mid : memberIds) { Offer parameter = new Offer(); parameter.setMemberId(mid); assertNull(getSqlMapClientTemplate().queryForObject(selectSqlActionTwo, parameter)); } } public List<Offer> createOffersWithMemberIdsFrom(Long[] mids) { List<Offer> offers = new ArrayList<Offer>(); for (Long mid : mids) { Offer offer = new Offer(); offer.setGmtUpdated(new Date()); offer.setMemberId(mid); offer.setSubject("anything"); offers.add(offer); } return offers; } }