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.
Related
I have a jsf bean used in pretty much all jsf beans in the application and I prefer not to hardcode the bean name when injecting the bean instance. Is it possible make it a variable and use the variable everywhere?
#ManagedBean (name=ApplicationInfo.BEAN_NAME_APPLICATION_INFO, eager=true)
#ApplicationScoped
#SuppressWarnings("serial")
public class ApplicationInfo extends ParentBean
{
public static final String BEAN_NAME_APPLICATION_INFO="applicationInfo";
.....
}
Now the referring class
#ManagedBean
#ViewScoped
public class SearchResultsBean extends ParentBean
{
private static final long serialVersionUID = 1L;
#ManagedProperty (value="#{ApplicationInfo.BEAN_NAME_APPLICATION_INFO}")
private ApplicationInfo applicationInfo;
....
}
Is it even possible?
Thanks
No, sorry, you can't set a variable name for a managed bean.
Here you have the link to the docs of the ManagedBean annotation
https://docs.oracle.com/javaee/6/api/javax/faces/bean/ManagedBean.html
You can see that "Classes must be scanned for the presence of this annotation at application startup, before any requests have been serviced."
So the name of the bean maybe only a hardcoded String. Every evaluation (such as calculate the value of ApplicationInfo.BEAN_NAME_APPLICATION_INFO) would happen later, when the application is started.
can someone help out, I just don't get it, the other bean works fine, i'ts just that bean that sucks:
BEAN:
import java.io.Serializable;
import java.util.List;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#SessionScoped
#Named
class FeedbackController implements Serializable {
private static final long serialVersionUID = 1L;
private Lecture lecture;
private List<Feedback> filteredFeedbacks;
public Lecture getLecture() {
return lecture;
}
public void setLecture(Lecture lecture) {
this.lecture = lecture;
}
VIEW:
<p:dataTable var="feedback"
value="#{feedbackController.lecture.feedbacks}"
ERROR:
javax.el.PropertyNotFoundException: The class 'com.xxx.controller.FeedbackController' does not have a readable property 'lecture'.
Since I'm quite nooby to the subject, i dont even know what i'm possibly doing wrong. I dont get, why it is not possible to access 'lecture' when the Controller is #Named and has a public getLecture() method. Also to say, is that i've got another view with the same priciple and it works fine, so i suppose to know what i'm doing.
Thanks in advance!
fixed it:
Must be public class FeedbackController implements Serializable {
thanks to BalusC for helping me out!
#ManagedProperty("#{sessionBean}") is not injected properly. The sessionBean is declared in a JAR file and it has a JSF 2.0 compatible faces-config as well.
But when I use
FacesContext context = FacesContext.getCurrentInstance();
sessionBean = (SessionBean) context.getApplication().evaluateExpressionGet(context, "#{sessionBean}", SessionBean.class);
It evaluates the session bean correctly. What is the reason?
EDIT: The bean that I want to be injected(sessionBean) is in a JAR file which is annotated as #ManagedBean and #SessionScoped. Also the JAR contains a JSF2 compatible faces-config in the META-INF/resources
1.) Where are you injecting the sessionBean into? Show us the class definition. Is the class a #ManagedBean?
2.) Check if the setter setSessionBean(SessionBean sb) called.
3.) Is the provided value in the setter null?
4.) You can also try to do the following:
#PostConstruct
private void init() {
FacesContext context = FacesContext.getCurrentInstance();
sessionBean = (SessionBean) context.getApplication().evaluateExpressionGet(context, "#{sessionBean}", SessionBean.class);
}
... and check if the sessionBean is evaluated correctly.
For me this was an issue with packages, the following imports worked for me:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
Before I was using a combination of different packages (auto-imported by IDE):
import javax.faces.bean.ManagedProperty;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
I use CDI to annotate beans. One bean called SessionManager holds the logined user information with the declaration:
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import javax.ejb.Stateful;
#Stateful
#Named
#SessionScoped
public class SessionManagerImpl implements SessionManager, Serializable {
...
public UserDto getLoginedUser() {
...
}
}
And the other is called DashboardController as:
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import javax.inject.Inject;
#Named
#RequestScoped
public class DashboardController implements Serializable {
#Inject
private SessionManager sessionManager;
...
public void loadUserInfo() {
...
UserDto userDto = sessionManager.getLoginedUser();
}
}
The first time i open a page refer DashboardController, it works well. And if i continue to use the website, it still works. But if i don't click any page for some minutes, and come back to open the page, it will display a null pointer for the javassist$$getLoginedUser method invocation (sessionManager is not null when i use debug to watch). The session is still valid for i can get values from session map directly using faces context.
What's wrong with the SessionManager? Thanks.
This occurs because your Stateful Session Bean (EJB) has passivated, and is not reintroduced to your session. If there isn't a strong need to make your session scoped object a session bean, I would just make it a SessionScoped managed bean.
I'm probably really close to the solution but I'm new with JSF and I don't see my mistake.
I have a first SessionScoped Managed Bean that represents Business information (address, website, ...)
#Named(value = "businessController")
#SessionScoped
public class BusinessController implements Serializable {
private Business current;
#EJB private BusinessFacade ejbFacade;
....
I have a second SessionScoped Managed Bean that represents the logged in user
#Named(value = "loginController")
#SessionScoped
public class LoginController implements Serializable {
private Login current;
#EJB
private LoginFacade ejbFacade;
#ManagedProperty(value="#{businessController}")
private BusinessController businessController;
public BusinessController getBusinessController() {
return businessController;
}
public void setBusinessController(BusinessController businessController) {
this.businessController = businessController;
}
When a user logs in, I set the current attribute from the loginController
Depending on this current user, I want to set the business attribute from the businessController :
businessController.setCurrent(current.getBusiness());
My problem is that the businessController attribute is null !
I use NetBeans 7.0.1 and GlassFish 3.1
In debug mode, I can see a viewId variable with the value
>No current context (stack frame)<
Unfortunately it doesn't ring any bell to me.
Any help would be appreciated
Thanks
You are mixing JSF managed beans with CDI managed beans.
Your BusinessController is annotated with the CDI annotaion #Named but gets injected with the #ManagedProperty annotation (from JSF). CDI managed beans need to be injected with #Inject. No getter or setter needed in this case. If you tend to use CDI, make sure that you import the correct #SessionScoped:
CDI: javax.enterprise.context.SessionScoped
JSF: javax.faces.bean.SessionScoped
Try the following (After making sure to have the correct scope class imported):
#Inject private BusinessController businessController;