How to create a bean as instance of Interface Class - java

I have three classes 1)an Interface 2) A class which implements the interface 3) a static factory which return an instance second class as an instance Interface Class
public Interface MyInterface {
}
public class Myclass implements MyInterface {
}
public Class MyStaticFactory {
public static MyInterface getInstance() {
MyInterface myClassInstance = new Myclass();
return myClassInstance;
}
}
I want to create a bean of MyClass as an instance MyInterface. Mycode for that is
<bean id="staticFactory" class="MyStaticFactory">
</bean>
<bean id="myclass" class="MyInterface" factory-bean="staticFactory" factory-method="getInstance">
</bean>
But with the above code I am getting an exception
org.springframework.beans.factory.BeanCreationException: Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private MyInterface ; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [MyInterface] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at com.amazon.coral.reflect.instantiate.SpringInstantiatorFactory$1.newInstance(SpringInstantiatorFactory.java:175)
I am trying to access bean using the following code
#Autowired
private MyInterface MyclassInstance
Is It a valid thing to create a bean as as instance of InterfaceClass ? How can we load an instance of MyClass in a class variable of MyInterface using spring ?

You dont need to autowire any field as you have your own factory that will instantiate bean for you. Also you dont need to instantiate your factory class with static method in it. Instead you just can stay with:
<bean id="staticFactory" class="MyStaticFactory" factory-method="getInstance" />
Now let's say you have multiple implementation of MyInterface, you could do so by passing a parameter like:
<bean id="staticFactory" class="MyStaticFactory" factory-method="getInstance" scope="prototype">
<constructor-arg value="MyClass" />
</bean>
And in your factory class you could either use switch (from JDK 7) or if else ladder to check what's requested in parameter to method getInstance method and instantiate proper bean.
You could then do the following:
public static void main(String args[]) {
Application context = new ......
MyInterface myIface = context.getBean("staticFactory", MyInterface.class);
//myIface.mymethod();
}

My view on this is depending on the context, whether using XML based bean creation or using Java based "config"bean creation, the logic is pretty much the same.
You need to have a Class annotated with #Configuration if using Java configuration for you to create your beans, secondly, the Configuration class needs to be registered as a bean creator, i.e. the application context needs to be able to create and initialize the beans depending on their type (either Singleton or Prototype).
My configuration would look like this:
public Interface MyInterface {
void executeSomeMethod();
}
public class Myclass implements MyInterface {
#override
void executeSomeMethod(){
//some code executed here
}
}
The Configuration class would look something like this:
#Configuration
public MyConfigurationClass {
#Bean(name="someBeanName")
public MyInterface createBean() {
MyInterface bean = new Myclass();
return bean;
}
}
Assuming the MyConfigurationClass is registered in the application context, then using the bean would look something like:
#Component
public class SomeClassUsingTheBean {
#Autowired
MyInterface someBeanName;
public SomType method() {
someBeanName.executeSomeMethod();
}
}

Related

How to specify sub-dependency for AutoWired Beans

I have a Spring component defined like this:
#Component
public class SearchIndexImpl implements SearchIndex {
IndexUpdater indexUpdater;
#Autowired
public SearchIndexImpl(final IndexUpdater indexUpdater) {
Preconditions.checkNotNull(indexUpdater);
this.indexUpdater = indexUpdater;
}
}
along with two implementations of the IndexUpdater interface, like:
#Component
public class IndexDirectUpdater implements IndexUpdater, DisposableBean, InitializingBean {
}
#Component
public class IndexQueueUpdater implements IndexUpdater, DisposableBean, InitializingBean {
}
If I try to auto-wire SearchIndexImpl like this:
#Autowired
private SearchIndex searchIndex;
I get the following exception:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'IndexUpdater' available: expected single matching bean but found 2: indexDirectUpdater,indexQueueUpdater
which is expected since Spring cannot tell which IndexUpdater implementation to auto-wire for the indexUpdater parameter in the constructor of SearchIndexImpl. How do I guide Spring to the bean that it should use? I understand I can use the #Qualifier annotation, but that will hard-code the index updater to one of the implementation, while I want the user to be able to specify what index updater to use. In XML, I can do something like:
<bean id="searchIndexWithDirectUpdater" class="SearchIndexImpl">
<constructor-arg index="0" ref="indexDirectUpdater"/>
</bean>
How do I do the same using Spring's Java annotations?
Use the #Qualifier annotation to specify the dependency to use :
public SearchIndexImpl(#Qualifier("indexDirectUpdater") IndexUpdater indexUpdater) {
Preconditions.checkNotNull(indexUpdater);
this.indexUpdater = indexUpdater;
}
Note that #Autowired is not needed to autowire the arg constructor of a bean since Spring 4.
To answer to your comment.
To let the class that will use the bean to define the dependency to use you could allow it to define the IndexUpdater instance to inject in the container such as :
// #Component not required any longer
public class IndexDirectUpdater implements IndexUpdater, DisposableBean, InitializingBean {
}
// #Component not required any longer
public class IndexQueueUpdater implements IndexUpdater, DisposableBean, InitializingBean {
}
Declare the bean in a #Configuration class :
#Configuration
public class MyConfiguration{
#Bean
public IndexUpdater getIndexUpdater(){
return new IndexDirectUpdater();
}
The SearchIndexImpl bean will now resolve the dependency thanks to IndexUpdater getIndexUpdater().
Here we use #Component for one bean and #Bean for its dependency.
But we could also allow a full control on the beans to instantiate by using only #Bean and by removing #Component on the 3 classes :
#Configuration
public class MyConfiguration{
#Bean
public IndexUpdater getIndexUpdater(){
return new IndexDirectUpdater();
}
#Bean
public SearchIndexImpl getSearchIndexFoo(){
return new SearchIndexImpl(getIndexUpdater());
}

Property injection in the base class does not work

My problem is that a bean is not being injected in the base class. I read many questions and answers about this topic but none did really help me.
I have an abstract base class with a property that shall be injected:
public abstract class AbstractResearchService<R extends ResearchResult, S extends PredictionResult> {
#EJB(lookup = ResearchManager.JNDI_BINDING)
private ResearchManager researchManager;
protected R submit(final ResearchQuery query) {
// researchManager is null here
}
The inheriting child class is a stateless bean implementing a remote interface:
#Stateless
#Remote(VoyageResearchService.class)
#WebService(...)
public class VoyageResearchServiceBean extends AbstractResearchService<VoyageResearchResult, VoyagePredictionResult>
implements VoyageResearchService {
#Override
public VoyageResearchResult submitQuery(final VoyageResearchQuery query) {
return submit(query);
}
}
This is the bean with its interface that shall be injected:
#Local
public interface ResearchManager {
String JNDI_BINDING = "java:global/omd-research-manager/ResearchManagerBean";
ResearchResult submitQuery(ResearchQuery query);
}
#Singleton
#Startup
#ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class ResearchManagerBean implements ResearchManager {
...
}
I searched for the issue and found multiple statements:
Dependency injection in base classes does work.
The inheriting class must be container managed to make injection work.
Can you confirm these statements?
Since my VoyageResearchServiceBean is being instantiated by the container (due to the #Stateless annotation) I am wondering why the injection doesn't work. When the submit() method is being called, the property researchManager is null.
What I have tried:
When I inject the researchManager into the child class it works fine. But since I only need it in the base class, I would like to inject it there.
When I try to use setter injection:
#Inject
public void setResearchManager(final ResearchManager researchManager) {
this.researchManager = researchManager;
}
I get the following error:
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type ResearchManager with qualifiers #Default
at injection point [BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedMethod] #Inject public com.in.omd.researchmanager.AbstractResearchService.setResearchManager(ResearchManager)
Can you please give me an advice what is going wrong here or what I am overlooking? Thanks for your help in advance.

Autowire Generic Type Spring 4.1.7 [duplicate]

This question already has answers here:
Singleton Bean instance by generic parameter
(2 answers)
Closed 7 years ago.
I'm working in Spring version greater than 4.
I've got beans with the same super-class configured using #Configuration
#Configuration
public Class ConfigClass{
#Bean
public Apple apple(){stuff to return apple bean}
#Bean
public Orange orange(){stuff to return orange bean}
}
I've got an bean which maybe composed of either one of those two beans
#Component
public Class FruitEater<ReturnType extends Fruit>{
#Bean
ReturnType fruit;
}
And I get this beautiful ambiguity error message:
No qualifying bean of type [fruit] is defined: expected single matching bean but found 2: appleInjection,orangeInjection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: fruiteater.bean; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [fruit] is defined: expected single matching bean but found 2: apple,orange
My thinking is that since the ReturnType should be resolved at compile-time, spring should be able to Autowire based on the Generic Type. I've heard of the Spring's ResolvableType but I'm not sure how I can leverage that as I'm still pretty new to Spring.
Is there a way to resolve this and keep my FruitEater a generic FruitEater?
Thanks, in advance.
You've declared a singleton (default) FruitEater bean. Singleton beans are (YMMV) eagerly initialized.
In your case, Spring sees a bean definition for the type FruitEater, but that's it. There's no parameterization (argument for ReturnType), there's no hint for what should be injected into fruit. There's no way for it to pick between the two Apple and Orange beans.
Presumably, if, instead of a singleton, you had declared FruitEater with a prototype scope (or something similar) and had injection targets like
#Autowired
private FruitEater<Apple> fruitEater;
the bean to be injected would be created at injection time and there would be enough type information to create it and inject its field, ie. an Apple bean in this example.
This isn't currently supported.
One solution is to remove the FruitEater bean declaration (the #Component) and instead provide appropriate parameterized subtypes
#Component
class OrangeEater extends FruitEater<Orange> {
}
class FruitEater<ReturnType extends Fruit> {
#Autowired
protected ReturnType fruit;
}
Spring is now smart enough, with the type information provided in the extends clause, to create the OrangeEater bean and inject an Orange in its fruit field.
Complete example
public class Sample {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigClass.class);
System.out.println(ctx.getBean(Injected.class).orangerEater);
System.out.println(ctx.getBean(Injected.class).appleEater);
}
#Component
static class Injected {
#Autowired
FruitEater<Orange> orangerEater;
#Autowired
FruitEater<Apple> appleEater;
}
}
#Configuration
#ComponentScan
class ConfigClass {
#Bean
public Apple apple() {
return new Apple();
}
#Bean
public Orange orange() {
return new Orange();
}
}
class Fruit {
}
class Apple extends Fruit {
}
class Orange extends Fruit {
}
#Component
class AppleEater extends FruitEater<Apple> {
}
#Component
class OrangeEater extends FruitEater<Orange> {
}
class FruitEater<ReturnType extends Fruit> {
#Autowired
protected ReturnType fruit;
}
Alternatively, ditch the component scanning. Use constructor injection.
public FruitEater(ReturnType fruit) {
this.fruit = fruit;
}
then declare the beans explicitly
#Bean
public FruitEater<Apple> appleEater() {
return new FruitEater(apple());
}

SpringBeanAutowiringInterceptor - Configure to autowire by name instead of by type?

I'm using a SpringBeanAutowiringInterceptor in an EJB3 stateless session bean, as described in the Spring documentation.
#Stateless
#Interceptors(SpringBeanAutowiringInterceptor.class) // Allows spring injection for its setter methods
public class MyClassImpl extends MyAbstractClass implements MyClass
{
....
#Autowired
public void setMyCustomService2(MyService svc) {
this.service = svc;
}
And in SpringConfig.xml:
<bean id="myCustomService1" class="...MyService"/>
<bean id="myCustomService2" class="...MyService"/>
When Spring tries to autowire this I get
No unique bean of type [...MyService ] is defined:
expected single matching bean but found 2: [myCustomService1 , myCustomService2]
Unfortunately, it seems EJB autowiring defaults to byType mode, and I can't find a way to change it to byName mode.
Is this possible, and if so, how?
Have you tried with a Qualifier?
#Autowired
#Qualifier("myCustomService1")
public void setMyCustomService2(MyService svc) {
this.service = svc;
}

spring annotation NullPointerException

#Component
public class AnnotationTest extends TestCase{
ServiceTest serviceTest;
#Autowired(required=false)
public void setServiceTest(ServiceTest serviceTest) {
this.serviceTest = serviceTest;
}
public void testAnnotation () {
new ClassPathXmlApplicationContext(new String[]{"/com/test/spring/ioc/beans.xml"});
serviceTest.annotationTest("testName", "testPassword");
}
error:
Exception in thread "main" java.lang.NullPointerException
at com.test.spring.ioc.AnnotationTest.invokeIoC(AnnotationTest.java:16)
at com.test.spring.ioc.AnnotationTest.main(AnnotationTest.java:13)
service class:
#Service
public class ServiceTestImpl implements ServiceTest{
#Autowired
AnnotationDAO annotationDAO;
public List<String> annotationTest(String name, String pssword) {
return annotationDAO.annotationTest(name, pssword);
}
}
DAO class:
#Repository("AnnotationDAO")
public class AnnotationDAOImpl implements AnnotationDAO{
public List<String> annotationTest(String name, String pssword) {
List<String> list = new ArrayList<String>();
list.add("Test 1");
list.add("Test 2");
return list;
}
}
beans.xml:
<bean id="service" class="com.test.spring.ioc.service.ServiceTestImpl"/>
<context:annotation-config />
<context:component-scan base-package="com.test.spring" />
how can I solve this?
EDIT:
it was giving warning msg:
WARNING: Autowired annotation is not supported on static methods: public static void
com.test.spring.ioc.AnnotationTest.setServiceTest(com.test.spring.ioc.service.ServiceTest)
i moved to junit test instead of java main method as shown above by adding #Component( i am not sure this is required).
Now i am getting new error as:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'annotationTest': Injection of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not autowire field:
com.test.spring.ioc.service.ServiceTest com.test.spring.ioc.AnnotationTest.serviceTest;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
unique bean of type [com.test.spring.ioc.service.ServiceTest] is defined: expected single
matching bean but found 2: [service, serviceTestImpl] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProce ssPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
The problem is, you are defining the same bean twice:
Once explicitly:
<bean id="service" class="com.test.spring.ioc.service.ServiceTestImpl"/>
And once through Component Scanning:
<context:component-scan base-package="com.test.spring" />
Get rid of one of them and it will work.
BTW: you don't need to instantiate the container yourself when testing, just use the Spring TestContext Framework:
#RunWith(SpringJUnit4ClassRunner.class)
// ApplicationContext will be loaded from "/applicationContext.xml"
// and "/applicationContext-test.xml"
// in the root of the classpath
#ContextConfiguration({"/applicationContext.xml",
"/applicationContext-test.xml"})
public class MyTest {
// class body...
}
And of course, with JUnit 4.x you should no longer extend from TestCase, but use annotated methods instead:
#Test
public void testAnnotation () {
serviceTest.annotationTest("testName", "testPassword");
}
The AnnotationTest class is not instantiated by spring, so Spring never has a chance to inject the serviceTest dependency:
You can either explicitly get you bean:
public static void main(String[] args) {
ApplicationContext ctx =
new ClassPathXmlApplicationContext(
new String[]{"/com/test/spring/ioc/beans.xml"});
serviceTest = ctx.getBean(ServiceTest.class);
invokeIoC();
}
or you could tell annotate your AnnotationTest class with #Component so that an instance will be created by the component-scan. Note, though I think that would be a bit of a hack as you'll be instantiating an AnnotationTest object and never use it, so I'd do away with the autowiring in the main and use getBean...
EDIT:
In order to do the autowiring of a static field, you'd also have to fool spring into thinking that serviceTest is not actually static (again, I don't think that's a good idea):
#Component
public class AnnotationTest {
static ServiceTest serviceTest;
...
#Autowired
public void setServiceTest(ServiceTest serviceTest) {
AnnotationTest.serviceTest = serviceTest;
}
}

Categories

Resources