Hi,
While analyzing a problem in WS-RM, which I describe later, I
discovered this problem. I will mention it on this dev@cxf list
because potentially other components may be affected as well depending
on how they are using the instances of this class.

This EndpointImpl class extends AbstractAttributedInterceptorProvider
and this class in turn extends HashMap<String, Object>.
AbstractAttributedInterceptorProvider overwrites its hashCode() but it
simply calls its super class HashMap's hashCode().

Consequently, calling EndpointImpl's hashCode() will call HashMap's
hashCode() which will return a different value every time some new
items are inserted in the map.

So when you have something like

Endpoint endpoint = ...;
map = new HashMap<...>();
map.put(endpoint, "A");
map.get(endpoint) will still return "A" as long as no one has added
something to the endpoint.

But, for example, if you have something like

endpoint.put(USING_ADDRESSING, b);

which incidentally MAPAggregator does, you can no longer find the
endpoint in the map (i.e., map.get(endpoint) returns null even though
map.keySet().iterator().next().equals(endpoint) returns true).

This problem is causing the WS-RM runtime client to not being able to
find the existing endpoints in the reliableEndpoints map held by the
RMManager in some situation. In a normal situation, an endpoint is
placed in this map in RMOutInterceptor, which comes after
MAPAggregator. Consequently, no one manipulates the endpoint before a
lookup occurs and you don't observe this problem. However, in a client
restarting situation, the client recovers the endpoints during its
startup and places them in this map. When another call is sent to one
of these endpoints, MAPAggregator is invoked and this changes the
endpoint's hashCode value, invalidating the map and we can no longer
find this endpoint at RMOutInterceptor. (note that the current
ClientPersistenceTest in ws-rm systest does not cover this case).

So, if we want to allow EndpointImpl to be used as a map key, we
should overwrite its hashCode() to use its endpointInfo's hash value
so that its key value remains stable. I prefer this solution. But I am
not sure if someone intentionally wants to have a different hashCode
when some changes are made in the map (i.e., to verify if the endpoint
object has been manipulated or not).

If we do not choose this option and forbit EndpointImpl to be used as
a map key, we will need to fix RMManager to use a different key object
in its reliableEndpoints.

Let me know how you think.

Thanks.
Regards, aki

Reply via email to