0

Looking through this question why-is-my-spring-autowired-field-null, it seems the most common reason why an @Autowired member object is null is because the containing class was created with "new" without a @Configurable (and some other processes) and the next most common reason is that an @Autowired/@Component/@Service/@[Rest]Controller/@Repository tag was missing somewhere in the hierarchy of classes. There's also something involve AspectJ and AOP, but I don't know what those are so hopefully I'm not using them.

So, I assume it's one of the first 2, so can I have a fresh pair of eyes to find where I screwed up?

First the error: This happens when I use Postman to invoke POST /api/register

java.lang.NullPointerException: Cannot invoke "engine.Service.UserAccountService.addUser(engine.Entities.UserAuthenticate)" because "this.userAccountService" is null at engine.Controller.UserController.newUser(UserController.java:26) ~[classes/:na] {snip}

Second the UserController:

@CrossOrigin(origins = "*")
@RestController
@RequestMapping("api/")
@Validated
public class UserController {

  @Autowired
  private UserAccountService userAccountService;

  @PostMapping("register")
  private ResponseEntity<String> newUser(@Valid @RequestBody UserAuthenticate userAuthenticate){
    if (userAccountService.addUser(userAuthenticate)){
      return ResponseEntity.status(HttpStatus.OK).build();
    }
    else{
      return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
    }
  }
}

Third the UserAccountService:

@Service
public class UserAccountService {

  @Autowired
  private UserAccountRepository userAccountRepository;

  @Autowired
  private UserSecurityService userSecurityService;

  public boolean addUser(UserAuthenticate userAuthenticate) {
    if (userSecurityService.existsByUsername(userAuthenticate.getEmail())) {
      return false;
    }
    UserAccount sec = userSecurityService.save(userAuthenticate.getEmail(), userAuthenticate.getPassword());
    userAccountRepository.save(sec);
    return true;
  }
}

Now, from the link, my problem should be caused because UserController was created incorrectly, or is a member of a class that was created incorrectly. But UserController is, as far as I can tell, created by Spring. And I've search my entire code for accidentally "new"ing it and that all Spring controlled classes are properly annotated, and short of posting my entire project code, I'm not sure how to show that I have.

Does anyone know any tools or techniques I can use to track this down? Am I missing something obvious? Is the problem something completely else? Like, right now, it shouldn't matter if any of my program (or "business") logic is correct or not, because it's not even being called, right?

Note, I've found this and this, and every other search result is either irrelevant, or a literal copy of these three.

Edit: I'm not certain what you mean by ApplicationContext but here's my SpringApplication:

@SpringBootApplication
public class WebQuizEngine {

    public static void main(String[] args) {
        SpringApplication.run(WebQuizEngine.class, args);
    }

}

And my beans (note, this project is from a Hyperskill.org project/lesson so there's probably a lot of extra stuff: for one, the actuator/beans endpoint was already set up):

3,002 lines! is too much to paste here lol Looking through it, I can't find anything that stands out.

and yes, I've been debugging, but I have so much trouble debugging these Spring errors as the errors are often cryptic (in general, this error message is straight forward) and often don't point to where the error occurred. So if anyone has any debugging tips for Spring, I'd be very grateful. (The beans list looks interesting!)

bmargoat
  • 46
  • 7
  • how do you create the ApplicationContext and have you done some debugging? Furthermore, you can show all created beans by using https://stackoverflow.com/questions/33348937/print-all-the-spring-beans-that-are-loaded-spring-boot – wake-0 Jun 23 '22 at 20:41
  • In this narrow example, if you switch all of your autowired beans from field injection to [constructor injection](https://www.baeldung.com/constructor-injection-in-spring) with `final` fields, do you get a clearer error message? – Makoto Jun 24 '22 at 18:04
  • The only thing that stands out to me is that the newUser method in your controller is private, which is unusual. I’m not sure why it would cause the behaviour you’re seeing - possibly something to do with the way Spring is proxying the class, because private methods can’t be proxied. I’m actually surprised it finds it at all. – rimesc Jun 24 '22 at 19:29
  • A comment on https://stackoverflow.com/a/46031602/2945996 suggests that the private modifier can cause this, although it doesn’t explain why. – rimesc Jun 24 '22 at 19:36
  • The root of the problem *seems* to be that Spring ignores private mapping functions, so a non-Spring version of the function/class is used, which means Spring doesn't fulfill the dependencies. Although if Spring ignores the function, how is it still connected to the dispatcher with Spring annotations? – bmargoat Jun 27 '22 at 15:57
  • The problem was `newUser()` in the controller was marked `private` which I completely missed, so thank you @rimesc! – bmargoat Jul 01 '22 at 20:24

0 Answers0