How to find which component required a bean? - spring-boot

I have the error message "A component required a bean named XYZ that could not be found."
Is there a way to display, which component this is?
UPDATES:
This is the error message
***************************
APPLICATION FAILED TO START
***************************
Description:
A component required a bean named 'demoAnnotation' that could not be found.
Action:
Consider defining a bean named 'demoAnnotation' in your configuration.
I have a bean defined called demoAnnotation:
#Component
#Qualifier("demoAnnotation")
public class Demo implements IDemo {
private static final Logger log = LoggerFactory.getLogger(Demo.class);
#Value("${com.example.demo.Demo.beanName:BEAN_NAME_DEFAULT}")
private String beanName;
#Override
public String getBeanName() {
return beanName;
}
#Override
public void setBeanName(String beanName) {
this.beanName = beanName;
}
}

When you start your application, you should get a message like: Field repository in com.example.demo.Controller required a bean of type 'com.example.demo.Repository' that could not be found.
com.example.demo.Controller is the name of the class that needs the com.example.demo.Repository bean
Then it would be easier if you show us the exact error message

Related

Use configuration properties in Spring expression language

I have a class with configuration properties:
#Data
#ConfigurationProperties("message-starter")
public class JobProperties {
public Duration kafkaSendingPeriod;
public Duration rabbitSendingPeriod;
}
And class that aggregates this properties and uses them in #Scheduled annotation using Spring expression language:
#Component
#EnableConfigurationProperties(JobProperties.class)
#RequiredArgsConstructor
public class Job {
public final JobProperties jobProperties;
#Scheduled(fixedRateString="#{#jobProperties.getKafkaSendingPeriod()}")
public void fun(){
System.out.println("Time: " + LocalDateTime.now());
}
}
But when I run it I get the following exception:
Description:
A component required a bean named 'jobProperties' that could not be found.
Action:
Consider defining a bean named 'jobProperties' in your configuration.
Please tell me how to fix this exception so that I can get the value of the fields of the JobProperties class?

Error with repository injection in kafka consumer class

Im trying to run a simple spring boot application that just takes a message from kafka and saves in a db2 database.
The problem comes up when im trying to inject my repository in the consumer class!
#Service
#Slf4j
#AllArgsConstructor
public class KafkaConsumer {
private PortalOneRepository portalOneRepository;
private ObjectMapper objectMapper;
#KafkaListener(topics = "topicout")
public void consumeEventHubMessage(String consumerMessage) {
log.info("Received message from kafka queue: {}", consumerMessage);
//Convert string message to java object
try {
DocumentONE[] documentOne = objectMapper.readValue(consumerMessage, DocumentONE[].class);
//Salvar cada mensagem no db2
portalOneRepository.saveAll(Arrays.asList(documentOne));
} catch (JsonProcessingException e) {
log.error("Error receiving message: " + e.getMessage());
}
}
}
And this is my repository:
#Repository
public interface PortalOneRepository extends JpaRepository<DocumentONE, Long> {
}
So after run it shows the following error message:
*************************** APPLICATION FAILED TO START
Description:
Parameter 0 of constructor in
br.examplestream.eventhub.KafkaConsumer required a
bean of type
'br.examplestream.repository.PortalOneRepository'
that could not be found.
Action:
Consider defining a bean of type
'br.examplestream.repository.PortalOneRepository' in
your configuration.
I tried the config solution class but it shows a cyclic dependency injection problem:
> ***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
kafkaConsumer defined in file [Z:\Users\romulo.domingos\IdeaProjects\portal-one-stream\target\classes\br\examplestream\eventhub\KafkaConsumer.class]
┌─────┐
| getPortalOneRepository defined in class path resource [br/examplestream/config/PortalOneConfig.class]
└─────┘
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
This is the config class that i´ve tried :
#Configuration
public class PortalOneConfig {
private PortalOneRepository portalOneRepository;
#Autowired
ApplicationContext context;
#Bean
public PortalOneRepository getPortalOneRepository(){
return context.getBean(PortalOneRepository.class);
}
}
What is the correct way to inject my repository into my consumer class?
Problem solved.
The problem is caused by a property in application.yml file
autoconfigure: delete:
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
After removing the application starts to run normally again.

Encountered invalid #Scheduled method 'methodName': Only no-arg methods may be annotated with #Scheduled

plz I don't know wath is the exact problem in the code if I add Scheduled annotatiçon in my code suddenly this error appears
if you have any soulustion please.
plz I don't know wath is the exact problem in the code if I add Scheduled annotatiçon in my code suddenly this error appears
if you have any soulustion please.
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
12-09-2019 18:11:54.908 [restartedMain] ERROR o.s.boot.SpringApplication.reportFailure - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'missionResource': Unsatisfied dependency expressed through field 'missionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'missionImpl' defined in file [C:\Users\El Oussa\Desktop\vgas-api\vgas-manager\target\classes\ma\valueit\vgas\manager\business\impl\MissionImpl.class]: Initialization of bean failed; nested exception is java.lang.IllegalStateException: Encountered invalid #Scheduled method 'editMission': Only no-arg methods may be annotated with #Scheduled
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
I have added #EnableScheduling in SpringBootApplication
--------------------------------------------------------
#SpringBootApplication
#EnableScheduling
#ComponentScan("com.qaiboub.vs")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#Service
public class MissionImpl extends CrudManagerImpl<MissionDto, Integer, MissionEntity, MissionService, MissionConverter> implements MissionManager {
#Autowired
private MissionService missionService;
#Autowired
private MissionConverter missionConverter;
enter code here
#Override
public MissionService getService() {
return missionService;
}
#Override
public MissionConverter getConverter() {
return missionConverter;
}
#Scheduled(cron = "0 15 18 * * *")
public void editMission(Integer id, MissionDto missionDto) {
if (StringUtils.isEmpty(id)) {
throw new MissingIdException();
}
if (missionDto == null) {
throw new InvalidPayloadException();
}
if (!id.equals(missionDto.getId())) {
throw new BusinessException(CommonErrorCode.TRYING_TO_EDIT_ANOTHER_ENTITY);
}
missionEntity = missionConverter.convertFrom(missionDto);
missionEntity = missionService.save(missionEntity);
}
}
remove the function arg. Scheduler don't take arg in their functions
You need to remove all the arguments from the function, the scheduler does not accept any argument
public void syncData(#RequestParam(name = "created_at_from") String createdAtFrom,
#RequestParam(name = "created_at_to") String createdAtTo) {}
Correct format is
public void syncData() throws Exception {}
Use this link for additional details:
https://www.baeldung.com/shedlock-spring

Spring factory - NoUniqueBeanDefinitionException:

I am trying to implement factory pattern to get producer from a list of available ones. While doing it i am getting the below exception. Not able to figure out the issue with the code. Can you please let me know what i am missing.
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.test.interfaces.Producer] is defined: expected single matching bean but found 2: A,B
Please find the code below
public interface Producer<T> {
public void start();
public List<T> produce() throws CEHServiceException;
public void stop();
}
#Component("A")
public class ProducerA extends Producer {
//Autowire Services & Properties
}
#Component("B")
public class ProducerB extends Producer {
//Autowire Services & Properties
}
#Configuration
public class AgentConfiguration {
#Bean
public ServiceLocatorFactoryBean createProducerFactoryBean(){
ServiceLocatorFactoryBean bean = new ServiceLocatorFactoryBean();
bean.setServiceLocatorInterface(ProducerFactory.class);
return bean;
}
}
public interface ProducerFactory {
Producer getProducer(String producerName);
}
#Component
public class AdvancedAgentProcessor {
#Autowired
private ObjectFactory<AdvancedRunnerImpl> runnerFactory;
public void init(){
AdvancedRunnerImpl runner = runnerFactory.getObject();
runner.setProducerName("A");
runner.start();
}
}
#Component
#Scope("prototype")
public class AdvancedRunnerImpl implements Runner {
#Autowired private ProducerFactory producerFactory;
private Producer producer;
private String producerName;
public void start() {
producer = producerFactory.getProducer(this.producerName);
}
}
Full stack tracke
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.test.etl.interfaces.Producer] is defined: expected single matching bean but found 2: A,B
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:365)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:331)
at org.springframework.beans.factory.config.ServiceLocatorFactoryBean$ServiceLocatorInvocationHandler.invokeServiceLocatorMethod(ServiceLocatorFactoryBean.java:377)
at org.springframework.beans.factory.config.ServiceLocatorFactoryBean$ServiceLocatorInvocationHandler.invoke(ServiceLocatorFactoryBean.java:363)
at com.sun.proxy.$Proxy34.getProducer(Unknown Source)
at com.test.runner.AdvancedRunnerImpl.start(AdvancedRunnerImpl.java:54)
at com.test.app.AdvancedAgentProcessor.init(AdvancedAgentProcessor.java:48)
at com.test.app.DataAgentApplication.main(DataAgentApplication.java:25)
Spring does not know which component to autowire. It seems that the problem is in the ProducerFactoryImplementation but we cannot see it.
There are three possible solutions:
Use Qualifiers so you can tell Spring which specific implementation you want.There is an example in StackOverflow
here
Use the Primary annotation (See more here3). That means that in case of ambiguity Spring will give priority to the #Primary annotated component
Autowire a list of beans. Something like:
#Autowired private List<Producer> myAvalilableProducers;
public Producer getByName(name){
for( Producer producer: myAvalilableProducers){
if(producer.getName().equals(name)){ return producer; }
}
throw new RuntimeException("No producer with name " + name " found");
}
This third option more useful when you do not know the specific instance at compile time or if you really want to inject a list of components.
You have two beans that extend Producer. Somewhere you are trying to autowire a Producer. Spring does not know which Producer to use.
This happens when the dynamic proxy is not able to pick the correct Bean. Please check whether this.producerName is null or empty.

How to create a Spring bean for apache logging Log class?

I'd like to create an autowired bean in a Dao class in order to do logging opperations. My way was hitherto static final statement like this:
private static final Log log = LogFactory.getLog(LoggedClass.class);
But now I'm trying to use IoC to turn classes decoupled.
If just add configuration in pom.xml and try to do sth like
#Autowired
Log log;
I receive an error message:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'funciDaoImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.apache.commons.logging.Log br.com.bb.dirco.dao.impl.FunciDaoImpl.log; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'log' defined in class path resource [com/company/project/util/PersistenceConfig.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.lang.Class]: : No qualifying bean of type [java.lang.Class] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.Class] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
In order to get a logger, I had to provide a class to getLog method on LogFactory class and attribute it to Log instance. There's a way to do it using #Autowired Spring IoC? Thanks!
You can inject only those objects which are managed/created by Spring container. You have to register your bean (or factory method creating the bean) with container (with annotations like #Component/#Singleton/... or directly in xml)
In your case it's not very applicable since you have to have many different types (for every class) of logger objects provided by Spring and then when you inject they would have to be identified by different name/type for every class.
P.S. I don't see any problem using it the way you use it now
Where I work we have implemented support for #Autowired SLF4J Loggers using Springs BeanPostProcessor.
First you need to define an Logger placeholder bean in your application context. This bean is going to be injected by Spring into all bean with a #Autowired Logger field.
#Configuration
public class LoggerConfig {
#Bean
public Logger placeHolderLogger() {
return PlaceHolder.LOGGER;
}
#Bean
public AutowiredLoggerBeanPostProcessor loggerPostProcessor() {
return new AutowiredLoggerBeanPostProcessor();
}
}
Then you an AutowiredLoggerBeanPostProcessor which inspects all beans, indetify bean that contain Logger fields annotated with #Autowired (at this point should contain a reference to the Logger placeholder bean), create a new Logger for the partilcar bean an assigned it to the fields.
#Component
public class AutowiredLoggerBeanPostProcessor implements BeanPostProcessor, PriorityOrdered {
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
attachLogger(bean);
return bean;
}
#Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
attachLogger(bean);
return bean;
}
private void attachLogger(final Object bean) {
ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
if (Logger.class.isAssignableFrom(field.getType()) &&
(field.isAnnotationPresent(Autowired.class) ||
field.isAnnotationPresent(Inject.class))) {
ReflectionUtils.makeAccessible(field);
if (field.get(bean) == PlaceHolder.LOGGER) {
field.set(bean, LoggerFactory.getLogger(bean.getClass()));
}
}
}
});
}
#Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
}

Resources