Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"required a single bean, but 2 were found" - Spring

Here is my class:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import com.mportal.ec.exception.ApplicationSpecificException;

@ControllerAdvice
public class DefaultExceptionHandler extends ResponseEntityExceptionHandler {

    @Autowired
    private final MessageSourceAccessor messageSource;


    public DefaultExceptionHandler(MessageSourceAccessor messageSource) {
        Assert.notNull(messageSource, "messageSource must not be null");
        this.messageSource = messageSource;
     }

      //expected Exceptions
      @ExceptionHandler(ApplicationSpecificException.class)
      protected ResponseEntity<Object> handleApplicationSpecificException(final RuntimeException ex, final WebRequest request) {
          final String bodyOfResponse = "This should be application specific";
          return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
      }


      //unexpected Exceptions
      @ExceptionHandler(Exception.class)
        protected ResponseEntity<Object> handleException(final RuntimeException ex, final WebRequest request) {
          final String bodyOfResponse = "This should be application specific";
          return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
      }
}

In my project, I'm using spring-boot/hibernate/ java based configuration and trying to implement an exception handling mechanism.I'm using an example code i got from StackOverflow and learn what's the best way to handle exceptions in spring. But when I run the code, I get this error. But when I stopped using "MessageSourceAccessor" the error goes away.

Description:

Parameter 0 of constructor in com.mportal.ec.error.DefaultExceptionHandler required a single bean, but 2 were found:
    - linkRelationMessageSource: defined by method 'linkRelationMessageSource' in class path resource [org/springframework/hateoas/config/HateoasConfiguration.class]
    - resourceDescriptionMessageSourceAccessor: defined by method 'resourceDescriptionMessageSourceAccessor' in class path resource [org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.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

How do I resolve this?

like image 932
Harsha Jayamanna Avatar asked Jul 18 '17 09:07

Harsha Jayamanna


People also ask

What is the use of @qualifier and @primary?

It's worth noting that if both the @Qualifier and @Primary annotations are present, then the @Qualifier annotation will have precedence. Basically, @Primary defines a default, while @Qualifier is very specific.

Does spring allows multiple bean for the same class?

This is the simplest and easiest way to create multiple beans of the same class using annotations. In this approach, we'll use a Java-based configuration class to configure multiple beans of the same class.

Can we use @qualifier and @primary together?

We can use @Qualifier and @Primary for the same bean. Use @Qualifier to inject specific bean otherwise Spring injects bean by default which is annotated with @Primary.

Can you Autowire byType when multiple beans?

autowire byType - For this type of autowiring, class type is used. So there should be only one bean configured for this type in the spring bean configuration file. autowire by constructor - This is almost similar to autowire byType, the only difference is that constructor is used to inject the dependency.


1 Answers

You are using both constructor injection and field injection.

public DefaultExceptionHandler(MessageSourceAccessor messageSource) {
    Assert.notNull(messageSource, "messageSource must not be null");
    this.messageSource = messageSource;
 }

and

   @Autowired
   private final MessageSourceAccessor messageSource;

Choose only one.

like image 58
Anupama Boorlagadda Avatar answered Oct 14 '22 11:10

Anupama Boorlagadda