Pergunta

Estou tentando criar testes de integração para um aplicativo herdado implantado no WebLogic 8.1 usando uma subclasse de abstransactionaljunit4springContextTests.

Meu método de teste tem as seguintes anotações:

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

Minha classe de teste também faz referência a feijões do tipo org.springframework.ejb.access.simpleRemotestateSlessionProxyFactoryBean, que proxy os EJBs implantados no meu servidor WebLogic.

Quando eu chamo métodos nesse feijão proxy de maneira seqüencial no meu método de teste, a transação volta corretamente no final do teste.

por exemplo :

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

No entanto, gostaria de fazer 2 chamadas paralelas para o mesmo método EJB. Portanto, fiz uma classe interna que implementa chamável, a fim de chamar meus métodos em 2 threads diferentes e esperar executá -los em paralelo.
No entanto, isso parece fazer com que os métodos EJB sejam chamados fora da minha transação, e nada é revertido.

Aqui está o que a aula de teste completa gostaria quando eu executar o método chama em paralelo:

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;   
    } 
}

Existe uma maneira de fazer essa reversão ???

Obrigado pela ajuda.

Cumprimentos,

Philippe

Foi útil?

Solução

Não automaticamente, não. O problema é que os dois threads extras não participam da transação, portanto suas ações não revertem.

Qual é o objetivo das duas execuções paralelas? É improvável que você possa testar problemas de simultaneidade com essa abordagem, se é isso que você está buscando.

Editar: O problema é que os testes para problemas de simultaneidade são muito difíceis, porque seus testes são, na melhor das hipóteses, probabilísticos - sucesso ou falha dependem de problemas de tempo sutis que só podem surgir na corrida da Bilionésima. Ver Este artigo do servidor Para um bom resumo do básico.

A regra geral deve ser evitar a rosca de codificação manual sempre que possível, pois é difícil acertar e difícil de testar. Se puder, evite o estado compartilhado entre os threads e, se não houver maneira de contornar, confie nas estruturas de dados simultâneas e executores assíncronos do java.util.concurrent pacote.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top