ClassCastException when using XmlAdapter with XmlEnum
I wanted to serialize a fairly complex object structure and came across this ClassCastException. It looks like the XML Adapter is called too early when the type is an enum.
Below snippet demonstrates the error as a JUnit test
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import org.junit.jupiter.api.Test;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.*;
import static org.assertj.core.api.Assertions.assertThat;
public class XmlEnumAdapterTest {
private static final XmlMapper MAPPER =
XmlMapper.builder()
.defaultUseWrapper(true)
.addModule(new JaxbAnnotationModule())
.build();
@Test
void serialize() throws Exception {
final Document document = new Document(Code.RED);
String xml = MAPPER.writeValueAsString(document);
assertThat(xml).isEqualTo("<document><code>RED</code></document>");
}
@XmlRootElement(
name = "document"
)
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(
propOrder = {"_code"}
)
public static class Document {
@XmlElement(name = "code")
private final Code _code;
public Document(Code code) { _code = code; }
public Code getCode() {
return _code;
}
}
@XmlEnum
@XmlType(
name = "CodeType"
)
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
public enum Code {
@XmlEnumValue("RED")
RED;
}
}
The test was executed with jackson-module-jaxb-annotations-2.17.2.jar
First of all, thank you for reporting the issue.
Figuring out where to add tests is tricky: JAXB annotations module cannot depend on XML module (so can't be added here).
But looks like jackson-dataformat-xml does actually have test dependency on Jakarta XML bind annotations -- newer version of JAXB annotations. So might be able to add there.
However, the "correct" place would be here:
https://github.com/FasterXML/jackson-integration-tests/
where it is legal to have dependencies to any and all Jackson modules.
Is there anything I could/should do?
@wbiller No, I think this is all the information. I am pretty overloaded currently so it may take a while until I get to look into this, unfortunately.
One minor thing could be if you could try to find minimal reproduction (I suspect most JAXB annotations used are not required here). And perhaps including first couple of stack frames for exception.
But reproduction is the most important thing and you got it :)
Just realized that XML is probably not the problem here: can create JSON reproduction as well.
But looking at what is happening, I am not sure how code is supposed to work.
CollapsedStringAdapter is "converting" between String and String, basically just transforming content a bit.
But when serializing Enums, shouldn't type given (see https://docs.oracle.com/javase/8/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html) be Enum type, not String?
Only on deserialization could we get String (to convert/adapt to Enum type in question).
Does this work with JAXB? (I assume so).
If this is expected to work there's bit of impedance between how Jackson Converters and JAXB XmlAdapters work and it may be tricky to support these annotations with Jackson.