How to properly inject @Autowired between Spring Boot classes?

Solution for How to properly inject @Autowired between Spring Boot classes?
is Given Below:

I have a classA which implements an interfaceA, with a methodA, then I have a classB in which I call classA with an @Autowired to be able to use methodA, but it gives me a warning that I must create a method for classA. Why is this happening? Doesn’t @Autowired work like this in this case? Should I just instantiate classA? Thank you very much for your answers.

ClassA

@RequiredArgsConstructor
public class RepositoryImpl implements IRepository {

    @Autowired
    private final TransactionDataMapper transactionDataMapper;

    @Autowired
    private SpringDataColminvoice springDataColminvoice;

    @Override
    public <S extends TransactionDto> S save(S s) {
        
        Colm colm = transactionDataMapper.toEntity(s);

        //methodA
        springDataColminvoice.save(colm);
        return null;
    }
}

InterfaceA

public interface IRepository extends IRepository<TransactionDto, Integer> {}

ClassB

@Service
@RequiredArgsConstructor
public class ServiceImpl implements IInvoiceService {

    @Autowired
    private RepositoryImpl repositoryImpl;
        
    @Override
    public void save(CMessage cMessage) throws HandlerException {
        try {

            TransactionDto transactionDto = cMessage.getTransaction();

            // methodA
            repositoryImpl.save(transactionDto);
        } catch (Exception e) {
            throw new HandlerException(e.getMessage());
        }
    }
}

Exception

Action:

***************************
APPLICATION FAILED TO START
***************************

Description:

Field RepositoryImpl in com.st.ms.yyu.d.binvoce.infraestructure.rest.spring.services.impl.InvoiceServiceImpl required a bean of type 'com.st.ms.yyu.d.binvoce.infraestructure.db.springdata.repository.impl.ServiceImpl' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.st.ms.yyu.d.binvoce.infraestructure.db.springdata.repository.impl.RepositoryImpl' in your configuration.

(posting this as an answer since I do not have enough reputation to comment)

As others have pointed out already, a code sample would help tremendously.
That being said, though, it sounds like you’re missing implementation for “ClassA”.

If you have an interface that “ClassA” implements, you have to implement the interface’s methods in “ClassA” before you can use them.

I assume your code currently looks somewhat like this?

public interface InterfaceA {

    void methodA();

}

public class ClassA implements InterfaceA {
}

public class ClassB {

    @Autowired
    ClassA classA; // Cannot use {@link InterfaceA#methodA} because the class does not implement the function

}

If this is your code, make sure you add an implementation for your “methodA()” function in “ClassA”. Somewhat like so:

public class ClassA implements InterfaceA {

    @Override
    public void methodA() {
    }

}

Additionally, in order to autowire in Spring (Boot), you need to ensure that the class you’d like to autowire is marked as such. You can autowire beans.

To make “ClassA” in the example eligible for autowiring, make sure to instantiate it either as:

  • A bean (using the @Bean annotation).
  • A component (using the @Component annotation).
  • A service (using the @Service annotation).
  • Any of the other annotations that may match your use case the best.

In our example, this would look somewhat like this:

@Component // Or @Service / whatever you may need
public class ClassA implements InterfaceA {

    @Override
    public void methodA() {
    }

}

Hope you’ve found any of this helpful. All the best!

-T

As what I have understood, @Autowire means injecting the value/instance of the specific property where you put the annotation @Autowire. In this case, @Autowire only happens when there is defined/created Bean within your basePackage of your Spring Boot project that can match it, i.e. where your @Autowire referred to (meaning there is no conflict issue like ambiguity, etc. and the DataType(Class) can be implicitly casted). In your example, first you treat the IRepository and/or RepositoryImpl as Repository without using the @Repository annotation to inform the Spring Boot default configuration that this is a Repository bean. As you didn’t put the POM.xml or posted the related code, I presumed you are creating your own repository class. I think it’s much better to post your dependencies here.

But as what others pointed out. You need to create a bean that can match the @Autowired you’ve put on TransactDataManager & SpringDataColminvoice. You need also to inform the Spring Boot or register it that your class A is a Bean by annotating

@Bean - defining a regular bean, 
@Component - a Component in the Project, 
@Service - a Service in the Project, 
@Repository - a Repository (if you're using Spring JPA), etc. 
@<Other Annotations depending of what other Spring Project/Dependencies your using>

Since newer versions of Spring is moving to annotation based from XML mapping, we need to put proper annotation for each class/object that we want to be auto injected/instantiated from @Autowired using the above sample annotations depending on the role/purpose of your class/object is.

I suggest if you’re not sure. Then create a typical bean using common annotation @Bean. So your class A might be

@Component //Insert proper Annotation for your class if necessary. This is just a sample
@RequiredArgsConstructor
public class RepositoryImpl implements IRepository {

    @Autowired
    private final TransactionDataMapper transactionDataMapper;

    @Autowired
    private SpringDataColminvoice 
    springDataColminvoice;//segunda

    @Override
    public <S extends TransactionDto> S save(S s) {
       //Some implementation
    }

    @Bean
    private TransactionDataMapper getTransactionDataMapper(<Some parameters if needed>){
       return <an instance for TransactionDataManager>;
    }

    @Bean
    private SpringDataColminvoice getSpringDataColmInvoice(<Some parameters if needed>){
       return <an instance for SpringDataColminvoice>;
    }
}

Note that 2 beans definition are optional if there are already a Beans define on outside class or if it was marked by other annotation like @Service, @Component or other proper annotations and the other one bean is just a reference parameter for the other bean in order to properly instantiated.

In your class B is the following:

public class ClassB {

    @Autowired
    ClassA classA; 

    /*Note: ignore this Bean definition if Class A is annotated with @Component,
       @Service, or other proper @Annotation for Class A.
    */
    @Bean
    private ClassA getClassA(<Some Parameters if Needed>){
       return <Instance of Class A>
    }

}

Take note that, you don’t need to put a Bean definition inside the Class B if you put a proper annotation for your Class A like @Component, @Service, etc.