1

My application context XML is simple:

<context:component-scan base-package="com.depressio.spring" />

In that package, I have my configuration:

package com.depressio.spring

@Configuration
@ComponentScan(basePackages = "com.depressio")
public class DepressioConfiguration
{
    @Inject private ApplicationContext context;
}

Within com.depressio, there's a repository (DAO):

package com.depressio.dao;

@Repository
public class ParameterDAO
{
    public Parameter getParameter(long ID) { ... }
}

... and a service where injection is working just fine (no NPE when parameterDAO is used):

package com.depressio.resource;

@Service
@Path("/depressio/parameters")
public class ParameterResource
{
    @Inject private ParameterDAO parameterDAO;

    @Path("{id}")
    public Response getParameter(long parameterID)
    {
        return Response.ok(parameterDAO.getParameter(parameterID).legacyFormat()).build();
    }
}

However, the legacyFormat() method call there constructs another object. Within that object, I have to inject a different DAO (also annotated with @Repository, though). That injection isn't working.

So, we have the original Parameter object:

package com.depressio.domain;

public class Parameter
{
    ...
    public LegacyParameter legacyFormat()
    {
        return new LegacyParameter(this);
    }
}

... and the LegacyParameter where the injection isn't working:

package com.depressio.domain.legacy;

public class LegacyParameter
{
    @Inject private LegacyDAO legacyDAO;
    ....
    public LegacyParameter(Parameter newParameter)
    {
        // NullPointerException when using the injected legacyDAO.
    }
}

I've tried a few things, including:

  • Using an no-args constructor for LegacyParameter, then calling a populate method so I'm not using the injected DAO until after the object is constructed. This didn't work.

  • Injecting the LegacyDAO into the ParameterResource and passing it in. This worked, but isn't ideal since I have to pass it around a whole lot (which injection should help avoid, no?). It did prove that LegacyDAO is injectible... just not into LegacyParameter apparently.

  • Adding a @Service, @Component, or @Named annotation on LegacyParameter. All end up with the NullPointerException on the line I try to reference the injected legacyDAO.

What am I missing?

Depressio
  • 1,329
  • 2
  • 20
  • 39

1 Answers1

1

As Sotirios has pointed out, it can't work since you create a regular Java object and do not give Spring a chance to enhance it. Either let Spring create objects for which you want to enjoy the Spring 'magic' (like setting @Inject dependencies etc). Or create your own objects and set the dependencies yourself (yourObject.setDao(dao)).

That said, there are exceptional cases in which you still want to create your objects 'on the fly' by yourself but rely on Spring to inject dependencies to these objects. In this case you should call Spring explicitly: LegacyParameter p = new LegacyParameter(...); applicationContext.getAutowireCapableBeanFactory().autowireBean(p); I don't think you really need it in your case. (see this link inject bean reference into a Quartz job in Spring? for an example when this is really required).

In addition, I would advice to simplify your configuration. Why do you use both xml-based and java-based configuration that do actually the same? In your example you could keep only one of them and have the same effect.

Community
  • 1
  • 1
Alexander
  • 2,761
  • 1
  • 28
  • 33
  • How might I do that with annotations? I need to construct a new object each time, and I'd love to have spring do it, but it's unclear to me how to do that with annotations... especially given the constructor argument. I assume I have to define a `@Bean` in the configuration, but not quite sure what it should look like, nor how to invoke it inside of `legacyFormat()`. – Depressio Apr 29 '14 at 15:36
  • If you insist you wish to apply the Spring dependency injection capabilities to the domain objects that you create by yourself, use Spring with AspectJ, see http://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/aop.html#aop-atconfigurable – Alexander May 04 '14 at 17:30