New Method to Spring Controller causing Errors!

THIS IS A PSA

I'm a firm believer in learning from humility, and I maintain this blog to come back to when I forget to do something I spent time trying to figure out.


TLDR:

Make sure that all your endpoint methods have the same modifier. Private or Public (public makes more sense I think) or you will face a cycle of confusing bordering on insanity.


Here's the deal.

I had a controller to hande getting items. It looked something like this:

@RestController
@Secured("ROLE_USER")
@RequestMapping(value="/api/items")
public class ItemController extends AbstractController {  
  @Autowired
  private ItemService service;

  @RequestMapping(value="", method=RequestMethod.GET)
  @ResponseStatus(HttpStatus.OK)
  @ResponseBody
  private DtoObject getItems(@RequestParams Map<String, String> params){
    return service.getItems(params);
  }
}

Pretty simple, yes?
This worked just fine for a limited production application. This project is the definition of a CI project for an awkward internal startup-esque environment.

Whelp, I got sick of importing excel sheets manually into SQL Server so I decided to write an upload function. It's not at all awesome, nor reusable unless you are using my exact same POJO structure for Item, so I'm not sharing it.

Straight to the point - I added a new endpoint to the @RestController.

//...
  @RequestMapping(value="/upload", method = RequestMethod.POST)
  @ResponseStatus(HttpStatus.ACCEPTED)
  public void uploadItems(@RequestParam(value="file") MultipartFile file){
    service.handleItemUpload(file);
  }
//...

This also required me to set up a bean to handle Multipart File uploading, which was really simple. Just load it into my configuration class.

//...
  @Bean
  public MultipartResolver multipartResolver(){
    return new StandardServletMultipartResolver();
  }
//...

Run my tests like every good developer should and lo and behold:

Null Pointer Exception  
  at getItems(...

After a load of crawling through code, rolling back and slowly implementing piece by piece, I discovered this little tidbit:

//...
 public void uploadItems();
 private DtoObject getItems();
//...

Did you see it?
The problem lies in the use of modifiers. Which is a super noob error, but one that I encountered more than once. This time, it's documented and hopefully I don't forget about it in another 4 years.

I don't know if you're supposed to use private or public modifiers or if it matters, but make sure you use the same one for all your endpoint functions to avoid having this circle of chaos that I experienced today.

Cheers!