I am using #ComponentScan on SpringBootApplication to run cron, below is my code
package com.ravi
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
#org.springframework.boot.autoconfigure.SpringBootApplication
#ComponentScan(basePackages= {"com.ravi","com.ravi.cron"})
#EnableScheduling
public class SpringBootApplication extends SpringBootServletInitializer{
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SpringBootApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SpringBootApplication.class, args);
}
}
Cron :
package com.ravi.cron
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
#Component
#Lazy(false)
public class CleanDataJob {
private static Logger logger = Logger.getLogger(CleanDataJob.class);
#Autowired
DeleteDataFromDatabase deleteData;
#Scheduled
public void deleteData() {
// Cleaning data job code
deleteData.cleanData();
}
}
Below class is Autowired in cron
com.ravi.logic
import org.springframework.stereotype.Service;
#Service
public class DeleteDataFromDatabase {
public void cleanData() {
// Clean data code
}
}
If want to delete #ComponentScan annotation from SpringBootApplication, but below error is showing
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/com.ravi]]
And second error is
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'cleanDataJob ': Unsatisfied dependency expressed through field 'deleteData'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.ravi.logic.DeleteDataFromDatabase' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
After deleting #ComponentScan getting a 404 error on the web
On DeleteDataFromDatabase, checked with #Configuration, #Controller but not resolved
Related
I trying to implemet a singleton design pattern in Spring. I am running in an error wwhen running my code.
my configuration file is:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan("springdemo3")
public class AppConfig {
}
I have created a service interface as follow:
package springdemo3;
public interface Service {
void doSomething();
}
I have created interface called Pump as follow;
public interface Pump {
void features();
}
Created two types of pumps electric and water pump both implementing pump interface, as follow:
package springdemo3;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
#Component
public class ElectricPump implements Pump{
#Override
#Primary
public void features() {
System.out.println("This pump is an "
+ "electric pump");
}
}
package springdemo3;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
#Component
public class WaterPump implements Pump{
#Override
public void features() {
System.out.println("This pump is pumping"
+ " water");
}
}
My serviceB bean is created as follow:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
#Component //This is a bean
public class ServiceB implements Service{
#Autowired
#Qualifier("electricpump")
private Pump mPump;
public Pump getMpump() {
return mPump;
}
public void setMpump(Pump mPump) {
this.mPump = mPump;
}
public void doSomething() {
System.out.println("We have a water"
+ " pump running here");
mPump.features();
}
}
While my main function is as follow:
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/*** Here I'm not using XML configuration and using Singleton Design Pattern */
public class SpringDemo3 {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
ServiceB mServiceB = context.getBean(ServiceB.class);
mServiceB.doSomething();
}
}
When I run it, I get the following error:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'serviceB': Unsatisfied dependency expressed through field 'mPump'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'springdemo3.Pump' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier("electricpump")}
I'm trying to understand Spring Framework. Please note all these classes are in the same package. What is it that I'm doing wrong here?
But this worked
Please bear in mind that default naming convetion for spring beans is camel case, so in fact the proper name for your bean should be electricPump instead of electricpump. Then, you should be able to autowire the bean.
Other than that, field autowiring is not recommended as it makes unit testing of your service more difficult. Use constructor autowiring preferably.
Also, you've placed #Primary in the incorrect position, as it is the annotation which marks the bean to be the first preference for autowiring. It can be used on method level but it only makes sense when the method is defining a bean and is annotated with #Bean annotation as well.
As mentioned in my comment #Qualifier("electricpump") needed a capital P for Pump.
I created a branch and made a pull request to your project:
Restructured your project
Added a maven pom.xml (because I couldn't run your project)
Fixed the bean name 'electricPump'
Consider always using some project management tool. This way among other things, people can easily set up you project and help you out.
I'm trying to run the fallowing classes.
package com.example.demo;
import org.apache.catalina.core.ApplicationContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
var factory = new AnnotationConfigApplicationContext(AppConfig.class);
test tst = factory.getBean(test.class);
tst.getDummy().test();
SpringApplication.run(DemoApplication.class, args);
}
}
App config class:
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class AppConfig {
#Bean
public test gettest(){
return new test();
}
//
#Bean
public test2 gettest2(){
return new test2();
}
}
First test class:
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
#Component
public class test{
#Autowired
test2 dummy;
public void setDummy(test2 dummy) {
this.dummy = dummy;
}
public test2 getDummy() {
return dummy;
}
void test(){
System.out.println("test");
}
}
Second test class:
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
#Component
public class test2{
public test2(){
}
void test(){
System.out.println("test2");
}
}
I get this error at run time
Field dummy in com.example.demo.test required a single bean, but 2 were found:
- test2: defined in file [/Users/biliuta/IdeaProjects/demo/build/classes/java/main/com/example/demo/test2.class]
- gettest2: defined by method 'gettest2' in class path resource [com/example/demo/AppConfig.class]
If i comment out the public test2 gettest2() bean from AppConfig I'll get this error:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gettest': Unsatisfied dependency expressed through field 'dummy'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.demo.test2' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
How come in the first case test2 bean is found and when I comment it out from AppConfig it is unable to find it anymore (in the first error message you can clearly see that test2 is found)? Is #Configure annotation mandatory to add beans to the context?
When you define #Component you define a bean which can be found for autowiring
When you define #Bean (in `#Configuration) you define a bean which can be found for autowiring
So you define twice same bean which caused spring to failed to know which one is the correct bean to autowire
Solution is to define only one time
how #Autowired works is it first try to find the required bean by type and a fallback mechanism is by bean name(ex: there are multiple beans for the same type)
but when you disable the #Bean annotation from AppConfig there should have been at least one bean of type Test2 as you have annotated Test2 with #Component annotation but it can't find it. To solve this you need to add #ComponentScan(basePackageClasses = { Test2.class }) on your AppConfig class as follows
#Configuration
#ComponentScan(basePackageClasses = { Test2.class })
public class AppConfig {
#Bean
public Test gettest(){
return new Test();
}
//#Bean
public Test2 gettest2(){
return new Test2();
}
}
but if you enable the bean annotation as follows
#Configuration
#ComponentScan(basePackageClasses = { Test2.class })
public class AppConfig {
#Bean
public Test gettest(){
return new Test();
}
#Bean
public Test2 gettest2(){
return new Test2();
}
}
you need to change the injection of Test2 on Test as by using
#Autowired
Test2 test2;
or by using
#Autowired
Test2 gettest2;
There are a few ways of making your class a bean in Spring / Spring Boot
Annotating your class with #Component or any other derived annotation(#Service, #Repository, #Controller, #RestController)
Defining your class as a bean in XML configuration
Using #Bean annotation(this one can be applied only to a method specify that it returns a bean to be managed by Spring context). #Bean annotation is usually declared in Configuration classes methods
When Spring initializes its context, it looks for any bean definitions and creates beans. In your case, it finds duplicate declarations of both test and test2, so you need either to remove your configuration class or remove the #Component annotations from your classes.
See Spring Bean documentation for more information
I have a Spring app. I am using Eclipse IDE on Windows.
When initiating my Spring app I am instantiating my app with StorageService Interface.
package com.ayman.image;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import com.ayman.image.storage.StorageService;
#SpringBootApplication
#ComponentScan("com.ayman.image.storage") //added this line by myself
public class Main{
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
#Bean
CommandLineRunner init(StorageService storageService) {
return (args) -> {
storageService.deleteAll();
storageService.init();
};
}
}
When running this Spring App I am getting the error
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method init in com.mastercard.ayman.image.Main required a
bean of type 'com.mastercard.ayman.image.storage.StorageService' that could
not be found.
Action:
Consider defining a bean of type
'com.ayman.image.storage.StorageService' in your configuration.
I have defined my Bean using component scan. Is this the wrong approach?
The problem may come from StorageService not being a Spring bean. If the bean is not defined with pertinent spring annotations, you should initialize it in the same way as you did with CommandLineRunner.
change it like that it works for me
public class SpringBootSecurityJwtApplication implements CommandLineRunner {
#Resource
FilesStorageService storageService;
public static void main(String[] args) {
SpringApplication.run(SpringBootSecurityJwtApplication.class, args);
System.out.println("version: " + SpringBootVersion.getVersion());
}
#Override
public void run(String... args) throws Exception {
storageService.deleteAll();
storageService.init();
}
Spring Boot application fails to start?
Here is my Project Structure
Below is my main class.
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Start {
public static void main(String[] args) {
SpringApplication.run(Start.class, args);
}
}
And my console is
2017-11-28 11:48:52.187 WARN 7316 --- [ main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userController': Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.repository.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Description:
Field userRepository in com.example.controller.UserController required a bean of type 'com.example.repository.UserRepository' that could not be found.
Action:
Consider defining a bean of type 'com.example.repository.UserRepository' in your configuration.
Application.properties
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=example
UserRepository interface
package com.example.repository;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.example.model.User;
public interface UserRepository extends MongoRepository<User, String>{
public User findOneByName(String name);
}
Here is my controller
#RestController
#RequestMapping("/user/")
public class UserController {
#Autowired
public UserRepository userRepository;
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public void create(#RequestBody User user){
userRepository.save(user);
}
}
Try adding #EnableMongoRepositories(basePackages="com.example.repository") at the Start class.
Instead of MongoRepository, I tried CrudRepository interface. Its working fine.
I am currently trying out a Spring boot application with Redis.I have a problem related to spring boot concerning redis repositories when I try to execute the program.
When I run the app I get the following error:
2017-09-02 09:21:37.065 INFO 5130 --- [st-startStop-18] o.s.b.w.servlet.FilterRegistrationBean : Mapping filter: 'requestContextFilter' to: [/*]
2017-09-02 09:21:37.106 WARN 5130 --- [st-startStop-18] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'controller': Unsatisfied dependency expressed through method 'setSessionService' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sessionServiceImpl' defined in file [/rezsystem/apache-tomcat-8.0.36/webapps/sessionmanager/WEB-INF/classes/rezg/rezos/sessionmanager/services/SessionServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'mezg.mezos.sessionmanager.repositories.SessionRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
2017-09-02 09:21:37.118 INFO 5130 --- [st-startStop-18] utoConfigurationReportLoggingInitializer :
Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-09-02 09:21:37.306 ERROR 5130 --- [st-startStop-18] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
**Description:**
Parameter 0 of constructor in mezg.mezos.sessionmanager.services.SessionServiceImpl required a bean of type 'mezg.mezos.sessionmanager.repositories.SessionRepository' that could not be found.
**Action:**
Consider defining a bean of type 'mezg.mezos.sessionmanager.repositories.SessionRepository' in your configuration.
The related source files are listed below
Service Interface
package mezg.mezos.sessionmanager.services;
import java.util.List;
public interface SessionService {
List<String> listAll();
String getById(String Key);
}
Service Implemention
package mezg.mezos.sessionmanager.services;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import mezg.mezos.sessionmanager.repositories.SessionRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
#Service
public class SessionServiceImpl implements SessionService{
private SessionRepository sessionRepository; //error refere to this
#Autowired
public SessionServiceImpl(SessionRepository sessionRepository) {
this.sessionRepository = sessionRepository;
}
#Override
public List<String> listAll() {
List<String> allSessions = new ArrayList<>();
sessionRepository.findAll().forEach(allSessions::add);
return allSessions;
}
#Override
public String getById(String Key) {
return sessionRepository.findOne(Key);
}
}
Repository
package mezg.mezos.sessionmanager.repositories;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface SessionRepository extends CrudRepository<String, String> {
}
Controller
package mezg.mezos.sessionmanager.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import mezg.mezos.sessionmanager.services.SessionService;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.ui.Model;
#RestController
#RequestMapping(value="/sessionmanager")
public class SessionController {
final static Logger logger = LoggerFactory.getLogger(SessionController.class);
private SessionService sessionService;
#Autowired
public void setSessionService(SessionService sessionService) {
this.sessionService = sessionService;
}
#RequestMapping(value = "/servicecheck", method = RequestMethod.GET)
public String servicecheck() {
return "This is the First Message From Remote session manager service!";
}
#RequestMapping(value ="/all", method = RequestMethod.GET)
public String listAllSessions(Model model){
model.addAttribute("sessions", sessionService.listAll());
return "display all Sessions";
}
#RequestMapping("/session/show/{key}")
public String getProduct(#PathVariable String key, Model model){
model.addAttribute("product", sessionService.getById(key));
return "display selected Sessions";
}
}
Main class
package mezg.mezos.sessionmanager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#EnableAutoConfiguration
#ComponentScan("mezg.mezos.sessionmanager")
public class SessionStoreApplication {
public static void main(String[] args) {
SpringApplication.run(SessionStoreApplication.class, args);
}
Gradle Dependencies
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-redis')
compile('org.springframework.boot:spring-boot-starter-web')
providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
There were similar scenarios described on this forum and I did try out the suggested solutions but could resolve this issue.Some of these issue are listed below.
Stack overflow Reference
Consider defining a bean of type 'com.ensat.services.ProductService' in your configuration
Consider defining a bean of type 'package' in your configuration [Spring-Boot]
Consider defining a bean of type 'service' in your configuration [Spring boot]
Spring boot CrudRepo Define a bean
Spring boot + redis
Other References
http://www.cnblogs.com/exmyth/p/7119225.html
------------------------UPDATE 1-----------------------
Tried Updating the Main Class with #ComponentScan and #EnableRedisRepositories
package mezg.mezos.sessionmanager;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
#SpringBootApplication
#EnableAutoConfiguration
#ComponentScan({"mezg.mezos.sessionmanager","mezg.mezos.sessionmanager.controller","mezg.mezos.sessionmanager.services","mezg.mezos.sessionmanager.repositories"})
#EnableRedisRepositories("mezg.mezos.sessionmanager.repositories")
public class SessionStoreApplication {
public static void main(String[] args) {
SpringApplication.run(SessionStoreApplication.class, args);
}
}
------------------------UPDATE 2-----------------------
Full Logs
https://gist.github.com/lrrp/3065dff578daa92dacf4bdc78f90c9b5
Any suggestion on how how I can fix this Spring boot error and any best practices to follow in situations such as this?