jsf bean not working - jsf

This is my xhtml:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Keep alive</title>
</h:head>
<f:metadata>
<f:viewParam name="value" id="value" value="#{myBean.val}" ></f:viewParam>
</f:metadata>
<h:body>
Hello.<h:form><h:outputLabel value="#{myBean.val}"></h:outputLabel></h:form>
</h:body>
</html>
And this is my bean:
import javax.faces.bean.RequestScoped;
import javax.faces.bean.ManagedBean;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#RequestScoped
#ManagedBean
public class MyBean {
#PersistenceContext(unitName = "myPUhere")
private EntityManager em;
/**
* Creates a new instance of myBean
*/
public MyBean() {
System.out.println("mybeanload");
if (getWaarde() == "yes") {
System.out.println("IT WORKS!!");
}
}
private String val;
public String getVal() {
System.out.println("getting value");
return val;
}
public void setVal(String value) {
System.out.println("setting value to " + value);
this.val = value;
}
}
My Bean does not respond to this, what don't I see here? It does not display the value I enter in the URL, nor it displays my outputLabel.

So, you're retrieving the raw JSF source code in the browser instead of its generated HTML output. Browsers obviously don't understand JSF code (like as it doesn't understand JSP/PHP/ASP/etc code), but it only understands HTML code. This can happen when the FacesServlet hasn't been invoked, it's namely the one responsible for all the JSF works.
Perhaps your FacesServlet is based on some tutorial or IDE-autogenerated code been mapped on an URL pattern different than *.xhtml, such as *.jsf or *.faces. In that case, you've 2 options:
Fix the request URL in your browser's address bar to match exactly that URL pattern. So, assuming that it's *.jsf, then don't open the page by
http://localhost:8080/context/index.xhtml
but instead by
http://localhost:8080/context/index.jsf
Fix the URL pattern to be *.xhtml directly. This wasn't possible back in JSF 1.x as the FacesServlet would otherwise call itself in an infinite loop, but this is quite possible in JSF 2.x and a lot of books/tutorials/resources/IDEs didn't take this into account.
<url-pattern>*.xhtml</url-pattern>
See also:
JSF Facelets: Sometimes I see the URL is .jsf and sometimes .xhtml. Why?

Related

JSF access private/protected property of a super class

I am very new to JSF and this is the first project I work on (got a bit too lazy with jsp) so please forgive me if the question is trivial.
So I have a Super Class Device
#Entity
#Table(name = "Devices")
public class Device
{
protected bool Authorized
public bool isAuthorized()
{ return this.Authorized;}
public void setAuthorized(bool Authorized)
{ this.Authorized = Authorized;}
}
and a sub class SensorDevice that extends the Super Class Device
public class SensorDevice extends Device
{
// has its own properties which dont matter
}
and a Managed Bean UIDeviceManager
#ManagedBean(name = "DeviceManager")
#SessionScoped
public class UIDeviceManager
{
private List<SensorDevice> Pending;
// in constructor, Pending List gets populated with the devices requiring Authorization
}
and an xhtml page which contains a Table for the Pending Devices
<p:dataTable var="device" value="#{DeviceManager.pending}">
<p:column headerText="Device Authorization">
<h:form>
<p:inputSwitch
value="#{device.isAuthorized()}"
binding="#{AuthorizationInputSwitch}"
offLabel="UnAuthorized"
onLabel="Authorized">
<p:ajax
event="change"
listener="#{device.setAuthorized(AuthorizationInputSwitch.value)}" />
</p:inputSwitch>
</h:form>
</p:column>
Now unless the syntax in the xhtml is completely messed up (I tried my best there and would appreciate guidance), the function setAuthorized for that particular device instance should be called (even with the wrong input, but will sort that later by modifying the setter function), but that doesnt happen, the Ajax doesnt get called. Instead, the inputSwitch tries to update its "value property source" and attempts to look for a property isAuthorized() in the class SensorDevice which it fails to find.
Now I am aware that this could be easily solved by making the Boolean Authorized public in the super class but as you can see it is also a JPA entity that is persisted in a database to keep track of the devices, so the only option is to keep it protected.
So how do I update parameters of a Super class from a sub-class instance in a Managed Bean from a public function rather than direct access to the parameter itself (I thought JSF looked for the setters and getters but whatever)
Btw value="#{device.isAuthorized()}"works correctly but if I try the property directly it fails ( I guess its obvious at this point )
One last thing, if the approach/architecture is wrong, please advise on what is the correct layout to achieve this functionality. I am sure there is a standard way to integrate JSF and JPA without duplicating entities and wrappers
I think you must use field name in value attribute of InputSwitch component like this:
<p:inputSwitch
value="#{device.authorized}"
binding="#{AuthorizationInputSwitch}"
offLabel="UnAuthorized"
onLabel="Authorized">
Instead of:
<p:inputSwitch
value="#{device.isAuthorized()}"
binding="#{AuthorizationInputSwitch}"
offLabel="UnAuthorized"
onLabel="Authorized">
JSF will use isAuthorized and setAuthorized method (uses Java Beans standard convention to recognize getter and setter methods)
So i think you don't need the ajax part to call setter method.
To emphasize Mojtaba's answer, this is how you access properties in JSF:
Facelets page:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:outputText value="#{myBean.entity.someBool}"/>
</h:body>
</html>
Managed bean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class MyBean {
private SomeEntity entity = new SomeEntity();
public SomeEntity getEntity() {
return entity;
}
}
Entity classes:
public class SomeEntity extends SomeParent {
}
public class SomeParent {
private boolean someBool = true;
public boolean isSomeBool() {
return someBool;
}
public void setSomeBool(boolean someBool) {
this.someBool = someBool;
}
}
JSF doesn't know or care that your objects are JPA entities, and standard inheritance and access rules apply.
See also
JavaBean conventions

Composite component causes unique ID error when binding to view scoped bean

We are migrating a JSF 2.1 application, from JBoss AS 7.2 to Wildfly and thus JSF 2.2. The problem We're having is the following: We have a compositecomponent that is included in a #ViewScoped bean. The component has to retain its value through multiple requests, so a Request Scoped bean is not a solution.
The exception we're getting is a multiple component id one. After the request JSF starts to render the component for the second time, and fails.
I made a simple demo for this:
MyViewBean.java
#ViewScoped
#Named
public class MyViewBean implements Serializable {
private Component component;
public Component getComponent() {
return component;
}
public void setComponent(Component component) {
this.component = component;
}
public String increment(){
component.setCounter(component.getCounter()+1);
return "";
}
}
Component.java
#FacesComponent(value = "composite")
public class Component extends UINamingContainer {
private Integer counter = 0;
public Integer getCounter() {
return counter;
}
public void setCounter(Integer counter) {
this.counter = counter;
}
}
compositeTest.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
template="/WEB-INF/templates/default.xhtml"
xmlns:pelda="http://xmlns.jcp.org/jsf/composite/component">
<ui:define name="content">
<h1>Composite component Test!</h1>
<h:form>
<pelda:composite binding="#{myViewBean.component}" />
<h:commandButton action="#{myViewBean.increment()}" value="Push me!"/>
</h:form>
</ui:define>
</ui:composition>
composite.xhtml
<cc:interface componentType="composite">
</cc:interface>
<cc:implementation>
<h:outputText id="id_hello" value="Helloka" />
<h:outputText id="id_counter" value="#{cc.counter}" />
</cc:implementation>
</html>
How to achieve that the counter can be incremented (with #RequestScoped bean it resets) and won't fail with idUniqueness error? We're using Mojarra 2.2.8 (Default in wildfly), also tried with Mojarra 2.2.12 (the latest as per writing this).
Thanks in advance!
UIComponent instances are inherently request scoped. You should never reference UIComponent instances beyond the request scope. Carefully read How does the 'binding' attribute work in JSF? When and how should it be used? for an elaborate explanation on that.
You only want to save its state in the JSF state via the inherited getStateHelper() method. This acts basically as the view scope.
#FacesComponent(value = "composite")
public class Component extends UINamingContainer {
public Integer getCounter() {
return (Integer) getStateHelper().eval("counter", 0);
}
public void setCounter(Integer counter) {
getStateHelper().put("counter", counter);
}
}
Don't forget to get rid of the binding attribute in the view.
See also:
How to save state when extending UIComponentBase

How to stream a file download and display a JSF faces message?

We are streaming a binary file to our users, following the procedure elaborated in the SO question How to provide a file download from a JSF backing bean?
In general the workflow works as intended, but during the generation of the export file recoverable errors may occur and we want to display these as a warning to the user. The file itself shall still be generated in that case. So we want that export to continue and display faces messages.
Just to put emphasis on this: Yes, there is something not OK with the data, but our users want the export to continue and receive that flawed file anyway. Then they want to have a look at the file, contact their vendor and send him a message about the flaw.
So I need the export to finish in any case.
But it does not work out as we want it to. I have created a simplified example to illustrate our approach.
As alternative we are considering a Bean that will be hold the messages and display them after the export. But probably there is a way with JSF built-in mechanisms to achieve this.
Controller
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.apache.tomcat.util.http.fileupload.util.Streams;
#ManagedBean
#RequestScoped
public class ExportController {
public void export() {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
byte[] exportContent = "Hy Buddys, thanks for the help!".getBytes();
// here something bad happens that the user should know about
// but this message does not go out to the user
fc.addMessage(null, new FacesMessage("record 2 was flawed"));
ec.responseReset();
ec.setResponseContentType("text/plain");
ec.setResponseContentLength(exportContent.length);
String attachmentName = "attachment; filename=\"export.txt\"";
ec.setResponseHeader("Content-Disposition", attachmentName);
try {
OutputStream output = ec.getResponseOutputStream();
Streams.copy(new ByteArrayInputStream(exportContent), output, false);
} catch (IOException ex) {
ex.printStackTrace();
}
fc.responseComplete();
}
}
JSF Page
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<f:view contentType="text/html">
<h:body>
<h:form prependId="false">
<h:messages id="messages" />
<h:commandButton id="download" value="Download"
actionListener="#{exportController.export()}" />
</h:form>
</h:body>
</f:view>
</html>
Since you're actually performing a file download response and not a JSF one, it's not possible for your message to be added while the same request happens. The most clean solution for me, avoiding hacky asynchronous requests is to use a #ViewScoped bean and do your task in two steps. So, to have a button for preparing your file, notifying the user later on and allowing him to download it when it's ready:
#ManagedBean
#ViewScoped
public class ExportController implements Serializable {
private byte[] exportContent;
public boolean isReady() {
return exportContent != null;
}
public void export() {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.responseReset();
ec.setResponseContentType("text/plain");
ec.setResponseContentLength(exportContent.length);
String attachmentName = "attachment; filename=\"export.txt\"";
ec.setResponseHeader("Content-Disposition", attachmentName);
try {
OutputStream output = ec.getResponseOutputStream();
Streams.copy(new ByteArrayInputStream(exportContent), output, false);
} catch (IOException ex) {
ex.printStackTrace();
}
fc.responseComplete();
}
public void prepareFile() {
exportContent = "Hy Buddys, thanks for the help!".getBytes();
// here something bad happens that the user should know about
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage("record 2 was flawed"));
}
}
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<f:view contentType="text/html">
<h:body>
<h:form>
<h:messages id="messages" />
<h:commandButton value="Prepare"
action="#{exportController.prepareFile}" />
<h:commandButton id="download" value="Download"
disabled="#{not exportController.ready}"
action="#{exportController.export()}" />
</h:form>
</h:body>
</f:view>
</html>
Note this solution could be valid for small files (their entire content is stored in memory while user keeps in the same view). However, if you're going to use it with large files (or large number of users) your best is to store its content in a temporary file and display a link to it instead of a download button. That's what #BalusC suggests in the reference below.
See also:
File download from JSF with a rendered response
You may try this :
For primefaces, you can use remote command instead of command link, and call it with its name onsuccess. Otherwise give a widget var to the commandlink and call its click method.

How and when is a view scope bean removed from LRU cache in JSF?

I have read an excellent answer when view scoped bean is destroyed. (see How and when is a #ViewScoped bean destroyed in JSF?) and I automatically assumed that destroyed bean is also removed from the view scope cache. But I could see that bean is still in the cache, so I would like to know if destroyed view scoped bean should be also removed from the LRU view scope cache, if ever?
In our application we open all details in sepeare tabs/windows. After some opening/closing (depends on numberOfViewsInSession) we could see ViewExpiredException in case when the first detail window is still opened and user has been opening and closing another detail windows and after some time he wants to do some operation in the first window. I have done some debugging and I can see that closed view wasn't removed from the LRU cache.
So is it expected behaviour or is there something wrong in my code? And if it is expected behaviour, is there any useful strategy how to work with multitabs/multiwindow without lot of ViewExpiredException caused by the LRU cache?. I know I can change numberOfViewsInSession but it is the last choice that I want to use.
I prepared a simple testcase and when I'm opening/closing view.xhtml more times, I can see that LRUMap is growing.
Environment : JDK7, mojarra 2.2.4, tomcat 7.0.47
Thanks in advance
view.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html">
<head>
<title>View Bean</title>
<meta charset="UTF-8"/>
</head>
<body>
<h:form id="viewForm">
<div>#{viewBean.text}</div>
<h:commandButton id="closeButton" value="Close" action="/ClosePage.xhtml"/>
</h:form>
</body>
</html>
index.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>Session bean</title>
</h:head>
<h:body>
<h:form id="sessionForm">
<h:outputText value="#{sessionBean.text}"/>
<br/>
<h:link id="linkView" value="Open view.xhmtl" outcome="/view.xhtml" target="_blank"/>
</h:form>
</h:body>
</html>
ClosePage.xhmtl
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head><title>Window will be closed</title></head>
<body>
<script>window.close();</script>
</body>
</html>
ViewBean.java
package com.mycompany.mavenproject2;
import com.sun.faces.util.LRUMap;
import java.io.Serializable;
import java.util.Map;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
#ManagedBean(name = "viewBean")
#ViewScoped
public class ViewBean implements Serializable {
private static final long serialVersionUID = 13920902390329L;
private int lruMapSize;
/**
* Creates a new instance of ViewBean
*/
public ViewBean() {
Map<String, Object> sessionMap = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
LRUMap<String, LRUMap> lruMap = (LRUMap) sessionMap.get("com.sun.faces.renderkit.ServerSideStateHelper.LogicalViewMap");
lruMapSize = lruMap == null ? 0 : lruMap.size();
}
#PreDestroy
void destroyed() {
System.out.println("View bean destroyed");
}
public String getText() {
return "ViewBean LRU cache size:" + Integer.toString(lruMapSize);
}
}
SessionBean.java
package com.mycompany.mavenproject2;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name = "sessionBean")
#SessionScoped
public class SessionBean implements Serializable {
private static final long serialVersionUID = 1777489347L;
/**
* Creates a new instance of SessionBean
*/
public SessionBean() {
}
public String getText() {
return "Session bean text";
}
}
I think every JSF developer runs up against this eventually. The true problem lies in the fact that you can't devise a truly reliable stateful system in which the browser will signal back to the ViewScoped bean that it is done with the page, allowing the backing bean to destroy itself. This is why JSF implementations have LRU caches to limit the memory used by a session, which is a great catch-all solution for everyday apps.
There are a few cases in which you know that you are done with the ViewScoped bean, such as a redirect from that bean. For these, you could write your own view handler to perform a smarter caching system, but that's not a trivial task, and frankly, not worth the effort.
The simplest solution I came up with is to use a javascript timer to execute an ajax postback to the server on every page with a ViewScoped bean. (Setting this timer to execute every 30 seconds seems reasonable.) This will move the ViewScoped bean(s) associated with the page to the bottom of the LRU cache, ensuring they aren't expired.
In particular, I use a primefaces poll component to pull this off and stick in a template to be used by all ViewScoped beans. By placing this component in its own form, the request size remains small.

valueChangeListener method is called on selectOneMenu even though I have not changed the value

I have the following problem. When I click the button "Enviar", this calls another method that is associated to a selectOneMenu (in the attribute
valueChangeListener called "validarSelect"), and later, calls the method that this button has associated in the attribute actionListener called "validarBoton".
I wonder, why this happens. I expect the valueChangeListener to be not called since I have not changed the dropdown.
This is my page JSF:
<?xml version='1.0' encoding='windows-1252'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html">
<html xmlns="http://www.w3.org/1999/xhtml">
<h:head></h:head>
<h:body>
<h:form>
<h:commandButton value="Enviar..." id="validar" actionListener="#{Domiciliacion.validarBoton}"/>
<h:selectOneMenu valueChangeListener="#{Domiciliacion.validarSelect}"
binding="#{Domiciliacion.selectCombo}">
<f:selectItems value="#{Domiciliacion.lista}"/>
<f:ajax event="valueChange" render="#this"/>
</h:selectOneMenu>
</h:form>
</h:body>
</html>
And this, is the ManagedBean:
package domiciliaciontest;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlSelectOneMenu;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
#ManagedBean(name = "Domiciliacion")
#ViewScoped
public class MB0001 {
private HtmlSelectOneMenu selectCombo;
private List<String> lista = new ArrayList<String>();
public MB0001() {
super();
System.out.println("Entro al constructor...");
lista.add("Caracas");
lista.add("Bogota");
lista.add("Santiago");
}
public void validarBoton(ActionEvent actionEvent) {
System.out.println("Entro a validarBoton...");
// Add event code here...
}
public void validarSelect(ValueChangeEvent valueChangeEvent) {
// Add event code here...
System.out.println("Entro a validarSelect...");
}
public void setSelectCombo(HtmlSelectOneMenu selectCombo) {
this.selectCombo = selectCombo;
}
public HtmlSelectOneMenu getSelectCombo() {
return selectCombo;
}
public void setLista(List<String> lista) {
this.lista = lista;
}
public List<String> getLista() {
return lista;
}
}
this is the output when I click the button "Enviar":
Entro a validarSelect...
Entro a validarBoton...
The valueChangeListener method will be invoked when the submitted value is different from the initial value, regardless of whether you have changed it yourself or not. So, if the currently submitted value (which is "Caracas" in your case) is different from the initial value (which is null in your case), then the valueChangeListener method will be invoked.
See also:
When to use valueChangeListener or f:ajax listener?
Best way to add a "nothing selected" option to a selectOneMenu in JSF
Unrelated to the concrete problem, seeing this in combination with binding attribute gives me the impression that you're trying to achieve something which you've read in an article or answer targeted on JSF 1.x. This is namely recognizeable as part of a hack to populate child dropdowns in JSF 1.x. You do not need this approach for JSF 2.x. Further, your method names with "validar" ("validate") are misleading. Don't you actually need a fullworthy Validator? But as said, that's a different problem.
See also:
Make multiple dependent / cascading selectOneMenu dropdown lists in JSF

Resources