I am defining beans using @Bean annotation and trying to wire them using name , but receiving an exception.
Complete Example
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;
}
}
Controller
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'
}
Exception
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
By default, Spring Boot defines a bean of type MappingJackson2HttpMessageConverter
and tries to inject an ObjectMapper
into it. This typically allows you to simply declare an ObjectMapper
@Bean
, configure it any way you need to, and have Spring Boot do the rest for you.
Here, this has backfired because you declare two of them.
One solution, as described in the documentation, is to annotate the @Bean
definition of the one you want injected as @Primary
.
If you want to replace the default
ObjectMapper
completely, define a@Bean
of that type and mark it as@Primary
.
For example,
@Bean
@Primary
public ObjectMapper scmsObjectMapper() {
com.fasterxml.jackson.databind.ObjectMapper responseMapper = new com.fasterxml.jackson.databind.ObjectMapper();
return responseMapper;
}
Spring Boot will use that one.
Alternatively, you can declare your own MappingJackson2HttpMessageConverter
bean definition and configure everything internally. From the same documentation
Finally, if you provide any
@Bean
s of typeMappingJackson2HttpMessageConverter
then they will replace the default value in the MVC configuration.
For example (taken from 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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With