mitali
mitali

Reputation: 97

How to keep duplicate spring bean in container. [ConflictingBeanDefinitionException]

I am working on an application which uses some third java libraries which are build on top of core spring framework. Now when my application uses these libraries I am getting ConflictingBeanDefinitionException because two libraries have the same bean name. Now as these libraries are external I cannot change the bean name. Is there a way by which in my application I can use both the beans in same container?

 @Component
    class ApplicationLogic {

    @Autowire FetcherAndResolver fetchFromLibraryA;
    @Autowire FetcherAndResolver fetchFromLibraryB;  //Because both bean names are same here comes the exception.
}

Upvotes: 1

Views: 2655

Answers (2)

Denis Rodin
Denis Rodin

Reputation: 319

First component from third java libraries:

package com.example.component1;

import org.springframework.stereotype.Component;

@Component
public class MyComponent {
    public String makeSomeWork() {
        return "Component 1";
    }
}

Second component from third java libraries:

package com.example.component2;

import org.springframework.stereotype.Component;

@Component
public class MyComponent {
    public String makeSomeWork() {
        return "Component 2";
    }
}

Controller:

package com.example.controller;

import com.example.component1.MyComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Autowired
    private MyComponent myComponent;

    @Autowired
    private com.example.component2.MyComponent myComponent2;

    @RequestMapping("/components")
    public String getComponents() {
        return myComponent.makeSomeWork() + "_" + myComponent2.makeSomeWork();
    }
}

Upvotes: 1

Gaurav
Gaurav

Reputation: 3749

I think this would require a bit of a hack.

First of all, structure your packages in a way so that external beans are not added automatically.

So, if external class is located in package a.b. Then you have to move your own classes in either a.c or a.b.c. THis will ensure that you are in control of how beans are initialized.

Once this is done, you can add a @Configuration class where you can create Beans of both type:

@Configuration
public class ExternalBeanConfiguration {

   @Bean("internal-resolver" )
   public FetcherAndResolver internalResolver() {
       return new FetcherAndResolver();
   }

   @Bean("external-resolver" )
   public a.b.c.FetcherAndResolver externalResolver() {
       return new a.b.c.FetcherAndResolver();
   }

}

I am assuming that FetcherAndResolver is a class rather than an interface. If it is an interface, it is easier to do it as you won't have to use fully-qualified name for classes.

Then you can simply autowire with qualifiers.

@Component
public class SomeComponent {

    @Qualifier( "internal-resolver" )
    FetcherAndResolver internalResolver;

    @Qualifier( "external-resolver" )
    FetcherAndResolver externalResolver;

}

Upvotes: 1

Related Questions