Inject a p namespace attribute using spring annotations - java

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;
}
}

Related

Spring autowire custom #ConfigurationProperties object by prefix

I would like to achieve not-trivial bean injection implementation.
I have a custom properties file:
#Getter
#Setter
#ConfigurationProperties
public class DatabaseProperties {
private String url;
private String username;
private String password;
}
I Here is the configuration file:
#Configuration
#EnableConfigurationProperties(DatabaseProperties.class)
public class DBConfig {
#Bean
#ConfigurationProperties(prefix = "datasource.database1")
public JdbcTemplate jdbcTemplateDatabase1(DatabaseProperties databaseProperties) {
DataSource dataSource = new DriverManagerDataSource(
databaseProperties.getUrl(),
databaseProperties.getUsername(),
databaseProperties.getPassword());
return new JdbcTemplate(dataSource);
}
#Bean
#ConfigurationProperties(prefix = "datasource.database2")
public JdbcTemplate jdbcTemplateDatabase2(DatabaseProperties databaseProperties) {
DataSource dataSource = new DriverManagerDataSource(
databaseProperties.getUrl(),
databaseProperties.getUsername(),
databaseProperties.getPassword());
return new JdbcTemplate(dataSource);
}
}
The goal I want to achieve is to instantiate a new DatabaseProperties instance based on prefix.
There are two possible solutions:
create two beans of type DatabaseProperties using corresponding prefixes and two JdbcTemplate beans where parameter is qualified DatabaseProperties bean accordingly.
in each JdbcTemplate bean provide 3 parameters (String url, String username, String password) and inject them through #Value
BUT Is it possible to get rid of creating DatabaseProperties beans for each JdbcTemplate or using #Value ?
You don't need create a DatabaseProperties. Spring already does this for us on datasources and proprierties variable
#Configuration
public class ConfigDataSource {
#Bean("datasource-1") // this name will qualify on #autowired
#ConfigurationProperties(prefix="spring.datasource.yourname-datasource-1") // this is the name for the prefix for datasource on .properties settings
public DataSource dataSourcePostgres() {
return DataSourceBuilder.create().build();
}
#Bean("datasource-2") // this name will qualify on #autowired
#ConfigurationProperties(prefix="spring.datasource.yourname-datasource-2") // this is the name for the prefix for datasource on .properties settings
public DataSource dataSourceMySql() {
return DataSourceBuilder.create().build();
}
}
.properties
# Its required use the same name declared in bean
spring.datasource.yourname-datasource-1.url=...
spring.datasource.yourname-datasource-1.jdbcUrl=${spring.datasource.yourname-datasource-1}
spring.datasource.yourname-datasource-1.username=user
spring.datasource.yourname-datasource-1.password=pass
spring.datasource.yourname-datasource-1.driver-class-name=your.driver
spring.datasource.yourname-datasource-2.url=...
spring.datasource.yourname-datasource-2.jdbcUrl=${spring.datasource.yourname-datasource-2}
spring.datasource.yourname-datasource-2.username=user
spring.datasource.yourname-datasource-2.password=pass
spring.datasource.yourname-datasource-2.driver-class-name=your.driver
using on services
#Awtowired
#Qualifier("datasource-1")
private DataSource dataSource1;
#Awtowired
#Qualifier("datasource-2")
private DataSource dataSource2;
public testJdbcTemplate(){
// You can qualifier JdbcTemplate below on bean and not necessary need instance on service
JdbcTemplate jdbcTemplateDatasource1 = new JdbcTemplate(dataSource1);
JdbcTemplate jdbcTemplateDatasource2 = new JdbcTemplate(dataSource2);
}
To my knowledge, there is no way around the fact that if you want to have access to multiple databases Spring will not be able to do the magic for you. You will need to create the two JdbcTemplate Spring-managed beans and then inject them where needed using the #Qualifier annotation.
This approach has two benefits:
It actually work;
You are explicit about what you are doing. A Spring application has already a good load of magic happening in there, so we might want to avoid some additional one when we need something a little bit more custom and that is not that complex to achieve.

Java Spring Annotation equivalent of reference

I am attempting to move from the XML configuration, and am confused about what the equivalent of
<spring:property name="beanName" ref="beanToReference">
I thought it would be something similar to the #Value("${Property.Value}") annotation
Any help would be much appreciated!
You can reference it like this:
#Bean
MyAnotherBean myAnotherBean() {
return new MyAnotherBean();
}
#Bean
MyBean myBean(MyAnotherBean beanToReference) {
final MyBean myBean = new MyBean();
myBean.setAnotherBean(beanToReference);
return myBean;
}
Or like this (in case both beans in the same configuration class):
#Bean
MyAnotherBean myAnotherBean() {
return new MyAnotherBean();
}
#Bean
MyBean myBean() {
final MyBean myBean = new MyBean();
myBean.setAnotherBean(myAnotherBean());
return myBean;
}
Lets assume that you have two beans like this
#Compenent
public class SampleBeanOne{
}
#Compenent
public class SampleBeanTwo{
}
and you want to use them like you define in your xml file in the main component
#Compenent
public class MainComponent{
#Autowired
private SampleBeanOne sampleBeanOne;
#Autowired
private SampleBeanTwo sampleBeanTwo;
}
First things first you should enable #Autowired annotation like this
<beans
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
</beans>
Once annotation injection is enabled, autowiring can be used on properties, setters, and constructors.
By default, Spring uses #Autowired by type. If you have more than one beans of the same type, the framework will throw an exception indicating that more than one bean is available for autowiring. for resolving that you can use #Qualifier annotation.
Spring uses the bean name as a default qualifier value so if you use it like this :
#Autowired
private SampleBeanOne myBean;
it assumes that you have MyBean implementation of SampleBeanOne and try to fine and inject it on your component construction.

Create Bean and Name using #Bean annotation and Spring EL Expressions

I try to create a Bean and its name using #Bean(value="") attribute. The value should be set with Spring EL Expression.
#Configuration
public class TestClass{
#Autowired
TestProperty testProperty
#Bean(value="#{testProperty.name}")
public MyBean myBean(){
MyBean b = new MyBean();
return b;
}
}
My testProperty is correct injected and holds a value for example testProperty.name = "Bean1"
At the moment my created Bean just have the EL expression as its name: {"bean":"#{testProperty.name}"
How can I give MyBean its name from testProperty.name?
You can use property value for cron attribute of #Scheduled annotation:
#Scheduled(cron = "${testProperty.name}")
So no need for SpEL at all.

java Spring factory-bean factory-method autowiring

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();
}
}

Spring JavaConfig for java.util.Properties field

Can you please tell me how to use Spring Javaconfig to directly load/autowire a properties file to a java.util.Properties field?
Thanks!
Later edit - still searching for the answer:
Is it possible to load with Spring JavaConfig a properties file directly into a java.util.Properties field?
The XML base Way:
in spring config:
<util:properties id="myProperties" location="classpath:com/foo/my-production.properties"/>
in your class:
#Autowired
#Qualifier("myProperties")
private Properties myProperties;
JavaConfig Only
It looks like there is an annotation:
#PropertySource("classpath:com/foo/my-production.properties")
Annotating a class with this will load the properties from the file in to the Environment. You then have to autowire the Environment into the class to get the properties.
#Configuration
#PropertySource("classpath:com/foo/my-production.properties")
public class AppConfig {
#Autowired
private Environment env;
public void someMethod() {
String prop = env.getProperty("my.prop.name");
...
}
I do not see a way to directly inject them into the Java.util.properties. But you could create a class that uses this annotation that acts as a wrapper, and builds the properties that way.
declare a PropertiesFactoryBean.
#Bean
public PropertiesFactoryBean mailProperties() {
PropertiesFactoryBean bean = new PropertiesFactoryBean();
bean.setLocation(new ClassPathResource("mail.properties"));
return bean;
}
Legacy code had following config
<bean id="mailConfiguration" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="classpath:mail.properties"/>
</bean>
Converting that to Java config is super easy as shown above.
It is an old subject but there are also a more basic solution.
#Configuration
public class MyConfig {
#Bean
public Properties myPropertyBean() {
Properties properties = new Properties();
properties.load(...);
return properties;
}
}
There is also this approach for injecting properties directly using xml configurations. The context xml has this
<util:properties id="myProps" location="classpath:META-INF/spring/conf/myProps.properties"/>
and the java class just uses
#javax.annotation.Resource
private Properties myProps;
Voila!! it loads.
Spring uses the 'id' attribute in xml to bind to the name of variable in your code.
You can try this
#Configuration
public class PropertyConfig {
#Bean("mailProperties")
#ConfigurationProperties(prefix = "mail")
public Properties getProperties() {
return new Properties();
}
}
Make sure to define properties in application.properties
application.yml:
root-something:
my-properties:
key1: val1
key2: val2
Your type-safe pojo:
import java.util.Properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
#ConfigurationProperties(prefix = "root-something")
public class RootSomethingPojo {
private Properties myProperties;
Your container configuration:
#Configuration
#EnableConfigurationProperties({ RootSomethingPojo .class })
public class MySpringConfiguration {
This will inject the key-value pairs directly into the myProperties field.

Categories