[jdom-interest] NullPointerException in Element.setAttribute(final String name, final String value, final Namespace ns)

Rolf Lear jdom at tuis.net
Mon Apr 9 09:06:48 PDT 2012


Hi Gisella.

I pushed through a change for 2.0.0.... 
Issue: https://github.com/hunterhacker/jdom/issues/71
Commit:
https://github.com/hunterhacker/jdom/commit/587efe408670d112f6e1af7094373e20f5a8d0aa

In JDOM 2 I have more flexibility with changing the API, and this one
makes it all somewhat more consistent....

So, the fix is already in for 2.0.0, and released.

I don't expect this to be changed in 1.1.4. It is possible it could break
existing behaviour for other people....

Rolf

On Mon, 9 Apr 2012 18:59:54 +0300, <gisella.saavedra at navis.com> wrote:
> thank you, Rolf. 
> I had patched our code using JDOM 1.1.3, to check for null.
> 
> A solution for the NPE in  JDOM 1.1.3/2.x could be:
> 
> As in Element.java:
> 
>     public Attribute getAttribute(final String name) {
>         return getAttribute(name, Namespace.NO_NAMESPACE);
>     }
> 
> then:
> 
>     public Attribute getAttribute(final String name, final Namespace ns)
{
>         return (Attribute) attributes.get(name, (ns == null)?
>         Namespace.NO_NAMESPACE : ns);
>     }
> 
> Thanks.
> 
> -----Original Message-----
> From: Rolf Lear [mailto:jdom at tuis.net] 
> Sent: Friday, April 06, 2012 7:09 PM
> To: Saavedra Gisella
> Cc: jdom-interest at jdom.org; Jason Hunter
> Subject: Re: [jdom-interest] NullPointerException in
> Element.setAttribute(final String name, final String value, final
Namespace
> ns)
> 
> Hi again Gisella.
> 
> I think your examples are great, in the sense that they perfectly 
> illustrate the inconsistencies. On the other hand, they do not help 
> solve the problem of which one is right or wrong. It does make me want 
> to make sure that new Element(String, null) throws NPE though!
> 
> Currently the Attribute handling is 'consistent'... get, remove, set all

> throw NPE for null Namespace.
> 
> I can't think of a nice way to put it, but the easiest thing to do would

> be to change your code to use a conditional:
>    emt.setAttribute(String, String,
>         ns == null ? Namespace.NO_NAMESPACE : ns);
> 
> That's for 1.1.3 at least.
> 
> I still think that maybe I could change the logic on JDOM 2.0.0...
> 
> For all the get/set/remove Attribute I can maybe put the if-logic in.
> 
> Yes, I have played with it, and it's a reasonable thing to do for 2.0.0.

> It is also consistent with 'new Attribute(String, String, null).
> 
> On the whole, I would agree with you, it should not throw NPE, and get 
> and remove should not throw NPE either.
> 
> I just changed to code to 'work', and, surprisingly, all the tests pass.
> 
> That's the wonders of wvwn with 100% code coverage you still miss some 
> things.
> 
> Maybe that will inspire you to try JDOM 2.0.0 ;-)
> 
> Rolf
> 
> 
> On 06/04/2012 8:28 PM, gisella.saavedra at navis.com wrote:
>> I see the inconsistencies
>> I would say that when removing the nullpointerexception is OK. But when
>> creating, you can see for example
>> new Element(string name)
>> new Element (String name, null)
>> both set the value of Namespace to NO_NAMESPACE.
>> And Element.setAttribute(final String name, final String value) does
not
>> throw a NPE
>> but Element.setAttribute(final String name, final String value, null) 
>> does.
>>
>>
>> -----Original Message-----
>> From: Rolf Lear [mailto:jdom at tuis.net]
>> Sent: Friday, April 06, 2012 4:39 PM
>> To: Saavedra Gisella
>> Cc: jdom-interest at jdom.org
>> Subject: Re: [jdom-interest] NullPointerException in
>> Element.setAttribute(final String name, final String value, final
>> Namespace ns)
>>
>> Hi Gisella
>>
>> Yes, I can see now where the change is. It happened between JDOM 1.0
and
>> 1.1, back in 2006 ...
>>
https://github.com/hunterhacker/jdom/commit/b48373d95cd91986f83ac5345566258d80e88027#L0R1139
>>
>> In fact, this issue has been reported before:
>> http://markmail.org/message/atybnwqqvlxk7ut4 and there was never any
>> follow-up...
>>
>> So, I can see the problem, and it still exists in JDOM 2.x.
>>
>> But, I can't see an easy fix.
>>
>> I am of the opinion that null input values deserve a
>> NullPointerException unless documented that nulls are allowed... but I
>> also recognize that compatibility is important, and JDOM has some
>> consistency in it when treating null Namespace values
>> as Namespace.NO_NAMESPACE.
>>
>> So, I am going to think about it for a moment.... but, I would not
>> expect a fix in the short term for JDOM 1.x. Even in the best
>> circumstances it would take a month or so to get a 1.1.4 out...
>>
>> For JDOM 2.x, it is also very late in the game.... too late, in fact.
>>
>> In order to fix it properly I would have to decide on a strategy for
>> dealing with null Namespace input. A quick 'poll' of the JDOM 2.x code
>> suggests:
>>
>>
>> Change null to NO_NAMESPACE:
>> ----------------------------
>> Element Constructor.
>> Element.setNamespace(Namespace)
>>
>>
>> Treats null as 'wildcard':
>> --------------------------
>> Element.getChild(String,Namespace)
>> Element.getChildren(String,Namespace)
>> Element.getChildText*(String,Namespace)
>> Element.removeChild(String,Namespace)
>> Element.removeChildren(String,Namespace)
>>
>>
>> Just ignores it.
>> ----------------
>> Element.removeNamespaceDeclaration(Namespace)
>>
>>
>> Throws NPE:
>> -----------
>> Element.addNamespaceDeclaration(Namespace)
>> Element.getAttribute(String,Namespace)
>> Element.getAttributeValue(String,Namespace);
>> Element.getAttributeValue(String,Namespace, String);
>> Element.removeAttribute(String,Namespace);
>> Element.setAttribute(String,String,Namespace)
>>
>>
>> I think, having looked at the 'poll' results, when it comes to
>> Attributes, the NPE is the 'right' thing.
>>
>> Given that getAttribute(String,Namespace) throws NPE (and
>> removeAttribute), and they have 'always' thrown NPE, I think it is
>> logical that setAttribute(String,String,Namespace) throws NPE too.
>>
>> Bottom line is that I am not convinced that it is a bug in 1.1.3.
>> Perhaps it was a bug in 1.0 to allow the null.
>>
>> So, this all comes around to the 'push-back' option. How difficult is
it
>> for you to do the null-check yourself before you call setAttribute()?
>>
>> That is the obvious workaround, and it is the 'right thing'....
>>
>> Rolf
>>
>>
>>
>>
>> On 06/04/2012 5:53 PM, gisella.saavedra at navis.com wrote:
>>> the stack trace belongs to JDOM 1.1.3
>>>
>>> -----Original Message-----
>>> From: Saavedra Gisella
>>> Sent: Friday, April 06, 2012 2:49 PM
>>> To: 'Rolf Lear'
>>> Cc: jdom-interest at jdom.org
>>> Subject: RE: [jdom-interest] NullPointerException in
>>> Element.setAttribute(final String name, final String value, final
>>> Namespace ns)
>>>
>>> Rolf,
>>>
>>> I believe you might be looking at the wrong method:
>>>
>>> This is JDOM 1.0  (ns is passed as null)
>>>
>>>      public Element setAttribute(String name, String value, Namespace
>>>      ns) {
>>>           return setAttribute(new Attribute(name, value, ns));
>>>       }
>>>
>>> Inside this code, the constructor new Attribute(name, value, ns)
calls:
>>>
>>> public Attribute(String name, String value, Namespace namespace) {
>>>           setName(name);
>>>           setValue(value);
>>>           setNamespace(namespace);
>>>       }
>>>
>>> Here setNamespace(namespace) calls:
>>> public Attribute setNamespace(Namespace namespace) {
>>>           if (namespace == null) {
>>>               namespace = Namespace.NO_NAMESPACE;
>>>           }
>>>
>>>           // Verify the attribute isn't trying to be in a default
>>>           namespace
>>>           // Attributes can't be in a default namespace
>>>           if (namespace != Namespace.NO_NAMESPACE&&
>>>               namespace.getPrefix().equals("")) {
>>>               throw new IllegalNameException("", "attribute
namespace",
>>>                   "An attribute namespace without a prefix can only be
>>>                   the " +
>>>                   "NO_NAMESPACE namespace");
>>>           }
>>>           this.namespace = namespace;
>>>           return this;
>>>       }
>>>
>>> where namespace being null is set to NO_NAMESPACE.
>>>
>>>
>>>
>>>
>>> Stack trace (JODM 1.1.3):
>>>
>>> java.lang.NullPointerException
>>>       at org.jdom.AttributeList.indexOf(AttributeList.java:378)
>>>       at org.jdom.AttributeList.get(AttributeList.java:366)
>>>       at org.jdom.Element.getAttribute(Element.java:1004)
>>>       at org.jdom.Element.setAttribute(Element.java:1178)
>>>       at
>>>      
com.navis.argo.business.snx.AbstractXmlExporter.setAttribute(AbstractXmlExporter.java:40)
>>>
>>>
>>> --------------
>>>
>>>
>>> -----Original Message-----
>>> From: Rolf Lear [mailto:jdom at tuis.net]
>>> Sent: Friday, April 06, 2012 2:40 PM
>>> To: Saavedra Gisella
>>> Cc: jdom-interest at jdom.org
>>> Subject: Re: [jdom-interest] NullPointerException in
>>> Element.setAttribute(final String name, final String value, final
>>> Namespace ns)
>>>
>>> Hi Gisella.
>>>
>>> I have looked through the JDOM 1.0 code. JDOM 1.0 was released in
>>> September 2004. Here's the code as it was at the time:
>>>
>>> Here's the getAttribute method:
>>>
https://github.com/hunterhacker/jdom/blob/jdom-1.0/core/src/java/org/jdom/Element.java#L980
>>>
>>> Here's the attributes.get(String,Namespace) method:
>>>
https://github.com/hunterhacker/jdom/blob/jdom-1.0/core/src/java/org/jdom/AttributeList.java#L365
>>>
>>> And that calls the indexOf(String,Namespace) method:
>>>
https://github.com/hunterhacker/jdom/blob/jdom-1.0/core/src/java/org/jdom/AttributeList.java#L377
>>>
>>> Which calls namespace.getURI().
>>>
>>> The way I see it is that JDOM 1.0 would always throw a
>>> NullPointerException if you gave it a null Namespace.
>>>
>>> I don't think it would have ever worked in JDOM 1.0...
>>>
>>> Did you have your own custom build of JDOM 1.0?
>>>
>>> Rolf
>>>
>>> On 06/04/2012 5:08 PM, Rolf Lear wrote:
>>>> Hi Gisella.
>>>>
>>>> Is it possible to send us a stack trace, at least the parts including
>>>> the org.jdom.* code.
>>>>
>>>> Thanks
>>>>
>>>> Rolf
>>>>
>>>>
>>>> On 06/04/2012 1:43 PM, gisella.saavedra at navis.com wrote:
>>>>> I just upgraded from jdom 1.0 to jdom 1.1.3
>>>>>
>>>>> and I was setting an attribute where the namespace was NULL.
>>>>>
>>>>> The old code was different, it was NOT calling get(...), so it was
>>>>> setting
>>>>> the namespace to namespace.NO_NAMESPACE when the namespace was NULL,
>>>>>
>>>>> before calling this get(...)
>>>>>
>>>>> but the new code, when it calls getAttribute(name, ns) (first line
of
>>>>> method described)
>>>>>
>>>>> is getting a null pointer on the namespace.
>>>>>
>>>>> Probably the namespace needs to be set to NO_NAMESPACE before
calling
>>>>> get(..) when it is NULL.
>>>>>
>>>>> *Gisella Saavedra**
>>>>> *Framework Team
>>>>> _gsaavedra at navis.com<mailto:gsaavedra at navis.com>_
>>>>>
>>>>>
>>>>>
>>>>> http://www.navis.com/images/spacer.gif
>>>>>
>>>>> 1000 Broadway, Suite 150, Oakland, CA 94607 | T+1 510 267 5123 T
>>>>> Main+1
>>>>> 510 267 5000 F+1 510 267 5100 | _http://www.navis.com
>>>>> <http://www.navis.com/>_
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> To control your jdom-interest membership:
>>>>>
http://www.jdom.org/mailman/options/jdom-interest/youraddr@yourhost.com
>>>>
>>>> _______________________________________________
>>>> To control your jdom-interest membership:
>>>>
http://www.jdom.org/mailman/options/jdom-interest/youraddr@yourhost.com
>>>>
>>>
>>


More information about the jdom-interest mailing list