Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

After upgrade to 2.12.0, NPE when deserializing an empty element to ArrayList #435

Closed
ilgrosso opened this issue Nov 30, 2020 · 9 comments
Closed
Milestone

Comments

@ilgrosso
Copy link

This code:

        XML_MAPPER = new XmlMapper();
        XML_MAPPER.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
        XML_MAPPER.configOverride(Set.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
        XML_MAPPER.configOverride(Map.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
        XML_MAPPER.enable(ToXmlGenerator.Feature.WRITE_NULLS_AS_XSI_NIL);        
        XML_MAPPER.enable(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL);

        List<LoggerTO> original = new ArrayList<>();

        StringWriter writer = new StringWriter();
        XML_MAPPER.writeValue(writer, original);

generates the following XML:

<ArrayList/>

With same XML_MAPPER initialization, however, the following code:

        List<LoggerTO> actual = XML_MAPPER.readValue(writer.toString(), new TypeReference<List<LoggerTO>>() {
        });

raises the following NPE:

java.lang.NullPointerException
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromString(CollectionDeserializer.java:305)
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:250)
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28)
        at com.fasterxml.jackson.dataformat.xml.deser.XmlDeserializationContext.readRootValue(XmlDeserializationContext.java:91)
        at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4591)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3546)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3529)

Without the init line

XML_MAPPER.enable(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL);

this works as expected but I have failures elsewhere, when the Java list is part of a POJO:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.ArrayList<org.apache.syncope.common.lib.to.MembershipTO>` from String value (token `JsonToken.VALUE_STRING`)
 at [Source: (StringReader); line: 1, column: 206] (through reference chain: org.apache.syncope.common.lib.request.AnyObjectCR["dynMemberships"])
        at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
        at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1603)
        at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1377)
        at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1324)
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.handleNonArray(CollectionDeserializer.java:384)
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:274)
        at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28)
        at com.fasterxml.jackson.databind.deser.impl.SetterlessProperty.deserializeAndSet(SetterlessProperty.java:134)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:324)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:225)
        at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:197)
        at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:135)
        at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:105)
        at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1277)
        at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:74)
        at com.fasterxml.jackson.dataformat.xml.deser.XmlDeserializationContext.readRootValue(XmlDeserializationContext.java:91)
        at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4591)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3546)
        at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3514)

With none of the lines:

        XML_MAPPER.enable(ToXmlGenerator.Feature.WRITE_NULLS_AS_XSI_NIL);        
        XML_MAPPER.enable(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL);

all is working with Jackson 2.11.3.

Anything obvious I am missing? Thanks for your support.

@cowtowncoder
Copy link
Member

Thank you for reporting this & contributing possible fix! I think I'll first try to reproduce this, and then can use your patch to verify fix.

@cowtowncoder cowtowncoder changed the title After upgrade to 2.12.0, NPE when deserializing and empty ArrayList After upgrade to 2.12.0, NPE when deserializing an empty element to ArrayList Dec 1, 2020
@cowtowncoder cowtowncoder modified the milestones: 2.12.-, 2.12.1 Dec 1, 2020
@cowtowncoder
Copy link
Member

Ok, this was interesting... coercion from empty XML element to null token occurred at low level method, caller not realizing this, and reporting it as JsonToken.VALUE_STRING but with null String contents.
Changed so that it gets properly reported as JsonToken.VALUE_NULL, as expected.

Thank you for reporting the issue and suggesting a patch -- this made it easy to resolve the problem!

@ilgrosso
Copy link
Author

ilgrosso commented Dec 1, 2020

@cowtowncoder Thanks to you for checking and adding all needed for a proper fix 👍

@ilgrosso
Copy link
Author

ilgrosso commented Dec 1, 2020

@cowtowncoder is 2.12.1-SNAPSHOT artifacts available somewhere?

@cowtowncoder
Copy link
Member

Thank you for reporting this -- it is too bad we didn't yet have unit test coverage for this particular case, but better late than never! :)

Snapshots should be built by Travis, and available from Sonatype OSS repo. But I'll make sure to force manual deploy of snapshot version too. It looks like free Travis builds do not work very well any more for whatever reason. :-/

@ilgrosso
Copy link
Author

ilgrosso commented Dec 1, 2020

It looks like free Travis builds do not work very well any more for whatever reason. :-/

Oh, I am well aware of this...
Anyway it seems that https://travis-ci.org/github/FasterXML/jackson-dataformat-xml/builds/746882344 is green so I'll go ahead and try.

Thanks again.

@ilgrosso
Copy link
Author

ilgrosso commented Dec 1, 2020

@cowtowncoder with 2.12.1-SNAPSHOT the following code:

        XML_MAPPER = new XmlMapper();
        XML_MAPPER.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
        XML_MAPPER.configOverride(Set.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
        XML_MAPPER.configOverride(Map.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
        XML_MAPPER.enable(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL);

        List<LoggerTO> original = new ArrayList<>();

        StringWriter writer = new StringWriter();
        XML_MAPPER.writeValue(writer, original);

        List<LoggerTO> actual = XML_MAPPER.readValue(writer.toString(), new TypeReference<List<LoggerTO>>() {
        });
        assertEquals(original, actual);

fails with message

org.opentest4j.AssertionFailedError: expected: <[]> but was: <null>

I have verified that serialization produces

<ArrayList/>

@cowtowncoder
Copy link
Member

@ilgrosso Ok, I know this is related but could you create a separate issue for this part of the problem (null-handling ignored) -- I'll have to check it separately. I'll have to see if null coercion was to be applied for root values or not (in regular JSON handling).

@ilgrosso
Copy link
Author

ilgrosso commented Dec 1, 2020

@cowtowncoder sure - see #437

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants