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

No Object Id found for an instance when using @ConstructorProperties #1367

Closed
kajo-bellabeat opened this issue Sep 8, 2016 · 7 comments
Closed
Milestone

Comments

@kajo-bellabeat
Copy link

kajo-bellabeat commented Sep 8, 2016

Hi! We recently migrated from 2.4.6. to 2.8.1. and we encountered the issue. We use lombok's @AllArgsConstructor which adds @ConstructorProperties to constructor. We also used @JsonIdentityInfo on our POJO which lead to JsonMappingException: No Object Id found for an instance exception.

The following test code demonstrates the issue

import java.beans.ConstructorProperties;
import java.io.IOException;

import org.junit.Test;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.annotation.SimpleObjectIdResolver;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonTest {

    @Test
    public void failDeser() {
        A a = new A();
        a.setName("a");

        ObjectMapper om = new ObjectMapper();
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        try {
            String json = om.writeValueAsString(a);
            A deser = om.readValue(json, A.class);
        } catch (IOException e) {
            e.printStackTrace();
            throw new AssertionError("Test failed");
        }
    }

    @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id",
            resolver = SimpleObjectIdResolver.class)
    public static class A {
        public String id;
        public String name;

        public A() { }

        @ConstructorProperties({"id", "name"})
        public A(String id, String name) {
            this.id = id;
            this.name = name;
        }

        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
}

Stack trace

com.fasterxml.jackson.databind.JsonMappingException: No Object Id found for an instance of test.JacksonTest$A, to assign to property 'id'
 at [Source: {"id":null,"name":"a"}; line: 1, column: 22]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:261)
    at com.fasterxml.jackson.databind.DeserializationContext.reportUnresolvedObjectId(DeserializationContext.java:1258)
    at com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer.handleIdValue(PropertyValueBuffer.java:242)
    at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.build(PropertyBasedCreator.java:140)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:401)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1194)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:314)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithObjectId(BeanDeserializerBase.java:1165)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:146)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3789)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2833)
    at test.JacksonTest.failDeser(JacksonTest.java:33)
    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:497)
    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.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)` 

Prior to the version 2.5.0 this was not an issue, because the offending method (com.fasterxml.jackson.databind.deser.impl.PropertyValueBuffer.handleIdValue(DeserializationContext, Object)) had a comment// TODO: is this an error case? and did nothing else.

@cowtowncoder
Copy link
Member

One comment: you usually should not use

om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

on tests, as it tends to hide legitimate problems. It can be useful in production systems, to avoid errors from changing data definitions, but in tests it tends to more hassle than worth.

Anyway, thank you for reporting this, will look into the issue.

@cowtowncoder
Copy link
Member

I can reproduce this issue. Test seems to have minor flaw in that id is not assigned (with PropertyGenerator, id property is accessed, and no id is generated), but even after fixing, exception is thrown.

cowtowncoder added a commit that referenced this issue Sep 16, 2016
@kajo-bellabeat
Copy link
Author

Would it make sense to add a deserialization feature for this case which would enable us to turn off this exception? Something like DeserializationFeature.FAIL_ON_NO_OBJECT_ID_FOUND or something to that effect?

@cowtowncoder
Copy link
Member

@kajo-bellabeat There is DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS which could help. It was added in 2.5.

But I'll want to first figure out what is going with the real issue of failing even in presence of the id, and we'll see if there are other potential concerns left.

@vnnv
Copy link

vnnv commented Nov 1, 2016

any development here?

@cowtowncoder
Copy link
Member

@vnnv haven't worked on this one at all, no update from me.

cowtowncoder added a commit that referenced this issue Feb 4, 2017
@cowtowncoder
Copy link
Member

Big thanks to @diegode for providing the fix; I merged it in for 2.7.9 / 2.8.7

@cowtowncoder cowtowncoder removed the 2.9 label Feb 4, 2017
@cowtowncoder cowtowncoder added this to the 2.7.9 milestone Feb 4, 2017
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

3 participants