While running my launcher class i am getting the below error
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'roles' available
My RoleLauncher Class
// reads spring config java class
package come.rahul.spring.launcher;
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(RolesConfig.class);
Roles roles = context.getBean("roles", Roles.class);
My RolesConfig.class is just annotated with #Configuration and #ComponentScan("com.rahul.spring"). Its in the
package come.rahul.spring.configuartion;
My Roles Class is
package come.rahul.spring.entity;
#Component
public class Roles {
private Long roleId;
private String roleName;
//getter and setter omitted for brevity
I have one Dao and it's implementaion too
package come.rahul.spring.dao;
public interface RolesDao
{
//List<Roles> getRoles(); omitted for brevity
void print() ;
}
Its implementation is below :
package come.rahul.spring.dao;
#Repository
public class RolesDaoImpl implements RolesDao
public void print() {
System.out.println( " Inside Print method of RolesDaoImpl");
}
}
You use #ComponentScan("com.rahul.spring") but everywhere, you use package come.rahul.spring;. You need to use com everywhere instead of come
Related
Folks, am trying to access config properties from within a class that I've extended from a dependency. Apparently the config class is returning a null pointer in my implementation class (CustomUtil).
pom.xml
...
<dependency>
<groupId>com.utilapp</groupId> //3rd party library that I need to use
<artifactId>util-lib</artifactId>
</dependency>
...
The BaseUtil is from the dependency. CustomUtil is a bean in my SpringBoot App & am overriding the method as below to check the key from the config property ignoreKeyList .
package com.myapp
...
#Component
public class CustomUtil extends BaseUtil {
#Autowired
private ClientConfig clientConfig; // This returns null!
#Override
protected boolean shouldExcludeFromList(String key) {
return this.clientConfig.getIgnoreKeyList.contains(key); // their library/util excludes certain keywords from the content being formatted
}
}
Config class in my SpringBoot App.
package com.myapp
...
#Configuration
#Getter
#Setter
public class ClientConfig {
#Value("${myapp.ignorekeys}")
private List<String> ignoreKeyList;
...
...
}
Main class in my app.
package com.myapp
...
#SpringBootApplication
public class MyClientApplication {
public static void main(String[] args) {
SpringApplication.run(MyClientApplication.class, args);
}
}
Service implementation class in my SpringBoot App.
package com.myapp
import com.utilapp.formatters.FormatBuilder;
import com.utilapp.formatters.TextFormatter;
...
#Service
public class ServiceImpl implements MyService {
#Autowired
private ClientConfig clientConfig; // works here!
public String formatContent(String content) {
TextFormatter formatter = this.getTextFormatter();
return formatter.parseAndFormat(content);
}
private TextFormatter getTextFormatter() {
return FormatBuilder.custom() // FormatBuilder is from the dependency
.withApplication(this.clientConfig.getAppName()) // In their library, the BaseUtil gets instantiated which am extending in my CustomUtil bean
...
...
.withIndentSupport(Boolean.TRUE)
.build();
}
}
Controller in my app
package com.myapp
...
#RestController
#RequestMapping("/app/v1")
public class StyleController {
#Autowired
private MyService myService;
#GetMapping("/format")
public String formatContent(#RequestParam String content) {
return this.myService.formatContent(content);
}
}
When I debug ClientConfig, it loads the properties from the config file; application.properties in src\main\resources.
But for some reason the ClientConfig is returning null from within the CustomUtil bean. Not sure why!
I originally thought it was due to ordering of bean instantiation. I tried playing around with #Order, #DependsOn, #ComponentScan, #ScanBasePackages etc, but none yields.
Any pointers/guidance please.
Thanks.
In my application, I have two classes having the same name, but of course in different packages.
Both classes need to be injected in the application; Unfortunately, I get the following error message:
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'myFeature' for bean class [org.pmesmeur.springboot.training.service.feature2.MyFeature] conflicts with existing, non-compatible bean definition of same name and class [org.pmesmeur.springboot.training.service.feature1.MyFeature]
My issue can be reproduced by the following sample:
#Component
#EnableConfigurationProperties(ServiceProperties.class)
public class MyService implements IService {
private final ServiceProperties serviceProperties;
private final IProvider provider;
private final org.pmesmeur.springboot.training.service.feature1.IMyFeature f1;
private final org.pmesmeur.springboot.training.service.feature2.IMyFeature f2;
#Autowired
public MyService(ServiceProperties serviceProperties,
IProvider provider,
org.pmesmeur.springboot.training.service.feature1.IMyFeature f1,
org.pmesmeur.springboot.training.service.feature2.IMyFeature f2) {
this.serviceProperties = serviceProperties;
this.provider = provider;
this.f1 = f1;
this.f2 = f2;
}
...
package org.pmesmeur.springboot.training.service.feature1;
public interface IMyFeature {
void print();
}
package org.pmesmeur.springboot.training.service.feature1;
import org.springframework.stereotype.Component;
#Component
public class MyFeature implements IMyFeature {
#Override
public void print() {
System.out.print("HelloWorld");
}
}
package org.pmesmeur.springboot.training.service.feature2;
public interface IMyFeature {
void print();
}
package org.pmesmeur.springboot.training.service.feature2;
import org.springframework.stereotype.Component;
#Component
public class MyFeature implements IMyFeature {
#Override
public void print() {
System.out.print("FooBar");
}
}
If I use different names for my classes MyFeature, my problem disappears!!!
I am used to work with Guice and this framework does not have this kind of problem/limitation
It seems that the spring dependencies injection framework uses only
the class-name instead of package-name + class-name in order to
select its classes.
In "real-life" I have this problem with a far-bigger project and I would strongly prefer not to have to rename my classes: can anyone help me?
One last point, I would prefer to avoid "tricks" such as using
#Qualifier(value = "ABC") when injecting my classes: in my sample,
there should be no ambiguity for finding the correct instance of
MyFeature as they do not implement the same interface
Simply re-implementing BeanNameGenerator adds a new problem for beans declared/instantiated by names
#Component("HelloWorld")
class MyComponent implements IComponent {
...
}
#Qualifier(value = "HelloWorld") IComponent component
I solved this issue by extending AnnotationBeanNameGenerator and redefining method buildDefaultBeanName()
static class BeanNameGeneratorIncludingPackageName extends AnnotationBeanNameGenerator {
public BeanNameGeneratorIncludingPackageName() {
}
#Override
public String buildDefaultBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry beanDefinitionRegistry) {
return beanDefinition.getBeanClassName();
}
}
You can assigna a value for each component e.g. #Component(value="someBean") and then inject it with #Qualifier e.g.
#Autowired
public SomeService(#Qualifier("someBean") Some s){
//....
}
Spring provides autowire by type and name. Your classname are same. By default spring considers only className not package. But you can override this behaviour by defining custom implementation of BeanNameGenerator interface in which you can generate name using both package and name. I am not providing code solution because i think you should explore more on this.
You can do something like this;
in package a
public class MyFeature implements IMyFeature {
#Override
public void print() {
System.out.print("FooBar");
}
}
in package b
public class MyFeature implements IMyFeature {
#Override
public void print() {
System.out.print("HelloWorld");
}
}
and in some config class;
#Configuration
public class Configuration {
#Bean
public a.MyFeature f1() {
return new a.MyFeature();
}
#Bean
public b.MyFeature f2() {
return new b.MyFeature();
}
}
Then you can autowire them with names f1 and f2, that are the names of their respective bean constructor methods.
You can do the similar thing with #Component("f1") &
#Component("f2")
Even though different interfaces are implemented and are in different packages, identical bean name causes this trouble, and you have to utilize some sort of custom naming to distinguish. Utilizing some custom Spring logic would be way too ugly compared to what you'd do with above solutions.
This is driving me nuts. I have the following files, it is a very simple setup.
public class MainApp {
public static void main(String[] args) {
//read the spring config java class
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("Config.class");
//System.out.println("Bean names: " + Arrays.toString(context.getBeanNamesForType(AccountDAO.class)));
//get the bean from spring container
AccountDAO accountDAO = context.getBean("accountDAO", AccountDAO.class);
//call the business method
accountDAO.addAccount();
//close the spring context
context.close();
}
}
Config.java:
#Configuration
#ComponentScan("com.aop")
#EnableAspectJAutoProxy
public class Config {
}
LoggingAspectDemo.java:
#Aspect
#Component
public class LoggingAspectDemo {
//this is where we add all our related advices for the logging
//let's start with an #Before advice
#Before("execution(public void addAccount())")
public void beforeAddAccountAdvice() {
System.out.println("\n=======>>>> Executing #Before advice on method addAccount() <<<<========");
}
}
AccountDAO.java
#Component
public class AccountDAO {
public void addAccount() {
System.out.println(getClass() + ": Doing my Db work: Adding an account");
}
}
Everytime I run the MainApp.java, I get:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'accountDAO' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
All the files are under "com.aop" package so #ComponentScan should be scanning all the components. It looks simple enough but I can't get my hands around the problem, can anyone help me where I am going wrong?
You're invoking the constructor of AnnotationConfigApplicationContext with "Config.class" as String argument, but this constructor is actually for invoking with base packages i.e. the argument must be a package name.
Since you want to use it with the Configuration class, use the constructor which accepts Class instance instead i.e.
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
I am trying to use an autowired reference from main class and am facing :
Cannot make a static reference to the non-static field
zipCodeLookupService.
This is obvious. But I want to know how to handle this situation. What is the correct way of autowiring when main class is involved. My code will be as below -
Interface class
package com.example.services;
public interface IZipCodeLookup {
String retriveCityForZip(String zipCode);
}
Service Class
package com.example.services;
import org.springframework.stereotype.Service;
#Service
public class ZipCodeLookupService implements IZipCodeLookup {
#Override
public String retriveCityForZip(String zipCode) {
//below is mock code. actual code does a db lookup using a DAO.
if(zipCode=="94123") return "San Francisco";
return "not found in DB";
}
}
here is the main class that requires the service class
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.example.services.IZipCodeLookup;
#SpringBootApplication
public class AutowireWithMainClassApplication {
#Autowired
IZipCodeLookup zipCodeLookupService;
public static void main(String[] args) {
SpringApplication.run(AutowireWithMainClassApplication.class, args);
String city;
//this will not work, compilation error
//Cannot make a static reference to the non-static field zipCodeLookupService
city=zipCodeLookupService.retriveCityForZip(args[0]);
System.out.println("city for zipcode " + args[0] + " is " +city);
}
}
Could someone suggest - how or what is the correct way of using autowiring when main class is involved.
(As making the Autowired reference as static does not work anyway)
in AutowireWithMainClassApplication class, changing to -
#Autowired
static IZipCodeLookup zipCodeLookupService;
throws
Exception in thread "main"
java.lang.NullPointerException
You can do one of the following:
Use the #Autowired object in a #PostConstruct method, which is executed after dependency injection is done, as davidxxx explained above
Use Spring's getBean() in your main() to explicitly ask Spring framework to return the object after the injection completes:
public static void main(String[] args) {
...
ConfigurableApplicationContext appContext = SpringApplication.run(StartApplication.class, args);
IZipCodeLookup service = appContext.getBean(IZipCodeLookup.class);
...
}
Use Spring's CommandLineRunner component (runs right after main), which will be responsible on autowiring your object:
#Component
public class MyRunner implements CommandLineRunner {
#Autowired
private IZipCodeLookup service;
#Override
public void run(String... args) throws Exception {
...
service.doSomething();
...
}
}
Implement Spring's ApplicationRunner's run method in your main:
#SpringBootApplication
public class StartApplication implements ApplicationRunner {
#Autowired
private IZipCodeLookup service;
public static void main(String[] args) {
ConfigurableApplicationContext appContext = SpringApplication.run(StartApplication.class, args);
}
#Override
public void run(ApplicationArguments args) throws Exception {
...
service.doSomething();
...
}
}
A class annotated with a #SpringBootApplication annotation is not a classic bean.It creates the Spring context from a static method.
But autowired dependencies cannot be static.
That's why this statement :
city=zipCodeLookupService.retriveCityForZip(args[0]);
doesn't throw a Spring exception but a classic NullPointerException as you declare zipCodeLookupService as a static field.
In your case, as workaround, you could move the processing that uses the Spring bean in a instance method annotated with javax.annotation.PostConstruct method inside your main class and store the arguments passed to the main() method in a field in order to be able to use it later :
private static String[] args;
#Autowired
IZipCodeLookup zipCodeLookupService;
public static void main(String[] args) {
AutowireWithMainClassApplication.args = args;
SpringApplication.run(AutowireWithMainClassApplication.class, args);
}
#PostConstruct
public void init() {
String city=zipCodeLookupService.retriveCityForZip(args[0]);
System.out.println("city for zipcode " + args[0] + " is " +city);
}
To answer to your comment, you should note several things about #PostConstruct
1) It is not an annotation specific to Spring. So, the official documentation may discuss about things more general than Spring or specific but different things such as EJB (it was originally introduced for them).
2) The first sentence of the javadoc summarizes the general expected behavior.
The PostConstruct annotation is used on a method that needs to be
executed after dependency injection is done to perform any
initialization.
But this sentence
"executed after dependency injection is done"
means indeed :
"executed after all dependency injections are done"
We talk about dependency injection in general, not about each dependency injection.
So, yes stick you to that.
Applying it to your case should make things clearer.
The AutowireWithMainClassApplication class is considered as a Spring bean as #SpringBootApplication is annotated with #Configuration that is itself annotated with #Component.
And as any Spring bean, it may declare dependency injection.
That is a dependency injection :
#Autowired
IZipCodeLookup zipCodeLookupService;
But you could of course declare as many dependency injections that you want to :
#Autowired
IZipCodeLookup zipCodeLookupService;
#Autowired
OtherClass otherClass;
...
So only as all dependencies are effectively injected, the PostConstructwill be invoked one and once.
I have started working with Spring framework. Here I am working with Spring Data - Cassandra Repository modular application. I could able to test a spring-data-cassandra application individually, whereas when I try to use as a moudle in a project and scan the packages of components from other module like...
<context:component-scan base-package="example.dao,example.domain" />
I am getting an error
No qualifying bean of type [example.domain.EventRepository] found for dependency [example.domain.EventRepository]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
I can share you the code, if required.
The way I have done for another modules works fine.
I am not getting where is the problem.
Please find the code below for DAO CLASS.
#Service
#Transactional
public class EventDao {
#Autowired
private EventRepository eventRepository;
/*public EventDao(EventRepository eventRepository) {
this.eventRepository = eventRepository;
}*/
private final static Logger logger = LoggerFactory.getLogger(EventDao.class);
public Event saveMember(Event member) {
eventRepository.save(member);
return member;
}
}
My Repository interface.
package example.domain;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.cassandra.repository.Query;
public interface EventRepository extends CassandraRepository<Event> {
#Query("select * from event where type = ?0 and bucket=?1")
Iterable<Event> findByTypeAndBucket(String type, String bucket);
}
My Cassandra configuration class.
package example;
#Configuration
#PropertySource(value = { "classpath:cassandra.properties" })
#EnableCassandraRepositories(basePackages = { "example" })
public class CassandraConfiguration extends AbstractCassandraConfiguration {
private static final Logger LOG = LoggerFactory.getLogger(CassandraConfiguration.class);
#Autowired
private Environment environment;
#Bean
public CassandraClusterFactoryBean cluster() {
CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
cluster.setContactPoints(environment.getProperty("cassandra.contactpoints"));
cluster.setPort(Integer.parseInt(environment.getProperty("cassandra.port")));
return cluster;
}
#Override
protected String getKeyspaceName() {
return environment.getProperty("cassandra.keyspace");
}
#Bean
public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
return new BasicCassandraMappingContext();
}
}
UPDATE
I could able to create individual spring-data-cassandra and spring-data-neo4j modules seperately with other service modules and its working fine in both the modules.
But I have another module with Neo4j spring-data-neo4j module in the same project, when I try to run both(neo4j+cassandra) the modules under the same project its creating the problem.
still waiting for the help! I have tried my best!
Thanks!