9

メッセージコンバーターを使用して JSON に変換したい JAXB アノテーションを持つエンティティがいくつかあります。

JAXB アノテーションを読み取る ObjectMapper が機能することはわかっています。

String correctJsonText = jacksonObjectMapper.writeValueAsString(entityWithJAXB); 

しかし、残りのサービスを呼び出すと、デフォルトで登録された MappingJacksonHttpMessageConverter (JAXB の読み取り用に構成されていない) が引き継がれるようです - @XmlTransient が無視されると、循環参照が原因でスタックオーバーフローが発生します...

MappingJackson2HttpMessageConverter を使用するように Spring を構成するにはどうすればよいですか?

現在の構成

<mvc:annotation-driven>
    <mvc:message-converters register-defaults="false">
        <bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
            <property name="objectMapper" ref="jacksonObjectMapper" />
            <property name="supportedMediaTypes">
                <list>
                    <bean class="org.springframework.http.MediaType">
                        <constructor-arg index="0" value="application" />
                        <constructor-arg index="1" value="json" />
                        <constructor-arg index="2" value="UTF-8" />
                    </bean>
                </list>
            </property>

        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

<bean id="jaxbAnnotationInspector" class="com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector" />

<bean id="jacksonObjectMapper" class="com.fasterxml.jackson.databind.ObjectMapper">
    <property name="annotationIntrospector" ref="jaxbAnnotationInspector" />
</bean>

REST サービス

@RequestMapping(value="/{id}", method=RequestMethod.GET, produces = "application/json;charset=UTF-8")
public @ResponseBody EntityWithJAXB readEntityWithJAXB(@PathVariable int id, Model model) {
    return entityService.getById(id);
}

依存関係

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.0.5</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.0.5</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-jaxb-annotations</artifactId>
    <version>2.0.5</version>
</dependency>

更新/解決策

コンテキストをデバッグすると、構成が効果がないことがわかりました<mvc:annotation-driven>

MockMcv を使用した単体テストでは、常にデフォルトの handleradapters が読み込まれるため、カスタム objectmapper が無視されることが判明しました。便宜上、junit test を使用してコントローラーのみをテストしました。コントローラーに問題なくヒットしたため、これをエラーの原因とは考えていませんでした...

テストの修正はまだ見つかりませんでしたが、curl を使用してサービスを呼び出すと、すべてが機能します。

更新/最終的な解決策

私のテストセットアップの解決策を見つけました。MockMvc (spring-test-mvc) を使用する場合は、カスタム メッセージ コンバーターを明示的に指定する必要があります。

private MockMvc mockMvc;

@Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;

@Autowired
private RestController restController;

@Before
public void initMockMvc(){
    mockMvc = MockMvcBuilders.standaloneSetup(restController)
            .setMessageConverters(jacksonMessageConverter).build();
} 

@Test
public void testRestController() throws Exception{
    DefaultRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/json/42");
    this.mockMvc.perform(requestBuilder).andDo(print()).andExpect(status().isOk());
}

唯一残っている問題は、httpsjacksonMessageConverter ://jira.springsource.org/browse/SPR-9469 の JIRA が解決されるまで直接オートワイヤーできないことです。それまでは、テスト コンテキストで jacksonMessageConverter のコピーを作成しました。

4

1 に答える 1

3

私はあなたの構成を複製しましたが、それは私にとって完璧に機能します. 属性を明示的に指定したため、デフォルトのメッセージコンバーターは有効になりませんregister-defaults=false。これは私の @XmlTransient アノテーションがどのように見えるかです:

@XmlAccessorType(XmlAccessType.FIELD)
public class EntityWithJAXB {


    @XmlTransient
    private EntityWithJAXB aChild;
于 2012-09-20T22:19:59.177 に答える