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


i understand managed bean works controller, because task "link" view layer model.

to use bean managed bean must declare @managedbeanannotation, doing can communicate jsf bean directly.

if want inject component (from spring) in managedbean have 2 possibles ways:

  1. choose property in managedbean (like "basicdao dao") , declare @managedproperty(#{"basicdao"}) above property. doing it, i'm injecting bean "basicdao" spring in managedbean.

  2. declared @controller in managedbean class, i'll have @managedbean , @controller annotations, together. , in property "basicdao dao" must use @autowired spring.

is understanding correct?

@managedbean vs @controller

first of all, should choose one framework manage beans. should choose either jsf or spring (or cdi) manage beans. whilst following works, fundamentally wrong:

@managedbean // jsf-managed. @controller // spring-managed. public class badbean {} 

you end two separate instances of same managed bean class, 1 managed jsf , 1 managed spring. it's not directly clear 1 actually used in el when reference #{somebean}. if have springbeanfaceselresolver registered in faces-config.xml, spring-managed one, not jsf-managed one. if don't have that, jsf-managed one.

also, when declare jsf managed bean specific scope, such @requestscoped, @viewscoped, @sessionscoped or @applicationscoped javax.faces.* package, recognized , used @managedbean. won't understood @controller expects own @scope annotation. defaults singleton (application scope) when absent.

@managedbean // jsf-managed. @viewscoped // jsf-managed scope. @controller // spring-managed (without own scope, becomes singleton). public class badbean {} 

when reference above bean via #{somebean}, return spring-managed application scoped bean, not jsf-managed view scoped bean.


@managedproperty vs @autowired

the jsf-specific @managedproperty works in jsf-managed beans, i.e. when you're using @managedbean. spring-specific @autowired works in spring-managed beans, i.e. when you're using @controller. below approaches less or more equivalent , cannot 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 when have springbeanfaceselresolver registered in faces-config.xml per javadoc,

<application>     ...     <el-resolver>org.springframework.web.jsf.el.springbeanfaceselresolver</el-resolver> </application> 

and can reference spring managed beans in el via #{springbeanname}, can reference them in @managedproperty too, sets evaluated result of given el expression. other way round, injecting jsf managed bean via @autowired, in no way supported. can use @autowired in jsf managed bean when manually register jsf managed bean instance in spring autowirable context below. see how integrate jsf 2 , spring 3 (or spring 4) nicely 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 available.     } } 

@xxxscoped vs @scope

spring's @scope has limited support jsf scopes. there's no equivalent jsf's @viewscoped. you'd either homegrow own scopes, or stick manually registering jsf managed bean instance in spring autowirable context shown above.

and, other side on, spring webflow taken on in jsf 2.2 via new @flowscoped annotation. if happen on jsf 2.2 already, don't need use spring webflow if solely want flow scope.


cdi - trying unify all

since java ee 6, cdi offered standard alternative spring di. has respectively @named , @inject annotations , own set of scopes. i'm not sure how interacts spring don't use spring, @inject works inside @managedbean, , @managedproperty inside @managedbean can reference @named bean. on other hand, @managedproperty doesn't work inside @named bean.

the purpose of cdi unify different bean management frameworks 1 specification/inteface. spring have been full cdi implementation, choosed partially implement (only jsr-330 javax.inject.* supported, jsr-299 javax.enterprise.context.* not). see will spring support cdi? , this tutorial.

jsf moving cdi bean management , deprecate @managedbean , friends in future version.

see also:


Comments