@Autowired service inside a @ManagedBean @Component class is null during JSF request [duplicate]
Asked Answered
E

3

5

I tried union Spring 3(MVC) with JSF 2. I have some experience in Spring and JSF, but never tried to join them before. In the end I have 2 files

@ManagedBean(name = "userBean")
@Scope
@Component
public class someBean {

  @Autowired
  private TestService testService;

  public void printString() {
    System.out.println(testService.getString());
  }
}

and

@ManagedBean(name = "studentBean")
@Scope
@Component
public class StudentBean {

  @Autowired
  private TestService testService;

  public void printString() {
    System.out.println(testService.getString());
  }
}

For these file I have right configuration for spring, jsf, and web.xml. And have .xhtml page where I start printString() for 'someBean' and for 'StudentBean'. I have the NPE in first case and 'some string' in the console in second case. The reason is simple - different bean names in the Spring context and JSF. all problems finished after

@Component => @Component("userBean") 
public class someBean {

In the debug I saw that

private TestService testService;

@Autowired
public void setTestService(TestService testservice) {
  this.testService = testService;
}

When JSF bean is creating testService sets not null, but it is null during JSF lifecycle when

public void pringString() {
  testService.blah();
}

testService is null. It is what I can't understand. Has someone deep knowledge the Spring and JSF to describe this situation in details?

Erzurum answered 9/2, 2015 at 23:57 Comment(0)
C
12

Both JSF and Spring can act as bean containers. The @ManagedBean annotation instructs the JSF managed bean facility to create a new instance of the class, and manage it under the given name. The @Component annotation instructs the Spring ApplicationContext to create a new instance of the class, and manage it under the given name. That is, both JSF and Spring create an instance of that class, the JSF one is reachable through EL, but the Spring one gets its dependencies injected (because, being a spring annotation, @Autowired is not understood by the JSF managed bean facility).

So you have a choice: Use the JSF managed bean facility for everything (which I would not recommend, as it is rather limited), use CDI for everything (which is an option, but does not use Spring), or use Spring for everything (which I usually do), by removing the @ManagedBean annotation, and making Spring beans accessible through EL by registering a SpringBeanFacesELResolver in your faces-config.xml. The Spring reference manual describes this in section 19.3.1.

Claudy answered 10/2, 2015 at 0:29 Comment(2)
In addition to that, the solution for this problem is verify the managed bean must use ´import javax.annotation.ManagedBean´ instead of ´import javax.faces.bean.ManagedBean´ (import that able the @ManagedBean notation) for transform that bean from "faces managed bean" (CDI) to "Spring managed bean" (ApplicationContext)Sleek
Can you please ellaborate on the 3rd option,@meriton? I've tried looking at the docs but no luck on how it should be done...Sp
S
1

I had the same issue, it was due to the property name of @ManagedBean annotation.My backing bean looks like this

@Component
@ManagedBean(name="mainBean")
@SessionScoped
public class MainManagedBean{...}

As you can see, the name given to the bean (mainBean) is different to the default name (mainManagedBean) that the backing bean should have.

I have fixed the issue by setting the property name to "mainManagedBean". My bean becomes like this:

@Component
@ManagedBean(name="mainManagedBean")
@SessionScoped
public class MainManagedBean{...}

I wish this can help you

Spirula answered 12/2, 2017 at 18:23 Comment(0)
G
0

I believe the reason why testService is null is because testService has not been instantiated yet when managed bean is being constructed. So you can use @PostConstruct to inject Spring beans into a managed bean.

@ManagedBean(name = "userBean")
@Scope
@Component
public class someBean {

    @Autowired
    private TestService testService;

    public void printString() {
        System.out.println(testService.getString());
    }

    @PostConstruct
    private void init() {
    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
        ServletContext servletContext = (ServletContext) externalContext.getContext();
    WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext).
                                   getAutowireCapableBeanFactory().
                                   autowireBean(this);
    }
}

@Service
public class TestService {
    ......
}
Goniometer answered 6/6, 2016 at 14:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.