3

I'm still pretty new to Spring, but I'm currently facing an issue of which I don't know the cause and I can't figure it out with only a nullpointerexception.

I have 2 classes that both implement the same Abstract class. InventoryService and InventoryMailService. All 3 are in the same package that is successfully being scanned with component-scan. I'm trying to use my globalPrefService bean, which I can succesfully use in my InventoryService but somehow not in my InventoryMailService.

This is my AbstractService that I use to wire my services together:

package com.paperfoam.inventory.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("abstractService")
public abstract class AbstractService {

    protected InventoryService inventoryService;
    protected FinancialCalculationService financialCalculationService;
    protected SupplierService supplierService;
    protected UserService userService;
    protected GlobalPrefService globalPrefService;

    @Autowired
    public void setGlobalPrefService(GlobalPrefService globalPrefService) {
        this.globalPrefService = globalPrefService;
    }

    @Autowired
    public void setInventoryService(InventoryService inventoryService) {
        this.inventoryService = inventoryService;
    }

    @Autowired
    protected void setFinancialCalculationService(FinancialCalculationService financialCalculationService) {
        this.financialCalculationService = financialCalculationService;
    }

    @Autowired
    protected void setSupplierService(SupplierService supplierService) {
        this.supplierService = supplierService;
    }

    @Autowired
    protected void setUsersService(UserService userService) {
        this.userService = userService;
    }


}

This is the the InventoryService (minus some non-related functions), when I try to call my GlobalPrefService it works just fine:

package com.paperfoam.inventory.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.paperfoam.inventory.dao.InventoryDao;
import com.paperfoam.inventory.dao.InventoryLogItemDao;
import com.paperfoam.inventory.objects.InventoryItem;
import com.paperfoam.inventory.objects.InventoryLogItem;

@Service("inventoryService")
public class InventoryService extends AbstractService {

    private InventoryDao inventoryDao;
    private InventoryLogItemDao inventoryLogItemDao;

    public InventoryDao getInventoryDao() {
        return inventoryDao;
    }

    @Autowired
    public void setInventoryDao(InventoryDao inventoryDao) {
        this.inventoryDao = inventoryDao;
    }

    @Autowired
    public void setInventoryLogItemDao(InventoryLogItemDao inventoryLogItemDao) {
        this.inventoryLogItemDao = inventoryLogItemDao;
    }
    // This is the method where I succesfully use my GlobalPrefService
    public List<InventoryItem> getAllInventoryItems() {
        System.out.println(globalPrefService.getPreferenceValue("mailusername")); // this succesfully prints my preferenceValue to the console
        return inventoryDao.getInventoryList();

    }
} 

However, I have my other class (same package) that extends the same AbstractService that returns a NullPointerException when I try to use it:

package com.paperfoam.inventory.service;

import java.io.File;
import java.util.logging.Logger;

import javax.mail.internet.MimeMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.mail.MailParseException;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import com.paperfoam.inventory.config.JavaBeanConfig;
import com.paperfoam.inventory.objects.InventoryItem;
import com.paperfoam.inventory.objects.Supplier;

@Service("inventoryMailService")
public class InventoryMailService extends AbstractService {


    public void sendMessageWithAttachment(String to, String subject, String text, String pathToAttachment) {

        System.out.println(globalPrefService.getPreferenceValue("mailusername")); // NullPointerException on the globalPrefService!
        /*
        JavaBeanConfig javaBean = new JavaBeanConfig();
        JavaMailSender mailSender = javaBean.getJavaMailSender(globalPrefService);

        try {

        MimeMessage message = mailSender.createMimeMessage();

        MimeMessageHelper helper = new MimeMessageHelper(message, true);


            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(text);

        Resource file = new ClassPathResource(pathToAttachment);
        helper.addAttachment("hoera.png", file);

        mailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
        */
    }
} 

The error I get:

SEVERE: Servlet.service() for servlet [paperfoam] in context with path [/bulletjournal] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
    at com.paperfoam.inventory.service.InventoryMailService.sendMessageWithAttachment(InventoryMailService.java:30) // This is the system.out line
    at com.paperfoam.inventory.controllers.InventoryController.showInventoryStatistics(InventoryController.java:165)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:624)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:110)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:506)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:962)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:445)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1115)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:637)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source) 

I have been staring at this for a while and I can't figure out what causes this. Everything is annotated in the same way, they extend the same class that autowires the bean in, they are in the same package that is being scanned and the access modifiers are also the same.

I also tried to clean/rebuild my project a few times, does anyone have any idea what I am missing here?

Thank you for reading.

In response to the comment:

My InventoryService gets Autowired in the controller.

protected InventoryService inventoryService;

@Autowired
    public void setInventoryService(InventoryService inventoryService) {
        this.inventoryService = inventoryService;
    } 

But I manually instantiate my InventoryMailService (and I'm starting to think thats the mistake) for debugging.

    @RequestMapping(value = { "/statistics", "/" })
    public String showInventoryStatistics(Model model) {

        Map<Integer, Long> calculated = financialCalculationService.getSuppliersWithTotalWorth();
        List<Supplier> allSuppliers = supplierService.convertSupplierHashmapToObjectList(calculated);

        List<InventoryItem> lowItems = inventoryService.getLowInventoryItems();
        List<InventoryLogItem> recentChanges = inventoryService.getRecentChanges();

        model.addAttribute("suppliers", allSuppliers);
        model.addAttribute("lowitems", lowItems);
        model.addAttribute("recentchanges", recentChanges);

        InventoryMailService mail = new InventoryMailService();
        System.out.println(mail.toString());
        mail.sendMessageWithAttachment("Redacted@gmail.com", "betere mail", "test123", "com/paperfoam/inventory/mail/success.png");

        return JspPage.INVENTORY_STATISTICS;
    } 

I didn't even stop to think that that might affect the autowiring down the road, does that matter to spring?

Roy
  • 102
  • 1
  • 8
  • 1
    Are you autowiring InventoryMailService in InventoryController? – brub Dec 21 '17 at 12:47
  • 1
    How are you triggering InventoryService and InventoryMailService. Put that code as well – pvpkiran Dec 21 '17 at 12:48
  • Ill make an edit, code doesnt work in the comment – Roy Dec 21 '17 at 12:52
  • @pvpkiran I edited my post – Roy Dec 21 '17 at 12:58
  • But I manually instantiate my InventoryMailService (and I'm starting to think thats the mistake) ----> You are learning fast. :D – pvpkiran Dec 21 '17 at 12:59
  • I already tried it out and that fixed it! Thanks for the fast advice. I somehow completely missed that you can't manually instantiate a wiring dependent class! Thank you! – Roy Dec 21 '17 at 13:01

1 Answers1

1

For spring to handle dependency injection the entire dependency chain needs to be autowired, so you need to also autowire InventoryMailService in InventoryController.

brub
  • 1,083
  • 8
  • 18
  • Thanks I did not know this, I made the mailService yesterday with everything hardcoded in to figure out how it worked so I was a bit stumped. Never making that mistake again! – Roy Dec 21 '17 at 13:03
  • heh- how do you think I learned it? :) – brub Dec 21 '17 at 13:08