IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required when extending JdbcUserDetailsManager - java

I´m pretty new to Spring, and I´m currently struggling with an exception being thrown when I´m attempting to extend JdbcUserDetailsManager since I need additional features besides the ones provided. The class signature looks looks like this, with a default constructor.
#Repository
public class PrimeUserDetailsManager extends JdbcUserDetailsManager implements CustomUserDetailsManager {
public static String CUSTOM_USERS_BY_USERNAME_QUERY = "select username,password,enabled from users where username like ?%";
public static String FIND_ALL_USERS_QUERY = "select username,password,enabled from users";
#Override
public List<UserDetails> loadUsersByUsername(String username) {
return super.loadUsersByUsername(username);
}
#Override
public List<UserDetails> findAllUsers() {
return getJdbcTemplate().query(FIND_ALL_USERS_QUERY, new RowMapper<UserDetails>() {
public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
String username = rs.getString(1);
String password = rs.getString(2);
boolean enabled = rs.getBoolean(3);
return new User(username, password, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES);
}
});
}
}
}
My custom Interfaces looks like this:
public interface CustomUserDetailsManager extends UserDetailsManager {
public List<UserDetails> loadUsersByUsername(String username);
public List<UserDetails> findAllUsers();
}
Simple autowire:
#Service("userService")
public class UserServiceImpl implements UserService{
#Autowired
public UserServiceImpl(CustomUserDetailsManager customUserDetailsManager) {
this.customUserDetailsManager = customUserDetailsManager;
}
private CustomUserDetailsManager customUserDetailsManager;
....
}
And in my ApplicationContext, I have this:
<beans:bean id="jdbcUserService" class="org.primefaces.examples.moviecollector.custom.PrimeUserDetailsManager">
<beans:property name="dataSource" ref="dataSource"/>
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="enableGroups" value="true"/>
<beans:property name="enableAuthorities" value="false"/>
</beans:bean>
Still, when staring my application, I get the exception below, so apperently I must have missed something? Can someone please tell me what?
Complete stacktrack:
2011-sep-07 13:08:49 org.apache.catalina.core.StandardContext listenerStart
ALLVARLIG: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userBean' defined in file [C:\Program\springsource\vfabric-tc-server-developer-2.5.0.RELEASE\Localhost\wtpwebapps\prime-sweet\WEB-INF\classes\org\primefaces\examples\moviecollector\beans\UserBean.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.security.provisioning.GroupManager]: : Error creating bean with name 'primeUserDetailsManager' defined in file [C:\Program\springsource\vfabric-tc-server-developer-2.5.0.RELEASE\Localhost\wtpwebapps\prime-sweet\WEB-INF\classes\org\primefaces\examples\moviecollector\custom\PrimeUserDetailsManager.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'primeUserDetailsManager' defined in file [C:\Program\springsource\vfabric-tc-server-developer-2.5.0.RELEASE\Localhost\wtpwebapps\prime-sweet\WEB-INF\classes\org\primefaces\examples\moviecollector\custom\PrimeUserDetailsManager.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:730)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:196)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1003)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:907)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4701)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5204)
at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5199)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'primeUserDetailsManager' defined in file [C:\Program\springsource\vfabric-tc-server-developer-2.5.0.RELEASE\Localhost\wtpwebapps\prime-sweet\WEB-INF\classes\org\primefaces\examples\moviecollector\custom\PrimeUserDetailsManager.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:844)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:786)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:795)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:723)
... 23 more
Caused by: java.lang.IllegalArgumentException: 'dataSource' or 'jdbcTemplate' is required
at org.springframework.jdbc.core.support.JdbcDaoSupport.checkDaoConfig(JdbcDaoSupport.java:112)
at org.springframework.dao.support.DaoSupport.afterPropertiesSet(DaoSupport.java:44)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
... 34 more
EDIT:
I´ve included the entire body of PrimeUserDetailsManager above. Here´s the dataSource definition:
<bean id="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>

You've got two beans. One is defined in XML. There's another one being created because you've annotated your class with #Repository. That's the one giving you the trouble because you haven't given it any instructions about wiring the required "'dataSource' or 'jdbcTemplate'". Note in the exception that the bean's name is given as "primeUserDetailsManager". That's the lower-cased simple class name, which is the default name for beans created via component scanning with annotations.

I create an intermediate JdbcDaoSupport derived super class that all my DAO classes extend from that looks like this:
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
public class MyJdbcDaoSupport extends JdbcDaoSupport {
#Autowired private DataSource dataSource;
#PostConstruct
private void initialize() {
setDataSource(dataSource);
}
}
This assumes you have a data source bean with id "dataSource", as shown by the OP.
Works for me in Spring 4.x but should work with earlier versions too.

The only way I managed to solve is by defining following in my DAO.
private SimpleJdbcTemplate simpleJdbcTemplate;
protected SimpleJdbcTemplate getSimpleJdbcTemplate() {
return simpleJdbcTemplate;
}
#Autowired
public void setDataSource(DataSource dataSource) {
this.simpleJdbcTemplate = new SimpleJdbcTemplate(dataSource);
}
It seems the SimpleJdbcDaoSupport does not have #Autowired annotation to its setDataSource method.

This works even in spring 2.5
/**
* Sets the parent class DataSource to the auto-wired data source.
*
*
*/
#Autowired
public void setParentDataSource(
#Qualifier("dataSource") DataSource dataSource) {
super.setDataSource(dataSource);
}

Related

Error creating bean with name Unsatisfied dependency expressed through field

It's been 3rd day I've been trying to implement a simple CRUD application using Mybatis XML configuration and I'm new to the whole Spring ecosystem. The question is a bit long but I've only sharec the essentials.
I have a class Employee.java:
import lombok.*;
#Getter #Setter #AllArgsConstructor #NoArgsConstructor #ToString
public class Employee {
private long emp_Id;
private String emp_name;
private String emp_dept;
}
Then I wrote a Mapper
#Mapper
public interface EmployeeMapper {
public Employee getEmployee(#Param("emp_Id") Long emp_Id);
public List<Employee> getAllEmployee();
}
Then I wrote a mapper XML named EmployeeMapper.xml
...
<mapper namespace="Employee">
<select id="getAllEmployee" resultType="com.tmb.mybatiscrudproj.domains.Employee">
select * from employee
</select>
<select id="getEmployee" resultType="com.tmb.mybatiscrudproj.domains.Employee">
select * from employee where emp_Id = #{emp_Id}
</select>
</mapper>
Then I have written a service:
public interface EmployeeService {
public Employee getEmployee(Long emp_Id);
public List<Employee> getAllEmployee();
}
and here is the service implementation:
#Service
public class EmployeeServiceImpl implements EmployeeService {
#Autowired
EmployeeMapper employeeMapper;
#Override
public List<Employee> getAllEmployee() {
List<Employee> list = employeeMapper.getAllEmployee();
return list;
}
#Override
public Employee getEmployee(Long emp_Id) {
return employeeMapper.getEmployee(emp_Id);
}
}
and finally the controller class
#RestController
#RequestMapping("/employee")
public class EmployeeController {
#Autowired
EmployeeService empService;
#RequestMapping(value="/getEmp/{empId}",method = RequestMethod.GET)
public Employee getEmployee(#PathVariable Long empId){
return empService.getEmployee(empId);
}
#GetMapping(value="/getAllEmp")
public List<Employee> getAllEmployee(){
return empService.getAllEmployee();
}
I'm confused about the configurations. As I have a built-in application.properties inside the resources older and in it I have:
server.port: 8081
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.datasource.url=jdbc:h2:~/test
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
mybatis.config-location=classpath:mapper/mybatisConfig.xml
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
mybatis.type-aliases-package=com.tmb.mybatiscrudproj.domains
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-fetch-size=100
mybatis.configuration.default-statement-timeout=30
Following many tutorials and answers, I created a mybatisConfig.xml and EmployeeMapper.xml file is also inside the `resources folder.
In the mybatisConfig.xml I've done almost the same thing as I did in .properties file
...
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:~/test"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
<property name="path" value="/h2"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="EmployeeMapper.xml"/>
</mappers>
</configuration>
Here is the screenshot of the project structure:
when I run the project I get the following errors:
Error creating bean with name 'employeeController': Unsatisfied dependency expressed through field 'empService';
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'employeeServiceImpl': Unsatisfied dependency expressed through field 'employeeMapper';
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'employeeMapper' defined in file [MY_PATH/mybatiscrudproj/target/classes/com/tmb/mybatiscrudproj/mapper/EmployeeMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; nested exception is java.lang.IllegalStateException: Property 'configuration' and 'configLocation' can not specified with together
Now based on the searches I have done I made sure the in the main class I add:
#MappedTypes({Employee.class})
#MapperScan("com.tmb.mybatiscrudproj.mapper")
#SpringBootApplication
public class MybatiscrudprojApplication {
public static void main(String[] args) {
SpringApplication.run(MybatiscrudprojApplication.class, args);
}
}
but still the same error. How can I successfully configure the project with the structure I have shared in this question?
Your "employeeMapper" is not declared as a spring bean, so when dependency injection, there's no bean with this type. Try adding a #Component on your class.

Bean instance is not getting loaded

I need a help regarding dependency injection.
I hava a bean class which is having a object reference of JdbcTemplate and I am using #Autowired to
create instance of that object. But that object is not getting loaded and as a result NullPointerException is thrown
from setCustName() method.
Please help
Bean Class :
class CustomerBean {
private String custName;
#Autowired
private JdbcTemplate jdbcTemplate;
public void setCustName(String custName) {
this.custName = custName;
jdbcTemplate.update(query);
}
}
XML :
<bean id="myjdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="custBean" class="com.test.CustomerBean">
<property name="custName" value="John" />
</bean>
Stacktrace:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'custName' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:334)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1419)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1160)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
you get NullPointerException as jdbcTemplate is null / not injected.
if you describe bean custBean by xml , as you did, you should add :
< property name="jdbcTemplate" value="myjdbcTemplate" /> for inject jdbcTemplate into your bean.
you have mixed configuration - xml and annotation. in your xml should be :
<context:component-scan base-package="package....." />
to support #Autowired and CustomerBean should be #service or #component.
vaiant1 :
add into xml and
#Component
class CustomerBean {
private String custName;
#Autowired
private JdbcTemplate jdbcTemplate;
public void setCustName(String custName) {
this.custName = custName;
jdbcTemplate.update(query);
}
}
variant2 :
class CustomerBean {
private String custName;
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
this.jdbcTemplate = jdbcTemplate;
}
public void setCustName(String custName) {
this.custName = custName;
jdbcTemplate.update(query);
}
}
and xml
<bean id="custBean" class="com.test.CustomerBean">
<property name="custName" value="John" />
<property name="jdbcTemplate" ref="myjdbcTemplate" />
</bean>
Add #Component annotation to the bean class which contains beans that can be autowired.
After adding the above #Component annotation on beans, we need to tell spring to scan these respective beans and load all the autowired dependencies. This can be done by declaring the following XMLconfiguration
<context:component-scan base-packages="<your_package_names>"/>
for example if my package structure is com.mycompany
<context:component-scan base-packages="com.mycompany"/>
Use <context:annotation-config> which enables the usage of different annotations in bean classes.
Also I strongly recommend against usage of different dependencies in properties setters. In your code sample you assume that the jdbcTemplate was autowired before the call of the setter, fact that you cannot be sure of.
Therefore the logic that you placed in the setter, regarding the jdbc template would be more properly placed in a method annotated with #PostConstruct.

Error creating bean with name 'as' defined in class path resource

I have a Account Business Service which in which i am coding my Business Requirements. And for that Business Service i have a Advice class of SecurityCheck
package com.jlcindia.spring.bservices;
public class AccountService {
public void getBal() {
System.out.println("Get bal is successfull");
}
public void myDeposit() {
System.out.println("MY Deposit is successfull");
}
public void myWithdraw() throws Exception {
System.out.println("WIthdraw begin");
int i=0;
if (i == 1){
throw new InSufficientFundsException();
}
System.out.println("WIthdraw end");
}
}
The advice class is as follows:
package com.jlcindia.spring.mservices;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
#Aspect
public class SecurityService {
#Pointcut(value="execution(* com.jlcindia.spring.bservices.AccountService.my*(..))")
public void pc1(){}
#Pointcut(value="execution(* com.jlcindia.spring.bservices.CustomerService.del*(..))")
public void pc2(){}
#Around("pc1() or pc2()")
public void verifyUser(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("SS-verifyUser()-Begin");
pjp.proceed();
System.out.println("SS-verifyUser()-END");
}
}
I use annotation-config.xml file to configure the Business Service and Advice class as follows:
<bean id="as" class="com.jlcindia.spring.bservices.AccountService" />
<bean id="security" class="com.jlcindia.spring.mservices.SecurityService"/>
Here is the code to test it:
package com.jlcindia.spring.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.jlcindia.spring.bservices.AccountService;
public class Client {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("application-context.xml");
AccountService ast = (AccountService)ctx.getBean("as");
ast.myDeposit();
ast.getBal();
try{
ast.myWithdraw();
}catch(Exception e){
System.out.println("***sorry****");
}
}
}
When I am running my client code to test the services whether the advice is applying or not I am getting this exception;
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'as' defined in class path resource [application-context.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut pc1
The full stack trace is:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'as' defined in class path resource [application-context.xml]: Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut pc1
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.jlcindia.spring.aop.Client.main(Client.java:11)
Caused by: java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut pc1
at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:316)
at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:195)
at org.springframework.aop.aspectj.AspectJExpressionPointcut.checkReadyToMatch(AspectJExpressionPointcut.java:181)
at org.springframework.aop.aspectj.AspectJExpressionPointcut.getClassFilter(AspectJExpressionPointcut.java:162)
at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:200)
at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:254)
at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:286)
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:117)
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:87)
at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:68)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:359)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1426)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
... 11 more</h3>
Please help to figure out why this error occuring while creating the bean 'as'(AccountService). I don't have much knowledge on AOP, i am learner now... so please i need a little help on this question. thank you for your patience to read this...
There is a syntax error in your pointcut. Please change
#Around("pc1() or pc2()")
to
#Around("pc1() || pc2()")
P.S.: And please use less chaotic source code and prose text formatting next time, it took me 5+ minutes to edit your question in order to make it more readable for myself and others.

org.springframework.beans.NotWritablePropertyException: Invalid property 'adminEmails' of bean class

I got stuck on this error given below:
Stack Trace
Apr 16, 2014 12:21:23 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'collectionsWithProps' defined in class path resource [beans.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'adminEmails' of bean class [com.student.spring.impl.CollectionsWithProps]: Bean property 'adminEmails' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1396)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at com.student.spring.test.MyTest.main(MyTest.java:26)
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'adminEmails' of bean class [com.student.spring.impl.CollectionsWithProps]: Bean property 'adminEmails' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1064)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:924)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:58)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1393)
... 8 more
Here is my MyTest.java
package com.student.spring.test;
import java.util.Properties;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import com.student.spring.impl.CollectionsWithProps;
#SuppressWarnings("deprecation")
public class MyTest {
public static void main(String[] args) {
Resource resource = new ClassPathResource("beans.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
CollectionsWithProps cWP = (CollectionsWithProps) beanFactory
.getBean("collectionsWithProps");
System.out.println(cWP);
}
}
Here is CollectionsWithProps.java
package com.student.spring.impl;
import java.util.Properties;
public class CollectionsWithProps {
private Properties emails=null;
public Properties getEmails() {
return emails;
}
public void setEmails(Properties emails) {
this.emails = emails;
}
public String toString(){
return "College [Props=" + emails + "]";
}
}
Here is my beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="collectionsWithProps" class="com.student.spring.impl.CollectionsWithProps">
<property name="adminEmails">
<props>
<prop key="admin">admin#appa.com</prop>
<prop key="support">support#appa.com"></prop>
<prop key="hr">hr#appa.com</prop>
</props>
</property>
</bean>
</beans>
In beans.xml you are trying to set the field adminEmails of CollectionsWithProps.
However the class doesn't have that field, it has the emails field.
Either fix beans.xml to use emails instead of adminEmails, or fix the source code of CollectionsWithProps be renaming emails to adminEmails (along with the getters and setters)
There is property name mismatch:
private Properties emails=null;
should ideally be:
private Properties adminEmails=null;
getters and setters should be renamed accordingly. This will match with what you have mentioned in the configuration files.
I had the same issue and it got resolved by just removing getter. As I required only setter for my application. Sometimes Spring gives this error.
Check for name value in .xml and Variables spelling And case should be same.

What is wrong with my #component?

I want to autowire my components , but it seems I cannot figure it out. I know how to do it with #Autowired & #Qualifier using context:annotation-config in my xml. But how can I do the same job with components? My snippet is:
The component where I want to inject bean.
#Component
public class Pianist implements Performer{
private Instruments instrument;
#Autowired
public void makeInstrument(Instruments instrument) {
this.instrument = instrument;
}
#Override
public void perform() {
instrument.play();
}
My component which will be injected:
#Component
public class Piano implements Instruments{
#Override
public void play() {
System.out.println("Piano");
}
}
My xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan
base-package = "com.city.lt">
</context:component-scan>
</beans>
My main:
ApplicationContext context = new ClassPathXmlApplicationContext("builder.xml");
Performer performer = (Performer)context.getBean("Pianist");
performer.perform();
Then I try to run it, I am getting this error:
Could not autowire method: public void com.city.lt.Pianist.makeInstrument(com.city.lt.Instruments);
What is wrong with that? Thanks
EDITED: stacktrace
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pianist': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.city.lt.Pianist.makeInstrument(com.city.lt.Instruments); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.city.lt.Instruments] is defined: expected single matching bean but found 2: [guitar, piano]
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:287)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.city.lt.main.main(main.java:11)
you need the #Autowired on a setter/constructor/or field.
If you chose setter, please name it like a setter
#Autowired
public void setInstrument(Instruments instrument) {
this.instrument = instrument;
}
All Beans created start with a lower case (by default):
Performer performer = (Performer)context.getBean("pianist");
The problem is that you have 2 implementations of Instrument. Spring does not know which one to chose (because it is really uncreative and doesn't care about music)
You need to tell Spring what exactly it should use. Ether by annotating one with #Primary or wire all implementations into a Collection or use the implementation class you want to wire as field type or use #Qualifier("piano") with your autowired annotation.
#Autowired
public void makeInstrument(#Qualifier("piano") Instruments instrument) {
this.instrument = instrument;
}
If you don't need the "makeInstrument" method after, it's easier this way:
#Component
public class Pianist implements Performer{
#Autowired
private Instruments instrument;
#Override
public void perform() {
instrument.play();
}
}
Take a look at the stack trace
No unique bean of type [com.city.lt.Instruments] is defined: expected single matching bean but found 2: [guitar, piano]
You have 2 classes implementing the Instruments interface. Spring, by default, when using #Autowired does this by type. As there are 2 beans of the same type it doesn't know which one to inject. (Which is also what your stack trace tells you).
To only way to make this work is to use, indeed, a #Qualifier to specify which one to inject.

Categories