I am trying to get NoUniqueBeanDefinitionException but i am not getting it any clue why i am not getting - spring

I am trying to get NoUniqueBeanDefinitionException but i am not getting it any clue why i am not getting
package com.example.demo;
public interface IDateGen {
}
package com.example.demo;
import org.springframework.stereotype.Service;
#Service
public class DateGen implements IDateGen {
}
package com.example.demo;
import org.springframework.stereotype.Service;
#Service
public class DateGen2 implements IDateGen {
}
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class DateGenUtil {
#Autowired
private IDateGen dateGen;
public IDateGen getDateGen() {
return dateGen;
}
public void setDateGen(IDateGen dateGen) {
this.dateGen = dateGen;
}
}
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class Demo3Application {
public static void main(String[] args) {
ApplicationContext appContext = SpringApplication.run(Demo3Application.class, args);
DateGenUtil util = appContext.getBean(DateGenUtil.class);
System.out.println(util.getDateGen());
}
}
When i run the main method i getting
com.example.demo.DateGen#6075b2d3
Can anyone tell why i am not getting NoUniqueBeanDefinitionException ? Thanks in advance

The dependency injection first checks for autoWiring by type and then autowire by name, wen it looks for dateGen dependency in class DateGenUtil it checks by type then it is getting two Objects, then again it tries to do autoWiringByName it gets the one object
if we rename the variable like in the below code it gives the exception, hope anyone can confirm this
#Component
public class DateGenUtil {
#Autowired
//private IDateGen dateGen;
private IDateGen date;
}

Related

Encountered error "Consider defining a bean of type 'java.util.concurrent.atomic.AtomicReference' in your configuration"

I am getting the below error while starting spring boot application.
The injection point has the following annotations:
#org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type
'java.util.concurrent.atomic.AtomicReference' in your configuration.
Below is the code .
package de.summer.sampleapplayerv1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#SpringBootApplication(scanBasePackages = {"de.summer.sampleapplayerv1"})
#EnableConfigurationProperties
#EnableJpaRepositories (basePackages ="de.summer.sampleapplayerv1.repository")
#EnableTransactionManagement
public class Sampleapplayerv1Application {
public static void main(String[] args) {
SpringApplication.run(Sampleapplayerv1Application.class, args);
}
}
package de.summer.sampleapplayerv1.service;
import de.summer.sampleapplayerv1.domain.QueueAndPublish;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
#Slf4j
#Service
public class QueueAndPublishServiceImpl implements QueueAndPublishService{
private final AtomicReference<List<QueueAndPublish>> currentJob;
public QueueAndPublishServiceImpl(
#Qualifier("currentJob") AtomicReference<List<QueueAndPublish>> currentJob
){
this.currentJob=currentJob;
}
#Override
public QueueAndPublish getJobStatus(UUID jobId) {
return (QueueAndPublish) currentJob.get().stream()
.filter(j -> j.getJobId()==jobId)
.collect(Collectors.toList());
}
#Override
public List<QueueAndPublish> getAllJobStatus() {
return currentJob.get();
}
#Override
public QueueAndPublish getCategoryDataProcess() {
List<QueueAndPublish> processList=new ArrayList<QueueAndPublish>();
QueueAndPublish process=QueueAndPublish.builder()
.jobId(UUID.randomUUID())
.jobName("Name for Job")
.jobStatus("Not Yet Started")
.build();
Thread t1=new Thread(process.getJobId().toString()){
#Override
public void run(){
log.info("How are you doing");
process.setJobStatus("Completed");
}
};
t1.start();
processList.add(process);
currentJob.set(processList);
return process;
}
#Override
public QueueAndPublish getCatgeoryDataProcessStatus() {
return null;
}
}
package de.summer.sampleapplayerv1.domain;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.io.Serializable;
import java.util.UUID;
#Getter
#Setter
#Builder
#Entity
public class QueueAndPublish implements Serializable {
#Id
private UUID jobId;
private String jobName;
private String jobStatus;
}
If I remove the constructor, spring boot application is starting up without any errors. If included , start up is failing with unsatisfied dependency errors.
Can someone please help on what is wrong with config?
You expect Spring to create an instance of class QueueAndPublishServiceImpl for the implementation of QueueAndPublishService. This instance needs a constructor parameter of type AtomicReference<List<QueueAndPublish>> injected.
But you obviously do not define any Spring bean (Bean, Component, Service, ...) of that type.
Edit:
public QueueAndPublishServiceImpl(
#Qualifier("currentJob") AtomicReference<List<QueueAndPublish>> currentJob
){
this.currentJob=currentJob;
}
Here you define a constructor parameter to have a AtomicReference<List<QueueAndPublish>>, and even specify it with a #Qualifier. So you need to provide a Spring bean of this class with this qualifier, otherwise Spring cannot inject it into the constructor call.
Consider defining a bean of type 'java.util.concurrent.atomic.AtomicReference' in your configuration.
Means "something like" adding this to your Sampleapplayerv1Application:
#Bean("currentJob") AtomicReference<List<QueueAndPublish>> currentJob() {
// or a list implementation of your choice.
return new AtomicReference<>(new java.util.ArrayList<>());
}

Spring Boot did not Autowiring

Can someone tell me please what I'm doing wrong, I'm trying to develop a little application but I just simply can't Autowire a class in the controller, I have been researching and I Know that for Autowire works, my class must be in a child package of my #SpringBootApplication annotation, or I should specify in #ComponentScan annotation the package of my class, but no matters what I do I still getting the same error:
This is my project structure:
package net.spring.auditoria;
import org.springframework.boot.SpringApplication;T
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class AuditoriaApplication {
public static void main(String[] args) {
SpringApplication.run(AuditoriaApplication.class, args);
}
}
Controller:
package net.spring.auditoria.bll;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
#Controller
public class AuditoriaController {
#Autowired
private AuditoriaManagement am;
private final Logger LOGGER = LoggerFactory.getLogger(AuditoriaController.class);
#GetMapping("/auditar")
public String auditar() {
LOGGER.info("auditar()");
return "main";
}
}
https://github.com/jlpm-mex/auditoria
Because AuditoriaManagement is not a Spring bean or component.

I'm trying to autowire my beans using #qualifier, but even after adding the qualifier I'm getting a "required single bean" exception

BubbleSort.java
This class implements SortAlgorithm interface
package com.prakash.Spring.Example;
import org.springframework.stereotype.Component;
#Component
#Qualifier("bubbleSort")
public class BubbleSort implements SortAlgorithm {
public void sort() {
System.out.println("Sort from Bubble Sort");
}
}
QuickSort.java
This class implements SortAlgorithm interface
package com.prakash.Spring.Example;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
#Component
#Qualifier("quickSort")
public class QuickSort implements SortAlgorithm {
#Override
public void sort() {
System.out.println("Sort from Quick Sort");
}
}
SortAlgorithm.java
package com.prakash.Spring.Example;
public interface SortAlgorithm {
void sort();
}
BinarySearch.java
In this class, I would like to use quickSort bean as my component.
package com.prakash.Spring.Example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
#Component
public class BinarySearch {
#Autowired
#Qualifier("quickSort")
private SortAlgorithm sortAlgorithm;
public BinarySearch(SortAlgorithm sortAlgorithm) {
super();
this.sortAlgorithm = sortAlgorithm;
}
public int[] search(int[] numbers) {
sortAlgorithm.sort();
System.out.println("This is from BinarySearch");
return numbers;
}
}
ComplexBusinessService.java
In this class, I'm getting the bean using getBean method
package com.prakash.Spring.Example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
#SpringBootApplication
public class ComplexBussinessService {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(ComplexBussinessService.class, args);
BinarySearch binarySearch = applicationContext.getBean(BinarySearch.class);
int[] result = binarySearch.search(new int[] { 2, 4, 3 });
for (int i : result) {
System.out.print(i+" ");
}
applicationContext.close();
}
}
Here is why. Actually, this is tricky part of Spring, understanding when and how dependency injection occurs.
Here is the order of dependency injection:
Injecting with the constructor of the class
Injecting fields (annotated by #Autowired)
Injecting the setters (also annotated with #Autowired)
The tricks is here:
If a class annotated by #Component has also only one non-default constructor, then this constructor is automatically called. As you call first the constructor, and then the field, your #Qualifier is not even interpreted by Spring because it fails during the constructor call, hence the exception.
To solve this, you have two options:
Either, remove your constructor from BinarySearch. Spring will then call the default constructor new BinarySearch() and then performing the injection in your field sortAlgorithm using the #Qualifier.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
#Component
public class BinarySearch {
#Autowired
#Qualifier("quickSort")
private SortAlgorithm sortAlgorithm;
public int[] search(int[] numbers) {
sortAlgorithm.sort();
System.out.println("This is from BinarySearch");
return numbers;
}
}
Or remove the annotation of your field and add a #Qualifier in your constructor parameter:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
#Component
public class BinarySearch {
private SortAlgorithm sortAlgorithm;
public BinarySearch(#Qualifier("quickSort") SortAlgorithm sortAlgorithm) {
super();
this.sortAlgorithm = sortAlgorithm;
}
public int[] search(int[] numbers) {
sortAlgorithm.sort();
System.out.println("This is from BinarySearch");
return numbers;
}
}
Hope it helps !
you also have to set your #Qualifier annotation on the type you annotated with #Component, e.g. like this:
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
#Component
#Qualifier("quickSort")
public class QuickSort implements SortAlgorithm {
#Override
public void sort() {
System.out.println("Sort from Quick Sort");
}
}
package com.prakash.Spring.Example;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Qualifier;
#Component
#Qualifier("bubbleSort")
public class BubbleSort implements SortAlgorithm {
public void sort() {
System.out.println("Sort from Bubble Sort");
}
}
I can't see import statement for Qualifier annotation in BubbleSort class. Could you import and then try if it works
Adding to the excellent answer from "RUARO Thibault", another way to resolve this error is how Spring Boot mentions when the application fails to start up.
Annotating one of the implementation class with #Primary will make that bean as the primary candidate when multiple candidates are found for autowiring.
#Component
#Qualifier("b")
#Primary
public class BubbleSortAlgorithm implements SortAlgorithm {}
In this case , BinarySearch bean will be constructed with the candidate marked #Primary . Then the field injection happens are replaces it with the bean with #Qualifier("quickSort")

Field required a bean of type that could not be found.'

The structure has no problem. The spring-boot can scan UserMapper but can't scan UserService. I tried to give my UserService #Mapper component, then it could be scanned. But I don't know how to use other methods to let it be scanned. I tried #Service but it doesn't work.
package com.mywebprojet.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class MywebprojectApplication {
public static void main(String[] args) {
SpringApplication.run(MywebprojectApplication.class, args);
}
}
package com.mywebprojet.springboot.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.mywebprojet.springboot.entity.User;
import com.mywebprojet.springboot.mapper.UserMapper;
import com.mywebprojet.springboot.service.UserService;
#RestController
#RequestMapping(value = "user")
public class UserController {
#Autowired
private UserMapper userMapper;
#Autowired
private UserService userService;
}
package com.mywebprojet.springboot.service;
import java.util.List;
import org.springframework.stereotype.Service;
import com.mywebprojet.springboot.entity.User;
#Service
public interface UserService{
void insert(User user);
}
You should write a UserService Implementation and have it annotated with #Service, not the interface. For example:
#Service
public class UserServiceImpl implements UserService {
#Override
public void insert(User user) {
// Implementation
}
}

How to make post request in apache camel rest

I am new apache rest dsl with spring boot, have made following changes
Main Class
package com.javaoutofbounds.pojo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = {"com.ccs.batchfile"})
public class BatchFileApplication {
public static void main(String[] args) {
SpringApplication.run(BatchFileApplication.class, args);
}
}
Service class
package com.ccs.batchfile.service;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.stereotype.Component;
#Component
public class BatchFileService extends RouteBuilder {
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/batchFile").consumes("application/json").produces("application/json").get("/routeStart").to("direct:startRoute");
}
}
Route class
package com.ccs.batchfile.routes;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ccs.batchfile.processor.StartRouteProcessor;
#Component
public class StartRoute extends RouteBuilder{
#Autowired
private StartRouteProcessor startRouteProcessor;
#Override
public void configure() throws Exception {
from("direct:startRoute").log("Inside StartRoute")
.process(startRouteProcessor);
}
}
Processor class
package com.ccs.batchfile.processor;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.springframework.stereotype.Component;
#Component("startRouteProcessor")
public class StartRouteProcessor implements Processor{
public void process(Exchange exchange) throws Exception {
String message = exchange.getIn().getBody(String.class);
System.out.println(message);
}
}
I am not getting control to StartRouteProcessor, when i make below post request in postman
http://localhost:8080/batchFile/routeStart/
I have used below test payload to check if works.
{
"title" : "test title",
"singer" : "some singer"
}
When i post the above request i am getting 404 error. Kindly help on this please
I tried your example and you need to add two changes.
In your "main" class, the 'component scan' annotation is right, but you have to add a 'ServletRegistrationBean' with name 'CamelServlet':
package org.funcode.app.main;
import org.apache.camel.component.servlet.CamelHttpTransportServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
#SpringBootApplication(scanBasePackages = {"org.funcode.app"})
public class BatchFileApplication {
private static final String CAMEL_URL_MAPPING = "/api/*";
private static final String CAMEL_SERVLET_NAME = "CamelServlet";
public static void main(String[] args) {
SpringApplication.run(BatchFileApplication.class, args);
}
#Bean
public ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean registration =
new ServletRegistrationBean(new CamelHttpTransportServlet(), CAMEL_URL_MAPPING);
registration.setName(CAMEL_SERVLET_NAME);
return registration;
}
}
And if you want view on the log the content you posted on the request, you need to change the method of the request to "post":
package org.funcode.app.main;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.stereotype.Component;
#Component
public class BatchFileService extends RouteBuilder {
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/batchFile")
.consumes("application/json")
.produces("application/json")
.post("/routeStart")
.to("direct:startRoute");
}
}
I hope it helps.

Resources