2

AbstractTransactionalJUnit4SpringContextTestsのサブクラスを使用して、Weblogic8.1にデプロイされたレガシーアプリケーションの統合テストを作成しようとしています。

私のテストメソッドには次のアノテーションがあります。

@Test
@Rollback(true)
public void testDeployedEJBCall throws Exception {...}

テストクラスは、org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBeanタイプのBeanも参照します。これは、weblogicサーバーにデプロイされたEJBをプロキシします。

テストメソッドでこのプロキシBeanのメソッドを順番に呼び出すと、テストの終了時にトランザクションが正しくロールバックされます。

例:

@Test
@Rollback(true)
public void testDeployedEJBCall throws Exception {
    Long result1 = myejb.method(100L);
    Long result2 = myejb.method(200L);
    ...
}

ただし、同じEJBメソッドに対して2つの並列呼び出しを行いたいと思います。したがって、2つの異なるスレッドでメソッドを呼び出し、それらを並行して実行するために、Callableを実装する内部クラスを作成しました。
ただし、これを行うと、ejbメソッドがトランザクションの外部で呼び出されるようになり、何もロールバックされません。

メソッド呼び出しを並行して実行する場合、完全なテストクラスは次のようになります。

import org.springframework.test.annotation.*;

@RunWith(SpringJUnit4ClassRunner.class)
@Transactional
@ContextConfiguration(locations = {"classpath:path/to/tests-config.xml"})
@TransactionConfiguration(defaultRollback=true)
public final class IntegrationTests extends AbstractTransactionalJUnit4SpringContextTests {
    @Autowired
    protected JndiTemplate jndiTemplate;
    @Resource
    protected Proxy myEJB;

    public IntegrationTests() {
        super();
        this.logger = Logger.getLogger(IntegrationTests.class);
    }

    @Test
    @Rollback(true)
    public void testDeployedEJBCall() throws Exception {
        // Create a thread pool for parallel execution. 
        ExecutorService exec = Executors.newFixedThreadPool(2);

        // Prepare the tasks for parallel execution
        List<CallEJBTask> tasks = new ArrayList<CallEJBTask>();
        tasks.add(new CallEJBTask(100L, this.myEJB));
        tasks.add(new CallEJBTask(200L, this.myEJB));

        // Execute all pending tasks in the exec Threadpool
        List<Future<Long>> results = exec.invokeAll(tasks);

        // Get the results of each task
        Long result1 = results.get(0).get();
        Long result2 = results.get(1).get();

        ...
    }
}

private class CallEBJTask implements Callable<Long> {
    private final Long valueToTest;
    private final MyEJB myEJB;

    public CallEJBTask(Long valueToTest, Proxy myEJBProxy)
        this.valueToTest = valueToTest;
        this.myEJB = (MyEJB)myEJBProxy;
    }

    public Long call() throws Exception {
        return getResult();
    }

    public Long getResult() {
        Long result = null;

        try {
            result = this.myEJB.method(this.patient);

        } catch (Exception e) {
            ...
        }
        return result;   
    } 
}

このロールバックを作成する方法はありますか?

ご協力いただきありがとうございます。

よろしく、

フィリップ

4

1 に答える 1

2

自動的ではありません。問題は、2つの余分なスレッドがトランザクションに参加しないため、それらのアクションがロールバックされないことです。

2つの並列実行の目的は何ですか?それがあなたが目指しているものであるならば、あなたはこのアプローチで並行性の問題をテストすることができないでしょう。

編集:問題は、同時実行の問題のテストが非常に難しいことです。テストはせいぜい確率的であるためです。成功または失敗は、10億回の実行でのみ表面化する可能性のある微妙なタイミングの問題に依存します。基本の概要については、このサーバーサイドの記事を参照してください。

経験則では、正しく理解するのが難しく、テストするのが難しいため、可能な限り手動でスレッドをコーディングしないようにする必要があります。可能であれば、スレッド間の共有状態を回避し、それを回避する方法がない場合は、java.util.concurrentパッケージの同時データ構造と非同期エグゼキューターに依存します。

于 2010-01-14T13:23:50.700 に答える