Pregunta

Estoy tratando de crear pruebas de integración para una aplicación antiguo implementado en WebLogic 8.1 utilizando una subclase de AbstractTransactionalJUnit4SpringContextTests.

Mi método de prueba tiene las siguientes anotaciones:

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

Mi clase de prueba también hace referencia a los granos de tipo org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean, que proxy de los EJB desplegados en mi servidor WebLogic.

Cuando llamo métodos en este bean de proxy de una manera secuencial en mi método de ensayo, la transacción se deshace correctamente al final de la prueba.

por ejemplo. :

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

Sin embargo, me gustaría hacer 2 llamadas simultáneas al mismo método EJB. Por lo tanto he tomado una clase interna que implementa rescatable, con el fin de llamar a mis métodos en 2 hilos de diferentes y la esperanza de ejecutar aquellos en paralelo.
Sin embargo, hacer esto parece hacer que los métodos EJB para ser llamados fuera de mi operación, y nada se deshace.

Esto es lo que la clase de prueba completa le gustaría cuando corro las llamadas a métodos en 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;   
    } 
}

¿Hay una manera de hacer esta reversión ???

Gracias por su ayuda.

Saludos,

Philippe

¿Fue útil?

Solución

No de forma automática, no. El problema es que los dos hilos adicionales no participan en la transacción, por lo tanto, sus acciones no reversión.

¿Cuál es el propósito de las dos ejecuciones paralelas? Usted probablemente será capaz de probar los problemas de concurrencia con este enfoque, si eso es lo que usted está apuntando.

Editar: El problema es que las pruebas de problemas de concurrencia es muy difícil, debido a que sus pruebas son, en el mejor, probabilística - el éxito o el fracaso dependen de problemas de tiempo sutiles que sólo pueden superficie en la carrera billonésima . Ver este artículo Serverside para un buen resumen de los fundamentos.

La regla de oro debe ser evitar roscado codificación manual siempre que sea posible, ya que es difícil conseguir la derecha y difíciles de probar. Si es posible, evitar el estado compartido entre hilos, y si no hay manera de evitarlo, se basan en las estructuras de datos concurrentes y ejecutores asíncronos desde el paquete java.util.concurrent.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top