users@jms-spec.java.net

[jms-spec users] Re: [jsr343-experts] Re: JMSProducer#getProperyNames()

From: Philippe Marschall <kustos_at_gmx.net>
Date: Fri, 04 Jan 2013 19:57:54 +0100

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