Skip to content

ConverterRegisteringWebMvcConfigurer#0: defined in null, overriding RestTemplate #779

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

Open
drenda opened this issue Jan 2, 2019 · 11 comments

Comments

@drenda
Copy link

drenda commented Jan 2, 2019

I'm facing a weird exception involving ConverterRegisteringWebMvcConfigurer.

I posted my problem here.

I tried all things I could think about without any luck. I'm not sure it's a bug, but for sure the error message is quite weird:

Field restTemplate in cloud.test.server.rest.clients.TenantRestClient required a single bean, but 2 were found: - org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#0: defined in null - org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#1: defined in null

As described in my question, my code works until Spring Boot 2.0.3.

@gregturn
Copy link
Contributor

gregturn commented Jan 9, 2019

You may be rigging together a little differently than expected.

The idea of RestTemplateBuilder is to inject that bean into your code, and then "get" the a RestTemplate from it and use it right away. You're creating one then using it to register a RestTemplate bean.

I don't know what the @EnableRetry and other annotations might be doing that your code is getting in the way of.

You might want to back off of registering a RestTemplate into the app context and instead, autowire the RestTemplateBuilder into the target, building your RestTemplate there.

@drenda
Copy link
Author

drenda commented Jan 9, 2019

Thanks for your reply @gregturn . I would really like to do what you explained (it was the first thing I did), but I arrived to that weird solution because of this:

The dependencies of some of the beans in the application context form a cycle:

   webSecurityConfiguration
      ↓
   org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration
      ↓
   webMvcConfiguration (field private cloud.test.server.rest.clients.TenantRestClient cloud.test.server.config.WebMvcConfiguration.tenantRestClient)
┌─────┐
|  tenantRestClient defined in file [/Users/drenda/Documents/workspaceREST/test-server/target/classes/cloud/test/server/rest/clients/TenantRestClient.class]
↑     ↓
|  restTemplateBuilder defined in class path resource [org/springframework/boot/autoconfigure/web/client/RestTemplateAutoConfiguration.class]
↑     ↓
|  org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
↑     ↓
|  jacksonHttpMessageConverter defined in class path resource [org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.class]
↑     ↓
|  repositoryRestConfiguration defined in class path resource [org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.class]
↑     ↓
|  repositories defined in class path resource [org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.class]
↑     ↓
|  documentRepository
↑     ↓
|  (inner bean)#1ae90cb9
↑     ↓
|  entityManagerFactory defined in class path resource [cloud/test/server/config/HibernateConfig.class]
↑     ↓
|  multiTenantConnectionProviderImpl (field private cloud.test.server.tenants.ConnectionPoolManager cloud.test.server.tenants.MultiTenantConnectionProviderImpl.connectionPoolManager)
↑     ↓
|  connectionPoolManagerImpl (field private cloud.test.server.rest.clients.TenantRestClient cloud.test.server.tenants.ConnectionPoolManagerImpl.tenantRestClient)
└─────┘

In short: this is a multi-tenant application and in multiTenantConnectionProviderImpl I need TenantRestClient that use a RestTemplate to get DB infos for a central system. I would like to get advantage of Spring's restTemplate in order to have messageConverters and exceptions handling set properly.

Thanks

@gregturn
Copy link
Contributor

I'm honestly not sure how to disentangle your situation. You are mixing together a lot of technologies and the result is we can't track down a circular dependency of epic proportion.

Also, since you are using Spring Data REST, the problem may have nothing to do with Spring HATEOAS but instead custom code in Spring Data REST.

@fenrivymor
Copy link

@drenda Hello,
I'm receiving the same error, did you solved?


APPLICATION FAILED TO START


Description:

Field restTemplate in com.mycompany.services.rest.RestService required a single bean, but 2 were found:
- org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#0: defined in null
- org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#1: defined in null

@KISTERS-Development-LA
Copy link

I think it is a bug in org.springframework.hateoas.config.HypermediaSupportBeanDefinitionRegistrar. When I debuged it, this class will be registered in two times.

This error only occurs when Resttemplate is registered as Bean in ApplicationContext. See: org.springframework.hateoas.config.ConverterRegisteringBeanPostProcessor#postProcessBeforeInitialization

The postProcessBeforeInitialization tries to find the configurer and get this bean two times.

I fixed it very quick&dirty, by editing the registerSourcedBeanDefinition method:
` private static String registerSourcedBeanDefinition(
BeanDefinitionBuilder builder, AnnotationMetadata metadata, BeanDefinitionRegistry registry) {

AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
String generateBeanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, registry);
if (StringUtils.equals(
    generateBeanName,
    "org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#0")) {
  return registerSourcedBeanDefinition(builder, metadata, registry, generateBeanName);
}
return "";

} `

@gregturn will this help to fix this bug?

@GuiRitter
Copy link

GuiRitter commented Jun 27, 2019

I've had this problem as well, and I think I solved it by adding spring.main.allow-bean-definition-overriding=true to application.properties.

EDIT: Sorry, that wasn't it. That was for a conflict involving an ObjectMapper and a CsvMapper. I suspect it may still work for RestTemplate, though. Anyway, here's how I'm building my RestTemplate. It could be useful.

@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder, MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter) {
    RestTemplate restTemplate = restTemplateBuilder.build();
    mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(APPLICATION_JSON, APPLICATION_OCTET_STREAM));
    restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
    return restTemplate;
}

@Saran-Agiliz
Copy link

Facing similiar problem with below Exception

Field s2sClient_ in com.xxx.yyy.xxx.Class required a single bean, but 8 were found:
- org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#0: defined in null
- org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#1: defined in null
- org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#2: defined in null
- org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#3: defined in null
- org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#4: defined in null
- org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#5: defined in null
- org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#6: defined in null
- org.springframework.hateoas.config.ConverterRegisteringWebMvcConfigurer#7: defined in null

Action:

Consider marking one of the beans as @primary, updating the consumer to accept multiple beans, or using @qualifier to identify the bean that should be consumed

@fenrivymor
Copy link

Solved! I excluded a repeated declaration of ConverterRegisteringWebMvcConfigurer by removing redundant dependency declaration.

@ken4ward
Copy link

Solved! I excluded a repeated declaration of ConverterRegisteringWebMvcConfigurer by removing redundant dependency declaration.

@fabiohenriquebayma could you Kindly explain the redundancy dependency you removed? I need a fix for the issue as well.

@fenrivymor
Copy link

fenrivymor commented Sep 25, 2019

Solved! I excluded a repeated declaration of ConverterRegisteringWebMvcConfigurer by removing redundant dependency declaration.

@fabiohenriquebayma could you Kindly explain the redundancy dependency you removed? I need a fix for the issue as well.

I just removed the declaration of spring-boot-starter-web in favor of spring-hateoas. spring-hateoas has spring-web. I could also exclude spring-web from heteoas in favor of spring-boot-starter-web. I believe it is case-by-case.

@atomici
Copy link

atomici commented Oct 31, 2019

I solved the problem by using RestTemplateBuilder instead of RestTemplate.
Before I removed my @bean RestTemplate from configuration file.

 private RestTemplate restTemplate;
   public MyClass(RestTemplateBuilder restTemplate){
     this.restTemplate = restTemplate.build();
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants