I'd like to initiliaze the properties of a bean (application scope) from the faces-config.xml. I tried different configuration without success. At library level I'm using jsf 2.2 - jboss-jsf-api_2.2_spec.jar. At project level faces-config is configured to 2.0 version. I don't know if that is the problem. JBDS 7 don't let me to change to 2.2 beacouse of conflict with others Project Facets.
This is the faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
<managed-bean>
<managed-bean-name>appBean</managed-bean-name>
<managed-bean-class>package.ApplicationBean</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
<managed-property>
<property-name>cookieNameLocale</property-name>
<property-class>java.lang.String</property-class>
<value>someText</value>
</managed-property>
<managed-property>
<property-name>debug</property-name>
<property-class>boolean</property-class>
<value>true</value>
</managed-property>
</managed-bean>
<application>
<locale-config>
<default-locale>xx_XX</default-locale>
<supported-locale>xx_XX</supported-locale>
</locale-config>
<resource-bundle>
<base-name>locale</base-name>
<var>i18n</var>
</resource-bundle>
</application>
</faces-config>
This is the application scope bean:
public class ApplicationBean implements Serializable {
private boolean debug;
private String cookieNameLocale;
//respectively getters and setters
}
When #Inject the appBean into another session scope bean the properties are not initiliazed. There are not errors and appBean is created before session bean (using #PostConstruct to print)
The <managed-bean> entry in faces-config.xml basically declares a new #ManagedBean. I.e. a JSF managed bean. However, with #Inject you're basically injecting a CDI managed bean.
Those are two mutually exclusive ways of managing beans. Effectively, you end up with 2 instances of the very same bean class, one managed by JSF via faces-config.xml and another one managed by CDI via annotations. Only the one managed by JSF has those properties set.
You've 2 options:
Use #ManagedProperty to inject it as a JSF managed bean. This in turn however requires that the acceptor is by itself also a JSF managed bean.
Forget the faces-config.xml approach altogether. Define them as JNDI resources in either web.xml or server config and use #Resource to inject them. Alternatively, define them as .properties file settings or <context-param> entries in web.xml. CDI doesn't offer ways out the box to inject them, but it's possible to create a custom annotation with a CDI Producer for that.
Related
I am trying to Inject ServletContext in my dependant scope class but it always gives the failure.
java.lang.IllegalStateException: No CXF message usable for JAX-RS #Context injections in that thread so can't use interface javax.servlet.ServletContext
I am not able to undestand the reason that why can't I inject it here. I am using a producer method and when inside producer method,I try to access ServletContext obj then it gives above exception. I have also checked if the Injected servlet context is null but it is not null. But When I call any method using it for example sc.getContextPath() it gives the above exception. Below is the code snippet:
#Dependent
public class AuthContexthandler {
#Context
ServletContext sc;
#Produces
JWTAuthContextInfo getInfo() {
try{
System.out.println(sc.getContextPath()); //here I get the above mentioned error
//rest of the code
}catch(Exception e){
e.printStackTrace();
}
}
}
you must use #inject instead of #Context.
you can use #Context to inject object instances related to the context of HTTP requests into to JAX-RS source class and as AuthContextHandler(as #Christoph Böhme said) is not a JAX-RS source class so you cannot use #Context
but as http://docs.jboss.org/weld/reference/latest/en-US/html_single/ says:
An object bound to a lifecycle context is called a bean. CDI includes
built-in support for several different kinds of bean, including the
following Java EE component types:
managed beans, and EJB session beans. Both managed beans and EJB
session beans may inject other beans. But some other objects, which
are not themselves beans in the sense used here, may also have beans
injected via CDI. In the Java EE platform, the following kinds of
component may have beans injected:
message-driven beans,
interceptors,
servlets,
servlet filters and
servlet event listeners,
JAX-WS service endpoints and handlers,
JAX-RS resources,
providers and javax.ws.rs.core.Application subclasses, and
JSP tag handlers and tag library event listeners.
it means you also can use #Inject annotation in your JAX-RS source class.
there are also some predefined Beans in CDI such as ServletContext that you can use #inject annotation to inject them.
https://docs.jboss.org/seam/3/servlet/latest/reference/en-US/html/injectablerefs.html
https://docs.oracle.com/javaee/7/tutorial/cdi-adv004.htm
In my application in some places we are using #ManagedBean annoation for Person bean and for the same Person bean we defining in the faces-confing.xml like below at the same time.
#ManagedBean("name=person")
#SessionScoped
Public class Person{
}
faces-config.xml
<managed-bean>
<managed-bean-name>person</managed-bean-name>
<managed-bean-class>com.test.sample.Person</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
my question is does this approach create two instances for the Person bean or it does matter if I do this? Does this have any effect on performance of my application If I do this for every Bean in my application?
There's a priority defined for this case. #ManagedBean annotation avoids having to configure an entry in faces-config.xml but, if you have both, the <managed-bean> entry overrides the annotation.
In your case, there'll be only one instance configured like your faces-config.xml entry. In your case, both approaches are configured the same way but, should you change your faces-config.xml entry to something like
<managed-bean>
<managed-bean-name>personBean</managed-bean-name>
<managed-bean-class>com.test.sample.Person</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
Your bean will be registered under personBean rather than person (which is the name defined by the annotation).
In my application in some places we are using #ManagedBean annoation for Person bean and for the same Person bean we defining in the faces-confing.xml like below at the same time.
#ManagedBean("name=person")
#SessionScoped
Public class Person{
}
faces-config.xml
<managed-bean>
<managed-bean-name>person</managed-bean-name>
<managed-bean-class>com.test.sample.Person</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
my question is does this approach create two instances for the Person bean or it does matter if I do this? Does this have any effect on performance of my application If I do this for every Bean in my application?
There's a priority defined for this case. #ManagedBean annotation avoids having to configure an entry in faces-config.xml but, if you have both, the <managed-bean> entry overrides the annotation.
In your case, there'll be only one instance configured like your faces-config.xml entry. In your case, both approaches are configured the same way but, should you change your faces-config.xml entry to something like
<managed-bean>
<managed-bean-name>personBean</managed-bean-name>
<managed-bean-class>com.test.sample.Person</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
Your bean will be registered under personBean rather than person (which is the name defined by the annotation).
I see a lot of examples marking beans as entity beans (#Entity) & named beans (CDI), so as to avoid creating 2 classes (managed bean & entity bean) and also to make use of Bean Validation so that validation can be performed on both client & server.
So should I be using a single class or not, are there any issues or should I be having my managed beans or service layer create entity beans using the data from managed beans ?
The #Named or #ManagedBean annotations are typically used to let the bean container (CDI/JSF) create an instance of a bean on demand when referenced by expression language in JSF.
For an #Entity bean, it often doesn't make that much sense to just get an arbitrary new instance. An #Entity is very strongly connected to a persistent identity. Such an entity is therefor requested from the Entity Manager and not from a bean container.
The typical pattern is to have a (slim) backing bean that's named making a call to a service (which is in turn typically #Stateless in Java EE). The service then returns entities.
In some very trivial systems people sometimes do make the service named and thus directly available to EL. However, eventually you often want to let the "backing code" generate faces messages or handle (table) selections, which are all things that should not be the concern of a pure business service.
Another common shortcut is letting the backing bean contain business code directly (e.g. the entity manager that retrieves the entities). This makes the business code hard to re-use, but if the app is trivial and there's no need for re-use you might get away with it.
But letting the entity -be- the backing bean is rare and anti to the common Java EE patterns.
Just note that the backing bean can return the entity directly, so bean-validation can still be used. There is no need whatsoever for the strange 'scatter/gather' pattern that crept up a long time ago (See the second example in this question).
E.g.
#ViewScoped
#ManagedBean
public class BackingBean {
private SomeEntity myEntity; // + getter
#EJB
private Service service;
#PostConstruct
public void init() {
myEntity = service.getSomeEntity();
}
public void save() {
service.save(myEntity);
FacesContext.getCurrentInstance().addMessage(..., ...);
}
}
Assuming SomeEntity in an #Entity annotated bean, bean validation can now be used on a Facelet like:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
>
<h:body>
<h:form>
<h:inputText value="#{backingBean.myEntity.name}" />
<h:commandButton value="Save" action="#{backingBean.save}" />
</h:form>
</h:body>
</html>
If there's a constraint on SomeEntity.name it will be validated.
I'm trying to split my JSF2 pages into composite components. So I decided to put the composite components in a logical file tree. For example:
WebContent/resources/components/page1/component1.xhtml
The associated bean is in
Java resources/src/components/page1/component1.java
Its package is this components.page1.
In this example, component1.xhtml is found and rendered, but the bean is not found by the server.
If I don't use a subpackage:
WebContent/resources/page1/component1.xhtml
Java resources/src/page1/component1.java
So when the class is in the package page1, it works!
Is there a problem with composite component beans and subpackages?
I am using MyFaces 2.0, Tomcat 6 and Eclipse.
You need the componentType attribute of <cc:interface> to explicitly specify the backing component.
<cc:interface componentType="component1">
with
package components.page1;
#FacesComponent("component1")
public class Component1 extends UINamingContainer {
// ...
}