0

I can't figure out why all my beans are null in the controller. I understand that this is a common question but I am not instantiating the object with new.

Controller:

@Controller
@RequestMapping("/store")
public class MyController {

    @Autowired
    private MyService myService;

    @GetMapping("/getOptions")
    private String getOptions(HttpServletRequest request)
    {
        myService.doSomething(request);
        ....
    }
}

When I request http://localhost/store/getOptions I get a NullPointerException on myService.

MyService

@Service
public class MyService
{
    ....
}

WebConfig

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean
    BeanNameUrlHandlerMapping beanNameUrlHandlerMapping()
    {
        return new BeanNameUrlHandlerMapping();
    }
}

Main

@SpringBootApplication
@Configuration
@ComponentScan(basePackages = { "com.mypackage.config", "com.mypackage.service", "com.mypackage.controller"})
public class MyApplication
{
    public static void main(String[] args)
    {
        if (AuthConfigFactory.getFactory() == null)
            AuthConfigFactory.setFactory(new AuthConfigFactoryImpl());
        SpringApplication.run(MyApplication.class, args);
    }
}

When I start the application, I can see in the logs that the myService bean is actually being Autowired into the controller:

- Processing injected element of bean 'myController': AutowiredFieldElement for private com.mypackage.service.MyService com.mypackage.controller.MyController.myService
- Returning cached instance of singleton bean 'MyService'
- Autowiring by type from bean name 'myController' to bean named 'myService'

So I don't understand why when I try to access myService within the controller, it is null. I do not instantiate the controller anywhere with new.

Clipped Exception

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause:
java.lang.NullPointerException: null
at com.mypackage.controller.MyController.getOptions(MyController.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
....

Edit:

I've removed web.xml from my project, as it is irrelevant.

Freddie
  • 172
  • 1
  • 5
  • 15
  • 3
    Why are you using a web.xml if you have a Spring-boot project? – Roddy of the Frozen Peas Jan 30 '18 at 23:18
  • I used web.xml as directed by https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc-servlet – Freddie Jan 30 '18 at 23:30
  • What is the **root cause** the log error is talking about? – baao Jan 30 '18 at 23:32
  • 1
    That reference doc is not for spring-boot, it's for spring-webmvc. web.xml is the old way of doing things. I think (though I've never tried to mix these two) that you have to declare a dependency on spring-boot-legacy and register SpringBootContextLoaderListener as a listener as detailed [in this answer](https://stackoverflow.com/questions/43225549/dispatcherservlet-and-web-xml-in-spring-boot) so that Spring-boot knows that your webxml even exists. – Roddy of the Frozen Peas Jan 30 '18 at 23:34
  • @RoddyoftheFrozenPeas Thanks for pointing that out. If web.xml is the old way, then I don't want to do it that way. I have also tried implementing AbstractAnnotationConfigDispatcherServletInitializer and removing web.xml but the results are the same. – Freddie Jan 30 '18 at 23:37
  • @baao I've updated the exception on my original post. – Freddie Jan 30 '18 at 23:38
  • Can you show the definition of your MyService class? – Alejandro Agapito Bautista Jan 30 '18 at 23:49
  • @AlejandroAgapitoBautista Are you checking to see if I've annotated it properly? I have `@Service` on it. Added definition to the original question. – Freddie Jan 30 '18 at 23:57
  • @Makoto Please review their edit. – Sotirios Delimanolis Jan 31 '18 at 00:16
  • Sorry this has been marked as a duplicate, Freddie, since the "duplicate" question's answers aren't relevant. For starters, you only need to put the `@ComponentScan` on one class (usually the one annotated `@SpringBootApplication`). But if I were you I would start with the Spring [RESTful web service example](https://spring.io/guides/gs/rest-service/) tutorial (notice, no dispatcher servlet in sight since it's part of the spring-boot framework) and expand from there. – Roddy of the Frozen Peas Jan 31 '18 at 04:08
  • Are your Services in a different package than your main? If not, then simply remove `@ComponentScan` as it is already defined in `@Configuration`. If you do put your Services, etc. in an entirely different package than your main class, then make sure the package names are correct. – Merve Sahin Jan 31 '18 at 21:07

2 Answers2

1

My problem was that some of the methods in my controller were annotated as @Transactional. I did not provide enough information in my original post for anyone to figure that out. I found the answer here: Why we shouldn't make a Spring MVC controller @Transactional?

Freddie
  • 172
  • 1
  • 5
  • 15
0

Spring java configuration:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{

    @Bean 
    BeanNameUrlHandlerMapping beanNameUrlHandlerMapping(){
        return new BeanNameUrlHandlerMapping();
    }
}

Service class:

@Service("myService")
public class MyServiceImpl implements MyService{

    @Override
    public String getMessageinfo() {
        // TODO Auto-generated method stub
        return "Hello World!!";
    }
}

Service interface:

public interface MyService {
    public String getMessageinfo();
}

Controller class:

@RestController
@RequestMapping("/hello")
public class MyController {

    @Autowired
    private MyService myService;

    @GetMapping("/getMessage")
    //@ResponseBody
    private String getMessage(HttpServletRequest req){
        System.out.println("inside controller : - "+myService.getMessageinfo());
        return myService.getMessageinfo();
    }
}

SpringbootMain

@SpringBootApplication
@Configuration
@ComponentScan(basePackages={"com.example.demo.config","com.example.demo.controller","com.example.demo.service"})
public class Demo1Application {

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

This worked for me. without exception, but i used eclipse STS IDE and created Spring boot project. http://localhost:8080/hello/getMessage

Tim
  • 1,321
  • 1
  • 22
  • 47