Alexis Dufrenoy
Alexis Dufrenoy

Reputation: 11946

NullPointerException on dependency injection with Spring

I have 3 types.

ServiceAffaire.java:

package ws.magicnew.sync;

...

@Transactional
@Service("serviceAffaire")
public class ServiceAffaire implements IServiceAffaire {

    private static Log log = LogFactory.getLog(ServiceAffaire.class);

    //private static SimpleDateFormat sdf = new SimpleDateFormat(MagicFacade.WS_DATE_FORMAT);

    @Autowired
    @Qualifier("manifestationService")
    protected IManifestationService manifestationService;

    @Autowired
    @Qualifier("typeDeManifestationService")
    protected ITypeDeManifestationService typeService;

    @Autowired
    @Qualifier("espaceManifestationService")
    protected IEspaceManifestationService espaceManifService;

    @Autowired
    @Qualifier("siteService")
    protected ISiteService siteService;

    @Autowired
    @Qualifier("natureService")
    protected INatureService natureService;

    @Autowired
    @Qualifier("facadeGetAffaire")
    protected MagicFacade facadeGetAffaire;

    @Autowired
    @Qualifier("compteurManifestation")
    private Compteur compteurManifestation;

    @Autowired
    @Qualifier("compteurContenus")
    protected Compteur compteurContenus;

        public synchronized void synchronize(boolean setFlag) throws Exception {
            ...
        }
}

IServiceAffaire.java:

package ws.magicnew.sync;

public interface IServiceAffaire {

    public void synchronize(boolean setFlag) throws Exception;

}

and CacheAction.java:

package ws.magicnew.sync;

...

@Configurable
@Transactional
public class CacheAction extends DispatchAction {

    private static Log log = LogFactory.getLog(CacheAction.class);

    @Autowired
    @Qualifier("serviceAffaire")
    private IServiceAffaire serviceAffaire;

    public ActionForward getAffaire(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
        boolean setFlag = Boolean.parseBoolean(CmsProperties.SYNCRO_AFFAIRES_FLAG);
        log.info("getAffaire debut " +setFlag);
        serviceAffaire.synchronize(setFlag); // NullPointerException here: serviceAffaire is null
        log.info("getAffaire fin " +setFlag);
        request.setAttribute("message", "Le service get affaire a été lancé.");

        return mapping.findForward("cache");
    }
}

The wiring is made in a applicationContext-scanpackages.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
    xmlns:jaxws="http://cxf.apache.org/jaxws" 
    xmlns:cxf="http://cxf.apache.org/core" 
    xsi:schemaLocation="
            http://www.springframework.org/schema/aop 
                http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
            http://www.springframework.org/schema/beans 
                http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/jee 
                http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
            http://www.springframework.org/schema/tx 
                http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
            http://www.springframework.org/schema/util 
                http://www.springframework.org/schema/util/spring-util-3.0.xsd
            http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring 
                http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd 
            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
            http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd">
    <context:annotation-config />
    <context:component-scan base-package="ws.magicnew.sync" />
    <context:component-scan base-package="ws.magicnew.facade" />
</beans>

This seems ok to me, but I still get a NullPointerException when I'm calling the CacheAction.getAffaire() method. I can't figure out why and it's driving me crazy. Any clue?

I had previously some issues with the injection of the attributes of ServiceAffaire (which I solved), so Spring is actually autowiring them. But for some reason, it is unable to inject ServiceAffaire into CacheAction.

As indicated as comment in the code, the serviceAffaire attribute is null when ServiceAffaire.synchronize is called, as I can see when I execute in debug mode.

Upvotes: 0

Views: 6188

Answers (2)

Usha
Usha

Reputation: 1468

Can you try changing the dependency injection annotation for IServiceAffaire to @Resource and check if that works

@Autowired
@Qualifier("serviceAffaire")
private IServiceAffaire serviceAffaire; 

Change to

@Resource(name ="serviceAffaire")
private IServiceAffaire serviceAffaire;

Upvotes: 0

gguardin
gguardin

Reputation: 551

Your problem could be two things:

First you need to add "context:spring-configured" in applicationContext-scanpackages.xml to enable AspectJ.

http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-atconfigurable

Second, you have CacheAction as @Configurable, I suppose that you did this because you or some framework create instances of CacheAction with a classic "new CacheAction()" instead of letting Spring to create it.

If that's the case, a NPE could happend if you create an instance of CacheAction by code before Spring initializes an IServiceAffaire bean. I mean, when you create an instance of CacheAction using "new" you have to be sure that Spring have already finalized initializing all beans that CacheAction needs. Otherwise Spring won't be available to inject dependencies.

That could be tricky if some framework creates new instances of CacheAction and you can't control when those instances are created. It doesn't matters if you add annotations like "depends-on", since Spring won't be able to hold that instance creation until it finish creating the beans that needs to inject.

One way to solve this is to let Spring initialize some bean that will fire the initialization of whatever creates new instances of CacheAction, and add a "depends-on" IServiceAffaire bean there.

Anyway a right solution depends on how your application is initialized.

Upvotes: 2

Related Questions