Issue
I have an existing spring (5.3.9) converter. It is a state-less converter: no members, empty default constructor. With this form, it gets picked up and works well with my system:
class Conv implements Converter<A, B> {
public B convert(A a) {
...
}
}
When adding a state to this converter (any reference to another bean):
class Conv implements Converter<A, B> {
// the state
private final X x;
public Conv(X x) {
this.x = x;
}
public B convert(A a) {
...
}
}
... The Problem: now, the converter cannot be found at runtime:
No converter found capable of converting from type [A] to type [B]
The converter itself gets to be created successfully and is still picked up by the lifecycle. The dependency gets to be injected well and it exists (stood in debug inside the constructor). There aren't any exceptions in the bean initialization process.
I have tried using construction injection; @Autowired
injection - I am getting the same behavior.
Finally, after discussing with a colleague, he suggested adding @Lazy
to the constructor's argument:
class Conv implements Converter<A, B> {
// the state
private final X x;
public Conv(@Lazy X x) {
this.x = x;
}
public B convert(A a) {
...
}
}
Amazingly, it solved the problem! the converter can now be found and used as was before adding the state.
(update: I wasn't able to create a minimal example that reproduces this problem. it is probably related somehow to my real beans dependencies..).
Can you explain why @Lazy
did the trick?
Solution
The problem is that a Converter
needs to be registered at a certain time in the lifecycle. Adding a dependency to it has changed the point at which this converter can be created.
Now when adding @Lazy
the construction can be done at the right time again as the dependency will now only be used/detected when the dependency is used. The @Lazy
will make a proxy of the dependency and when used will at that point do an ApplicationContext.getBean
call instead of when constructing the object.
So basically it has to do with where in the lifecycle of the context the object can be constructed if it can be used or not.
Answered By - M. Deinum
Answer Checked By - Clifford M. (JavaFixing Volunteer)