Reputation: 13
I'm trying to write custom JSF converter for entity classes. I use spring-data and spring-boot in my project.
Know i have a lot of classes looks like `this:
@Component("myFirstConverter")
class MyFirstConverter implements Converter {
@Autowired
private MyFirstRepository myFirstRepository;
@Override
public Object getAsObject(FacesContext context, UIComponent component,
String value) {
return myFirstRepository.findOne(Long.parseLong(value));
}
//...
}
I created custom class EntityConverter. It works with CrudRepository. But i can't understand how to programmatically create array of beans and inject into each bean corresponded repository.
Know I tried to write @Configuration class with this code:
@Configuration
class MyConfig extends WebMvcConfigurerAdapter
@Bean
public static BeanFactoryPostProcessor registerConverters(ApplicationContext context) {
Map<String, Class<? extends CrudRepository>> converterBeans = new HashMap<>();
converterBeans.put("firstEntity", firstEntityRepository.class);
converterBeans.put("secondEntity", secondEntity.class);
return factory -> {
for (val entry : converterBeans.entrySet()) {
CrudRepository bean = context.getBean(entry.getValue()
factory.registerSingleton(entry.getKey()
.concat("Converter"), new EntityConverter(
entry.getKey(), bean));
}
};
But it doesn't work. Application failed in initialization.
19:07:59.546 [WARN ] o.s.c.support.AbstractApplicationContext:551 -
Exception encountered during context initialization - cancelling
refresh attempt:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'myFirstRepository': Cannot create inner bean
'(inner bean)#1fdfafd2' of type
[org.springframework.orm.jpa.SharedEntityManagerCreator] while setting
bean property 'entityManager'; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name '(inner bean)#1fdfafd2': Cannot resolve
reference to bean 'entityManagerFactory' while setting constructor
argument; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fe46103]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fe46103.<init>()Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fumoRepository': Cannot create inner bean '(inner bean)#1fdfafd2' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#1fdfafd2': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration$$EnhancerBySpringCGLIB$$fe46103]: No default constructor found; nested exception is java.lang.NoSuchMethodException:
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfigurati
on$$EnhancerBySpringCGLIB$$fe46103.<init>()
UPD:
Answer WiPU allowed to solve the problem. I changed my registerConverters method like this:
@Configuration
class MyConfig extends WebMvcConfigurerAdapter
@Bean
public static BeanFactoryPostProcessor
registerConverters(ApplicationContext context) {
Map<String, Class<? extends CrudRepository>> converterBeans = new HashMap<>();
converterBeans.put("firstEntity", firstEntityRepository.class);
converterBeans.put("secondEntity", secondEntity.class);
return factory -> {
BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry)
factory;
for (val entry : converterBeans.entrySet()) {
BeanDefinitionBuilder b =
BeanDefinitionBuilder.genericBeanDefinition(EntityConverter.class)
.addPropertyReference("repository", entry.getKey().concat("Repository"))
;
beanFactory.registerBeanDefinition(entry.getKey().concat("Converter"), b.getBeanDefinition());
factory.registerSingleton(entry.getKey()
.concat("Converter"), new EntityConverter(
entry.getKey(), bean));
}
};
Upvotes: 1
Views: 1151
Reputation: 443
Spring is failing to instantiate your Repository Beans according to your shown Exception.
A BeanFactoryPostProcessor
is called after all bean definitions are loaded, but not yet instantiated. You can find details here: Link
You can try to register you beans later in the process when all other beans are already correctly instantiated. You can find some details here: Link
At this point all your Repository should be already correctly instantiated and you can just add your additional EntityConverter
As alternative, if you need to inject your EntityConverter
into other beans, you can register BeanDefinitons
. Then Spring will instantiate your bean when the repositories are already created. Link to JavaDoc
regards, WiPu
Upvotes: 1