ResolveEngine does not initialize its dictatorResover field in the constructor. As the result, when
is called, the oldDictator local variable will be set to null in the beginning of the method. Then, in the end of the same method, inside the finally block, setDictatorResolver(null) will be called, which will not only set the private field in the ResolveEngine itself, but will also reset the dictator resolver in the global configuration. Why would it do that???
The problem manifests itself when an Ivy instance is configured (using Java API) with only a dictator resolver, it will be able to handle a single call to resolve(...) successfully, and all subsequent calls will fail because of "no resolver available" (because the one that is supposed to be available, has been reset by the ResolveEngine, as described above).
I have to admit that I am not very familiar with Ivy internals, but I find it extremely puzzling that an object that is a part of the internal implementation would change the global configuration at will.
Looking at the implementation of Ivy and IvyContext classes, I get the impression that an Ivy instance is supposed to be thread-safe, in the sense that it should allow to call resolve(...) on the same instance from multiple threads safely. Am I mistaken? If there is supposed to be any thread safety, it is broken by the peculiar behavior of ResolveEngine with respect to setting the dictator resolver.
In any case, I think it would be really helpful to explicitly mention thread safety (or lack thereof) in the Javadoc page of the main Ivy class.