5

I am fairly new to Sprint and am using Spring 3.x and roo1.1.1 for my application.

I have multiple implementation of an interface which would be @Autowired into other different classes. I would only be able to decide which implementation to go with at the runtime. This should be achieved with like a factory pattern.

public interface SomeInterface {
    public void doSomething();
}

Implementation 1.

public class SomeOb implements SomeInterface {
    public void doSomething() {
        //Do something for first implementation here
    }
}

Implementation 2.

public class SomeOtherOb implements SomeInterface {
    public void doSomething() {
        //Do something for first implementation here
    }
}

Now in my service i needed this Autowired like

@Service 
public class MyService {

   @Autowired
   SomeInterface ob;
   //Rest of the code here

}

1) The logic to choose which implementation to be Autowired is only know runtime, so i cannot use the @Qualifier annotation to qualify this. 2) I tried to create a FactoryBean like

public class SomeFactoryBean implements FactoryBean<SomeInterface> {
@Override
public SomeInterface getObject() throws Exception {
    if(/*Somecondition*/) {
        return new SomeOb();
    } else
        return new SomeOtherOb();
}

@Override
public Class<? extends SomeInterface> getObjectType() {
    if(/*Somecondition*/) {
        return SomeOb.class;
    } else
        return SomeOtherOb.class;
}

@Override
public boolean isSingleton() {
    return false;
}
}

In the applicationContext.xml i have the tag mentioned.

When i run the webserver i run into an error like

No unique bean of type [com.xxxx.xxxx.SomeInterface] is defined: expected single matching bean but found 3: [xxxx, xxxxxxx, xxxxFactory]

Can anyone please help me to resolve this issue. If i am not doing this right please direct me to do this the right way.

Thanks and appreciate any help, jjk

jjk
  • 81
  • 1
  • 1
  • 5

2 Answers2

3

Thanks for the suggestion. I was able to solve the problem with help from a colleague. What i was doing wrong

  1. I had the implementation of the SomeInterface with @Service. So this was picked up by the spring scanner and added to the bean.
  2. During trial and error i removed the @Component annotation from by FactoryBean implementation.

After making these changes it worked like a charm.

Devin Burke
  • 13,642
  • 12
  • 55
  • 82
jjk
  • 81
  • 1
  • 1
  • 5
0

return true from isSingleton() if you only need one implementation of the bean for a given instance of your application

But I question your design.

I would always use properties files to switch out implementations like this. I once had to implement CAPTCHA integration for a site. We were prototyping with the JCaptcah and ReCAPTCHA APIs. I created a new interface that contained just the functionality we needed and then created implementations for both APIs. Using a placeholders in the Spring configuration file and Maven profiles, we could switch out the implementation class at compile time or deployment time, for example, mvn jetty:run -DcaptchaImpl=recaptcha or -DcaptchaImpl=jcaptcha.

Without knowing the task that you want to accomplish, it's hard to provide more advice.

les2
  • 14,093
  • 16
  • 59
  • 76