CDI Factory Method
I’m working in a piece of software that needs a builder inside a loop inside a CDI managed bean, but the builder should be configured using CDI.
E.G. this is part of a JBatch step that processes rows from a ResultSet
@Dependent
public class BananaBuilder {}
@JobScoped
public class BananaProcessor extends AbstractBatchlet {
// ...
public void processRow(ResultSet rs) {
BananaBuilder bb = ...
..... do something with the bananabuilder
}
}
As the BananaBuilder
maintains some state that should be reset on
each invocation of processRow
, this is not an @Inject
away: the
injected instance of the BananaBuilder
will only be injected once in
the lifetime of the BananaProcessor
instance, but I need it to be
fresh on each invocation.
As I invoke processRow
myself, I can’t @Inject
the builder as a
parameter to the method, how would I obtain that particular instance?
A Google search didn’t reveal direct usable results, because factory and CDI are rather popular generic terms together.
The correct way of doing this is either through
Instance<BananaBuilder>
or
CDI.current().select(BananaBuilder.class).get()
.
So if you want to get a new instance everytime you need a
BananaBuilder
, then you could inject an Instance
into your context:
@JobScoped
public class BananaProcessor extends AbstractBatchlet {
@Inject
Instance<BananaBuilder> builderInstances;
public void processRow(ResultSet rs) {
BananaBuilder bb = builderInstances.get();
..... do something with the bananabuilder
}
}
This will get a new BananaBuilder
on each invocation of the
builderInstances.get()
, achieving what we wanted. Note that the
BananaBuilder
needs to have @Dependent
scope, which is the default
scope if you don’t annotate your bean with a specific scope.
Conclusion
Using CDI to make a new builder inside a loop is not too difficult, but it was a bit hard to discover documentation explaining this.