I'm working on a project in Spring using SpringMVC, i'm using the xml element <bean/> and i want to convert my code to #Bean
spring-bean.xml
<bean id="myDao" class="com.my.dao.EmployeImplDB" init-method="init"></bean>
<bean class="com.my.service.EmployeImplMetier" id="myMetier">
<property name="dao" ref="myDao"></property>
</bean>
how to convert xml to annotation #Bean?
You can write this way
#Repository
class EmployeImplDB{}
#Service
EmployeImplMetier{
#Autowired
EmployeImplDB myDao;
}
#Repository signifies that your bean is a DAO class
#Autowired injects dao class EmployeImplDB in the Service class
Like this:
#Bean(name = "myDao", initMethod = "init")
public EmployeDao myDao() {
EmployeDao eidb = new EmployeImplDB();
return eidb;
}
#Bean(name = "myMetier")
public Metier employeImplDB(EmployeDao myDao) {
Metier metier= new EmployeImplMetier(myDao);
return metier;
}
Note: Presuming that name of EmployeImplDB superclass (interface) is EmployeeDB.
Related
I have a class MyFactory which can create MyClass:
package com.mypackage
#Component
public class MyFactory{
#Bean
public MyClass createMyClass() {
return // magic class creation... ;
}
}
How to use that method to create a bean with xml?
<bean id="myClass" factory-method="com.mypackage.MyFactory.createMyClass"/>
doesn't work...
Remove the #Bean annotation from the factory method:
package com.mypackage;
#Component
public class MyFactory{
public MyClass createMyClass() {
return // magic class creation... ;
}
}
And then in XML:
<bean id="myClass" factory-bean="myFactory" factory-method="createMyClass"/>
If you also want the factory to be configured via XML, then remove the #Component annotation from class MyFactory and create it in XML as well:
<bean id="myFactory" class="com.mypackage.MyFactory"/>
<bean id="myClass" factory-bean="myFactory" factory-method="createMyClass"/>
See the documentation: Instantiation by Using an Instance Factory Method
I use generally xml configuration in my Spring project under the three files:
applicationContext.xml:
This file contains the main xml configuration: component scan, annotation-config and also an include of two other xml configuration files:
applicationContext-db.xml
This file contains all database beans: dataSource, SessionFactory, ...
applicationContext-security.xml
This file contains all spring security config.
I need to use also Spring Security ACL, for this I created a configuration class:
AclMethodSecurityConfiguration.java
package com.medkhelifi.tutorials.todolist.conf;
/**
/* all imports goes here.
**/
#Configuration
#ImportResource({"classpath*:conf/applicationContext-db.xml"})
#EnableGlobalMethodSecurity (prePostEnabled = true, securedEnabled = true)
public class AclMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
#Autowired
DataSource dataSource;
#Bean
public MethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
AclPermissionEvaluator permissionEvaluator = new AclPermissionEvaluator(aclService());
expressionHandler.setPermissionEvaluator(permissionEvaluator);
return expressionHandler;
}
#Bean
public JdbcMutableAclService aclService() {
return new JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());
}
#Bean
public AclAuthorizationStrategy aclAuthorizationStrategy() {
return new AclAuthorizationStrategyImpl(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
#Bean
public PermissionGrantingStrategy permissionGrantingStrategy() {
return new DefaultPermissionGrantingStrategy(new ConsoleAuditLogger());
}
#Bean
public EhCacheBasedAclCache aclCache() {
return new EhCacheBasedAclCache(
aclEhCacheFactoryBean().getObject(),
permissionGrantingStrategy(),
aclAuthorizationStrategy()
);
}
#Bean
public EhCacheFactoryBean aclEhCacheFactoryBean() {
EhCacheFactoryBean ehCacheFactoryBean = new EhCacheFactoryBean();
ehCacheFactoryBean.setCacheManager(aclCacheManager().getObject());
ehCacheFactoryBean.setCacheName("aclCache");
return ehCacheFactoryBean;
}
#Bean
public EhCacheManagerFactoryBean aclCacheManager() {
return new EhCacheManagerFactoryBean();
}
#Bean
public LookupStrategy lookupStrategy() {
return new BasicLookupStrategy(
dataSource,
aclCache(),
aclAuthorizationStrategy(),
new ConsoleAuditLogger());
}
}
My problem is the datasource autowired into Configuration file is null, I don't kwno if i missed something.
My XMLs files are all under: src/main/resources/conf/
There is my datasource bean definition in applicationContext-db.xml
<!-- DATASOURCE -->
<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
I already used this bean into Sessionfactory bean defined in the same applicationContext-db.xml file.
PS: When I remove the extended class GlobalMethodSecurityConfiguration my datasource is defined, but I need this org.springframework.security.config.annotation.method.configurationclass to set up my Spring Security ACL configuration.
I found a way to define my datasource bean by using the BeanFactoryAware interface.
BeanFactoryAware is used to inject the BeanFactory object. This way we get access to the BeanFactory which created the object.
#EnableGlobalMethodSecurity (prePostEnabled = true, securedEnabled = true)
#Configuration
#ImportResource({"classpath:/conf/applicationContext-db.xml"})
public class AclMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration implements BeanFactoryAware {
DataSource dataSource;
#Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.dataSource = beanFactory.getBean("dataSource", DataSource.class);
}
// rest of code goes here
}
I read that if we use this technic that means we are doing something wrong, I'll continue searching for a proper solution.
Please rename your bean as name="dataSource"
Use annotation in dao
#Repository("testDao")
public class TestDaoImpl extends JdbcDaoSupport implements BaseDao{
#Override
public Object addObject(String sqlid, Object obj) {
// TODO Auto-generated method stub
return null;
}
Caused by: java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required
I do not want to use :
<bean id="termsDao" class="com.manage.base.dao.impl.TestDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
this code set in xml, and “jdbcTemplate” has been defined in other “spring-xml”。
How to solve this problem by an annotation :“'dataSource' or 'jdbcTemplate' is required”
You can use one of the below approaches. The first one - taking a dataSource is preferred / recommended as you don't expose a SpringFramework class in your public interface. Both will work.
#Repository("testDao")
public class TestDaoImpl extends JdbcDaoSupport implements BaseDao{
#Autowired
TestDaoImpl(DataSource dataSource) {
setDataSource(dataSource);
}
}
Or
#Repository("testDao")
public class TestDaoImpl extends JdbcDaoSupport implements BaseDao{
#Autowired
TestDaoImpl(JDBCTemplate template) {
setJdbcTemplate(template);
}
}
I even feel injecting datasource as a constructor to your DAO is a unnecessary coding step.
Why not inject datasource in Spring config XML into JDBC template and just get jdbctTemplate
object in every DAO.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
and let your DAO extend JDBCSupport class.
public class PersonDao extends JdbcDaoSupport{
public List<Person> selectAll(){
String selectAllSql = "SELECT * FROM PERSON;";
return getJdbcTemplate().query(selectAllSql, new PersonRowMapper());
........
}
}
Full example :
http://www.studytrails.com/frameworks/spring/spring-jdbc-dao-support.jsp
Given the following MyConstructorClass:
#Component
public class MyConstructorClass{
MyObj var;
public MyConstructorClass( MyObj constrArg ){
this.var = var;
}
...
}
How can I autowire a field that requires a constructor argument from a previously #Autowired field? Below is an example.
Note - this question, I believe, is similar to this one, except that my constructor argument is not a String. This code sample is slightly modified from this question.
#Service
public class MyBeanService{
#Autowired
CustomObject customObj; // no arguments to constructor
#Autowired
MyConstructorClass myConstructorClass; // requires `customObj` as an argument
....
}
How can I modify MyBeanService to properly construct myConstructorClass with customObj?
You just need to annotated the constructor of MyConstructorClass with #Autowired:
#Component
public class MyConstructorClass {
final private CustomObject customObj;
#Autowired
public MyConstructorClass(CustomObject customObj) {
this.customObj = customObj;
}
}
Another alternative, (without adding the #Autowired constructor to MyConstructorClass) is to use a #Configuration bean:
#Configuration
public class MyConfiguration {
#Bean
public CustomObject customObj() {
return customObj;
}
#Bean
public MyConstructorClass myConstructorClass() {
return new MyConstructorClass(customObj());
}
#Bean
public MyBeanService myBeanService() {
return new MyBeanService();
}
}
you can use the <constructor-arg> in your servlet
<bean id="myConstructorClass" class="package.MyConstructorClass">
<constructor-arg>
<bean class="package.CustomObject"/>
</constructor-arg>
</bean>
If this is the only place you need to use that class could use #PostConstruct to instantiate itself. I think there is a better solution, but this is off the top of my head.
#Service
public class MyBeanService{
#Autowired
CustomObject customObj;
MyConstructorClass myConstructorClass;
#PostConstruct
public void construct()
{
myConstructorClass = new MyConstructorClass(customObj);
}
}
In the constructor, you can refer to other beans defined in Spring.
<bean id="myConstructorClass" class="package.MyConstructorClass">
<constructor-arg index="0" ref="customObj"/>
</bean>
I have a problem with creating two beans of the same class but different qualifier name. Basically One bean is created with the annotations #Repository and the other one is creating inside #Configuration class.
This is the class that we wont two instances with different datasources:
#Repository ("someDao")
public class SomeDaoImpl implements SomeDao {
private NamedParameterJdbcTemplate jdbcTemplate;
#Autowired
public void setDataSource(DataSource dataSource) {
jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}
}
And then we have a service like this:
#Service
public class SomeServiceImpl implements
SomeService {
#Resource(name = "someDao")
private SomeDao someDao;
#Resource(name = "someDaoAnotherDataSource")
private SomeDao someDaoAnotherDataSource;
}
My first bean is created by the annotation #Repository and the other one I declared in a Spring Configuration class:
#Configuration
#ComponentScan(basePackages = "mypackages")
public abstract class ApplicationRootConfiguration {
#Bean(name = "otherDataSource")
public DataSource otherDataSource() throws NamingException {
...
}
#Bean(name = "someDaoAnotherDataSource")
public SomeDao getSomeDaoAnotherDataSource(#Qualifier("otherDataSource")
DataSource dataSource) throws NamingException {
SomeDao dao = new SomeDaoImpl();
dao.setDataSource(dataSource);
return dao;
}
}
If I run my application, the property someDaoAnotherDataSource in SomeServiceImpl doesn't have my bean declared in the configuration class, it have the bean declared with the annotation Repository.
Also, if I running the same example in XML configuration it works:
<bean id="someDaoAnotherDataSource" class="SomeDaoImpl">
<property name="dataSource" ref="otherDataSource" />
</bean>
Any idea why is not autowiring the proper bean?
Thanks in advance.
Just a thought, instead of injecting the datasource into the method try the following
#Bean(name = "someDaoAnotherDataSource")
public SomeDao getSomeDaoAnotherDataSource() throws NamingException {
SomeDao dao = new SomeDaoImpl();
dao.setDataSource(otherDataSource());
return dao;
}
Although both should work.
Make sure that the name is correct in your #Resource annotation and instead of (or next to) specifing the name of the bean in the #Bean annotation, rename your method to the same.
#Bean(name = "someDaoAnotherDataSource")
public SomeDao someDaoAnotherDataSource() throws NamingException {
SomeDao dao = new SomeDaoImpl();
dao.setDataSource(otherDataSource());
return dao;
}
The name is basically an alias whereas the method name is used as the id of the bean. Could be that resolving isn't looking at aliases correctly. The same in xml would be
<bean id="getSomeDaoAnotherDataSource" name="someDaoAnotherDataSource" class="SomeDaoImpl">
<property name="dataSource" ref="otherDataSource" />
</bean>