users@jms-spec.java.net

[jms-spec users] [jsr343-experts] Re: JMS 2.0 Late update: JMSProducer.getPropertyNames()

From: Rüdiger zu Dohna <ruediger.dohna_at_1und1.de>
Date: Fri, 11 Jan 2013 17:22:06 +0100

+1

I only would like to suggest that the set should be unmodifiable (e.g. wrapped in Collections#unmodifiableSet), not a copy; but that's a minor detail.


On 11.01.2013, at 17:07, Nigel Deakin <nigel.deakin_at_oracle.com> wrote:

> I'd like to propose we accept Philippe's proposal and change the definition of JMSProducer#getPropertyNames() to return
> a Set <String> instead of an Enumeration.
>
> I propose that for simplicity this be a copy of the property names. It would not be backed by the underlying collection,
> unlike Map#keySet. I cannot conceive of a use case where that would be needed.
>
> Although this is a minor change, if we are going to make it we have to make it before JMS 2.0 is released, since we
> won't be able to change it after that.
>
> Any comments?
>
> Nigel
>
>
>
> On 07/01/2013 12:40, Nigel Deakin wrote:
>> Philippe - Thank you for your detailed and well-argued message. I think you make a very good case for changing
>> JMSProducer#getPropertyNames
>> from
>> Enumeration getPropertyNames()
>> to
>> Set<String>
>>
>> I think that probably is a good change.
>>
>> However I think it is worth me pointing out that this method (either version) will be used rarely, since all it does it
>> allow an application to discover what property names were set using prior calls to JMSProducer#setProperty() on the same
>> JMSProducer object.
>>
>> Although JMSProducer#getPropertyNames() and the various JMSProducer#get*Property methods such as
>> JMSProducer#getLongProperty() were added for completeness and consistency I think there are few use cases where they
>> would be used. So are they needed at all?
>>
>> Nigel
>>
>>
>> On 04/01/2013 18:57, Philippe Marschall wrote:
>>>
>>>
>>> On 04.01.2013 11:57, Nigel Deakin wrote:
>>>> Hi Philippe,
>>>>
>>>> On 03/01/2013 22:14, Philippe Marschall wrote:
>>>>> Hi
>>>>>
>>>>> Why is the return type of JMSProducer#getProperyNames() a raw (!)
>>>>> Enumeration instead of a Set<String>?
>>>>
>>>> Good question. This method (and many other methods on JMSProducer) is
>>>> simply a copy of the corresponding method on Message. And
>>>> Message#getPropertyNames returns a "raw" Enumeration.
>>>>
>>>> http://docs.oracle.com/javaee/6/api/javax/jms/Message.html#getPropertyNames%28%29
>>>>
>>>>
>>>>
>>>> (Both methods return a collection of message property names)
>>>>
>>>> Hmm. There are two issues here:
>>>>
>>>> 1. whether it should return an Enumeration or a Set
>>>> 2. whether it should use a generic type, i.e. <String>
>>>>
>>>> In general I think we should avoid try to keep the methods on
>>>> JMSProducer and Message consistent since the user will need to use both.
>>>>
>>>> (The exception to this is that whereas Message has nine methods to set
>>>> properties with names like setStringProperty, setShortProperty etc,
>>>> JMSProducer has nine methods all called setProperty. So I have broken my
>>>> own "rule" in this case in order to simplify the API.)
>>>
>>> My understanding is that JMSProducer is the "new, clutter free, boiler
>>> plate free, concise" API. Enumeration itself is a pretty useless
>>> interface. There are no useful methods like #contains or #size, you
>>> can't put it into an enhanced-for-loop and it likely won't work with
>>> Java 8 "functional methods". You always have to iterate which is
>>> inefficient or convert to a Set which is boiler plate.
>>>
>>> It starts with simple things, iteration with a Set you can do
>>>
>>> for (String properytName : producer.getProperyNames()) {
>>>
>>> }
>>>
>>> with an enumeration you do
>>>
>>> Enumeration<?> enumeration = producer.getProperyNames();
>>> while (enumeration.hasMoreElements()) {
>>> String properytName = enumeration.nextElement();
>>> }
>>>
>>> but goes on to things like #contains, with a Set you can do:
>>>
>>> producer.getProperyNames().contains("JMSXProducerTXID")
>>>
>>> but with an enumeration you write the following which is probably also
>>> less efficient because you do a linear scan
>>>
>>> boolean contains = false;
>>> Enumeration<?> enumeration = producer.getProperyNames();
>>> while (enumeration.hasMoreElements()) {
>>> if ("JMSXProducerTXID".equals(enumeration.nextElement())) {
>>> contains = true;
>>> break;
>>> }
>>> }
>>>
>>> With Java 8 (which should ship this year) and a Set you can do:
>>>
>>> Set<String> jmsxProperties = producer.getProperyNames().filter(p ->
>>> p.startsWith("JMSX"));
>>>
>>> If you don't return a Set you'll have to do
>>>
>>> Set<String> jmsxProperties = new HashSet<>();
>>> Enumeration<?> enumeration = producer.getProperyNames();
>>> while (enumeration.hasMoreElements()) {
>>> String nextElement = (String) enumeration.nextElement();
>>> if (nextElement.startsWith("JMSX")) {
>>> jmsxProperties.add(nextElement);
>>> }
>>> }
>>>
>>>
>>>
>>>> My feeling is that returning a generic type would be a fairly
>>>> transparent improvement.
>>>>
>>>> However, given that Message#getPropertyNames returns an Enumeration I
>>>> think it might be confusing if JMSProducer#getPropertyNames returns a
>>>> Set.
>>>
>>> Look at your current code that uses #getProperyNames and look how much
>>> simpler, easier to understand and less error prone it would be when
>>> #getProperyNames returned a Set.
>>>
>>> Could we at least have a second method that returns a Set?
>>>
>>>> So I suggest we change this to return an Enumeration <String>.
>>>
>>> Cheers
>>> Philippe