Baga
Baga

Reputation: 1442

Factory method getting new instance from DI Container

I'm trying to create a factory method in a Java Spring boot application. But instead of manually instantiating an object I would like to get it from DI container. Is that possible?

public interface PaymentService {
    public Payment createPayment(String taskId);
}

public class PaymentServiceImplA implements PaymentService {
    private JobService jobService;
    private ApplicationService applicationService;
    private UserService userService;
    private WorkService workService;

    @Inject
    public PaymentServiceImplA(JobService jobService, UserService userService, WorkService workService,
        ApplicationService applicationService) {
        this.jobService = jobService;
        this.applicationService = applicationService;
        this.userService = userService;
        this.workService = workService;
        //removed other constructor injected dependencies
    }
}

Getting error "No qualifying bean of type 'com.test.mp.service.PaymentServiceImplA' available" when getBean method is called.

@Configuration
public class PaymentFactory {

    private ApplicationContext applicationContext;

    @Inject
    public PaymentFactory(ApplicationContext applicationContext) {      
        this.applicationContext = applicationContext;
    }

    @Bean
    public PaymentService paymentService(){
        //Using getBean method doesn't work, throws error mentioned above             
        if(condition == true) 
            return applicationContext.getBean(PaymentServiceImplA.class);
        else
            return applicationContext.getBean(PaymentServiceImplB.class);

    }
}

Upvotes: 1

Views: 840

Answers (3)

Baga
Baga

Reputation: 1442

This is how I ended up solving this for now. By injecting the bean method with dependencies required to instantiate the implementation objects.

@Configuration
public class PaymentFactory {

    //private ApplicationContext applicationContext;

    public PaymentFactory() {      
        //this.applicationContext = applicationContext;
    }

    @Bean
    public PaymentService paymentService(JobService jobService, UserService userService
    , WorkService workService, ApplicationService applicationService){

        if(condition == true){
            return new PaymentServiceImplA(jobService, userService, workService,
    applicationService);
        }
        else {
            return new PaymentServiceImplB(jobService, userService, workService,
    applicationService);
        }
    }
}

Upvotes: 0

user3358994
user3358994

Reputation: 31

Yes it's possible with the help of ServiceLocatorFactoryBean. Infact if we write Factory code to create implementation object then in that implementation class class if we inject any repository or other objects then it will throw exception. The reason is if user is created object then for those object spring is not allowing to inject the dependency. So better give the responsibility of creating implementation object by factory pattern using Spring. Try with ServiceLocatorFactoryBean

Upvotes: 0

Naresh Kumar
Naresh Kumar

Reputation: 713

This could be solved after creating two more bean in the configuration file. i.e.

@Bean
public PaymentService paymentServiceA(){
 return new PaymentServiceImplA();
}

@Bean
public PaymentService paymentServiceB(){
 return new PaymentServiceImplA();
}

and the returning bean should be :

   @Bean
    public PaymentService paymentService(){            
        if(condition == true) 
            return paymentServiceA();
        else
            return paymentServiceB();

    }

Upvotes: 1

Related Questions