The holder concept is necessary because the Java language designers stuck with the "pass-by-value" semantics of the C-family of languages. If a parameter is a simple type its value is copied, if it is an object instance the reference (value) to it is copied. As a result you are unable to modify the value in the original simple type or the reference (value) to the object from the called method (while you can change the passed instance, you cannot replace the passed instance). The holder mimics "pass-by-reference" semantics.
In C/C++ is is done with a pointer-to-a-pointer - the Java language designers abolished pointers (they were considered too dangerous). So the holder is the Java equivalent to a "pointer-to-a-pointer" - though it isn't as flexible unless you are going to make the reference inside the holder the only reference to your object and pass the object holder around rather then a direct reference to the object.
In C# they decided to support "pass-by-reference" semantics directly through the ref keyword. However, this requires additional vigilance on the part of the method caller as they have to be aware that the object instance may be swapped out right under them (other copies of the reference will still would go stale - so now you have to make sure that there is only exactly one reference to that (replaceable) object instance) - the holder communicates this possibility much more clearly.
Statements that Java passes objects "by reference" are inaccurate - what is passed is the value of the reference (which isn't the same thing).
Peer would you find any value for the Holder class to provide a method that would automatically update the appropriate object references at run time? I'm not familiar with the language internals and if it is feasible but I think it would produce less error-prone code.
Also since Holders provide this pointer-to-pointer functionality that Java traditionally lacks, shouldn't we embrace them and try to use the relevant patterns where appropriate? I'm saying this since I sense a strong disapproval from your part.
Joined: Aug 19, 2005
I personally rarely had a problem and some circumstances dictated that I even had to use pointer-to-a-(pointer-to-a-pointer)s. However it does require a lot more mental book-keeping. And the Java language designers couldn't certify any applet code that used a "pointer" concept as "safe to run" because pointer arithmetic could be used to access all sorts of (undesirable) things.
But you have to realize that both the pointer-to-a-pointer and ref keyword are also limited - they can only update one single object reference, the one they have the address to. Any other references to the same object still won't be updated. And there is no way for the virtual machine to figure out which references to that object instance you want updated and which ones to leave alone because it doesn't know why you copied the reference in the first place.
So if you are concerned about stale secondary references simply make sure that you only have exactly one reference - the one in the holder. If you need secondary references (like in a collection) don't give a reference to the object instance but instead give a reference its holder. Following these type of conventions should then protect you from any unpleasant surprises.
As stated in the above link, some consider "attempts to fake call by reference are usually a sign of poor object-oriented design". WSDL never strived towards OO so that is where this mismatch comes from. Ultimately it may have been a better idea for Java to wrap the WSDL method return value and all of the OUT parameters into a single wrapper object which becomes the return value of the Java interface method; this would maintain the clear demarcation between IN and OUT that is typical in Java. I don't know what stood in the way of that type of mapping.