4

To run a Job in a TaskExecutor I need to instantiate new Jobs implementing the Runnable Interface. To solve this, i will create a new Spring Prototype Bean named Job "on Demand".

But in my application a Job has two fields LocationChanger and QueryTyper. These two should share the same WebDriver instance created by a WebDriverFactory.

Now the question is how to design this with Spring?

UML of the Architecture

This is the related code:

@Component
@Scope("prototype")
public class Job implements Runnable {

    @Autowired
    LocationChanger locationChanger;

    @Autowired
    QueryTyper queryTyper;

    @Override
    public void run() {
        // at this point the locationChanger and
        // queryTyper should share the same instance
    }

}

@Component
@Scope("prototype")
public class LocationChanger {

    @Autowired
    @Qualifier(...) // For every new Job Created, the same WebDriver instance should be injected.
    WebDriver webDriver
}

@Component
@Scope("prototype")
public class QueryTyper {

    @Autowired
    @Qualifier(...) // For every new Job Created, the same WebDriver instance should be injected.
    WebDriver webDriver
}

public class WebDriverFactoryBean implements FactoryBean<WebDriver> {
    @Override
    public WebDriver getObject() throws Exception {
        return // createdAndPrepare...
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

Thanks a lot!

Update 1: A possible solution could be to autowire the WebDriver in the Job only and then in a @PostConstruct inject this WebDriver to the LocationChanger and QueryTyper. But then i wire by hand.

@Component
@Scope("prototype")
public class Job implements Runnable {

    @Autowired
    LocationChanger locationChanger;

    @Autowired
    QueryTyper queryTyper;

    @Autowired
    WebDriver webDriver;

    @PostConstruct
    public void autowireByHand() {
        locationChanger.setWebDriver(this.webDriver);
        queryTyper.setWebDriver(this.webDriver);
    }
}

// + remove all @Autowired WebDriver's from LocationChanger and QueryTyper
d0x
  • 11,040
  • 17
  • 69
  • 104
  • So you want `WebDriver` to be a singleton? – NilsH Apr 16 '13 at 10:52
  • No, everytime if a `Job` is instantiated, this `Job` and it's childs should share the same `WebDriver`. So it's not Singleton :( – d0x Apr 16 '13 at 10:56

1 Answers1

2

If I understand your requirement, you need WebDriver to be shared between a Job and LocationChanger. So it's not prototype scope, and it's not singleton scope. To solve this, I think you either have to do it by hand, as you suggest, or you could try to implement your own scope, as described in the Spring reference documentation

Edit

I don't think you "handwired" solution looks that bad BTW.

NilsH
  • 13,705
  • 4
  • 41
  • 59
  • Thanks for the idea of a custom Scope. Maybe that's the Way. I thought about dynamic Qualifiers. For Example: The `LocationChanger` and `QueryTyper` should mark the Webdriver like this: `@Autowire @Qualifier(Somehow Relate this String to the created Instance of Job) webDriver` annotation. – d0x Apr 16 '13 at 12:10
  • A custom scope should be possible. You just have to figure out where to store your instances for retrieval, and then correlate them with the "conversation id". – NilsH Apr 16 '13 at 12:18