Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to refactor this in Spring?

Tags:

java

spring

private final ExecutorService executorParsers = Executors.newFixedThreadPool(10);

public void parse(List<MyObjInt> objs) {
   //... bunch of elided stuff ....

   CompletionService<AsupParseObj> parserService = new ExecutorCompletionService<AsupParseObj>(executorParsers);

   for (final AsupStoreObj obj : objs) {
      parserService.submit(new ParseThread(obj));
   }
}

I would like to DI the "ParseThread" but surely there has to be a better way to do this than burying a call to getBean on a prototype scoped bean and as I am new to Spring I figured I would ask...

like image 973
user1085751 Avatar asked Dec 07 '11 14:12

user1085751


1 Answers

Here is the full configuration using lookup-method (see 3.4.6.1 Lookup method injection):

<bean id="executorParsers" class="java.util.concurrent.Executors" 
        factory-method="newFixedThreadPool" 
        destroy-method="shutdownNow">
    <constructor-arg value="10"/>
</bean>

<bean id="parserService" class="java.util.concurrent.CompletionService">
    <constructor-arg ref="executorParsers"/>
</bean>

<bean id="foo" class="Foo">
    <lookup-method name="createThread" bean="parseThread"/>
</bean>

<bean id="parseThread" class="ParseThread" scope="prototype" lazy-init="true"/>

And the Java code:

abstract class Foo {

    @Autowired
    CompletionService parserService;

    protected abstract ParseThread createThread();

    public void parse(List<MyObjInt> objs) {
        for (final AsupStoreObj obj : objs) {
            ParseThread t = createThread();
            t.setObject(obj);
            parserService.submit(t);
        }
    }
}

Unfortunately you cannot pass any parameters to lookup-method (see SPR-7431 and my article Creating prototype Spring beans on demand using lookup-method), hence the need for artificial setObject().

If you don't like abstract methods/classes, lookup method can be non-abstract no-op method or (better) the default implementation can throw an exception. Spring will override the implementation at runtime, effectively calling getBean() for you.

Bonus: I translated Executor/CompletionService to Spring managed beans as well. Note that Spring supports these out-of-the-box: Task Execution and Scheduling.

like image 78
Tomasz Nurkiewicz Avatar answered Sep 21 '22 23:09

Tomasz Nurkiewicz