-3

I am very new to Spring Boot. I have created a repository, which looks like this:

public interface UserRepository extends CrudRepository<User, Long> {
    List<User> findByEmail(String email);
    User findById(long id);
}

user.java

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String email;
    private String password;
    private boolean verified;

    protected User() {}

    public User(String email, String password, boolean verified) {
        this.email = email;
        this.password = password;
        this.verified = verified;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean isVerified() {
        return verified;
    }

    public void setVerified(boolean verified) {
        this.verified = verified;
    }
}

And now I want to inject the repository into my controller. This is how I tried it:

@RestController
public class Register {

    @Autowired
    private UserRepository userRepository;

    @PostMapping("/register")
    public User registerUser() {
        return userRepository.save(new User("test@example.com", "password", true));
    }
}

Is my approach correct? If so, then why do I get a warning on @Autowired that says:

Field injection is not recommended

?

Tefly
  • 3
  • 2
  • 1
    Which IDE do you use. In my opinion your approach is correct – Jens Sep 01 '22 at 09:59
  • 8
    The question seems to be misleading. Field injection like you're doing is one way of doing it so if that works the title question would already be answered. Now the question would be: Why is field injection not recommended and what do I use instead? This might help answer the second question: https://stackoverflow.com/questions/39890849/what-exactly-is-field-injection-and-how-to-avoid-it – Thomas Sep 01 '22 at 10:01
  • @Jens I am using Intellij – Tefly Sep 01 '22 at 10:06
  • you need `@Repository` annotation on your repository interface. The field injection thing is different and you can find a link which @Thomas has posted. So basically what you have done is works but not recommended. Why? you can check the link Thomas mentioned. – Sangam Belose Sep 01 '22 at 10:09
  • Remove `@Autowired` from field and define a constructor to inject repository through constructor. Ignore advice about `@Repository` on the interface, it would have no impact at all (stereotype annotations are meant to be used with classes). – Alexander Ivanchenko Sep 01 '22 at 10:22

1 Answers1

3

You are applying field injection into your controller layer. There is a more efficient way to do that but first, take a look at why field injection is not recommended.

Reasons

  1. you can not define your dependent components as final(immutable).
  2. you can not instantiate your components for test purposes.
  3. your application may lead to circular dependencies.
  4. your application is tightly coupled to your container.

There may be more reasons that you can search for them if you want. So now take a look at better ways to perform dependency injection.

Constructor Injection

This purpose is just to define your required dependencies as parameters to the class's constructor.

Let's say we have a class called A

@Component
Class A {}

Notice that we have to define our class as a Component so the container can use it later.

Now we want to inject class A to class B with constructor injection purpose.

Class B {
    private final A a;
    
    Public B(A a) {
        this.a = a;
    }
}

We successfully performed constructor injection instead of field injection.

There is another way to do dependency injection called setter injection which is useful for injecting optional dependent components.

That's it.