JSF button is not working after AJAX call - jsf

I have this JSF button which calls Java method when it's pressed:
<h:commandButton id="editdata" value="HiddenDelete" style="position:absolute; bottom:25px; right:650px;" actionListener="#{bean.saveData}" rendered="#{bean.editable}">
<f:ajax render="#form" execute="#form"></f:ajax>
</h:commandButton>
public void saveData() throws SQLException
{
.....
}
When I make a AJAX call the button is not working properly. Can you help me to find why the Java method is not called after AJAX call?

You're not passing the event:
public void saveData(AjaxBehaviorEvent event) { ... }
Also, what do you expect to happen with the Exception you're throwing? Shouldn't you catch it?
try {
// logic
}
catch(SQLException ex) {
FacesContext facesContext = FacesContext.getCurrentInstance();
FacesMessage facesMessage = new FacesMessage(
"There was an error, ....");
facesContext.addMessage(null, facesMessage);
}
This will be printed in HTML by <h:messages />.

Related

Exception from persistence layer does not hit catch block in managed bean [duplicate]

This question already has answers here:
Handling service layer exception in Java EE frontend method
(3 answers)
Closed 6 years ago.
I've looked around for help with this issue but actually I don't have any idea where the problem is coming from so I don't know what to look for.
To be simple:
- I have a form that persist an object in DB in Ajax generated by JSF using JPA.
- When there is a PersistenceException I want to handle it and send a message to the user.
In my DAO I catch PersistenceException and throw a new custom DAOException to my Backing Bean in order to add a FacesMessage to the view.
Facelet :
<h:outputLabel for="codePF" styleClass="control-label">Code PF <span class="requis">*</span>
</h:outputLabel>
<h:inputText id="codePF" value="#{gestionDemandes.demande.motCle}" required="true" size="20" maxlength="20" styleClass="form-control">
<f:ajax event="blur" render="codePFMessage" />
</h:inputText>
<h:message id="codePFMessage" for="codePF" errorClass="erreur" />
<br />
<h:messages globalOnly="true" infoClass="info" />
<h:commandButton id="boutonDemande" value="Inscription" action="#{gestionDemandes.creerDemande()}" styleClass="btn btn-primary">
<f:ajax execute="#form" render="#form" />
<h:message id="boutonDemandeMessage" for="boutonDemande" errorClass="bg-danger" infoClass="bg-success" />
</h:commandButton>
<br />
</h:form>
Backing Bean:
#ManagedBean
#RequestScoped
public class GestionDemandes implements Serializable {
private static final String ERREUR_AJOUT = "Erreur de création de la demande";
private static final String SUCCES = "Demande ajoutée !";
// Injection de notre EJB (Session Bean Stateless)
#EJB
private DAODemande daoDemande;
// Demande utilisée par le formulaire de création de demandes
public void creerDemande() {
FacesMessage message;
try {
daoDemande.creer(demande);
} catch (DAOException dao) {
message = new FacesMessage(FacesMessage.SEVERITY_ERROR, ERREUR_AJOUT,
dao.getMessage());
FacesContext.getCurrentInstance().addMessage(null, message);
return;
}
message = new FacesMessage(SUCCES);
FacesContext.getCurrentInstance().addMessage(null, message);
}
DAO:
#Stateless
public class DAODemande {
// Injection du manager
#PersistenceContext(unitName = "gamabddactuelle_PU")
private EntityManager em;
// Enregistrement d'un nouvel utilisateur
public void creer(Demande demande) throws DAOException {
demande.setIdDemande(demande.getIdClientDemande());
try {
em.persist(demande);
em.flush();
} catch (PersistenceException e) {
throw new DAOException(e.getCause());
}
}
First, I had to add the em.flush() in DAO or I wouldn't even catch the PersistenceException.
Then when I throw my DAOException, I don't catch it in my Backing Bean.
It seems the DAOException is thrown in an other thread than the Ajax Call where I persist my Object.
I read this :
Better Exception Handling in JPA
Honestly I found it a bit complicated just to handle a simple Exception.
Can someone explain what is going on here ? Is it a thread problem ?
My Conf:
TOMEE 7 with/Openjpa 2.4/myfaces 2.2.8
JRE 1.8
I had a similar issue and after hours of breaking my head, I found what was actually happening.
When my DAO had an exception and when I threw a custom app exception from DAO, I realized that when still in my transaction scope, the custom exception was overridden by hibernate's exception and hence my view layer could not catch my application's custom exception.
All I had to do is handle in my transaction the exception and rollBack the transaction. (It was an insert operation)
Things to do:
Check if hibernate is overridden your exception
In your transaction handle the hibernate exception (I did a rollback handle)
Make sure the custom app exception is thrown all the way up to the view layer.

How to show a primefaces growl message on the next page? [duplicate]

This question already has answers here:
How to use Primefaces' p:growl and redirect to a page
(3 answers)
Closed 6 years ago.
I'm using primefaces 3.5 and I can't figure it out how to growl a message on the next page. For instance I want to add a record in database and after that I make a redirection to another page where I want to show a growl message with "The record has been added with success!"
I tried something like this:
public String addLabelInDB() {
try {
//logic to add a record in DB
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success!", "Label has been added with success!"));
} catch (Exception e) {
logger.debug(e.getMessage());
}
return "listLabelsPage";
}
and in listLabelsPage.xhtml I have:
<p:growl id="msgs" showDetail="true" autoUpdate="true"/>
but it doesn't work.
I supposed the message is getting lost because is another request or something? It's there any possibility to store the message on request and show it on the next page? Thanks!
You can have a preRender set on the listLabelsPage.xhtml page you're loading
<f:event type="preRenderView" listener="#{yourBean.showGrowl}" />
and a showGrowl method having only
public void showGrowl() {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success!", "Label has been added with success!"));
}
I post an answer to my own question in order to help another people which face the same problem like I did:
public String addLabelInDB() {
try {
//some logic to insert in db
//below I set a flag on context which helps me to display a growl message only when the insertion was done with success
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.getRequestMap().put("addedWithSuccess","true");
} catch (Exception e) {
logger.debug(e.getMessage());
}
return "listLabelsPage";
}
public void showGrowl() {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
String labelAddedWithSuccess = (String) ec.getRequestMap().get("addedWithSuccess");
//if the flag on context is true show the growl message
if (labelAddedWithSuccess!=null && labelAddedWithSuccess.equals("true")) {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success!", "Label has been added with success!"));
}
}
and in my xhtml I have:
<f:event type="preRenderView" listener="#{labelsManager.showGrowl}" />
How about this? Make a separated redirect button which will be hit after showing msg:
HTML:
<h:form prependId="false">
<p:growl />
<p:button outcome="gotoABC" id="rdr-btn" style="display: none;" />
<p:commandButton action="#{bean.process()}" update="#form" />
</form>
Bean:
public void process(){
addInfoMsg(summary, msgDetail); //Add msg func
RequestContext.getCurrentInstance().execute("setTimeout(function(){ $('#rdr-btn').click(); }, 3000);"); // 3 seconds delay. I put the script in Constants to config later.
}

Setter of application scoped bean fails to set value

I'm making page using Primefaces with form with ability to ajax-upload image and preview it before submitting whole form.
To achieve this I made dialog outside main form:
<p:dialog id="imageDlg" header="Load Image" modal="true"
widgetVar="imageUploadWidget">
<h:form id="imageForm" enctype="multipart/form-data">
<p:fileUpload mode="advanced" auto="true" sizeLimit="9999999"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"
fileUploadListener="#{pageBean.imageUploadHandler}">
</p:fileUpload>
</h:form>
</p:dialog>
Inside main form there is p:graphicImage component to display just uploaded image and button to show dialog. Page is backed by view scoped bean (PageBean), but to pass StreamedContent to p:graphicImage value bean should be session or application scoped (because method called multiply times). So I made second application scoped bean (ImageBean) only for this purpose.
<p:graphicImage value="#{imageBean.imageStreamedContent()}"/>
<p:commandButton value="Choose image" type="button"
onclick="imageUploadWidget.show();"/>
Code of ImageBean:
#ApplicationScoped
#ManagedBean
public class ImagesBean implements Serializable {
private byte[] image;
//getter & setter
public StreamedContent imageStreamedContent() {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
} else {
return new DefaultStreamedContent(new ByteArrayInputStream(getImage()));
}
}
}
The next part is fileUploadListener. Idea is simple — set corresponding fields of PageBean (to save it later on form submit) of ImageBean (to show it after partial refresh) and update part of main form:
#ManagedBean
#ViewScoped
public class PageBean implements Serializable {
#ManagedProperty(value="#{imageBean}")
ImagesBean imagesBean;
...
public void imageUploadHandler(FileUploadEvent event) {
getImagesBean().setImage(event.getFile().getContents());
RequestContext.getCurrentInstance().update("form:tabPanel1");
}
Here comes strange thing. Inside setImage() method everything is OK - field is set, getter works fine. But then page refresh, imageBean.getImage() inside imageBean.imageStreamedContent() returns null.
More accurate — it returns old value, as if setter was never called or was called on another instance of bean. I checked it on another String field: initialized it in ImageBean constructor, in handler invoked setter with another value and refreshed part of main form. Same thing: old value from constructor.
I think, that I'm missing something about bean life cycle or scope specific. Or maybe there is less complicated way to implement this task?
There is a problem with using StreamedContent in Primefaces for p:graphicImage and p:media.
You can see Cagatay Civici 's comments on this topic in Primefaces forum here.
In my experience, when I had the slimier(more or less) problem This and This answers by BalusC helped me.
I used a saperate Servlet instead of Managedbean to stream the dynamic content to p:media (in mycase).
Here is my code for your reference(if you need any):
PreviewFileServlet.java
#WebServlet("/PreviewFile")
public class PreviewFileServlet extends HttpServlet {
public PreviewFileServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext context = request.getServletContext();
String path = request.getParameter("PREVIEW_FILE_PATH");
logger.info("Received pathe for Preview:"+path);
try{
if(null!=path){
java.io.File f = new java.io.File(path);
if(f.exists()){
FileInputStream fin = new FileInputStream(f);
byte b[] = new byte[(int)f.length()];
fin.read(b);
response.setContentLength(b.length);
response.setContentType(context.getMimeType(path));
response.getOutputStream().write(b);
response.getOutputStream().close();
logger.info("File sent successfully for Preview.");
}
else{
logger.warn("File sepecified by path:-"+path+"-:, NOT found");
}
}
}catch(Exception e){
}
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Facelet Code
<p:media value="/PreviewFile?PREVIEW_FILE_PATH=#{fileManager.previewFilePath}" />
Hope this helps.
And there are lot of questions on this topic of StreamedContent in stackoverflow itself, go through them once.

Session Scoped Managed Bean constructor being called on each page refresh

I am using a session scoped managed bean for handling login in a Java EE application. After I authenticate the user, the user object is saved in this session bean. However, after I refresh the page, the session bean values are gone.
I was debugging the code and it results that the constructor of the session scoped managed bean is called again on page refresh, therefore initializing the user object with a new user. I guess this is not a normal behavior since it should be preserved on the session shouldn't it?
I am posting some parts of the login managed bean including the parameters and the login method. Basically the enteredEmail and enteredPassword stand for the entered data on the login form. If the authentication succeeds, the loggedIn boolean is turned to true and the logged in user object is stored in the checkedUser variable.
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class LoginController implements Serializable {
#EJB
private LoginSessionBean loginSessionBean;
#EJB
private LecturerFacade lecturerFacade;
private Lecturer checkedUser;
private String enteredEmail;
private String enteredPassword;
private boolean loggedIn;
/** Creates a new instance of loginController */
public LoginController() {
loggedIn = false;
checkedUser = new Lecturer();
}
public String login(){
RequestContext context = RequestContext.getCurrentInstance();
FacesMessage msg = null;
this.setCheckedUser(lecturerFacade.findLecturerByEmail(enteredEmail));
if(loginSessionBean.checkPassword(checkedUser, enteredPassword))
{
loggedIn = true;
msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Welcome", checkedUser.getFirstName()+ " " + checkedUser.getLastName());
FacesContext.getCurrentInstance().addMessage(null, msg);
context.addCallbackParam("loggedIn", loggedIn);
}
return "Index";
I am also posting the two EJBs that the above managed bean uses. The lecturerFacade retrieves the user object with the entered email, while the loginSessionBean checks the password.
#Stateless
public class LecturerFacade extends AbstractFacade<Lecturer> {
#PersistenceContext(unitName = "EffectinetWebPU")
private EntityManager em;
Logger logger = Logger.getLogger("MyLog");
FileHandler fh;
protected EntityManager getEntityManager() {
return em;
}
public LecturerFacade() {
super(Lecturer.class);
}
public Lecturer findLecturerByEmail(String email) {
try {
return (Lecturer) this.getEntityManager().createQuery("SELECT l FROM Lecturer l WHERE l.email = :email").setParameter("email", email).getSingleResult();
} catch (NoResultException e) {
System.err.println("Caught NOResultException: "+ e.getMessage());
return null;
} catch (NonUniqueResultException e) {
System.err.println("Caught NonUniqueResultException: "+ e.getMessage());
return null;
} catch (IllegalStateException e) {
System.err.println("Caught IllegalStateException: "+ e.getMessage());
return null;
}
}
_
#Stateless
public class LoginSessionBean {
// Add business logic below. (Right-click in editor and choose
// "Insert Code > Add Business Method")
#PersistenceContext(unitName = "EffectinetWebPU")
private EntityManager em;
protected EntityManager getEntityManager() {
return em;
}
public void setEntityManager(EntityManager em) {
this.em = em;
}
public boolean checkPassword(Lecturer user, final String enteredPassword) {
if (user.getPassword().equals(enteredPassword)) {
return true;
} else {
return false;
}
}
}
Please if someone has any suggestion of what is going wrong, please tell me
Im using glassfish 3.1 as application server and Primefaces as JSF library. Also, I have checked and the imported the sessionScoped annotation from the right package and not from javax.enterprise...
Your problem is thus here:
<p:menuitem value="Logout" ... onclick="#{loginController.logout()}"/>
The onclick attribute should represent a JavaScript handler function which is to be executed in the webbrowser when the enduser clicks the element. Something like
onclick="alert('You have clicked this element!')"
The onclick attribute also accepts a ValueExpression, so you can even let JSF/EL autogenerate its value accordingly:
onclick="#{bean.onclickFunction}"
with
public String getOnclickFunction() {
return "alert('You have clicked this element!')";
}
All the EL is thus evaluated when the page is rendered. In your particular case, the logout() method is called everytime the EL is evaluated and thus you're invalidating the session everytime the page is rendered!
You need to bind it to an attribute which takes a MethodExpression like <h:commandLink action>, <h:commandButton action> and in this particular case <p:menuitem action>.
<p:menuitem value="Logout" ... action="#{loginController.logout()}"/>
This can be understood by understanding basic HTML and JavaScript concepts and keeping in mind that JSF ultimately produces HTML/CSS/JS. Open the JSF page in webbrowser, rightclick and View Source to realize it.
Well I managed to solve it today. This was the problem, although I cannot explain why:
I was using Primefaces 3.2 as JSF library so this was the main menu of the index page.
<h:form>
<p:menubar >
<p:menuitem id="registerLink" value="Register" rendered="#{!loginController.loggedIn}" onclick="registerDialog.show()" />
<p:menuitem id="loginLink" value="Login" rendered="#{!loginController.loggedIn}" onclick="loginDialog.show()" />
<p:submenu label="Units" rendered="true">
<p:menuitem id="addNew" value="Add New" onclick="createUnitDialog.show()" />
<p:menuitem id="myUnits" value="My Units" onclick="" />
</p:submenu>
<p:menuitem id="results" value="Results/Statistics" rendered="#{loginController.loggedIn}" onclick=""/>
<p:menuitem id="profile" value="My Profile" rendered="#{loginController.loggedIn}" onclick=""/>
<p:menuitem id="logout" value="Logout" rendered="#{loginController.loggedIn}" onclick="#{loginController.logout()}"/>
</p:menubar>
</h:form>
After setting breakpoints to the whole code I discovered that the logout() method, which is supposed to destroy the managed bean, was called on every page refresh. I don't know why this happened as it should be called when the logout menuitem was clicked.
However, after changing the onclick="#{loginController.logout()} with action="#{loginController.logout()} the problem was solved.
I checked the documentation of Primefaces but nowhere this behavior was explained

How to invoke a JSF bean action from a link?

We have the following requirement in our project.
On click of a link,
A JSF managed bean method should be invoked which will return a URL
to a document.
This document should be opened in a new window.
How can I do this?
How about a <h:commandLink/> with a target="_blank" attribute:
<h:commandLink action="#{bean.action}" target="_blank" value="Open document"/>
And in your bean:
public void action() {
try {
FacesContext.getCurrentInstance().getExternalContext()
.redirect("page2.xhtml");
} catch (IOException ex) {
// do something here
}
}
Replace page2.xhtml with your target url.

Resources