JoinFaces #Configurable does not inject services - jsf

I am migrating an old JSF application to newer versions.
I have the problem with the lazyDataModel of Primefaces
#Configurable
public class PerfilSeleccionLazyDataModel extends LazyDataModel<Perfil> {
#Autowired
private transient PerfilService perfilService;
Now these classes do not inject services and are null
My new project is with Spring Boot, JoinFaces 4 and Spring 5.
Can someone tell me what new strategy I should use or if I should add some extra confirmation, so that my services are injected well?

I am using JoinFaces and here is what my LazyDatatable looks like. Use JSF ViewScoped on the bean and use normal Inject to inject the bean you want.
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
#Named
#ViewScoped
public class PerfilDatatable extends LazyDataModel<Perfil> {
#Inject
private transient PerfilService perfilService;
JoinFaces config:
joinfaces:
jsf:
project-stage: Development
state-saving-method: server
facelets-refresh-period: -1
facelets-skip-comments: true
interpret-empty-string-submitted-values-as-null: true
datetimeconverter-default-timezone-is-system-timezone: true
primefaces:
theme: babylon-bluegrey-accent
font-awesome: true
transform-metadata: true
move-scripts-to-bottom: true
submit: partial
omnifaces:
combined-resource-handler-cache-ttl: 3628800
combined-resource-handler-disabled: true
myfaces:
support-managed-beans: false
early-flush-enabled: true
check-id-production-mode: false

I faced the similar issue while using Spring-Boot-2.5.4 and JoinFaces_4.5.4. My solution is to pass the dependency from outside.
public class LazyProductsDataModel extends LazyDataModel<Product> {
private static final long serialVersionUID = 1L;
private transient ProductRepository productRepository;
public LazyProductsDataModel(ProductRepository productRepository) {
this.productRepository = productRepository;
}
}
and then in you can initialize it like this:
#Named
#ViewScoped
public class ProductListView {
#Autowired
private ProductRepository productRepository;
private LazyProductsDataModel lazyProductsDataModel;
#PostConstruct
private void init() {
lazyProductsDataModel = new LazyProductsDataModel(productRepository);
}
}

Related

Set JSF managed bean property from JAX-RS endpoint

I have a JSF managed bean and a JAX-RS web service.
ManagedBean - myBean class
#ManagedBean
#ViewScoped
public class MyBean implements Serializable {
private String id;//getters && setters ommited
}
Web Service - myService class
#ApplicationPath("/myService")
#Path("/")
#Consumes("application/json")
public class MyService extends Application {
#Inject
MyBean myBean;
#Path("doSth")
#POST
public Response doSomething(){
//make an action here and set myBean.id value
myBean.id = 'a random value';
}
}
I debugged the code above, but then I realised that inside myBean class, the property "id" was equal to null even though I had set it in the doSomething() method before, is it possible to achieve the scenario described above with these technologies? Before #Inject, I also tried the injection of my managedBean using #ManagedProperty, but the managedBean was null and not injected.
Then I would like this myBean.id property to be changed for the bean when I call it using myBean.id, is that feasible?
Thanks in advance!

JSF Converter - NullPointerException [duplicate]

How can I inject a dependency like #EJB, #PersistenceContext, #Inject, #AutoWired, etc in a #FacesConverter? In my specific case I need to inject an EJB via #EJB:
#FacesConverter
public class MyConverter implements Converter {
#EJB
protected MyService myService;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
// myService.doSomething
}
}
However, it didn't get injected and it remains null, resulting in NPEs. It seems that #PersistenceContext and #Inject also doesn't work.
How do I inject a service dependency in my converter so that I can access the DB?
Can I use #EJB to inject my service into a #FacesConverter?
No, not until JSF 2.3 is released. The JSF/CDI guys are working on that for JSF 2.3. See also JSF spec issue 1349 and this related "What's new in JSF 2.3?" article of my fellow Arjan Tijms. Only then dependency injection like #EJB, #PersistenceContext, #Inject, etc will work in a #FacesConverter when you explicitly add managed=true attribute to the annotation.
#FacesConverter(value="yourConverter", managed=true)
public class YourConverter implements Converter {
#Inject
private YourService service;
// ...
}
If not, what's the "correct" way to do this?
Before JSF 2.3, you have several options:
Make it a managed bean instead. You can make it a JSF, CDI or Spring managed bean via #ManagedBean, #Named or #Component. The below example makes it a JSF managed bean.
#ManagedBean
#RequestScoped
public class YourConverter implements Converter {
#EJB
private YourService service;
// ...
}
And the below example makes it a CDI managed bean.
#Named
#RequestScoped
public class YourConverter implements Converter {
#Inject
private YourService service;
// ...
}
Reference it as <h:inputXxx converter="#{yourConverter}"> instead of <h:inputXxx converter="yourConverter">, or as <f:converter binding="#{yourConverter}"> instead of <f:converter converterId="yourConverter">. Don't forget to remove the #FacesConverter annotation!
The disadvantage is that you cannot specify forClass and thus need to manually define the converter everywhere in the view where necessary.
Inject it in a regular managed bean instead.
#ManagedBean
#RequestScoped
public class YourBean {
#EJB
private YourService service;
// ...
}
And in your converter, grab or call it via EL.
YourBean yourBean = context.getApplication().evaluateExpressionGet(context, "#{yourBean}", YourBean.class);
// Then e.g. either
YourEntity yourEntity = yourBean.getService().findByStringId(value);
// Or
YourEntity yourEntity = yourBean.findEntityByStringId(value);
This way you can keep using #FacesConverter.
Manually grab the EJB from JNDI.
YourService yourService = (YourService) new InitialContext().lookup("java:global/appName/YourService");
The disadvantage is that there is a certain risk that this is not entirely portable. See also Inject EJB bean from JSF managed bean programmatically.
Install OmniFaces. Since version 1.6, it transparently adds support for #EJB (and #Inject) in a #FacesConverter without any further modification. See also the showcase. If you happen to need the converter for <f:selectItem(s)>, then the alternative is to use its SelectItemsConverter which will automatically perform the conversion job based on select items without the need for any database interaction.
<h:selectOneMenu ... converter="omnifaces.SelectItemsConverter">
See also Conversion Error setting value for 'null Converter'.
See also:
How to inject in #FacesValidator with #EJB, #PersistenceContext, #Inject, #Autowired
CDI Injection into a FacesConverter
Getting an #EJB in a #FacesValidator and #FacesConverter
The answer is Yes if you can accommodate Seam Faces module in your web application. Please check this post Injection of EntityManager or CDI Bean in FacesConverter. You can use #EJB in similar fashion.
You could access it indirectly through FacesContext, which is a parameter in both Converter methods.
The converter could be also annotated CDI Named with Application scope. When accessing the facade, two instances of the same class are used. One is the converter instance itself, dumb, without knowing EJB annotation. Another instance retains in application scope and could be accessed via the FacesContext. That instance is a Named object, thus it knows the EJB annotation. As everything is done in a single class, access could be kept protected.
See the following example:
#FacesConverter(forClass=Product.class)
#Named
#ApplicationScoped
public class ProductConverter implements Converter{
#EJB protected ProductFacade facade;
protected ProductFacade getFacadeFromConverter(FacesContext ctx){
if(facade==null){
facade = ((ProductConverter) ctx.getApplication()
.evaluateExpressionGet(ctx,"#{productConverter}",ProductConverter.class))
.facade;
}
return facade;
}
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return getFacadeFromConverter(context).find(Long.parseLong(value));
}
...
#Inject will only works in CDI managed instances
This only works at least Java EE 7 and CDI 1.1 server:
#FacesConverter
public class MyConverter implements Converter {
protected MyService myService;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
myService = CDI.current().select(MyService .class).get();
myService.doSomething();
}
}
https://docs.oracle.com/javaee/7/api/javax/enterprise/inject/spi/CDI.html
https://stackoverflow.com/a/33017416/5626568
By Luis Chacon, Sv
Works fine, tested
definition EJB :
#Stateless
#LocalBean
public class RubroEJB {
#PersistenceContext(unitName = "xxxxx")
private EntityManager em;
public List<CfgRubroPres> getAllCfgRubroPres(){
List<CfgRubroPres> rubros = null;
Query q = em.createNamedQuery("xxxxxxx");
rubros = q.getResultList();
return rubros;
}
}
define bean with the Aplication bean scope, for get the EJB Object
#ManagedBean(name="cuentaPresService", eager = true)
#ApplicationScoped
public class CuentaPresService {
#EJB
private RubroEJB cfgCuentaEJB;
public RubroEJB getCfgCuentaEJB() {
return cfgCuentaEJB;
}
public void setCfgCuentaEJB(RubroEJB cfgCuentaEJB) {
this.cfgCuentaEJB = cfgCuentaEJB;
}
}
final Access to Ejb Object from Converter:
#FacesConverter("cuentaPresConverter")
public class CuentaPresConverter implements Converter {
#EJB
RubroEJB rubroEJB;
public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
if(value != null && value.trim().length() > 0) {
try {
CuentaPresService service = (CuentaPresService) fc.getExternalContext().getApplicationMap().get("cuentaPresService");
List<CfgCuentaPres> listCuentas=service.getCfgCuentaEJB().getAllCfgCuentaPres();
................

CDI Beans and Hibernate Envers

I'm beggining with Hibernate Envers. I'm already able to properly annotate classes with #Audited and create revisions, but I'm unable to record logged user data with my revisions.
My JSF 2.0 test application is running on CDI, JPA/Hibernate in a jbossEAP6 / wildfly server. I'm neither using Spring or Seam.
Here is some code:
revisionEntity.java
#Entity
#RevisionEntity(AuditListener.class)
public class RevisionEntity {
#Id
#GeneratedValue
#RevisionNumber
private int id;
#RevisionTimestamp
private long timestamp;
private String username;
LoginBean.java
#Named
#Stateful
#SessionScoped
public class LoginBean implements Serializable{
private String username;
...
AuditListener.java
import javax.ejb.Stateful;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;
import org.hibernate.envers.RevisionListener;
import br.test.login.filterlogin.beans.LoginBean;
#Named
#Stateful
#SessionScoped
public class AuditListener implements RevisionListener {
#Inject
private LoginBean loginBean;
public void newRevision(Object revisionEntity) {
RevisionEntityEx RevEntity = (RevisionEntityEx) revisionEntity;
RevEntity.setUsername(loginBean.getUsername());
}
The loginBean injection fails, giving me a NullPointerException. Any ideas?
Sorry about my terrible grammar.
Regards,
Marcelo.
The listener is not managed by the container so your loginBean will not be injected.
We need to lookup for it...
Notice that UsuarioService should be changed to your type: LoginBean.
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.CDI;
BeanManager beanManager = CDI.current().getBeanManager();
Bean<UsuarioService> bean = (Bean<UsuarioService>) beanManager.getBeans(UsuarioService.class).iterator().next();
CreationalContext<UsuarioService> context = beanManager.createCreationalContext(bean);
this.usuarioService = (UsuarioService) beanManager.getReference(bean, UsuarioService.class, context);
You didn't give any stacktrace, so I'm guessing. AFAIK you cannot combine together both
#Stateful
#SessionScoped
Because the first annotation is for making a class an EJB stateful session bean, but the second one is for making class a CDI managed bean, with scope Session.
It seems to me that you are trying to use technologies you don't understand at all. Please read a specification or at least some CDI tutorials/ sample GitHub projects.
Personal advice: most of the time you should prefer to use #Stateless over #Stateful for EJB beans. Then all data related to HTTP session you can store e.g. in some additional #SessionScoped CDI bean.

#ManagedBean(name="foo") not available by its name in EL #{foo}

I'm trying to use an application scoped bean in JSF2, but for some reason it is always null in my request scoped bean. Here's the code I'm using:
The application scoped bean:
#ManagedBean(eager=true, name="applicationTracking")
#ApplicationScoped
public class ApplicationTracking implements Serializable {
private static final long serialVersionUID = 4536466449079922778L;
public ApplicationTracking() {
System.out.println("ApplicationTracking constructed");
}
}
The request scoped bean:
#ManagedBean
#RequestScoped
public class SearchResults implements Serializable {
private static final long serialVersionUID = 4331629908101406406L;
#ManagedProperty("#{applicationTracking}")
private ApplicationTracking appTracking;
public ApplicationTracking getAppTracking() {
return appTracking;
}
public void setAppTracking(ApplicationTracking appTrack) {
this.appTracking = appTrack;
}
#PostConstruct
public void init() {
System.out.println("SearchResults.init CALLED, appTracking = " + appTracking);
}
}
According to everything I'm seeing in the forums this should work without any other configurations. When I start the server (Tomcat) I'm seeing the ApplicationTracking constructor and init methods getting called.
But in my SearchResults component the printout in the PostConstruct is always null:
SearchResults.init CALLED, appTracking = null
What am I missing?
Provided that you imported those annotations from the right package javax.faces.bean.*, then this problem will happen if you re-registered the very same managed bean class in faces-config.xml on a different managed bean name. Get rid of that faces-config.xml entry. That's the JSF 1.x style of registering managed beans. You don't need it in JSF 2.x. When you do so anyway, then it will override any annotation based registration on the managed bean class, causing them to be ineffective.
Make sure you don't read JSF 1.x targeted resources while learning and working with JSF 2.x. Many things are done differently in JSF 2.x.

How to inject #EJB, #PersistenceContext, #Inject, #Autowired, etc in #FacesConverter?

How can I inject a dependency like #EJB, #PersistenceContext, #Inject, #AutoWired, etc in a #FacesConverter? In my specific case I need to inject an EJB via #EJB:
#FacesConverter
public class MyConverter implements Converter {
#EJB
protected MyService myService;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
// myService.doSomething
}
}
However, it didn't get injected and it remains null, resulting in NPEs. It seems that #PersistenceContext and #Inject also doesn't work.
How do I inject a service dependency in my converter so that I can access the DB?
Can I use #EJB to inject my service into a #FacesConverter?
No, not until JSF 2.3 is released. The JSF/CDI guys are working on that for JSF 2.3. See also JSF spec issue 1349 and this related "What's new in JSF 2.3?" article of my fellow Arjan Tijms. Only then dependency injection like #EJB, #PersistenceContext, #Inject, etc will work in a #FacesConverter when you explicitly add managed=true attribute to the annotation.
#FacesConverter(value="yourConverter", managed=true)
public class YourConverter implements Converter {
#Inject
private YourService service;
// ...
}
If not, what's the "correct" way to do this?
Before JSF 2.3, you have several options:
Make it a managed bean instead. You can make it a JSF, CDI or Spring managed bean via #ManagedBean, #Named or #Component. The below example makes it a JSF managed bean.
#ManagedBean
#RequestScoped
public class YourConverter implements Converter {
#EJB
private YourService service;
// ...
}
And the below example makes it a CDI managed bean.
#Named
#RequestScoped
public class YourConverter implements Converter {
#Inject
private YourService service;
// ...
}
Reference it as <h:inputXxx converter="#{yourConverter}"> instead of <h:inputXxx converter="yourConverter">, or as <f:converter binding="#{yourConverter}"> instead of <f:converter converterId="yourConverter">. Don't forget to remove the #FacesConverter annotation!
The disadvantage is that you cannot specify forClass and thus need to manually define the converter everywhere in the view where necessary.
Inject it in a regular managed bean instead.
#ManagedBean
#RequestScoped
public class YourBean {
#EJB
private YourService service;
// ...
}
And in your converter, grab or call it via EL.
YourBean yourBean = context.getApplication().evaluateExpressionGet(context, "#{yourBean}", YourBean.class);
// Then e.g. either
YourEntity yourEntity = yourBean.getService().findByStringId(value);
// Or
YourEntity yourEntity = yourBean.findEntityByStringId(value);
This way you can keep using #FacesConverter.
Manually grab the EJB from JNDI.
YourService yourService = (YourService) new InitialContext().lookup("java:global/appName/YourService");
The disadvantage is that there is a certain risk that this is not entirely portable. See also Inject EJB bean from JSF managed bean programmatically.
Install OmniFaces. Since version 1.6, it transparently adds support for #EJB (and #Inject) in a #FacesConverter without any further modification. See also the showcase. If you happen to need the converter for <f:selectItem(s)>, then the alternative is to use its SelectItemsConverter which will automatically perform the conversion job based on select items without the need for any database interaction.
<h:selectOneMenu ... converter="omnifaces.SelectItemsConverter">
See also Conversion Error setting value for 'null Converter'.
See also:
How to inject in #FacesValidator with #EJB, #PersistenceContext, #Inject, #Autowired
CDI Injection into a FacesConverter
Getting an #EJB in a #FacesValidator and #FacesConverter
The answer is Yes if you can accommodate Seam Faces module in your web application. Please check this post Injection of EntityManager or CDI Bean in FacesConverter. You can use #EJB in similar fashion.
You could access it indirectly through FacesContext, which is a parameter in both Converter methods.
The converter could be also annotated CDI Named with Application scope. When accessing the facade, two instances of the same class are used. One is the converter instance itself, dumb, without knowing EJB annotation. Another instance retains in application scope and could be accessed via the FacesContext. That instance is a Named object, thus it knows the EJB annotation. As everything is done in a single class, access could be kept protected.
See the following example:
#FacesConverter(forClass=Product.class)
#Named
#ApplicationScoped
public class ProductConverter implements Converter{
#EJB protected ProductFacade facade;
protected ProductFacade getFacadeFromConverter(FacesContext ctx){
if(facade==null){
facade = ((ProductConverter) ctx.getApplication()
.evaluateExpressionGet(ctx,"#{productConverter}",ProductConverter.class))
.facade;
}
return facade;
}
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return getFacadeFromConverter(context).find(Long.parseLong(value));
}
...
#Inject will only works in CDI managed instances
This only works at least Java EE 7 and CDI 1.1 server:
#FacesConverter
public class MyConverter implements Converter {
protected MyService myService;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
myService = CDI.current().select(MyService .class).get();
myService.doSomething();
}
}
https://docs.oracle.com/javaee/7/api/javax/enterprise/inject/spi/CDI.html
https://stackoverflow.com/a/33017416/5626568
By Luis Chacon, Sv
Works fine, tested
definition EJB :
#Stateless
#LocalBean
public class RubroEJB {
#PersistenceContext(unitName = "xxxxx")
private EntityManager em;
public List<CfgRubroPres> getAllCfgRubroPres(){
List<CfgRubroPres> rubros = null;
Query q = em.createNamedQuery("xxxxxxx");
rubros = q.getResultList();
return rubros;
}
}
define bean with the Aplication bean scope, for get the EJB Object
#ManagedBean(name="cuentaPresService", eager = true)
#ApplicationScoped
public class CuentaPresService {
#EJB
private RubroEJB cfgCuentaEJB;
public RubroEJB getCfgCuentaEJB() {
return cfgCuentaEJB;
}
public void setCfgCuentaEJB(RubroEJB cfgCuentaEJB) {
this.cfgCuentaEJB = cfgCuentaEJB;
}
}
final Access to Ejb Object from Converter:
#FacesConverter("cuentaPresConverter")
public class CuentaPresConverter implements Converter {
#EJB
RubroEJB rubroEJB;
public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
if(value != null && value.trim().length() > 0) {
try {
CuentaPresService service = (CuentaPresService) fc.getExternalContext().getApplicationMap().get("cuentaPresService");
List<CfgCuentaPres> listCuentas=service.getCfgCuentaEJB().getAllCfgCuentaPres();
................

Resources