I'm trying to programatically add a inner bean to my application context within a jUnit test. I do not want to pollute my context by having the bean annotated with @Component
as it will affect all other tests that run within the same context.
public class PatchBaseImplTest extends TestBase{
/**
* Sample test patch to modify the schema
*/
public class SchemaUpdatePatch extends PatchBaseImpl {
public SchemaUpdatePatch(){
super();
}
@Override
public void applyPatch() throws Exception {
}
};
@Before
public void setUp(){
// add patch to context
beanRegistry.registerBeanDefinition("SchemaUpdatePatch", SchemaUpdatePatch.class, BeanDefinition.SCOPE_PROTOTYPE);
schemaPatch = (Patch)applicationContext.getBean("SchemaUpdatePatch", SchemaUpdatePatch.class);
}
}
where registerBeanDefinition is defined as:
public void registerBeanDefinition( String name, Class clazz, String scope){
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(clazz);
definition.setScope(scope);
definition.setAutowireCandidate(true);
definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
registry.registerBeanDefinition(name, definition);
}
I can see that the bean defn has been added to the application context, but when I try to retrieve the bean using appContext.getBean() Spring throws errors that the class is missing a constructor:
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.ia.system.patch.PatchBaseImplTest$SchemaUpdatePatch]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.ia.system.patch.PatchBaseImplTest$SchemaUpdatePatch.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:83)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1000)
... 35 more
Caused by: java.lang.NoSuchMethodException: com.ia.system.patch.PatchBaseImplTest$SchemaUpdatePatch.<init>()
at java.lang.Class.getConstructor0(Class.java:2800)
at java.lang.Class.getDeclaredConstructor(Class.java:2043)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:78)
... 36 more
I've tried adding a default constructor to the SchemaUpdatePatch class, but it does not seem to matter.
If however, I annotate it with @Component instead of adding it to the context programatically, and try to access it via applicationContext.getBean(), it works fine.
What is the correct way of adding this bean to the applicationContext programatically? Is my GenericBeanDefinition wrong? Am I missing something to specify what the constructor is?
Writing up this post was actually cathartic. Helped me find my bug/error. Have to make the inner class Static or Spring cannot instantiate it. Hopefully this may help someone else in the future.
ie:
/**
* Sample test patch to modify the schema
*/
static public class SchemaUpdatePatch extends PatchBaseImpl {
public SchemaUpdatePatch(){
super();
}
@Override
public void applyPatch() throws Exception {
}
};
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments