I am not able to connect with Redis Sentinal nodes using Spring boot. I am getting UnsatisfiedDependencyException while creating bean cacheManager and localCacheManager. I am not getting where I am doing wrong. Can anyone please help me out.
Using Spring boot version - 2.6. Maven dependencies are -
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.6.6</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.2.2</version>
<optional>true</optional>
</dependency>
Code -
#EnableAutoConfiguration
#Configuration
#EnableCaching
public class RedisCacheConfig {
private final Logger logger = LoggerFactory.getLogger(RedisCacheConfig.class);
#Value("${spring.profiles.active}")
private String profiles;
#Value("${redis.sentinel.nodes}")
private String sentinelNodes;
#Value("${redis.sentinel.password}")
private String redisPassword;
#Value("${redis.sentinel.master.name}")
private String redisMasterName;
#Value("${redis.sentinel.master.node}")
private String redisMasterNode;
#Value("${redis.sentinel.port}")
private Integer redisSentinelPort;
#Value("${redis.port}")
private Integer redisPort;
#Value("${pool.max.wait.seconds}")
public int secondsToWait;
#Value("${pool.max.total}")
public int maxTotal;
#Value("${pool.max.idle}")
public int maxIdle;
#Value("${pool.min.idle}")
public int minIdle;
public String cacheNames;
#Bean
public CacheManager cacheManager(RedisTemplate<String, String> redisTemplate) {
if(!StringUtils.hasLength(profiles)) {
if(profiles.toLowerCase().contains("dev")) {
cacheNames = ":DEV:";
} else if(profiles.toLowerCase().contains("qa")) {
cacheNames = ":PROD:";
}
}
RedisCacheManager.builder(connectionFactory())
.cacheDefaults(RedisCacheConfiguration
.defaultCacheConfig().prefixCacheNameWith(cacheNames)).build();
return cacheManager(redisTemplate);
}
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public JedisConnectionFactory connectionFactory() {
JedisConnectionFactory factory = null;
try {
long seconds=secondsToWait * 1000L;
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(maxTotal);
poolConfig.setMaxIdle(maxIdle);
poolConfig.setMinIdle(minIdle);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);
poolConfig.setMaxWaitMillis(seconds);
factory = new JedisConnectionFactory(sentinelConfig(), poolConfig);
factory.setUsePool(true);
factory.setPassword(redisPassword);
factory.setPort(redisPort);
factory.afterPropertiesSet();
} catch(Exception e) {
e.printStackTrace();
}
return factory;
}
#Bean
public RedisSentinelConfiguration sentinelConfig() {
String[] nodes = StringUtils.commaDelimitedListToStringArray(sentinelNodes);
logger.info("===================== Connecting to Redis 3 =====================");
logger.info(Arrays.toString(nodes));
final RedisSentinelConfiguration SENTINEL_CONFIG = new RedisSentinelConfiguration().master(redisMasterName).sentinel(redisMasterNode, redisSentinelPort);
SENTINEL_CONFIG.setPassword(redisPassword);
for (String node : nodes) {
SENTINEL_CONFIG.sentinel(node, redisSentinelPort);
}
return SENTINEL_CONFIG;
}
}
Code (RedisTemplate) -
#Bean
public RedisTemplate<Object, Object> redisTemplate(JedisConnectionFactory cf) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<Object, Object>();
redisTemplate.setConnectionFactory(cf);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setKeySerializer(new GenericToStringSerializer<Long>(Long.class));
return redisTemplate;
}
Error code I am getting below -
cancelling refresh attempt: creating bean with name
'localCacheManager': Unsatisfied dependency expressed through field
'redisCacheManager';
nested exception Error creating bean with name 'cacheManager' defined
in class path resource [com/RedisCacheConfig.class]:
nested exception Error creating bean with name 'stringRedisTemplate'
defined in class path resource
[org/springframework/boot/autoconfigure/data/redis/RedisAutoConfiguration.class]:
Unsatisfied dependency expressed through method 'stringRedisTemplate'
parameter 0;
nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'connectionFactory' defined in class path
resource [com/abc/mbile/xyz/RedisCacheConfig.class]: Bean
instantiation via factory method failed;
nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate
[org.springframework.data.redis.connection.jedis.JedisConnectionFactory]:
Factory method 'connectionFactory' threw exception;
nested exception is java.lang.NoClassDefFoundError:
redis/clients/jedis/GeoUnit
You are trying to use Jedis 4.x with Spring boot 2.x.
It could be a difficult job to use Jedis 4.x with Spring boot 2.x.
There are some users who are using Jedis 4 but this is possible IFF you are not using some certain features and are willing to go through some extra works.
Until Spring releases support for Jedis 4, you may consider sticking to Jedis 3.x.
Related
I'm trying to add Apache shiro 1.7.0 as security manager bellow you will find my configuration class :
public class ShiroConfig {
#Bean(name="shiroFilter")
#DependsOn({"securityManager"})
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
log.info("ShiroConfiguration.shirFilter()");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/captcha", "anon");
filterChainDefinitionMap.put("/app/code/**", "anon");
filterChainDefinitionMap.put("admin/**/page-query", "user");
filterChainDefinitionMap.put("/app/web/logout", "logout");
filterChainDefinitionMap.put("admin/**/detail", "authc");
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
#Bean(name = "lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
LifecycleBeanPostProcessor lifecycleBeanPostProcessor = new LifecycleBeanPostProcessor();
return lifecycleBeanPostProcessor;
}
#Bean(name="ehCacheManager")
#DependsOn("lifecycleBeanPostProcessor")
public EhCacheManager ehCacheManager() {
log.info("ShiroConfiguration.getEhCacheManager()");
EhCacheManager cacheManager = new EhCacheManager();
cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
return cacheManager;
}
#Bean(name="adminRealm")
#DependsOn("lifecycleBeanPostProcessor")
public AdminRealm adminRealm(EhCacheManager ehCacheManager) {
AdminRealm adminRealm = new AdminRealm() ;
adminRealm.setCacheManager(ehCacheManager);
return adminRealm;
}
#Bean(name="simpleCookie")
public SimpleCookie getSimpleCookie(){
SimpleCookie simpleCookie = new SimpleCookie();
simpleCookie.setName("rememberMe");
simpleCookie.setHttpOnly(true);
simpleCookie.setMaxAge(7*24*60*60);
return simpleCookie ;
}
#Bean(name="cookieRememberMeManager")
#DependsOn({"simpleCookie"})
public CookieRememberMeManager getCookieRememberMeManager(SimpleCookie simpleCookie){
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(simpleCookie);
cookieRememberMeManager.setCipherKey(Base64.decode("2AvVhdsgUs0FSA3SDFAdag=="));
return cookieRememberMeManager ;
}
#Bean(name = "securityManager")
#DependsOn({"adminRealm","ehCacheManager","cookieRememberMeManager"})
public DefaultWebSecurityManager getDefaultWebSecurityManager(AdminRealm realm, EhCacheManager ehCacheManager,CookieRememberMeManager cookieRememberMeManager) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(realm);
defaultWebSecurityManager.setCacheManager(ehCacheManager);
defaultWebSecurityManager.setRememberMeManager(cookieRememberMeManager);
return defaultWebSecurityManager;
}
#Bean
#DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
defaultAAP.setProxyTargetClass(true);
return defaultAAP;
}
#Bean
#DependsOn("securityManager")
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
my pom.xml entry for shiro :
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.7.0</version>
</dependency>
The project compile successfully but i'm getting the above error while trying to access the web app, i appreciate any hemp or suggestion.
Error starting Tomcat context. Exception:
org.springframework.beans.factory.BeanCreationException. Message: Error creating bean with name 'filterShiroFilterRegistrationBean' defined in class path resource [org/apache/shiro/spring/config/web/autoconfigure/ShiroWebFilterConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.web.servlet.FilterRegistrationBean]: Factory method 'filterShiroFilterRegistrationBean' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'shiroFilterFactoryBean' available
Try adding #Configuration annotations to the class,like this:
try changing the name of your bean from #Bean(name="shiroFilter") to #Bean(name="shiroFilterFactoryBean").
Since the different configs, I have written two LettuceConnectionFactory:
ItemFactoryConfig
ActivityFactoryConfig
the code as follows:
#Configuration
#PropertySource(value = "classpath:config/redis.properties", encoding = "UTF-8")
public class ItemFactoryConfig {
#Value("${item.host}")
private String host;
#Value("${item.port}")
private int port;
#Bean
public LettuceConnectionFactory itemFactory(){
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
redisConfiguration.setHostName(host);
redisConfiguration.setPort(port);
return new LettuceConnectionFactory(redisConfiguration);
}
}
#Configuration
#PropertySource(value = "classpath:config/redis.properties", encoding = "UTF-8")
public class ActivityFactoryConfig {
#Value("${activity.host}")
private String host;
#Value("${activity.port}")
private int port;
#Bean
public LettuceConnectionFactory activityFactory(){
RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
redisConfiguration.setHostName(host);
redisConfiguration.setPort(port);
return new LettuceConnectionFactory(redisConfiguration);
}
}
And I added #Qualifier when these LettuceConnectionFactories were autowired.
#Configuration
public class ItemTemplateConfig {
#Autowired
#Qualifier("itemFactory")
private LettuceConnectionFactory itemFactory;
#Bean
public RedisTemplate<String, String> itemTemplate(){...}
}
#Configuration
public class ActivityTemplateConfig {
#Autowired
#Qualifier("activityFactory")
private LettuceConnectionFactory activityFactory;
#Bean
public RedisTemplate<String, String> activityTemplate(){...}
}
However, spring boot still report the NoUniqueBeanDefinitionException.
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' available: expected single matching bean but found 2: activityFactory,itemFactory
Spring boot Description:
Parameter 0 of method redisTemplate in org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration required a single bean, but 2 were found:
- activityFactory: defined by method 'activityFactory' in class path resource [com/lyf/redisdemo/config/Activity/ActivityFactoryConfig.class]
- itemFactory: defined by method 'itemFactory' in class path resource [com/lyf/redisdemo/config/Item/ItemFactoryConfig.class]
Action:
Consider marking one of the beans as #Primary, updating the consumer to accept multiple beans, or using #Qualifier to identify the bean that should be consumed
spring boot: 2.1.0.RELEASE
I have just develop a configuration with Spring Session and Redis, everything work fine, but in my console logs, I got
2015-06-29 15:45:44,088 [main] DEBUG org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor - Could not find default ScheduledExecutorService bean
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.scheduling.TaskScheduler] is defined
How can I configure ScheduledExecutorService bean?
Update :
#Configuration
#EnableRedisHttpSession
#Conditional(RedisDeclarationCondition.class)
public class LocalRedisConfig extends WebMVCConfig{
#Value("${redis.host}")
private String host;
#Value("${redis.port}")
private String port;
#Bean
public JedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory();
}
#Bean
public RedisConnectionFactory jedisConnectionFactory(){
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(5);
poolConfig.setMaxTotal(10);
poolConfig.setMinIdle(1);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(true);
JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(poolConfig);
// RedisOperationsSessionRepository cleanup = new RedisOperationsSessionRepository(jedisConnectionFactory);
//optional
//jedisConnectionFactory.setHostName(host);
//jedisConnectionFactory.setPort(Integer.valueOf(port));
return jedisConnectionFactory;
}
#Bean
public StringRedisTemplate redisTemplate(){
StringRedisTemplate redisTemplate = new StringRedisTemplate(jedisConnectionFactory());
return redisTemplate;
}
it is a DEBUG message, could be ignored by set your logging.level.org.springframework=INFO
Using #Scheduled and #EnableScheduling but gives NoSuchBeanDefinitionException
i am trying to run full package of junit test classes, and i have an audit classes for my domain classes as follows:
#PrePersist
public void prePersist(AuditableEntity e) {
UserService userService = SpringBeanFactory.getBean(UserService.class);
// some auditing here
}
- SpringBeanFactory class:
public class SpringBeanFactory {
private static ApplicationContext applicationContext;
public static <T> T getBean(final String name, final Class<T> requiredType) {
T bean = null;
if (applicationContext != null) {
bean = applicationContext.getBean(name, requiredType);
}
return bean;
}
public static <T> T getBean(final Class<T> requiredType) {
T bean = null;
if (applicationContext != null) {
bean = applicationContext.getBean(requiredType);
}
return bean;
}
public static void setApplicationContext(final ApplicationContext applicationContext) {
if (SpringBeanFactory.applicationContext == null) {
SpringBeanFactory.applicationContext = applicationContext;
}
}
}
-Test class config:
#Autowired
private ApplicationContext applicationContext;
#Before
public void before() throws Exception {
SpringBeanFactory.setApplicationContext(applicationContext);
}
-SpringTestingConfig class:
#Configuration
#ComponentScan(basePackages = "com.myapp.data", excludeFilters = { #Filter(Configuration.class) })
#PropertySource("classpath:/test.properties")
#Profile("test")
public class SpringTestingConfig {
private static Logger log = (Logger)LoggerFactory.getLogger(SpringTestingConfig.class);
#Autowired
private ApplicationContext applicationContext;
#Bean
public DataSource XdataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
if(log.isDebugEnabled()) log.debug("profile.name", "test");
System.setProperty("profile.name", "test");
dataSource.setDriverClassName("org.h2.Driver");
String schemaName = ConfigurationUtil.config().getString("db.schema.name").toLowerCase();
log.debug("SCHEMA IS " + schemaName);
String url = "jdbc:h2:mem:test;MODE=Mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS " +schemaName +"\\;" + "SET SCHEMA "+schemaName;
dataSource.setUrl(url);
//dataSource.setUrl("jdbc:h2:mem:test;MODE=Mysql;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS " + schemaName);
dataSource.setUsername("sa");
//use your own local mysql in tests here...
// dataSource.setDriverClassName("com.mysql.jdbc.Driver");
// dataSource.setUrl("jdbc:mysql://localhost:3306/mv_tests?characterEncoding=UTF-8");
// dataSource.setUsername("tomcat");
// dataSource.setPassword("tomcat");
//
return dataSource;
}
#Bean
public DataSource dataSource() {
SpringBeanFactory.setApplicationContext(applicationContext);
LoggerUtils.setAllApplicationLogs("DEBUG");
DriverManagerDataSource dataSource = new DriverManagerDataSource();
if(log.isDebugEnabled()) {
log.debug("profile.name", "test");
}
System.setProperty("profile.name", "test");
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
String schemaName = ConfigurationUtil.config().getString("db.schema.name");
String username = ConfigurationUtil.config().getString("db.username");
String password = ConfigurationUtil.config().getString("db.password");
if( log.isDebugEnabled() ) {
log.debug( "SCHEMA IS " + schemaName );
log.debug( "Username IS " + username );
log.debug( "Password IS " + password );
}
dataSource.setUrl("jdbc:mysql://localhost:3306/"+schemaName);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
-Test class annotations:
#RunWith(SpringJUnit4ClassRunner.class)
#TestExecutionListeners({ WebContextTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class, TransactionalTestExecutionListener.class })
#ActiveProfiles("test")
#DirtiesContext
#ContextConfiguration(loader = AnnotationConfigContextLoader.class, classes = { SpringConfig.class, SpringTestingConfig.class, SpringLocalContainerJPAConfig.class, CustomConfiguration.class })
#Transactional
when my test method tries to save an entity, it makes call to PrePersist method which in turn makes call to the getting spring service:
UserService userService = SpringBeanFactory.getBean(UserService.class);
which in turns produces the following exception:
Error creating bean with name 'userService':
Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Could not autowire field: private com.motivosity.data.repository.UserRepository com.motivosity.service.impl.UserServiceImpl.userRepository;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepositoryImpl':
Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'springLocalContainerJPAConfig': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field:
javax.sql.DataSource com.motivosity.data.config.SpringLocalContainerJPAConfig.dataSource;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'springTestingConfig': Initialization of bean failed;
nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'org.springframework.cache.annotation.ProxyCachingConfiguration':
Initialization of bean failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No bean named 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry' is defined
i have to mention that this exception occurs when running full package of test classes, but when running this test class separately no exception is produced.
BTW, i am using spring 3.2.3.RELEASE
UPDATE: when i upgraded the spring version to latest release 4.0.3, i am getting a new exception on the same get UserService line:
org.springframework.context.support.GenericApplicationContext#3aa54263 has been closed already
please advise how to fix this exception.
When you annotate a test class or test method with #DirtiesContext, you are telling Spring to close the ApplicationContext after that test class or method. Thus, if you later attempt to retrieve a bean from a closed context you will get an exception like you're seeing.
My guess is that you are using #DirtiesContext in other test classes within your test suite, and a result the logic in SpringBeanFactory.setApplicationContext() is broken since it can potentially maintain a reference to a closed context. Thus, you'll need allow the current ApplicationContext to be set for each test. In other words, remove the null-check like follows
public static void setApplicationContext(final ApplicationContext applicationContext) {
// always set the current context
SpringBeanFactory.applicationContext = applicationContext;
}
Hope this helps!
- Sam (author of the Spring TestContext Framework)
Here's my scenario. My project is using Spring (3.2.3.RELEASE), Struts2 (2.3.14.3) and JPA (2.0). We have a project (let's call it project A) that contains various entities and common classes. We use project A to generate a .jar file so that other projects can use these classes. In project A we've used the Spring stereotypes: #Component. #Service or #Repository for those classes we want Spring to inject. Whenever we try to inject beans from the jar, we get an error similar to:
No qualifying bean of type
[com.ceiwc.bc.commonsql.service.CommonSQLService] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Could not autowire field: private com.ceiwc.bc.commonsql.service.CommonSQLService
com.ceiwc.ma.mvc.action.LoginAction.commonSQLService; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[com.ceiwc.bc.commonsql.service.CommonSQLService] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Error creating bean with name 'com.ceiwc.ma.mvc.action.LoginAction': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private
com.ceiwc.bc.commonsql.service.CommonSQLService
com.ceiwc.ma.mvc.action.LoginAction.commonSQLService; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[com.ceiwc.bc.commonsql.service.CommonSQLService] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Unable to instantiate Action, com.ceiwc.ma.mvc.action.LoginAction, defined for 'doLogin' in namespace '/Login'Error creating bean with
name 'com.ceiwc.ma.mvc.action.LoginAction': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private
com.ceiwc.bc.commonsql.service.CommonSQLService
com.ceiwc.ma.mvc.action.LoginAction.commonSQLService; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[com.ceiwc.bc.commonsql.service.CommonSQLService] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
We are using Java configuration for Spring. Here is our configuration class:
package com.zzz.bc.config;
#Configuration
#ImportResource({"/WEB-INF/spring/spring-config.xml"})
#ComponentScan(basePackages = "com.zzz")
public class ApplicationConfig {
#Bean
public JavaMailSender mailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(${app.mail.host});
return mailSender;
}
}
package com.zzz.bc.config;
#Configuration
#EnableTransactionManagement
#Import(ApplicationConfig.class)
#PropertySource({"classpath:db.properties"})
public class DataConfig {
#Autowired
Environment environment;
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
return transactionManager;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
String[] packagesToScan =
{environment.getProperty("db.packagesToScan1"), environment.getProperty("db.packagesToScan2")};
Map<String, Object> jpaProperties = new HashMap<String, Object>();
jpaProperties.put("eclipselink.weaving", "false");
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPackagesToScan(packagesToScan);
entityManagerFactoryBean.setLoadTimeWeaver(new InstrumentationLoadTimeWeaver());
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter());
entityManagerFactoryBean.setJpaPropertyMap(jpaProperties);
return entityManagerFactoryBean;
}
#Bean
public DriverManagerDataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getProperty("db.driver"));
dataSource.setUrl(environment.getProperty("db.url"));
dataSource.setUsername(environment.getProperty("db.username"));
dataSource.setPassword(environment.getProperty("db.password"));
return dataSource;
}
#Bean
public JpaVendorAdapter vendorAdapter() {
EclipseLinkJpaVendorAdapter vendorAdapter = new EclipseLinkJpaVendorAdapter();
vendorAdapter.setDatabase(Database.ORACLE);
vendorAdapter.setShowSql(true);
return vendorAdapter;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
We have #ComponentScan set to check to bean in the package of com.zzz. In project B, we have a Struts2 Action that we want to inject a bean from project A. Here is a snippet of the class from project B:
#SuppressWarnings("rawtypes")
#Service("CommonSQLService")
public class CommonSQLServiceImpl implements CommonSQLService {
#Autowired
CommonSQLDao cdao;
#Override
public Policy getPolicyById(String policyNo) {
return cdao.getPolicyById(policyNo);
}
#Override
public Policy getPolicy(Policy parmRec) {
return cdao.getPolicy(parmRec);
}
#Override
public ArrayList<Policy> getPolicies(String policyNo) {
return cdao.getPolicies(policyNo);
}
#Override
public List<Policy> getPolicies(Policy parmRec){
return cdao.getPolicies(parmRec);
}
}
Here is our action (removed getters/setters):
package com.zzz.ma.mvc.action;
#SuppressWarnings("serial")
#Component
#Scope("prototype")
#Namespace("/Login")
public class LoginAction extends ActionParent {
#Autowired
private IUserService userService; //Contained in project B
#Autowired
private CommonSQLService commonSQLService; //What's autowired from project A
private User user;
private String updateFlag;
private Integer parentMenuId;
private IwifWebNavmenuItem record;
public static final String LOGIN_STR = "login";
#Action(value = "doLogin", results = { #Result(name = "success", location = "/pages/login.jsp") })
public String login() {
updateFlag = "Y";
return SUCCESS;
}
#Action(value = "validate", results = {
#Result(name = "success", location = "/BrowseOptions/showOptions", type = "redirect"),
#Result(name = "login", location = "/pages/login.jsp") })
public String validateUser() {
if (updateFlag == null) {
session.remove(LOGIN_STR);
return LOGIN;
}
if (userService.validateUser(user.getUsername(), user.getPassword()) == null) {
addActionError(getText("invalid.user"));
return LOGIN;
}
session.put(LOGIN_STR, user.getUsername());
return SUCCESS;
}
#Action(value = "logout", results = { #Result(name = "success", location = "/pages/login.jsp") })
public String logout() {
updateFlag = StringUtils.EMPTY;
session.invalidate();
return SUCCESS;
}
}
Whenever we try to do this autowire, we get an error like the one listed above. What are we missing? Can't classes contained in a jar file with Spring Stereotypes be autowired?
Thanks for you help in advance!
Change #Service("CommonSQLService") to #Service("commonSQLService") or you can just use #Service if you're not implementing the CommonSQLService interface anywhere else.