(Please read and give your preference to A or B below)
We're still debating whether the Set returned by JMSProducer#getPropertyNames (which returns all the property names
configured on the JMSProducer) should be
(1) A copy - so changing the JMSProducer would have no effect on the Set, and vice versa.
(2) A "live" set backed by the underlying JMSProducer. If we follow the semantics of Map.keySet() changing the
JMSProducer will change the Set, and vice versa.
(3) A "live" set backed by the JMSProducer whereby changing the changing the JMSProducer will change the Set but where
any attempt to change the Set would throw an exception. John Ament and Rüdiger were keen on this.
I see a JMSProducer as a temporary place where message properties can be held prior to setting them on the message. They
would simply be stored in a HashMap prior to being copied into the message when send(destination,message) is called.
I can see the benefit of (2) since it doesn't require any copying of data. Although I originally proposed (1) I am now
keener on (2). It is also consistent with the behaviour of Map.
Rüdiger's argument for (3) was based on the possibility that the producer is "backed by a native system" for efficiency
reasons and that this temporary store of properties might be as well. If this were the case it would defeat the purpose
of using native storage if getPropertyNames were to return a copy.
I can see the logic here, even though I don't think it is likely that an implementer would want to implement it any way
other than using a Map (in the normal Java heap). However I don't see the logic in requiring this to be unmodifiable. A
"native system" would already need to support methods on JMSProducer which allows properties to be set, modified and
cleared, so I don't see why it would be particularly difficult to implement, say, Set#remove(key) so that it deletes the
property with the specified key.
There are two reasons why I don't think it is likely that an implementer would want to implement it any way other than
using a Map. The first is that every time the JMSProducer is used to send a message, all its properties need to be
copied to the message. So you might as well store it in the heap. The other is that it is safe to assume that the amount
of data stored in message properties is small. JMS 1.1 already states that use of properties should be kept to a minimum:
"JMS providers will likely handle data in a message’s body more efficiently than data in a message’s properties. For
best performance, applications should use message properties only when they need to customize a message’s header." (JMS
1.1 3.5.3)
So, I would like to propose two alternatives based on (2) and (3) above and ask for your views.
OPTION A
--------
Set<String> getPropertyNames()
Returns a Set view of the names of all the message properties that have been set on this JMSProducer.
Note that JMS standard header fields are not considered properties and are not returned in this Set.
The set is backed by the JMSProducer, so changes to the map are reflected in the set, and vice-versa. Its behaviour
matches that defined in the java.util.Map method keySet.
Returns:
a Set containing the names of all the message properties that have been set on this JMSProducer
Throws:
JMSRuntimeException - if the JMS provider fails to get the property names due to some internal error.
See Also:
Map.keySet()
OPTION B
--------
Set<String> getPropertyNames()
Returns an unmodifiable Set view of the names of all the message properties that have been set on this JMSProducer.
Note that JMS standard header fields are not considered properties and are not returned in this Set.
The set is backed by the JMSProducer, so changes to the map are reflected in the set. However the set may not be
modified. Attempts to modify the returned collection, whether directly or via its iterator, will result in an
UnsupportedOperationException. Its behaviour matches that defined in the java.util.Collections method unmodifiableSet.
Returns:
a Set containing the names of all the message properties that have been set on this JMSProducer
Throws:
JMSRuntimeException - if the JMS provider fails to get the property names due to some internal error.
See Also:
Collections.unmodifiableSet()
Please express your views! (If you don't care then please say so as well)
Nigel
On 24/01/2013 21:11, Rüdiger zu Dohna wrote:
> Nigel,
>
> On 2013-01-22, at 12:29, Nigel Deakin<nigel.deakin_at_oracle.com> wrote:
>> If it's backed by the JMSProducer's internal map, why do you think it needs to be unmodifiable? There's no
>> technical reason why this needs to be the case. This is just a simple map (and does not need to be threadsafe).
>
> It could be that the producer is backed by a native system, so the map would be as well. Changing the map would have
> to be forwarded to that native system. While quite possible, it would be extra effort over the dedicated methods to
> add/remove/change the properties. Maybe the native system doesn't distinguish between header fields and properties...
> things can get ugly for the implementers.
>
>> I think the set returned should either be
>>
>> * backed by the JMSProducer's internal map, in which case it should follow the semantics of Map.keySet()
>>
>> * a simple copy of the keys in the JMSProducer's internal map, in which case it will follow the obvious semantics
>> of a copy.
>>
>> My feeing is that to make it "backed", but not allow the application to delete properties by removing property
>> names from the set, would be unnecessarily inconsistent. It should either be "fully" backed, or a simple copy.
>
> Right, this would have to be consistent.
>
> I think the question we should ask is: Do developers want to modify the properties map/set directly or are the
> methods sufficient? If the latter, make it immutable.
>
> Having a copy wouldn't help anybody, would it? It would just cause extra load on the GC (maps are comparably huge!).
> This reminds me of the Swing issues with all those defensive copies of the mutable Rectangle/Point classes.
>
>
> Rüdiger
>