Reputation: 182
When I am trying to access the login method of my managed bean by following code in my xhtml:
<p:commandButton value="Login" update="growl"
actionListener="#{loginView.login}"/>
my LoginView class looks like this:
@Component
@ManagedBean(name="loginView",eager=true)
@SessionScoped
public class LoginView {
@Autowired
LoginService loginServiceImpl;
Student student=loginServiceImpl.login(username, password);
public void login(ActionEvent event) {
RequestContext context = RequestContext.getCurrentInstance();
FacesMessage message = null;
boolean loggedIn = false;
if(username != null && student!=null && password != null ) {
loggedIn=True;
try {
FacesContext.getCurrentInstance()
.getExternalContext()
.redirect(location);
} catch (IOException e) {
e.printStackTrace();
}
}
}
when I am calling pressing the button its giving me the following error:
javax.el.ELException: /login1.xhtml @105,62 actionListener="#{loginView.login}": java.lang.NullPointerException
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:111)
at javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:147)
at javax.faces.event.ActionEvent.processListener(ActionEvent.java:88)
at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:818)
at javax.faces.component.UICommand.broadcast(UICommand.java:300)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1008)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NullPointerException
at org.primefaces.showcase.view.menu.LoginView.login(LoginView.java:62)
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.apache.el.parser.AstValue.invoke(AstValue.java:278)
at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:274)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
... 26 more
Strangely, When I am commenting the line
Student student=loginServiceImpl.login(username, password);
The code is working fine. I want my bean to be both, Spring based as I want to autowire loginServiceImpl and jsf based as I want to call my method. If It's not possible, what approach should I chose.
Upvotes: 0
Views: 1007
Reputation: 182
Thanks wittakarn to spend time to answer the question, but it answers the question partially. I researched on the topic and found a really good article on the same here
We can't inject spring bean by using @Autowired in a JSF managed bean as JSF beans are serializable which is not the case with Spring bean. Approach taken by @wittakarn is nice, except there is one problem. In the setter of the loginService, I have to create a new loginService object and give it's reference to "this" class, where all the concept of loose coupling breaks!!!
rather, there is one good approach. Spring wants it's bean to be non-seriazable. So first we have to make the loginService, a non serialized property by making it transient, and then in the init method call the externalContext and give the capabilities of autowiring to "this" class. The code would look like this:
@Autowired
transient LoginService loginServiceImpl;
@PostConstruct
private void init() {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
ServletContext servletContext = (ServletContext) externalContext.getContext();
WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext).
getAutowireCapableBeanFactory().
autowireBean(this);
}
and guess what!! it's working :)
Upvotes: 1
Reputation: 3162
You cannot inject a Spring bean by using @Autowired
inside JSF managed bean.
You should change to
@ManagedProperty(value="#{something}")
private LoginService loginServiceImpl; // getter and setter.
See also: Null pointer when autowiring the bean into JSF Managed bean
Upvotes: 2