2015-10-19 1 views
3

Я определяю bean-компоненты, используя аннотацию @Bean и пытаюсь связать их с использованием имени, но получая исключение.Невозможно вставлять несколько компонентов ObjectMapper в Spring Boot application

Полный пример

package com.example; 

import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import com.fasterxml.jackson.databind.ObjectMapper; 

@SpringBootApplication 
@ComponentScan({"com.example"}) 
public class SampleSpringBootApplication { 

    public static void main(String[] args) { 
     SpringApplication.run(SampleSpringBootApplication.class, args); 
    } 


    @Bean 
    public ObjectMapper scmsObjectMapper() { 
     com.fasterxml.jackson.databind.ObjectMapper responseMapper = new com.fasterxml.jackson.databind.ObjectMapper(); 
     return responseMapper; 
    } 

    @Bean 
    public ObjectMapper scmsWriteObjectMapper() { 
     com.fasterxml.jackson.databind.ObjectMapper responseMapper = new com.fasterxml.jackson.databind.ObjectMapper(); 
     return responseMapper; 
    } 
} 

Контроллер

package com.example; 

import org.springframework.http.HttpStatus; 
import org.springframework.http.MediaType; 
import org.springframework.http.ResponseEntity; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.RequestParam; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.ResponseStatus; 
import org.springframework.web.bind.annotation.RestController; 

@RestController 
public class SampleController { 

    @RequestMapping(method={RequestMethod.GET}, value="sample/hello", produces=MediaType.APPLICATION_JSON_VALUE) 
    @ResponseStatus(HttpStatus.OK) 
    public @ResponseBody ResponseEntity<String> getCart() { 
     return new ResponseEntity<String>("Hello", HttpStatus.OK); 
    } 


} 

build.gradle

buildscript { 
    ext { 
     springBootVersion = '1.2.7.RELEASE' 
    } 
    repositories { 
     mavenCentral() 
    } 
    dependencies { 
     classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
     classpath('io.spring.gradle:dependency-management-plugin:0.5.2.RELEASE') 
    } 
} 

apply plugin: 'java' 
apply plugin: 'eclipse' 
apply plugin: 'idea' 
apply plugin: 'spring-boot' 
apply plugin: 'io.spring.dependency-management' 

jar { 
    baseName = 'Sample-SpringBoot' 
    version = '0.0.1-SNAPSHOT' 
} 
sourceCompatibility = 1.8 
targetCompatibility = 1.8 

repositories { 
    mavenCentral() 
} 


dependencies { 
    compile('org.springframework.boot:spring-boot-starter') 
    testCompile('org.springframework.boot:spring-boot-starter-test') 
    compile("org.springframework.boot:spring-boot-starter-web:1.2.3.RELEASE") 
    compile('com.fasterxml.jackson.core:jackson-databind:2.5.1') 
} 


eclipse { 
    classpath { 
     containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER') 
     containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8' 
    } 
} 

task wrapper(type: Wrapper) { 
    gradleVersion = '2.7' 
} 

Исключение

Caused by: 
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No 
qualifying bean of type [com.fasterxml.jackson.databind.ObjectMapper] 
is defined: expected single matching bean but found 2: 
scmsObjectMapper,scmsWriteObjectMapper 
+0

Sorry Нир, это была опечатка, когда я напечатал здесь. Я использую правильный код в моем коде. –

+0

Я не могу воспроизвести это. Пожалуйста, напишите полный пример. –

+0

@SotiriosDelimanolis опубликовал полный пример. Сервер даже не запускается, я получаю сообщение об ошибке после того, как я нажимаю кнопку запуска как приложение для загрузки весны. –

ответ

8

По умолчанию Spring Boot определяет компонент типа MappingJackson2HttpMessageConverter и пытается ввести в него ObjectMapper. Обычно это позволяет просто объявить ObjectMapper@Bean, настроить его так, как вам нужно, и загрузить Spring Boot для вас.

Здесь это обратное, потому что вы объявляете два из них.

Одно решение, as described in the documentation, состоит в том, чтобы комментировать @Bean определение того, которое вы хотите ввести как @Primary.

Если вы хотите полностью заменить по умолчанию ObjectMapper, определить @Bean этого типа и пометить его как @Primary.

Например,

@Bean 
@Primary 
public ObjectMapper scmsObjectMapper() { 
    com.fasterxml.jackson.databind.ObjectMapper responseMapper = new com.fasterxml.jackson.databind.ObjectMapper(); 
    return responseMapper; 
} 

Spring загрузки будет использовать этот один.

В качестве альтернативы, вы можете объявить о своем собственном MappingJackson2HttpMessageConverter bean definition и настроить все внутренне. Из той же документации

Наконец, если вы предоставляете какие-либо @Bean S типа MappingJackson2HttpMessageConverter тогда они будут заменить значение по умолчанию в конфигурации MVC.

Например (взято из here)

@Bean 
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { 
    MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter(); 
    ObjectMapper objectMapper = new ObjectMapper(); 
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
    jsonConverter.setObjectMapper(objectMapper); 
    return jsonConverter; 
} 
+0

благодарит за подробное объяснение. Это очень помогло мне и решило мою проблему :-) –