You might instead have the Set of Animals Inject ed into the Zoo.
You might instead have the Set of Animals @Injected into the Zoo. @Component public class Zoo { @Inject private Set animals = new HashSet(); // ... } Then Zoo's @PostConstruct should only be called once all the Animals are injected. The only gotcha is that there must be at least one Animal in the system, but it doesn't sound like that should be an issue.
Yes, this is the best idea, as also suggested by @ptyx. – wool.in. Silver Aug 16 at 11:08.
The best way, IMO, is to avoid doing too much work during the construction of the object graph (just as in Java, you avoid doing too much work in the constructor), and to avoid calling methods from dependencies when you're not sure they're fully initialized yet. If you just remove the @PostConstruct annotation from the Test#init() method, and simply invoke it from your main method, after the context has been created, you won't have this problem anymore.
Perhaps my example code was too simplified; actually my application is a webapp, so I have a XmlWebApplicationContext, courtesy of a DispatcherServlet. So, I'm not sure I have that opportunity. – wool.in.
Silver Aug 15 at 16:07 You could still initialize your Test class (or whatever its real name is) in a lazy way (first time one of its method is called, or first time it's accessed through a factory), or using a ServletContextListener. – JB Nizet Aug 15 at 16:11.
It looks to me that in your case there is a dependency between the Zoo object and all your animal types. If you design your Zoo object to reflect this dependency the problem is solved. For example you could do: instead of using the register method.
Ah, no - that's exactly what I'm trying to avoid :-) Neither the ZooPatron nor the Zoo want to have a "hard" list of animals. The real world situation is actually that I have a bunch of games that are contributed from various Maven artifacts, and a game registry in the 'core' of the system. Only the game registry will be visible to the rest of the system, the individual games are not known to the developer who consumes the game registry, but they are known to Spring at compile time when a "distribution" is assembled from the various games and other components.
I'll edit the q to clarify. – wool.in. Silver Aug 15 at 16:10 You are right: in the problem domain, the zoo depends upon the animals.
Expressing it any other way leads to problems. My stupidity was in assuming I had to make an explicit list of animals, when Spring can inject a collection for me. – wool.in.
Silver Aug 16 at 11:10.
I don't think there is a way to ensure @PostConstruct order without introducing dependencies. I think you're looking for trouble trying to mix injection or self registration. To some extent, @PostConstruct call order should not matter - if it does, it might not be the right tool for the job.
A couple ideas for your example try to have an @Autowired on Zoo#animals: no need for self-registration by animals, also the zoo is aware of the animals but not the reverse, which feels cleaner keep the register, but let external actors do the registration (someone is putting the animals in the zoo, right? - they're not showing up at the entrance all by themselves) if you need to insert new animals at any time, but don't want manual insertion, do a more dynamic accessor on zoo: don't store the list of animals, but use the spring context to get all existing instances of the interface. I don't think there is a 'right' answer, it all depends on your use case.
I think you've hit the nail on the head - I can't find a way to make this work without distorting the purpose of PostConstruct. At the root of the problem is that I don't want anyone to be aware of particular animals (which is probably more to do with my build architecture than anything else); I can't have code changes if I change the set of animals. Having an animal on the classpath should be sufficient for him to be wired into the system.
However, other people need to know the total set of such animals at runtime. – wool.in. Silver Aug 15 at 16:33 If your animals are beans, then use a collection autowired.
Spring will automatically put all declared beans in a autowired Map animals; - you don't need to list them one by one in the Zoo bean. – ptyx Aug 15 at 23:02 Yes, a collection autowired is the best solution. Once the dependencies are expressed correctly, then the sequence of PostConstruct invocations is not important.
– wool.in. Silver Aug 16 at 11:13.
Reframe your problem so that it doesn't rely on invocation order.
Yes. I see now that the dependencies as expressed in the code are back-to-front; fixing that means that I don't have to rely on invocation order. – wool.in.
Silver Aug 16 at 11:11.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.