Java - Spring
I have spring factory bean creation in .xml
<bean id="concurrentHashMapFactory" class="com.abc.HashMapFactory.ConcurrentHashMapFactory"/>
<bean id="idCorpMap" factory-bean="concurrentHashMapFactory" factory-method="createIdCorpMapInstance"/>
but i want to convert above .xml statement into equivalent using annotation any help ?
Roughly like this (I didn't test it)..
#Configuration
public class Config {
#Bean(name = "concurrentHashMapFactory")
public ConcurrentHashMapFactory createConcurrentHashMapFactory() {
return new ConcurrentHashMapFactory();
}
#Bean(name = "idCorpMap")
public IdCorpMapType createIdCorpMap(ConcurrentHashMapFactory factory) {
return factory.createIdCorpMapInstance();
}
}
Related
I have a spring boot with the main class with #SpringBootApplication (so it is has implied tags #EnableAutoConfiguration, #ComponentScan, and #Configuration).
What happens if I create another class with annotation #Configuration and #ComponentScan? Do I create another container of beans? In this way the beans are duplicates? Is a good way create more #Configuration class? #Configuration create a container of beans? If yes the two containers share the bean?
I need to understand these question.
What happens if i create another class with annotation #Configuration and #Component Scan?
that is ok, is perfectly normal..
I create another container of beans ? In this way the beans are Duplicates ?
If you create two beans of the same type, you will have an error when the app is starting.. you need to declare one of them as #Primary
you can define multiple #configuration in spring boot as
Matias Elorriaga mentioned.
#Configuration equals to <beans> tag in spring xml which hold many <bean> (equal to #Bean) inside of this, same a class with annotation #Configuration say hey you can define multiple beans inside me
e.f:
#Configuration
public class AppConfig {
#Bean
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("message");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public Validator validator() {
final LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
localValidatorFactoryBean.setValidationMessageSource(messageSource());
return localValidatorFactoryBean;
}
#Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
sessionLocaleResolver.setDefaultLocale(Locale.ENGLISH);
return sessionLocaleResolver;
}
}
Also if you have 2 different class with same type of Bean
e.g. class: SpringConfigA have Composite bean
#Configuration
public class SpringConfigA {
#Bean
public Composite composite() {
Composite c = new Composite();
return c;
}
}
and another class SpringConfigB have same Composite bean
#Configuration
public class SpringConfigB {
#Bean
public Composite composite() {
Composite c = new Composite();
return c;
}
}
then it's will throw the exception of during bean initialization because of ambiguity with Composite beans so
here you can use Qualifier to fixed this issue
so
#Configuration
public class SpringConfigA {
#Bean
#Qualifier("compositeA")
public Composite composite() {
Composite c = new Composite();
return c;
}
}
and another class SpringConfigB have same Composite bean with Qualifier name "compositeB"
#Configuration
public class SpringConfigB {
#Bean
#Qualifier("compositeB")
public Composite composite() {
Composite c = new Composite();
return c;
}
}
yes you can register a bean using #ComponentScan by either registering configuration bean in dispatcher servlet or by importing a seperate configuration bean which is lready registered in spring container.
suppose you have Config class in which you are scanning component-
#ComponentScan(basePackages = {"xyz"})
#Configuration
public class Config {
....
}
To register Config in container you must do-
new AnnotationConfigWebApplicationContext().register(Config .class);
Or
#Configuration
#Import({MvcConfig.class})
public class AnotherConfig {
....
}
I have a bean defined similar to below in my spring.xml. I am converting all my beans into annotation based. How can I inject the attributes in the below listed bean?
<bean
id = "dataPropDao"
class = "com.service.ref.DataPropDaoImpl"
p:dataSource-ref = "data.dataSource"
p:sql = "PROFILE_PKG.GetProfileByCode"
p:function = "true"/>
"p" namespace is used to set bean properties using setters. Equivalent of your code in Java config would be similar to:
#Configuration
class MyConfig {
#Bean
DataPropDaoImpl dataPropDao(DataSource datasource) {
DataPropDaoImpl dao = new DataPropDaoImpl();
dao.setDataSource(datasource);
dao.setSql("PROFILE_PKG.GetProfileByCode");
dao.setFunction(true);
return dao;
}
}
I am trying to configure multiple JPA entity/transaction managers within the same application context using Spring's #Configuration class.
When the context loads, Spring is having difficulties auto-wiring the beans because they implement the same interfaces.
Unfortunately, I'm using legacy code so I can't auto-wire the beans directly and use the #Qualifier annotations, which is why I'm trying to do it using the configuration class.
Within a #Bean declaration, is there any way to qualify which bean should be injected? I thought that using a direct method call would be enough, but it typically results in errors such as
NoUniqueBeanDefinitionException: No qualifying bean of type
[javax.sql.DataSource] is defined: expected single matching bean but
found 4
Here's an example of what I'm trying to do below:
#Configuration
public class ApplicationConfig {
#Bean(name = "transactionManager1")
public PlatformTransactionManager transactionManager1() {
return new JpaTransactionManager(entityManagerFactory1());
}
#Bean(name = "entityManagerFactory1")
public EntityManagerFactory entityManagerFactory1() {
...
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource1());
...
}
#Bean(destroyMethod = "")
#ConfigurationProperties(prefix = "datasource.test1")
public JndiObjectFactoryBean jndiObjectFactoryBean1() {
return new JndiObjectFactoryBean();
}
#Bean(name = "dataSource1")
public DataSource dataSource1() {
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiObjectFactoryBean1().getJndiName());
}
#Bean(name = "transactionManager2")
public PlatformTransactionManager transactionManager2() {
return new JpaTransactionManager(entityManagerFactory2());
}
#Bean(name = "entityManagerFactory2")
public EntityManagerFactory entityManagerFactory2() {
...
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(dataSource2());
...
}
#Bean(destroyMethod = "")
#ConfigurationProperties(prefix = "datasource.test2")
public JndiObjectFactoryBean jndiObjectFactoryBean2() {
return new JndiObjectFactoryBean();
}
#Bean(name = "dataSource2")
public DataSource dataSource2() {
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiObjectFactoryBean2().getJndiName());
}
I suppose I could try to inject the beans directly via the Spring context's getBean() method, but is there a cleaner way of doing this?
I'm not too familiar with the #Primary annotation, but based on what I've read I don't know how spring would autowire the secondary data source in this case since it looks like it would always pick the beans with #Primary first.
If you cannot change the injection sites to add qualifiers, then you're going to have to create a delegating DataSource based on some logic (which you haven't detailed in the question).
Something like this.
#Primary #Bean
public DelegatingDataSource delegatingDataSource(List<DataSource> sources) {
return new DelegatingDataSource() {
#Override
public DataSource getTargetDataSource() {
// decide which dataSource to delegate to
return sources.get(0);
}
}
}
I've used DelegatingDataSource, but that may not be able to provide what you need. You may need to get more advanced with some kind of interceptor/aspect to get details of the caller on which to base the DataSource selection.
However it's implemented, you need to specify a #Primary bean and use it as a proxy.
What is the equivalent of
<bean id="myClass" class="com.xxx.MyClass" factory-method="aspectOf" />
when using a Spring 4 #Bean-annotated method?
There is no annotation for the factory method, but you can use the #Configuration and #Bean annotations
#Configuration
public class MyClass {
#Bean
public MyClass myObject() {
return MyStaticFactory.getObject();
}
}
MyStaticFactory does not require any Spring annotations.
Use #Configurable with <context:spring-configured>
How can I get Spring to instantiate a bean that does not have a no-argument constructor? I'm using java-config (not xml-config). It seems to work using XML -but shouldn't I be able to do the same thing with annotations somehow?
Straight from the tutorial, the following example is the equivalent in xml-config:
<bean id="exampleBean" class="examples.ExampleBean">
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
</bean>
It also mentions the use of #ConstructorProperties annotation, which I've tried to use -but I can't get it to work. I keep getting a BeanInstantiationException.
#Configuration
public class MyConfiguration {
#Bean
public ExampleBean exampleBean() {
return new ExampleBean(7500000, 42);
}
}
Or:
#Configuration
#PropertySource(value = { "my.properties" })
public class MyConfiguration {
#Value("{prop.value1}")
private int value1;
#Value("{prop.value2}")
private int value2;
#Bean
public ExampleBean exampleBean() {
return new ExampleBean(value1, value2);
}
}
also from the link below
http://docs.oracle.com/javase/6/docs/api/java/beans/ConstructorProperties.html
what i understood is, #ConstructorProperties annotation is not to be used as a replacement for your xml-config.
Can you use #Autowired with #Qualifier, like in another SO Article?
You can use #Autowired or #Inject