I have a JSF backing bean that is Spring managed but I would like to be able to make use of the #ManagedProperty from JSF. The following does not work:
#Component
#Scope(Scopes.REQUEST)
public class MyRequestBean {
#ManagedProperty(value="#{param.bcIndex}")
private int bcIndex;
public int getBcIndex() {
return bcIndex;
}
public void setBcIndex(int bcIndex) {
this.bcIndex = bcIndex;
}
}
Suggestions?
Actually it is quite simple. I know of three ways to do your injection:
Use Spring's #Value annotation together with implicit El #{param} object:
#Value("#{param.bcIndex}")
private int bcIndex;
Make use of ExternalContext#getRequestParameterMap in a #PostConstruct / preRenderView listener:
//#PostConstruct
public void init() {
bcIndex = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("bcIndex");
}
Make a binding in your view utilizing <f:viewParam>:
<f:metadata>
<f:viewParam name="index" value="#{myRequestBean.bcIndex}" />
</f:metadata>
Related
I use Spring boot with JSF 2.2. My problem is that I can create #ManagedBean from javax.annotation.ManagedBean and it is working in my index.xhtml when I run the app, but when I want to use javax.faces.bean.ManagedBean is not displaying the value. What's the difference between those two? Why I can't use the javax.faces.bean.ManagedBean? ( I don't have web.xml file, all is configured in classes)
The javax.annotation.* annotations are meant to be a move from the classic JSF annotations to a CDI approach. The Spring Framework has the ability to read some CDI annotations, so that could be the reason why this annotation "works". However, the trend in CDI is to use #Named, overall.
In a Spring Boot application, it's Spring the one scanning your annotations, not JSF. So, even you could think that the application works with #ManagedBean, you'll see that the #*Scoped annotations are useless, because all the created beans happen to be singletons, which is Spring's default scope.
In the end the choice I made was to use vanilla Spring annotations and scopes. As Spring lacks the JSF view scope, also a custom scope to emulate it.
MyBean.java:
#Component
#Scope("view")
public class MyBean {
//Here it goes your logic
}
ViewScope.java:
public class ViewScope implements Scope {
#Override
public Object get(String name, ObjectFactory<?> objectFactory) {
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
if (viewMap.containsKey(name)) {
return viewMap.get(name);
} else {
Object object = objectFactory.getObject();
viewMap.put(name, object);
return object;
}
}
#Override
public String getConversationId() {
return null;
}
#Override
public void registerDestructionCallback(String arg0, Runnable arg1) {
}
#Override
public Object remove(String name) {
return FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(name);
}
#Override
public Object resolveContextualObject(String arg0) {
return null;
}
}
Register the view scope with a CustomScopeConfigurer:
#Bean
public static CustomScopeConfigurer viewScope() {
CustomScopeConfigurer configurer = new CustomScopeConfigurer();
configurer.setScopes(
new ImmutableMap.Builder<String, Object>().put("view", new ViewScope()).build());
return configurer;
}
Finally, do not forget to add the Spring EL resolver in your faces-config.xml to make the Spring beans available through EL expressions:
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
See also:
Why are there different bean management annotations
Backing beans (#ManagedBean) or CDI Beans (#Named)?
Configuring Spring Boot with JSF
I have Spring bean with annotations:
#Named
#Scope("session")
And this bean property:
#Autowired
ApplicationContext appContext;
The Spring configuration file has entry (that works for other anotations/injections):
<context:component-scan base-package="my.package.name" />
Why appContext is null after such code and configuration?
I am trying to get ApplicationContext (to call getBean(...) on it) and this can be quite involved task (judging from other discussions) in previous Spring versions (e.g. one is required to get ServletContext in Spring web application to create ApplicationContext and getting ServletContext can be quite involved task for beans that don't directly access HTTP Request objects). In Spring 3.x, as I understand, simple #Autwired injection can be used. How AppContext can be accessed?
Here the first problem is you are using #Named which is Java EE annotation and as for as I know Spring yet to support Java EE annotations. Hence instead of using #Named try to use Spring annotation #Service, #Component, #Repository etc.
Here is the example for you I have used JSF Managed bean as well to show how to integrate beans.
#ManagedBean(name="myBacking")
#RequestScoped
public class MyBacking {
private String myText;
#ManagedProperty(value="#{mySpring}")
MySpringBean mySpring;
public String getMyText() {
myText = mySpring.getText();
return myText;
}
public void setMyText(String myText) {
this.myText = myText;
}
public MySpringBean getMySpring() {
return mySpring;
}
public void setMySpring(MySpringBean mySpring) {
this.mySpring = mySpring;
}
}
#Service("mySpring")
#Scope("request")
public class MySpringBean {
#Autowired
MySecond mySecond;
public String getText(){
return "Hello KP" + mySecond.appObj();
}
}
#Service
#Scope("request")
public class MySecond {
#Autowired
ApplicationContext applicationContext;
public String appObj(){
MyThrid mythird =(MyThrid)applicationContext.getBean("myThrid");
return "My Second Bean calld "+ mythird.getTxt();
}
}
#Service
public class MyThrid {
public String getTxt(){
return "from thrid Bean";
}
}
I'm using Spring Roo and want to access a bean within of Controller class which has following configuration in applicationContext.xml:
<bean class="com.reservation.jobs.Configuration" id="jobsConfiguration" autowire="byType">
<property name="skipWeeks" value="4" />
</bean>
The configuration class itself is:
package com.reservation.jobs;
public class Configuration {
private int skipWeeks;
public void setSkipWeeks(int value) {
System.out.println("SkipWeeks set auf: " + value);
this.skipWeeks = value;
}
public int getSkipWeeks() {
return this.skipWeeks;
}
}
In my Controller I thought that a simple Autowired annotation should do the job
public class SomeController extends Controller {
#Autowired
private com.reservation.jobs.Configuration config;
}
During startup Spring prints the message within the setSkipWeeks method. Unfortunately whenever I call config.getSkipWeeks() within the controller it returns 0.
Have I to use the getBean method of the ApplicationContext instance or is there some better way?
autowire="byType" is redundant. It indicates that fields of the Configuration class should be autowired, and you have just one primitive. So remove that attribute.
Apart from that, config.getSkipWeeks() must return 4 unless:
you are using a different instance (made by you with new)
you have called the setter somewhere with a value of 0
I have a JSF 2.0 bean:
#ManagedBean
#SessionScoped
public class LoginBean implements Serializable
{
protected String name;
public String getName()
{
return name;
}
//....
}
I have a Spring 3.0 bean:
#Repository
public class Logins
{
#ManagedProperty(value="#{loginBean}")
protected LoginBean loginBean;
public void recordLogin()
{
//... record in db that loginBean.getName() just logged in
}
}
This code doesn't work, Logins.loginBean is never set.
Alternatively (its the same question, simplified) - would the following code ever work?
#Repository
public class SpringBean
{
#ManagedProperty(value="#{session.id}")
protected String id;
//....
}
The ContextLoaderListener and RequestLoaderListener are declared in web.xml.
Is it possible at all to inject a JSF bean into a Spring bean? (Without using yet another extra framework)
Or should I rather convert my JSF bean into a Spring bean and use the DelegatingVariableResolver trick in faces-config.xml? I have already tested this with a test Spring bean, and it works.
Using JSF annotations in spring-managed beans doesn't work. And it shouldn't - you should not inject things from the web layer in the other layers. It should be the other way around - inject spring services (or repositories) into web components (jsf managed beans), and invoke methods on them, passing the managed bean properties as arguments
Is there any way to use Lookup Method Injection using annotations?
Given the following class:
#Service
public abstract class A {
protected abstract createB();
}
In order to get it to work I have to declare in spring applicationContext.xml the following:
<bean id="b" class="com.xyz.B">
</bean>
<bean id="a" class="com.xyz.A">
<lookup-method name="createB" bean="b"/>
</bean>
Even though I am using <context:component-scan base> I have to declare it also in the XML. Not a good approach I think.
How to do it with annotations?
It is possible to use javax.inject.Provider. All thanks go to Phil Webb.
public class MySingleton {
#Autowired
private Provider<MyPrototype> myPrototype;
public void operation() {
MyPrototype instance = myPrototype.get();
// do something with the instance
}
}
It is also possible with org.springframework.beans.factory.ObjectFactory if you want to keep up with Spring API
public class MySingleton {
#Autowired
private ObjectFactory<MyPrototype> myPrototypeFactory;
public void operation() {
MyPrototype instance = myPrototypeFactory.getObject();
// do something with the instance
}
}
you can read more in the documentation.
It is implemented only with Spring >= 4.1 See the ticket.
Finally introduced as #Lookup annotation. Here is discussion on how to use it.