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

Fail to serialize Enum instance which includes a method override as POJO (shape = Shape.OBJECT) #2576

Closed
ylhuang-veeva opened this issue Dec 20, 2019 · 3 comments
Milestone

Comments

@ylhuang-veeva
Copy link

This problem of failing to serialize an Enum instance which includes a method override only occurs in 2.10.1, not 2.10.0.
Here is a simple test:

public class EnumSerializationTestU {
    @Test
    public void testSerializationOfEnumInstanceWithOverrideMethod() {
        ObjectMapper om = new ObjectMapper();
        om.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
        try {
            String stringResult = om.writeValueAsString(EnumWithOverrideMethod.ATTRIBUITES);
            Map result = (Map) om.readValue(stringResult, Map.class);
            assertEquals("attributes", result.get("key"));
        } catch (JsonProcessingException e) {
            System.err.println("Serialization Of EnumInstanceWithOverrideMethod fails: ");
           e.printStackTrace();
        }
    }

    @JsonFormat(shape = JsonFormat.Shape.OBJECT)
    public enum EnumWithOverrideMethod {
        DEFAULT("default"),
        ATTRIBUITES("attributes") {
            public Class sectionInfoClass () {
                return AttributesSectionInfo.class;
            }
        },
        DOC_LAYOUT("doclayout") {
            public Class sectionInfoClass () {
                return DocLayoutSectionInfo.class;
            }
        }
        ;
        private final String key;
        private EnumWithOverrideMethod(String key) {
            this.key = key;
        }
        public String getKey() { return this.key; }

        public Class sectionInfoClass() {
            return null;
        }
    }

    public interface LayoutSectionInfo {
    }

    public class AttributesSectionInfo implements LayoutSectionInfo {
        private LinkedHashMap attributes;
        public LinkedHashMap getAttributes() {
            return attributes;
        }
    }

    public class DocLayoutSectionInfo implements LayoutSectionInfo {
        private String relatedDocField;

        public String getRelatedDocField() {
            return relatedDocField;
        }
        public void setRelatedDocField(String relatedDocField) {
            this.relatedDocField = relatedDocField;
        }
    }
}
**The stack trace for above is:**
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class veeva.ecm.ui.interfaces.web.contract.admin.vobjects.layout.WidgetTypeSerializationTestU$EnumWithOverrideMethod$1 and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
	at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
	at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
	at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:404)
	at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
	at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
	at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:4094)
	at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3404)
	at veeva.ecm.ui.interfaces.web.contract.admin.vobjects.layout.WidgetTypeSerializationTestU.testSerializationOfEnumInstanceWithOverrideMethod(WidgetTypeSerializationTestU.java:31)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
@cowtowncoder
Copy link
Member

Thank you for reporting this issue: I was able to reproduce it with a simplified example. Also does not seem to fail for 2.9. I suspect this may be related to type introspection optimizations, wherein some resolution would be avoid for Enum types (I vaguely recall some work that attempted this to improve cold-start performance). This would not affect "regular" Enum handling, even with sub-classing (due to method overload), but in this particular case due to Shape (effectively Enum is treated as POJO) it does.

@cowtowncoder
Copy link
Member

cowtowncoder commented Dec 20, 2019

Hmmh. Odd. 2.10 fails, 2.11 does not. And master (3.0.0-SNAPSHOT) does. Would have expected all of those to fail.

@cowtowncoder cowtowncoder changed the title jackson-databind 2.10.1 fails to serialize an Enum instance which includes a method override Fail to serialize Enum instance which includes a method override as POJO (shape = Shape.OBJECT) Dec 20, 2019
@cowtowncoder cowtowncoder added this to the 2.10.2 milestone Dec 20, 2019
@cowtowncoder
Copy link
Member

Fixed for 2.10. Problem was not quite what I thought, but was able to pinpoint it to specific change in detecting Enum types (JavaType.isEnum() does NOT work for subtypes for 2.10; this was fixed in 2.11, however, which prevented problme there -- but 2.10 breakage was due to refactoring of some kind).

Thank you again for reporting this; fix will be in 2.10.2 which should be released quite soon.

cowtowncoder added a commit that referenced this issue Dec 20, 2019
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