Spring managed JSF beans [duplicate] - spring

This question already has an answer here:
How to use Spring services in JSF-managed beans?
(1 answer)
Closed 7 years ago.
I am using Spring managed JSF beans, now do i have to use annotation tags Ex.#scope of spring or of JSF ?
I noticed that #ViewScoped which is JSF annotation not working and still behaving as request scope ?

If you are using org.springframework.web.jsf.el.SpringBeanFacesELResolver for Spring + JSF integration, then you need to to mark scope with org.springframework.context.annotation.Scope annotation.

There is no View scope in Spring, but we can custom implement such scope.Refer this or this

Read this article: info in this article: http://www.beyondjava.net/blog/integrate-jsf-2-spring-3-nicely/
I did this:
Define an abstract superclass for JSF backing beans like this:
public abstract class AutowireableManagedBean {
protected Logger logger = LoggerFactory.getLogger(getClass());
protected AutowireCapableBeanFactory ctx;
#PostConstruct
protected void init() {
logger.debug("init");
ctx = WebApplicationContextUtils
.getWebApplicationContext(
(ServletContext) FacesContext.getCurrentInstance()
.getExternalContext().getContext())
.getAutowireCapableBeanFactory();
// The following line does the magic
ctx.autowireBean(this);
}
...
}
Then, make your backing beans extend that superclass and you will be able to autowire Spring beans and have make use of JSF-specific view scope:
#ManagedBean
#ViewScoped
public class MyBackingBean extends AutowireableManagedBean {
#Autowired
private MyDao myDao;

Related

JSF 2.3 CDI, spring integration [duplicate]

I understand that a managed bean works like a controller, because your only task is "link" the View Layer with Model.
To use a bean as a managed bean I must declare #ManagedBeanannotation, doing that I can communicate JSF with bean directly.
If I want to inject some component (from Spring) in this managedBean I have two possibles ways:
Choose the property in ManagedBean (like "BasicDAO dao") and declare #ManagedProperty(#{"basicDAO"}) above the property. Doing it, i'm injecting the bean "basicDAO" from Spring in ManagedBean.
Declared #Controller in ManagedBean Class, then i'll have #ManagedBean and #Controller annotations, all together. And in property "BasicDAO dao" i must use #Autowired from Spring.
Is my understanding correct?
#ManagedBean vs #Controller
First of all, you should choose one framework to manage your beans. You should choose either JSF or Spring (or CDI) to manage your beans. Whilst the following works, it is fundamentally wrong:
#ManagedBean // JSF-managed.
#Controller // Spring-managed.
public class BadBean {}
You end up with two completely separate instances of the very same managed bean class, one managed by JSF and another one managed by Spring. It's not directly clear which one would actually be used in EL when you reference it as #{someBean}. If you have the SpringBeanFacesELResolver registered in faces-config.xml, then it would be the Spring-managed one, not the JSF-managed one. If you don't have that, then it would be the JSF-managed one.
Also, when you declare a JSF managed bean specific scope, such as #RequestScoped, #ViewScoped, #SessionScoped or #ApplicationScoped from javax.faces.* package, it will only be recognized and used by #ManagedBean. It won't be understood by #Controller as it expects its own #Scope annotation. This defaults to singleton (application scope) when absent.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
#Controller // Spring-managed (without own scope, so actually becomes a singleton).
public class BadBean {}
When you reference the above bean via #{someBean}, it would return the Spring-managed application scoped bean, not the JSF-managed view scoped bean.
#ManagedProperty vs #Autowired
The JSF-specific #ManagedProperty works only in JSF-managed beans, i.e. when you're using #ManagedBean. The Spring-specific #Autowired works only in Spring-managed beans, i.e. when you're using #Controller. Below approaches are less or more equivalent and cannot be mixed:
#ManagedBean // JSF-managed.
#RequestScoped // JSF-managed scope.
public class GoodBean {
#ManagedProperty("#{springBeanName}")
private SpringBeanClass springBeanName; // Setter required.
}
#Component // Spring-managed.
#Scope("request") // Spring-managed scope.
public class GoodBean {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
}
Do note that when you have the SpringBeanFacesELResolver registered in faces-config.xml as per the javadoc,
<application>
...
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
and thus you can reference Spring managed beans in EL via #{springBeanName}, then you can just reference them in #ManagedProperty too, as it basically sets the evaluated result of the given EL expression. The other way round, injecting a JSF managed bean via #Autowired, is in no way supported. You can however use #Autowired in a JSF managed bean when you extend your bean from SpringBeanAutowiringSupport. This will automatically register the JSF managed bean instance in Spring autowirable context during constructor invocation, which means that everything #Autowired will be available in #PostConstruct and later.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport implements Serializable {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
// springBeanName is now available.
}
}
Or when your architecture doesn't allow extending beans from a different base class, then you can always manually register the JSF managed bean instance in Spring autowirable context as below. See also How to integrate JSF 2 and Spring 3 (or Spring 4) nicely for the trick.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
FacesContextUtils
.getRequiredWebApplicationContext(FacesContext.getCurrentInstance())
.getAutowireCapableBeanFactory().autowireBean(this);
// springBeanName is now available.
}
}
#XxxScoped vs #Scope
Spring's #Scope has limited support for JSF scopes. There's no equivalent for JSF's #ViewScoped. You'd basically either homegrow your own scopes, or stick to manually registering the JSF managed bean instance in Spring autowirable context as shown above.
And, from the other side on, Spring WebFlow was taken over in JSF 2.2 via new #FlowScoped annotation. So if you happen to be on JSF 2.2 already, then you don't necessarily need to use Spring WebFlow if you solely want the flow scope.
CDI - trying to unify it all
Since Java EE 6, CDI is offered as standard alternative to Spring DI. It has respectively #Named and #Inject annotations for this and also its own set of scopes. I'm not sure how it interacts with Spring as I don't use Spring, but #Inject works inside a #ManagedBean, and #ManagedProperty inside a #ManagedBean can reference a #Named bean. On the other hand, #ManagedProperty doesn't work inside a #Named bean.
The purpose of CDI is to unify all different bean management frameworks into only one specification/inteface. Spring could have been a full CDI implementation, but they choosed to only partially implement it (only JSR-330 javax.inject.* is supported, but JSR-299 javax.enterprise.context.* not). See also Will Spring support CDI? and this tutorial.
JSF will be moving to CDI for bean management and deprecate #ManagedBean and friends in a future version.
#Named // CDI-managed.
#ViewScoped // CDI-managed scope.
public class BetterBean implements Serializable {
#Inject
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
// springBeanName is now available.
}
}
See also:
When is it necessary or convenient to use Spring or EJB3 or all of them together?
JSF Service Layer
Backing beans (#ManagedBean) or CDI Beans (#Named)?
Using JSF as view technology of Spring MVC
How to install and use CDI on Tomcat?
There is another way to use Spring-managed beans in JSF-managed beans by simply extending your JSF bean from SpringBeanAutowiringSupport and Spring will handle the dependency injection.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
// springBeanName is now available.
}
The easy way to do this is via XML. I used #Component in already made jsf managed bean but #Autowired did not work because managed bean was already there in faces-config.xml. If it is mandatory to keep that managed bean definition along with its managed property in the xml file then it is suggested to add the spring bean as another managed property inside the managed bean tag. Here the spring bean is there defined in spring-config.xml(can be autowired somewhere alternately). please refer
https://stackoverflow.com/a/19904591/5620851
edited by me. I suggest to either implement it altogether through annotation #Managed and #Component or via xml for both.
You can autowire individual beans without #Autowired by leveraging getBean of the current WebApplication context.
Please refer to #BalusC's answer for more details. This is just a slight modification over his example:
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
// #Autowired // No Autowired required
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
WebApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
this.springBeanName = ctx.getBean(SpringBeanClass.class);
// springBeanName is now available.
}
}

XHTML page not recognizing #Controller or #Component in controller [duplicate]

I understand that a managed bean works like a controller, because your only task is "link" the View Layer with Model.
To use a bean as a managed bean I must declare #ManagedBeanannotation, doing that I can communicate JSF with bean directly.
If I want to inject some component (from Spring) in this managedBean I have two possibles ways:
Choose the property in ManagedBean (like "BasicDAO dao") and declare #ManagedProperty(#{"basicDAO"}) above the property. Doing it, i'm injecting the bean "basicDAO" from Spring in ManagedBean.
Declared #Controller in ManagedBean Class, then i'll have #ManagedBean and #Controller annotations, all together. And in property "BasicDAO dao" i must use #Autowired from Spring.
Is my understanding correct?
#ManagedBean vs #Controller
First of all, you should choose one framework to manage your beans. You should choose either JSF or Spring (or CDI) to manage your beans. Whilst the following works, it is fundamentally wrong:
#ManagedBean // JSF-managed.
#Controller // Spring-managed.
public class BadBean {}
You end up with two completely separate instances of the very same managed bean class, one managed by JSF and another one managed by Spring. It's not directly clear which one would actually be used in EL when you reference it as #{someBean}. If you have the SpringBeanFacesELResolver registered in faces-config.xml, then it would be the Spring-managed one, not the JSF-managed one. If you don't have that, then it would be the JSF-managed one.
Also, when you declare a JSF managed bean specific scope, such as #RequestScoped, #ViewScoped, #SessionScoped or #ApplicationScoped from javax.faces.* package, it will only be recognized and used by #ManagedBean. It won't be understood by #Controller as it expects its own #Scope annotation. This defaults to singleton (application scope) when absent.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
#Controller // Spring-managed (without own scope, so actually becomes a singleton).
public class BadBean {}
When you reference the above bean via #{someBean}, it would return the Spring-managed application scoped bean, not the JSF-managed view scoped bean.
#ManagedProperty vs #Autowired
The JSF-specific #ManagedProperty works only in JSF-managed beans, i.e. when you're using #ManagedBean. The Spring-specific #Autowired works only in Spring-managed beans, i.e. when you're using #Controller. Below approaches are less or more equivalent and cannot be mixed:
#ManagedBean // JSF-managed.
#RequestScoped // JSF-managed scope.
public class GoodBean {
#ManagedProperty("#{springBeanName}")
private SpringBeanClass springBeanName; // Setter required.
}
#Component // Spring-managed.
#Scope("request") // Spring-managed scope.
public class GoodBean {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
}
Do note that when you have the SpringBeanFacesELResolver registered in faces-config.xml as per the javadoc,
<application>
...
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
and thus you can reference Spring managed beans in EL via #{springBeanName}, then you can just reference them in #ManagedProperty too, as it basically sets the evaluated result of the given EL expression. The other way round, injecting a JSF managed bean via #Autowired, is in no way supported. You can however use #Autowired in a JSF managed bean when you extend your bean from SpringBeanAutowiringSupport. This will automatically register the JSF managed bean instance in Spring autowirable context during constructor invocation, which means that everything #Autowired will be available in #PostConstruct and later.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport implements Serializable {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
// springBeanName is now available.
}
}
Or when your architecture doesn't allow extending beans from a different base class, then you can always manually register the JSF managed bean instance in Spring autowirable context as below. See also How to integrate JSF 2 and Spring 3 (or Spring 4) nicely for the trick.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
FacesContextUtils
.getRequiredWebApplicationContext(FacesContext.getCurrentInstance())
.getAutowireCapableBeanFactory().autowireBean(this);
// springBeanName is now available.
}
}
#XxxScoped vs #Scope
Spring's #Scope has limited support for JSF scopes. There's no equivalent for JSF's #ViewScoped. You'd basically either homegrow your own scopes, or stick to manually registering the JSF managed bean instance in Spring autowirable context as shown above.
And, from the other side on, Spring WebFlow was taken over in JSF 2.2 via new #FlowScoped annotation. So if you happen to be on JSF 2.2 already, then you don't necessarily need to use Spring WebFlow if you solely want the flow scope.
CDI - trying to unify it all
Since Java EE 6, CDI is offered as standard alternative to Spring DI. It has respectively #Named and #Inject annotations for this and also its own set of scopes. I'm not sure how it interacts with Spring as I don't use Spring, but #Inject works inside a #ManagedBean, and #ManagedProperty inside a #ManagedBean can reference a #Named bean. On the other hand, #ManagedProperty doesn't work inside a #Named bean.
The purpose of CDI is to unify all different bean management frameworks into only one specification/inteface. Spring could have been a full CDI implementation, but they choosed to only partially implement it (only JSR-330 javax.inject.* is supported, but JSR-299 javax.enterprise.context.* not). See also Will Spring support CDI? and this tutorial.
JSF will be moving to CDI for bean management and deprecate #ManagedBean and friends in a future version.
#Named // CDI-managed.
#ViewScoped // CDI-managed scope.
public class BetterBean implements Serializable {
#Inject
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
// springBeanName is now available.
}
}
See also:
When is it necessary or convenient to use Spring or EJB3 or all of them together?
JSF Service Layer
Backing beans (#ManagedBean) or CDI Beans (#Named)?
Using JSF as view technology of Spring MVC
How to install and use CDI on Tomcat?
There is another way to use Spring-managed beans in JSF-managed beans by simply extending your JSF bean from SpringBeanAutowiringSupport and Spring will handle the dependency injection.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
// springBeanName is now available.
}
The easy way to do this is via XML. I used #Component in already made jsf managed bean but #Autowired did not work because managed bean was already there in faces-config.xml. If it is mandatory to keep that managed bean definition along with its managed property in the xml file then it is suggested to add the spring bean as another managed property inside the managed bean tag. Here the spring bean is there defined in spring-config.xml(can be autowired somewhere alternately). please refer
https://stackoverflow.com/a/19904591/5620851
edited by me. I suggest to either implement it altogether through annotation #Managed and #Component or via xml for both.
You can autowire individual beans without #Autowired by leveraging getBean of the current WebApplication context.
Please refer to #BalusC's answer for more details. This is just a slight modification over his example:
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
// #Autowired // No Autowired required
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
WebApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
this.springBeanName = ctx.getBean(SpringBeanClass.class);
// springBeanName is now available.
}
}

Spring 4 and JSF 2 ManagedBean [duplicate]

I understand that a managed bean works like a controller, because your only task is "link" the View Layer with Model.
To use a bean as a managed bean I must declare #ManagedBeanannotation, doing that I can communicate JSF with bean directly.
If I want to inject some component (from Spring) in this managedBean I have two possibles ways:
Choose the property in ManagedBean (like "BasicDAO dao") and declare #ManagedProperty(#{"basicDAO"}) above the property. Doing it, i'm injecting the bean "basicDAO" from Spring in ManagedBean.
Declared #Controller in ManagedBean Class, then i'll have #ManagedBean and #Controller annotations, all together. And in property "BasicDAO dao" i must use #Autowired from Spring.
Is my understanding correct?
#ManagedBean vs #Controller
First of all, you should choose one framework to manage your beans. You should choose either JSF or Spring (or CDI) to manage your beans. Whilst the following works, it is fundamentally wrong:
#ManagedBean // JSF-managed.
#Controller // Spring-managed.
public class BadBean {}
You end up with two completely separate instances of the very same managed bean class, one managed by JSF and another one managed by Spring. It's not directly clear which one would actually be used in EL when you reference it as #{someBean}. If you have the SpringBeanFacesELResolver registered in faces-config.xml, then it would be the Spring-managed one, not the JSF-managed one. If you don't have that, then it would be the JSF-managed one.
Also, when you declare a JSF managed bean specific scope, such as #RequestScoped, #ViewScoped, #SessionScoped or #ApplicationScoped from javax.faces.* package, it will only be recognized and used by #ManagedBean. It won't be understood by #Controller as it expects its own #Scope annotation. This defaults to singleton (application scope) when absent.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
#Controller // Spring-managed (without own scope, so actually becomes a singleton).
public class BadBean {}
When you reference the above bean via #{someBean}, it would return the Spring-managed application scoped bean, not the JSF-managed view scoped bean.
#ManagedProperty vs #Autowired
The JSF-specific #ManagedProperty works only in JSF-managed beans, i.e. when you're using #ManagedBean. The Spring-specific #Autowired works only in Spring-managed beans, i.e. when you're using #Controller. Below approaches are less or more equivalent and cannot be mixed:
#ManagedBean // JSF-managed.
#RequestScoped // JSF-managed scope.
public class GoodBean {
#ManagedProperty("#{springBeanName}")
private SpringBeanClass springBeanName; // Setter required.
}
#Component // Spring-managed.
#Scope("request") // Spring-managed scope.
public class GoodBean {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
}
Do note that when you have the SpringBeanFacesELResolver registered in faces-config.xml as per the javadoc,
<application>
...
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
and thus you can reference Spring managed beans in EL via #{springBeanName}, then you can just reference them in #ManagedProperty too, as it basically sets the evaluated result of the given EL expression. The other way round, injecting a JSF managed bean via #Autowired, is in no way supported. You can however use #Autowired in a JSF managed bean when you extend your bean from SpringBeanAutowiringSupport. This will automatically register the JSF managed bean instance in Spring autowirable context during constructor invocation, which means that everything #Autowired will be available in #PostConstruct and later.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport implements Serializable {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
// springBeanName is now available.
}
}
Or when your architecture doesn't allow extending beans from a different base class, then you can always manually register the JSF managed bean instance in Spring autowirable context as below. See also How to integrate JSF 2 and Spring 3 (or Spring 4) nicely for the trick.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
FacesContextUtils
.getRequiredWebApplicationContext(FacesContext.getCurrentInstance())
.getAutowireCapableBeanFactory().autowireBean(this);
// springBeanName is now available.
}
}
#XxxScoped vs #Scope
Spring's #Scope has limited support for JSF scopes. There's no equivalent for JSF's #ViewScoped. You'd basically either homegrow your own scopes, or stick to manually registering the JSF managed bean instance in Spring autowirable context as shown above.
And, from the other side on, Spring WebFlow was taken over in JSF 2.2 via new #FlowScoped annotation. So if you happen to be on JSF 2.2 already, then you don't necessarily need to use Spring WebFlow if you solely want the flow scope.
CDI - trying to unify it all
Since Java EE 6, CDI is offered as standard alternative to Spring DI. It has respectively #Named and #Inject annotations for this and also its own set of scopes. I'm not sure how it interacts with Spring as I don't use Spring, but #Inject works inside a #ManagedBean, and #ManagedProperty inside a #ManagedBean can reference a #Named bean. On the other hand, #ManagedProperty doesn't work inside a #Named bean.
The purpose of CDI is to unify all different bean management frameworks into only one specification/inteface. Spring could have been a full CDI implementation, but they choosed to only partially implement it (only JSR-330 javax.inject.* is supported, but JSR-299 javax.enterprise.context.* not). See also Will Spring support CDI? and this tutorial.
JSF will be moving to CDI for bean management and deprecate #ManagedBean and friends in a future version.
#Named // CDI-managed.
#ViewScoped // CDI-managed scope.
public class BetterBean implements Serializable {
#Inject
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
// springBeanName is now available.
}
}
See also:
When is it necessary or convenient to use Spring or EJB3 or all of them together?
JSF Service Layer
Backing beans (#ManagedBean) or CDI Beans (#Named)?
Using JSF as view technology of Spring MVC
How to install and use CDI on Tomcat?
There is another way to use Spring-managed beans in JSF-managed beans by simply extending your JSF bean from SpringBeanAutowiringSupport and Spring will handle the dependency injection.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
// springBeanName is now available.
}
The easy way to do this is via XML. I used #Component in already made jsf managed bean but #Autowired did not work because managed bean was already there in faces-config.xml. If it is mandatory to keep that managed bean definition along with its managed property in the xml file then it is suggested to add the spring bean as another managed property inside the managed bean tag. Here the spring bean is there defined in spring-config.xml(can be autowired somewhere alternately). please refer
https://stackoverflow.com/a/19904591/5620851
edited by me. I suggest to either implement it altogether through annotation #Managed and #Component or via xml for both.
You can autowire individual beans without #Autowired by leveraging getBean of the current WebApplication context.
Please refer to #BalusC's answer for more details. This is just a slight modification over his example:
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
// #Autowired // No Autowired required
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
WebApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
this.springBeanName = ctx.getBean(SpringBeanClass.class);
// springBeanName is now available.
}
}

#Autowired service inside a #ManagedBean #Component class is null during JSF request [duplicate]

This question already has answers here:
Spring JSF integration: how to inject a Spring component/service in JSF managed bean?
(4 answers)
Closed 6 years ago.
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?
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.
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
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 {
......
}

Spring JSF integration: how to inject a Spring component/service in JSF managed bean?

I understand that a managed bean works like a controller, because your only task is "link" the View Layer with Model.
To use a bean as a managed bean I must declare #ManagedBeanannotation, doing that I can communicate JSF with bean directly.
If I want to inject some component (from Spring) in this managedBean I have two possibles ways:
Choose the property in ManagedBean (like "BasicDAO dao") and declare #ManagedProperty(#{"basicDAO"}) above the property. Doing it, i'm injecting the bean "basicDAO" from Spring in ManagedBean.
Declared #Controller in ManagedBean Class, then i'll have #ManagedBean and #Controller annotations, all together. And in property "BasicDAO dao" i must use #Autowired from Spring.
Is my understanding correct?
#ManagedBean vs #Controller
First of all, you should choose one framework to manage your beans. You should choose either JSF or Spring (or CDI) to manage your beans. Whilst the following works, it is fundamentally wrong:
#ManagedBean // JSF-managed.
#Controller // Spring-managed.
public class BadBean {}
You end up with two completely separate instances of the very same managed bean class, one managed by JSF and another one managed by Spring. It's not directly clear which one would actually be used in EL when you reference it as #{someBean}. If you have the SpringBeanFacesELResolver registered in faces-config.xml, then it would be the Spring-managed one, not the JSF-managed one. If you don't have that, then it would be the JSF-managed one.
Also, when you declare a JSF managed bean specific scope, such as #RequestScoped, #ViewScoped, #SessionScoped or #ApplicationScoped from javax.faces.* package, it will only be recognized and used by #ManagedBean. It won't be understood by #Controller as it expects its own #Scope annotation. This defaults to singleton (application scope) when absent.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
#Controller // Spring-managed (without own scope, so actually becomes a singleton).
public class BadBean {}
When you reference the above bean via #{someBean}, it would return the Spring-managed application scoped bean, not the JSF-managed view scoped bean.
#ManagedProperty vs #Autowired
The JSF-specific #ManagedProperty works only in JSF-managed beans, i.e. when you're using #ManagedBean. The Spring-specific #Autowired works only in Spring-managed beans, i.e. when you're using #Controller. Below approaches are less or more equivalent and cannot be mixed:
#ManagedBean // JSF-managed.
#RequestScoped // JSF-managed scope.
public class GoodBean {
#ManagedProperty("#{springBeanName}")
private SpringBeanClass springBeanName; // Setter required.
}
#Component // Spring-managed.
#Scope("request") // Spring-managed scope.
public class GoodBean {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
}
Do note that when you have the SpringBeanFacesELResolver registered in faces-config.xml as per the javadoc,
<application>
...
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
and thus you can reference Spring managed beans in EL via #{springBeanName}, then you can just reference them in #ManagedProperty too, as it basically sets the evaluated result of the given EL expression. The other way round, injecting a JSF managed bean via #Autowired, is in no way supported. You can however use #Autowired in a JSF managed bean when you extend your bean from SpringBeanAutowiringSupport. This will automatically register the JSF managed bean instance in Spring autowirable context during constructor invocation, which means that everything #Autowired will be available in #PostConstruct and later.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport implements Serializable {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
// springBeanName is now available.
}
}
Or when your architecture doesn't allow extending beans from a different base class, then you can always manually register the JSF managed bean instance in Spring autowirable context as below. See also How to integrate JSF 2 and Spring 3 (or Spring 4) nicely for the trick.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
FacesContextUtils
.getRequiredWebApplicationContext(FacesContext.getCurrentInstance())
.getAutowireCapableBeanFactory().autowireBean(this);
// springBeanName is now available.
}
}
#XxxScoped vs #Scope
Spring's #Scope has limited support for JSF scopes. There's no equivalent for JSF's #ViewScoped. You'd basically either homegrow your own scopes, or stick to manually registering the JSF managed bean instance in Spring autowirable context as shown above.
And, from the other side on, Spring WebFlow was taken over in JSF 2.2 via new #FlowScoped annotation. So if you happen to be on JSF 2.2 already, then you don't necessarily need to use Spring WebFlow if you solely want the flow scope.
CDI - trying to unify it all
Since Java EE 6, CDI is offered as standard alternative to Spring DI. It has respectively #Named and #Inject annotations for this and also its own set of scopes. I'm not sure how it interacts with Spring as I don't use Spring, but #Inject works inside a #ManagedBean, and #ManagedProperty inside a #ManagedBean can reference a #Named bean. On the other hand, #ManagedProperty doesn't work inside a #Named bean.
The purpose of CDI is to unify all different bean management frameworks into only one specification/inteface. Spring could have been a full CDI implementation, but they choosed to only partially implement it (only JSR-330 javax.inject.* is supported, but JSR-299 javax.enterprise.context.* not). See also Will Spring support CDI? and this tutorial.
JSF will be moving to CDI for bean management and deprecate #ManagedBean and friends in a future version.
#Named // CDI-managed.
#ViewScoped // CDI-managed scope.
public class BetterBean implements Serializable {
#Inject
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
// springBeanName is now available.
}
}
See also:
When is it necessary or convenient to use Spring or EJB3 or all of them together?
JSF Service Layer
Backing beans (#ManagedBean) or CDI Beans (#Named)?
Using JSF as view technology of Spring MVC
How to install and use CDI on Tomcat?
There is another way to use Spring-managed beans in JSF-managed beans by simply extending your JSF bean from SpringBeanAutowiringSupport and Spring will handle the dependency injection.
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport {
#Autowired
private SpringBeanClass springBeanName; // No setter required.
// springBeanName is now available.
}
The easy way to do this is via XML. I used #Component in already made jsf managed bean but #Autowired did not work because managed bean was already there in faces-config.xml. If it is mandatory to keep that managed bean definition along with its managed property in the xml file then it is suggested to add the spring bean as another managed property inside the managed bean tag. Here the spring bean is there defined in spring-config.xml(can be autowired somewhere alternately). please refer
https://stackoverflow.com/a/19904591/5620851
edited by me. I suggest to either implement it altogether through annotation #Managed and #Component or via xml for both.
You can autowire individual beans without #Autowired by leveraging getBean of the current WebApplication context.
Please refer to #BalusC's answer for more details. This is just a slight modification over his example:
#ManagedBean // JSF-managed.
#ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {
// #Autowired // No Autowired required
private SpringBeanClass springBeanName; // No setter required.
#PostConstruct
private void init() {
WebApplicationContext ctx = FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
this.springBeanName = ctx.getBean(SpringBeanClass.class);
// springBeanName is now available.
}
}

Resources