0

我对我目前在 Spring MVC 应用程序中看到的那些东西有点困惑,我希望有人能告诉我我们做错了什么。由于谷歌没有给我答案,我确信我们错了。

我们有一个简单的 Spring 4.1.5.RELEASE 应用程序。没有什么特别值得一提的。有一个 MappingJackson2HttpMessageConverter 配置为通过 Jackson ObjectMapper 将 JSON 传递给 RestControllers 中的客户端。

通过杰克逊序列化的所有实体在 tpe 级别都有以下注释

@JsonIdentityInfo(generator = IntSequenceGenerator.class, property = "@jsonObjectId")

现在奇怪的部分:

有一个 spring 集成测试,它执行以下操作(objectMapper 从 Web 应用程序上下文自动装配,它是转换请求有效负载的同一实例)

objectMapper.writeValueAsString(dummy) // generate json from dummy object
mockMvc.perform(post(...)) // make a post request with JSON payload generated
evaluate reponse

执行一次测试是可以的。如果我复制该测试用例并执行两次,那么我会从服务器返回 400,说 IllegalArgumentExecption -> 已经有 POJO for id ... 问题可以在现实世界的应用程序中重现,所以它似乎没有测试问题。

我发现,在序列化过程中,每次需要序列化对象时都会创建负责生成“jsonObjectId”属性的 IntSequenceGenerator。到目前为止还好。但是对应的对应物,在我们的例子中,默认使用来自 jackson 的 SimpleObjectIdResolver 始终是同一个实例。所以第二个服务器请求(第二个反序列化过程)会导致 SimpleObjectIdResolver 中的那个异常。

如果有人能给我一个提示,我将非常感激,我们做错了什么......

4

1 回答 1

0

忘了说:使用的是 Jackson-Core 2.4.1。我们现在升级到 jackson 的 2.7.0 版本,并且 SimpleObjectIdResolver 现在为每次反序列化重新创建。这似乎是杰克逊 2.7.0 之前的一个错误。

编辑:我能够将问题减少到以下小测试:

public class DummyTest {

private Dummy dummy = new Dummy();

@Before
public void setUp() {
    dummy.setFoo("Foo");
}

@Test
public void testApp() throws Exception {
    ObjectMapper mapper = new ObjectMapper();
    String dummyAsJsonString = mapper.writeValueAsString(dummy);

    mapper.readValue(dummyAsJsonString, Dummy.class);
    mapper.readValue(dummyAsJsonString, Dummy.class);
}
}

其中 Dummy.class 定义为

@JsonIdentityInfo(generator = IntSequenceGenerator.class, property = "@jsonObjectId")
public class Dummy {

private String foo;

public String getFoo() {
    return foo;
}

public void setFoo(String foo) {
    this.foo = foo;
}

}

使用 jackson 2.4.1 执行它时,您将收到 IllegalStateException

于 2016-02-08T10:29:42.947 回答