-
Notifications
You must be signed in to change notification settings - Fork 628
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
Jackson Message Conversion - Allow Abstract Classes #1215
Comments
We will have to give this some thought; simply relaxing the the check could break many applications; currently, if the |
Can you provide more information? I just tested it with this code and it worked fine... @Test
void customAbstractClass() {
byte[] bytes = "{\"field\" : \"foo\" }".getBytes();
MessageProperties messageProperties = new MessageProperties();
messageProperties.setInferredArgumentType(Baz.class);
Message message = new Message(bytes, messageProperties);
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new BazModule());
Jackson2JsonMessageConverter j2Converter = new Jackson2JsonMessageConverter(mapper);
Baz baz = (Baz) j2Converter.fromMessage(message);
assertThat(((Qux) baz).getField()).isEqualTo("foo");
}
public interface Baz {
}
public static class Qux implements Baz {
private String field;
public Qux(String field) {
this.field = field;
}
public String getField() {
return this.field;
}
public void setField(String field) {
this.field = field;
}
}
public static class BazDeserializer extends StdDeserializer {
public BazDeserializer() {
super(Baz.class);
}
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
p.nextFieldName();
return new Qux(p.nextTextValue());
}
}
public static class BazModule extends SimpleModule {
public BazModule() {
addDeserializer(Baz.class, new BazDeserializer());
}
} It works because of this logic... @Override
public JavaType toJavaType(MessageProperties properties) {
JavaType inferredType = getInferredType(properties);
if (inferredType != null
&& ((!inferredType.isAbstract() && !inferredType.isInterface()
|| inferredType.getRawClass().getPackage().getName().startsWith("java.util")))) {
return inferredType; // we don't return here because Baz is abstract
}
String typeIdHeader = retrieveHeaderAsString(properties, getClassIdFieldName());
if (typeIdHeader != null) {
return fromTypeHeader(properties, typeIdHeader);
}
if (hasInferredTypeHeader(properties)) {
return fromInferredTypeHeader(properties); // this is the result because there are no type headers
}
return TypeFactory.defaultInstance().constructType(Object.class);
} I can see it would no work if type headers exist with incorrect information. Is that your case? |
That is correct. My situation is that the message comes from a different application. And that application has its own domain classes that are used to serialize the message, then the fully qualified domain class from that application is in the header. Then, on the receiving application, when the |
OK; thanks. I think we can handle it by adding I just need to figure out the best place to do that test without breaking anything... |
Resolves spring-projects#1215 Previously, the message converter would fall back to header type info if the inferred type was abstract. Furthermore, we did not examine container type content being abstract. With a custom deserializer, abstract classes can be deserialized.
Resolves #1215 Previously, the message converter would fall back to header type info if the inferred type was abstract. Furthermore, we did not examine container type content being abstract. With a custom deserializer, abstract classes can be deserialized.
Resolves #1215 Previously, the message converter would fall back to header type info if the inferred type was abstract. Furthermore, we did not examine container type content being abstract. With a custom deserializer, abstract classes can be deserialized. # Conflicts: # src/reference/asciidoc/whats-new.adoc
Resolves spring-projects#1279 Regression: spring-projects#1215 Test for abstract class should not be applied to container types, which can be abstract.
Resolves spring-projects#1279 Regression: spring-projects#1215 Test for abstract class should not be applied to container types, which can be abstract. **cherry-pick to 2.2.x**
I am using Kotlin, and I have a sealed class as follows:
Then
FooDeserializer
handles determining whether to instantiateFooA
orFooB
. The JacksonObjectMapper
handles this situation no problem. But, the message conversion functionality aroundJackson2JsonMessageConverter
does not allow abstract classes, which is whatFoo
gets compiled to.Please allow abstract classes and interfaces in the Jackson message conversion functionality. Let it be the responsibility of the Jackson
ObjectMapper
to handle this situation instead of preventing it.The text was updated successfully, but these errors were encountered: