I am currently trying to use the new Java based annotation configuration for both spring and my Java Web Servlets. I am currently having an issue using the @Autowired annotation inside the servlet itself, but I am unsure if it is my configuration files or a misstep with my use of AbstractAnnotationConfigDispatcherServletInitializer to bootstrap the servlet configuration.
I have searched the forum and thought I had found the answer using the following code snippet :
public void init(ServletConfig config) {
super.init(config);
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,config.getServletContext());
}
However it seems upon debugging that the "ServletConfig" - context is null and leads to the following error due to no beans being registered:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.fdmgroup.bookshop.service.BookService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1486)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.processInjection(AutowiredAnnotationBeanPostProcessor.java:387)
at org.springframework.web.context.support.SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(SpringBeanAutowiringSupport.java:110)
at com.fdmgroup.bookshop.controller.HomeController.init(HomeController.java:46)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1183)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1099)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:779)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:133)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
I am currently unsure whether the @ComponentScan is not being activated properly in my WebConfig Class, the ServletConfig context is not being loaded properly, or something else altogether is at play. any help would be much appreciated!
WebServlet:
@WebServlet("/")
public class HomeController extends HttpServlet {
private static final long serialVersionUID = 1L;
@Autowired
private BookService bookService;
public HomeController() {
}
public HomeController(BookService bookService) {
this.bookService = bookService;
}
public void init(ServletConfig config) throws ServletException {
super.init(config);
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this,config.getServletContext());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
List<Book> books = bookService.retrieveAllBooks();
request.setAttribute("books", books);
request.getRequestDispatcher("/WEB-INF/index.jsp").forward(request, response);
}
Java configuration files:
public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getServletConfigClasses() {
System.out.println("in Servlet Initializer");
return new Class[] { WebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class };
}
}
WebConfig.class:
@Configuration
@EnableWebMvc
@ComponentScan({ "com.fdmgroup.bookshop" })
public class WebConfig extends WebMvcConfigurerAdapter {
}
RootConfig.class:
@Configurable
public class RootConfig {
}
BookService.class:
@Service
public class BookService {
@Autowired
private CRUD<Book> bookRepository;
public BookService(CRUD<Book> bookRepository) {
this.bookRepository = bookRepository;
}
public BookService() {
}
public void createBook (Book book){
bookRepository.create(book);
}
public Book retrieveBook (long id){
return bookRepository.retrieve(id);
}
public void deleteBook (long id){
bookRepository.delete(id);
}
public List<Book> retrieveAllBooks (){
return bookRepository.retrieveAll();
}
}
Thanks!