Search code examples
javastruts-1

Java Dependency Injection - How to @Inject into a Callable


I have a Struts/J2EE application.

I have a class that creates a callable.

    ExecutorService executor = Executors.newFixedThreadPool(NO_THREADS);
    List<Future<Long>> tripFutureList = new ArrayList<>();
    for(Long tripId : tripIds) {
        Callable<Long> callable = new CallableTripAutoApprovalEscalation(tripId);
        Future<Long> future = executor.submit(callable);
        tripFutureList.add(future);
    }
    for(Future<Long> future : tripFutureList) {
        try {
            logger.fine("Processed trip auto approval escalation for trip: "+future.get());
        } catch (InterruptedException | ExecutionException e) {
            logger.severe("There was an error processing trip."+ e.getMessage());
        }
    }

    executor.shutdown();

This works, however my problem is when the callable needs to perform its call() method, the callable cannot @Inject any other classes, i.e. they are null. This is because the callable is created with the new keyword and looses its DI scope.

Question

How do I create the callable to still be able to do Dependency Injection?

More info:

Here is the callable class (the injected TripAutoApprovalEscalationService is null):

public class CallableTripAutoApprovalEscalation implements Callable<Long> {

    public CallableTripAutoApprovalEscalation() {}

    public static Logger logger = Logger.getLogger(CallableTripAutoApprovalEscalation.class.getName());

    @Inject
    private TripAutoApprovalEscalationService tripAutoApprovalEscalation;

    private Long tripId;

    public CallableTripAutoApprovalEscalation(Long tripId) {
        this.tripId = tripId;
    }

    @Override
    public Long call() throws Exception {
        logger.info("Execute trip for callable: "+tripId);
        return tripAutoApprovalEscalation.performEscalation(tripId);
    }

}

Solution

  • You can inject it to parent container and simply pass that instance

    //in your wrapping component
    @Resource
    private YourInjectableClass injectable;
    
    //and then pass it as ctor arg
    
    Callable<Long> callable = new CallableTripAutoApprovalEscalation(tripId, injectable);
    Future<Long> future = executor.submit(callable);