Question

We're developing a Web Frontend using JSF 2 and Weld Cdi on Tomcat.
Now I've a problem executing multiple webservices in parallel to optimize the request time.
The user may select mutliple items form a list.
For each selected item, the process gathers it's information from one webservice using the list key as parameter.

My current approach is using a Producer, that returns the webservice port interface, which is injected into the bean. The bean calls this webservie in a loop for each selected key.

@Inject
private WSAnzeigeAssetsummen serviceAccess;
:

for ( Integer pfNr : sessionKeys.getPfnrList() ) {
   summaryTable = serviceAccess.execute(snr, pfnr, requestType, "", desiredRows, userName);
   processResult(summaryTable):
}

To get faster, I tried to use a ExecutorService and as many workers as needed, which are returning Futures.

The problem of this construct is, that I can't inject the service port into the worker, cause the worker is not managed. Creating the service port by hand, works but is not appreciated, cause it ignores the producer class.

Also when testing, it's not possible to inject a dummy service port, which delivers predefined result sets.

Since I did not find anything, about parallel execution in a tomcat-weld enviroment, there must be something wrong with my approach.

What is the correct approach to solve such a situation ?

Edit: To be more clear what I tried...

public class DataCollector implements ISumRequest<Integer, Integer, String, FutureResult> {

ExecutorService pool = Executors.newCachedThreadPool();
@Inject
SessionBean sessionBean;

public Future<FutureResult> collectInformation(Integer snr, Integer pfnr, String requestType) {

    CollectWorker worker = new CollectWorker (snr,pfnr,requestType,sessionBean.getUserName());     
    return pool.submit(worker);        
}

}

When doing like this, the worker is not managed.

Was it helpful?

Solution

You can wrap your created worker in a CDI creational context, something like this:

@Inject
private BeanManager beanManager;

public <T extends Object> T performInjection(final T obj) {
    if (this.beanManager != null) { // only do injection if the bean manager is present.
        // Create a creational context from the BeanManager
        final CreationalContext creationalContext = this.beanManager.createCreationalContext(null);
        // Create an injection target with the Type of the instance we need to inject into
        final InjectionTarget injectionTarget = this.beanManager.createInjectionTarget(this.beanManager.createAnnotatedType(obj.getClass()));
        // Perform injection into the instance
        injectionTarget.inject(obj, creationalContext);
        // Call PostConstruct on instance
        injectionTarget.postConstruct(obj);
    }
    return obj;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top