Mar 5th, 2008, 10:28 AM
I am facing the following problem :
I created a few factory beans that create standard jobs, so that users only need to create a bean and assign them a ItemProvider, ItemWriter, etc to create a standard job with a single step and default tasklet (I am using M4, but the problem might still happen in M5).
The job factory bean (singleton) is a InializingBean, and the job is constructed in afterPropertiesSet(), where I also register the bean in the registry. The reason for registration here is that when the application context is created, the factory bean is inialized, but the object behind the factory bean (the job) is not resolved at this stage, and is therefore not post-processed, in particular, it is not registered by the job registerer post processor. Since I do usually not get a job from the context, but from the registry, I do not want to remove registration from factory bean initialization.
But I also want to provide a way to get the job directly from the context,
This worked fine until I tried to get the job directly from the context, by invoking context.getBean("nameOfFactoryBean"). When invoking the factory bean directly from the context, the object behind the factory (the job) is resolved and post-processed, and is registered a second time, which throws a DuplicateJobException.
I actually would like to provide both possibilities, i.e. locate a job from the registry, or from the context, without difference.
I tried many configuration possibilities (lazy-init, scope change, etc), without success.
Why is this a problem if register() is called twice with the same job instance and name ? If the same instance is presented twice, why don't you simply skip the second call ?
Mar 5th, 2008, 03:09 PM
Since you're registering it yourself, couldn't you just remove the jobConfigurationRegistryBeanPostProcessor? It seems like you wouldn't need it if you're doing the registration yourself.
Mar 6th, 2008, 01:20 AM
Actually, I also wanted to be able to load a job directly from the context. This is the reason why the registerer post-processor is still there.
Isn't there a problem if a get a reference to a job that is not present in the registry ? I mean, doesn't the framework need the registry for another purpose than just as a job locator ?
If jobs do not absolutely need to exist in the registry (as long as I can get a reference to them in some other way), then your are right, I can just remove the jobConfigurationRegistryBeanPostProcessor from my context.
Mar 6th, 2008, 10:50 AM
In response to your original question:
Because it most often indicates an ambiguity - remember that your choice to use a factory is not the way everyone uses the framework. If two Jobs are registered with the same identifying information, which Job definition should the registry point to? How should the batch framework decide what your intentions are? For your use case the answer is clear but it doesn't make sense as a rule to allow this.
The job registry is exactly a job locator and nothing more. It even implements an interface called JobLocator
Jobs do need to exist in the registry, but how jobs get registered is up to you. The post processor is just one method of registering Job objects with the registry. You could implement your own JobRegistry subclass and handle job registration however you like.
I would suggest modifying your factory to cache and return singleton instances of each unique job instead of generating a new object each time. This will solve your problem. Alternatively, if you manually register your jobs with the job registry as Lucas mentioned, you don't need the post processor at all.
Last edited by dkaminsky; Mar 6th, 2008 at 10:54 AM.