Immutables: Deserialization does not work in Spring Boot

Created on 13 Apr 2019  路  7Comments  路  Source: immutables/immutables

Using latest Immutables version 2.7.6, and Spring boot 2.x

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.company.model.adminApiTokens.CreateAdminApiTokenEntity]: Is it an abstract class?; nested exception is java.lang.InstantiationException
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:175)
    at 

My immutable is defined like this:

@Value.Immutable
@JsonAutoDetect
@JsonSerialize(as = ImmutableCreateAdminApiTokenEntity.class)
@JsonDeserialize(builder = ImmutableCreateAdminApiTokenEntity.Builder.class)
public abstract class CreateAdminApiTokenEntity {

    @Value.Parameter
    @JsonProperty
    public abstract String getName();

}

Most helpful comment

@rohshall At work we are using the 'as' for deserialization and Spring seems to know how to handle this. We don't use @Value.Parameter or @JsonAutoDetect so as whether they might also be contributing to the issues I don't know.

@Value.Immutable
@JsonDeserialize(as = ImmutableIdResponse.class)
public abstract class IdResponse {

public abstract String getId();

}

All 7 comments

I think something wrong with the usage of immutable type. The exception is coming from Spring container trying to instantiate abstract class, not from Jackson trying to deserialize JSON into immutable object of type CreateAdminApiTokenEntity.

If you have a bean of type CreateAdminApiTokenEntity it can fail to instantiate it, because it should use ImmutableCreateAdminApiTokenEntity.of( or ImmutableCreateAdminApiTokenEntity.Builder instead.

Please, also check if you need @JsonAutoDetect annotation, It's possible it's not needed or doing something wrong (@JsonDeserialize(builder and annotations on generated class makes any auto-detection ineffective or interfering)

I removed @JsonAutoDetect , but I am still getting the same error.

you can check or find out how spring instantiates this abstract class. This should not happen. You need to either deserialize it from JSON using Jackson or if you need it as a bean you need to construct it using builder or factory method. Spring cannot take just an abstract class and auto-instantiate it (as it can do with a plain object using public constructor). This is a Spring configuration mistake, which, I believe, is unrelated to any changes in Immutables in this case.

@rohshall At work we are using the 'as' for deserialization and Spring seems to know how to handle this. We don't use @Value.Parameter or @JsonAutoDetect so as whether they might also be contributing to the issues I don't know.

@Value.Immutable
@JsonDeserialize(as = ImmutableIdResponse.class)
public abstract class IdResponse {

public abstract String getId();

}

Same problem for me - either using @JsonDeserialize(as = ImmutableIdResponse.class) and @JsonDeserialize(builder = ImmutableIdResponse.Builder.class) doesn't help. When trying with interfaces instead abstract class I got java.lang.IllegalStateException: No primary or single public constructor found What is similar issue https://github.com/immutables/immutables/issues/1234

I don't understand the issue here. It is reported / explained as if it's the Jackson mechanism is not working, but it's not clear if error coming from Jackson, but from Spring's own custom undetermined mechanism. Basically if you can use new ObjectMapper() to serialize/deserialize immutable instance and it works, then we need to look for what exact mechanism Spring uses (which would not be Jackson in that case)

I made experiment: copied the generated class and added public constructor what fixes the issue. Jackson is not the problem it is rather spring.

At the end used @kaweston solution what worked out for me.

Was this page helpful?
0 / 5 - 0 ratings