4

I must be missing something simple, but I'm having trouble getting an Autowired property to be assigned to a bean. All similar answers posted here seem to revolve around one of three solutions:

  1. extend SpringBeanAutowiringSupport
  2. use <context:component-scan base-package="..." /> in applicationContext.xml
  3. use <context:annotation-config /> in applicationContext.xml

I tried to make a minimalist bean to represent my DAO and inject it into a Web Service.

DAO interface:

package wb;
public interface FooDAO {
    public String doNothing();
}

DAO implementation:

package wb;
import org.springframework.stereotype.Component;

@Component
public class FooDAOImpl implements FooDAO {
    public FooDAOImpl() {
        System.out.println("FooDAOImpl: Instantiated " + this);
    }

    @Override
    public String doNothing() {
        System.out.println("FooDAOImpl: doNothing() called");
        return "Did nothing!";
    }
}

Web Service with injection:

package ws;

import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import wb.FooDAO;

@WebService(serviceName = "WS")
public class WS extends SpringBeanAutowiringSupport {

    @Autowired(required = true)
    private FooDAO fooDAO;

    @WebMethod(exclude = true)
    public void setFooDAO(FooDAO fooDAO) {
        this.fooDAO = fooDAO;
        System.out.println("WS: fooDAO set = " + fooDAO);
    }

    public WS() {
        System.out.println("WS: WS bean instantiated!");
    }

    @WebMethod(operationName = "doNothing")
    @WebResult(name = "whatDidIDo")
    public String doNothing() {
        System.out.println("WS: doNothing() says DAO = " + fooDAO);
        return fooDAO == null ? "Could not do nothing!" : fooDAO.doNothing();
    }
}

applicationContext.xml content within the beans tags:

<context:annotation-config />
<context:component-scan base-package="ws"/>

<bean id="fooDAO" class="wb.FooDAOImpl" />

This was all created in the latest NetBeans, in a project created with Spring and Hibernate frameworks. When I deploy to JBoss, and the app starts up, I get the expected Bean instantiation:

11:01:46,767 INFO  [stdout] (MSC service thread 1-6) WS: WS bean instantiated!
11:01:47,571 INFO  [stdout] (MSC service thread 1-15) FooDAOImpl: Instantiated wb.FooDAOImpl@11176682

Once I call the web service, the log also reports:

11:03:07,097 INFO  [stdout] (http--127.0.0.1-8080-1) WS: doNothing() says DAO = null

What am I missing?

Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
user3207820
  • 55
  • 1
  • 1
  • 5

2 Answers2

9

SpringBeanAutowiringSupport must be a bean. You need to annotate that class with @Service or another annotation such as @Component that indicates a class should be a bean when component scanning occurs. These will be picked up by Spring and made into beans.

Remember that in order to be a participant in autowiring, such as having another bean injected, the class must be a bean itself and managed by Spring's IOC container.

Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
  • 1
    Thanks; could have sworn that's one of the things I'd tried previously. When I add @Component, it works. – user3207820 Jan 17 '14 at 19:14
  • @user3207820 Glad I could help. I struggled with some the same concepts early on when using Spring. Anytime you use the `new` keyword you really need to pause and wonder if its appropriate. – Kevin Bowersox Jan 17 '14 at 19:16
  • 4
    The WS instance created during App startup gets an auto-wired DAOImpl. But when calling the web service, a different WS instance is created to field the requests, and THAT instance doesn't get one. Weird. Anyway, thanks again. – user3207820 Jan 17 '14 at 22:30
  • 1
    I'm experiencing the same exact thing as the above comment. I can't get the instance created when calling the web service to have the autowired fields. Am I doing something wrong with how I'm creating the web service? Or did I not follow the solution correctly? Spring is definitely creating the WS class as a bean, but it's not the same instance used when calling the service. – Jurgen Camilleri Mar 26 '17 at 15:21
0

The spring should start before webservices.

The the webservices-rt*.jar is a plugable jar which starts automaticly to find the end points.

In some cases it may happen that the webservices starts before spring. So the injects can not be done. Make sure that the start up has correct order.

Alireza Fattahi
  • 42,517
  • 14
  • 123
  • 173