Domanda

Sto cercando di creare test di integrazione per un'applicazione precedente distribuito su Weblogic 8.1 utilizzando una sottoclasse di AbstractTransactionalJUnit4SpringContextTests.

Il mio metodo di prova ha le seguenti annotazioni:

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

La mia classe di test fa riferimento anche i fagioli di tipo org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean, che delega le EJB distribuiti sul mio server WebLogic.

Quando chiamo metodi su questo fagiolo delega in maniera sequenziale nel mio metodo di prova, la transazione rollback correttamente al termine del test.

es. :

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

Tuttavia, vorrei fare 2 chiamate parallele lo stesso metodo EJB. Quindi ho fatto una classe interna che implementa Callable, al fine di chiamare i miei metodi in 2 diversi thread e spero di farli funzionare in parallelo.
Tuttavia, questa operazione sembra rendere i metodi EJB per essere chiamati fuori dalla mia transazione, e nulla viene eseguito il rollback.

Ecco ciò che la classe test completo vorrebbe quando corro le chiamate di metodo in parallelo:

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

C'è un modo per rendere questo rollback ???

Grazie per il vostro aiuto.

Saluti,

Philippe

È stato utile?

Soluzione

Non automaticamente, no. Il problema è che i due thread in più non partecipano alla transazione, e quindi le loro azioni non rollback.

Qual è lo scopo delle due esecuzioni parallele? Sarà improbabile essere in grado di testare per problemi di concorrenza con questo approccio, se questo è ciò che si sta puntando.

Modifica: Il problema è che il test per i problemi di concorrenza è molto difficile, perché i test sono, nella migliore delle ipotesi, probabilistico - successo o il fallimento dipendono da problemi di temporizzazione sottili che possono unica superficie in fuga miliardesimo . Vedere questo articolo Serverside per una buona sintesi delle nozioni di base.

La regola generale dovrebbe essere quello di evitare threading codifica manuale, quando possibile, in quanto è difficile da ottenere e di difficile prova. Se è possibile, evitare stato condiviso tra thread, e se non c'è modo intorno ad esso, contare sulle strutture di dati simultanei ed esecutori asincrone dal pacchetto java.util.concurrent.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top