0

We have a Spring 4.0.5.RELEASE based application, and by mistake, we introduced two beans with the same name. Both beans are instances of RestTemplate version 4.2.2, the Spring framework to make HTTP calls:

First "restTemplate" bean

@Bean(name = "restTemplate")
protected RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    restTemplate.setErrorHandler(new RestTemplateErrorHandler());

    List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
    MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
    // Disable exceptions on unknown incoming properties
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    jacksonConverter.setObjectMapper(mapper);
    messageConverters.add(jacksonConverter);
    messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
    messageConverters.add(new StringHttpMessageConverter());

    restTemplate.setMessageConverters(messageConverters);

    return restTemplate;
}

Second "restTemplate" bean, totally raw

@Bean(name = "restTemplate")
protected RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();

    return restTemplate;
}

The main difference between the two, is the error handling. And this is the issue:

We have four server running, and we deployed the same war file in each one of them. As per logs, we are 100% sure that in the first two servers, the restTemplate instance with error handling is being used. And in the other two, the instance without error handling is not being used.

Why Spring behaves like that? It is injecting the "restTemplate" bean in a totally non-deterministic way. What might be the causes of this behaving? I would expect to have the same instance of "restTemplate" in the all of 4 servers.

Here I put the logs, showing what I'm trying to explain. Take a look to the bold statements!!

Sever One:

[timestamp=19:09:23.846] [thread="localhost-startStop-1"] [session="undefined"] [request="undefined"] [level=INFO ] [logger=o.s.b.f.s.DefaultListableBeanFactory] [class=org.springframework.beans.factory.support.DefaultListableBeanFactory] [line=839] - Overriding bean definition for bean 'restTemplate' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=configCommon; factoryMethodName=restTemplate; initMethodName=null; destroyMethodName=(inferred); defined in com.service.common.config.ConfigCommon] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=configCentralReservations; factoryMethodName=restTemplate; initMethodName=null; destroyMethodName=(inferred); defined in com.service.centralreservations.config.ConfigCentralReservations]

Server Two:

[timestamp=19:04:41.717] [thread="localhost-startStop-1"] [session="undefined"] [request="undefined"] [level=INFO ] [logger=o.s.b.f.s.DefaultListableBeanFactory] [class=org.springframework.beans.factory.support.DefaultListableBeanFactory] [line=839] - Overriding bean definition for bean 'restTemplate' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=configCentralReservations; factoryMethodName=restTemplate; initMethodName=null; destroyMethodName=(inferred); defined in com.service.centralreservations.config.ConfigCentralReservations] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=configCommon; factoryMethodName=restTemplate; initMethodName=null; destroyMethodName=(inferred); defined in com.service.common.config.ConfigCommon]

Perimosh
  • 2,304
  • 3
  • 20
  • 38
  • 1
    http://stackoverflow.com/questions/10993181/defining-the-same-spring-bean-twice-with-same-name – OPK Dec 28 '15 at 17:47
  • Thanks, that helped us out to double confirm that for some reason, Spring is overriding A for B in some servers, and B for A in others. – Perimosh Dec 28 '15 at 18:09
  • @Kayaman closed this question without any reason, because the link he provided doesn't answer my question. I will edit my question, so please Kayaman, before closing it again, try to understand the problem. I know Spring overrides beans with same name. The problem is that it is not behaving deterministically. Same war file, deployed in 4 different servers, in the first two servers is overriding A for B, in the last two, B for A. Any question? Please let me know. – Perimosh Dec 28 '15 at 20:23
  • @Kayaman, I just edited, can you please re open it? Thanks! – Perimosh Dec 28 '15 at 20:49
  • I can imagine many reasons: classpath scanning returns config-annotated classes in an unspecified order, Configuration classes are stored in a HashMap which has no specified order, methods returned by Class.getMethods() are returned in an unspecified order, etc. etc. You should rather ask yourself: why should it use one over the other? Have you specified an order anywhere? Does Spring offer any guarantee in that regard? If it doesn't, you shouldn't assume anything. – JB Nizet Dec 28 '15 at 22:07
  • I'm aware of this is not a very helpful question, since the obvious solution is to not have beans with the same name. Although, I thought it was interesting to share it here in stackoverflow. @JBNizet I would assume your comment as a valid response, since your are right, the order or methods, fields, classes, etc, is not guaranted in order to have the same sequence every time we start up our Spring context. You can reply as an answer if you want please. – Perimosh Dec 29 '15 at 13:26

1 Answers1

1

I can imagine many reasons:

  • classpath scanning returns config-annotated classes in an unspecified order,
  • Configuration classes are stored in a HashMap which has no specified order,
  • methods returned by Class.getMethods() are returned in an unspecified order,
  • etc. etc.

You should rather ask yourself: why should it use one over the other? Have you specified an order anywhere? Does Spring offer any guarantee in that regard? If it doesn't, you shouldn't assume anything.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255