I am developing a simple application on JSF having the following dependences
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-impl</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>2.0.2</version>
</dependency>
and being a simple page with it backing bean.
xhtml
<?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"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<title></title>
</head>
<body >
<h:form>
<f:view >
<h:commandButton id="otxMainPanelTextBt" value="click"
action="#{otherController.doSome}"/>
</f:view>
</h:form>
</body>
</html>
Java code
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "otherController")
#ViewScoped
public class Other implements Serializable {
private static final long serialVersionUID = -6493758917750576706L;
public String doSome() {
System.out.println(this);
return "";
}
}
If I click on the commandButton many times according to toString source code it should write
class name+hashCode
but it writes something like the following
de.controller.Other#118ea91
de.controller.Other#1e8f930
de.controller.Other#1a38f3c
So, everytime we click there is a different hashcode for the viewscoped bean. Is this incorrect? I have tryed with session beans and this doesn't happen.
EDIT
I modified the class following #BalusC suggestion in the following way.
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "otherController")
#ViewScoped
public class Other implements Serializable {
private static final long serialVersionUID = -6493758917750576706L;
#PostConstruct
public void init()
{
System.out.println("Post Construction");
}
public Other()
{
System.out.println("Constructor");
}
public void doSome() {
System.out.println(this);
}
}
And I found this output after clicking many times.
Constructor
Post Construction
de.controller.Other#b748dd
de.controller.Other#1620dca
de.controller.Other#116358
de.controller.Other#73cb2d
de.controller.Other#1cc3ba0
So, the constructor and PostConstructor Methods are invoked only once, and in spite of this the object still has a different hashcode in every call. This is weird because the constructor with no parameter is supposed to be called on a managed bean instantiation, but it is not, so i still don't understand how can be the object created several times?
When you return non-null from an action method, a new view is created.
If you want to keep the current view alive, just return null or void from the action method.
E.g.
public void doSome() {
System.out.println(this);
}
See also:
How to choose the right bean scope?
That said, your conclusion that this is a problem is correct, but the grounds on which you based off your conclusion, "incorrect hashcode implementation", makes no utter sense. It were just physically different bean instances everytime. Add a default constructor to the class, put a breakpoint on it and you'll see that it's invoked everytime after you returned from the action method, creating a brand new instance.
Related
I'm using poll from primefaces to update an image every n seconds. I'm flipping between two images right now just to make sure it's working. Now what I'm trying to do is display images that aren't stored on the server. I wrote a class that snaps a photo every n seconds. I don't want to save it to disk to reduce IO. So I'd like to do something like the following flow
#ManagedBean
#ViewScoped
public class myClass implements Serializable {
public Object getImage() {
Object newImage = MyClass.takePhoto();
return newImage;
}
public void increment() {
}
}
XHTML:
<?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"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form>
<h:graphicImage value="#{myClass.image}" id="img" cache="false"/>
<p:poll interval="1" listener="#{myClass.increment}" update="img" />
</h:form>
</h:body>
</h:html>
So my question is, is it possible to return an Image object to h:graphicImage in a similar way to the pseudo-code above?
Yes, try using the Primefaces StreamedContent class to provide a stream to graphicImage, rather than an object.
Something like:
public StreamedContent getImageStream() {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(myBufferedImage, "png", os);
InputStream is = new ByteArrayInputStream(os.toByteArray());
return new DefaultStreamedContent(is, "image/png");
}
Then in your JSF page:
<p:graphicImage value="#{myController.imageStream}" cache="false"/>
Note that this uses p:graphicImage, rather than h:graphicImage.
I am unable to access GET parameters in a backing bean. The example.xhtml file:
<!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"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:metadata>
<f:viewParam name="id" value="#{myBackingBean.unitId}" />
<f:viewAction action="#{myBackingBean.findUnits}" />
</f:metadata>
<head>
<title>Example Title</title>
</head>
<body>
I found #{myBackingBean.units.size()} units.
</body>
</html>
My understanding is that when I GET example.jsf?id=3 then JSF calls myBackingBean.setUnitId(3). Correct?
Here is MyBackingBean:
#Model
public class MyBackingBean {
private static Logger logger = Logger.getLogger(MyBackingBean.class
.getName());
//#ManagedProperty("#{param.id}")
private Long unitId;
#Inject
private IExampleEJB myExampleEjb;
private List<Unit> units;
#PostConstruct
public void postConstruct() {
Map<String, String> mymap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
for (String k:mymap.keySet()) {
logger.info(String.format("%s %s", k,mymap.get(k)));
}
}
public void findUnits() {
logger.info(String.format("MyBackingBean findUnits %d", unitId));
units = myExampleEjb.findUnits();
}
public List<Unit> getUnits() {
return units;
}
public void setUnits(List<Unit> units) {
this.units = units;
}
public Long getUnitId() {
return unitId;
}
public void setUnitId(Long unitId) {
this.unitId = unitId;
}
}
The id parameter is in the parameter request map in postConstruct().
In my case, setUnitId() is never called, nor is findUnits().
In a different but related question, the #ManagedProperty (currently commented out) does not work either.
Given the xmlns.jcp.org namespace, you're using JSF 2.2. The early Mojarra 2.2.0 and 2.2.1 versions have a known bug which causes the <f:viewParam> to not work.
As per the comments you're using GlassFish 4.0. If you didn't upgrade its bundled JSF implementation and thus are using the early Mojarra version 2.2.0, then you're definitely facing this bug and you need to upgrade.
You can get the JAR from http://javaserverfaces.java.net. All you need to do is to replace javax.faces.jar file in GlassFish's /modules folder with the newer version.
See also
f:viewParam doesn't pass required parameter when new xmlns.jcp.org namespace is used
I am trying to use <p:columns> but it renders nothing when I feed it with a List that is a property of the objects the enclosing <p:dataTable> is iterating over.
I can use that list succesfully in <ui:repeat> or access one of it's entries inside the <p:dataTable> using <p:column>. <p:columns> when a assign the list to a property of the backing bean.
But when using the property of the Car-object nothing is rendered at that place. There is no error message etc.
The part about Dynamic Columns in the Primefaces 4.0 User Guide confuses me as in the code example cars[colIndex] is used but still the <p:columns> has a value other than cars - I don't how this is supposed to be used.
Additional Info:
I need the list of columns for <p:columns> to be part of the class as I want to reuse the code for several classes with different properties and thus require different columns.
the Facelets code:
<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">
<h:head></h:head>
<h:messages />
<h:form>
<!-- works -->
<ui:repeat value="#{carBean.cars}" var="car">
ui:repeat: #{car.features}
</ui:repeat>
<p:dataTable value="#{carBean.cars}" var="car">
<!-- works too -->
<p:column>
p:column: #{car.features.get(0)}
</p:column>
<!-- works too -->
<p:columns value="#{carBean.beanFeatures}" var="feature" columnIndexVar="colIndex">
carBean p:columns: #{feature}
</p:columns>
<!-- renders nothing -->
<p:columns value="#{car.features}" var="feature" columnIndexVar="colIndex">
car p:columns: #{feature}
</p:columns>
</p:dataTable>
</h:form>
</html>
the backing bean:
package myPackage;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class CarBean implements Serializable {
List<Car> cars;
List<String> beanFeatures;
#PostConstruct
public void init(){
cars = new ArrayList<Car>();
Car car1 = new Car();
car1.features.add("windows");
car1.features.add("fridge");
Car car2 = new Car();
car2.features.add("wheels");
car2.features.add("nuclear engine");
cars.add(car1);
cars.add(car2);
beanFeatures = car1.getFeatures();
}
public List<Car> getCars() {
return cars;
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
public List<String> getBeanFeatures() {
return beanFeatures;
}
public void setBeanFeatures(List<String> beanFeatures) {
this.beanFeatures = beanFeatures;
}
}
the Car class
package myPackage;
import java.util.ArrayList;
import java.util.List;
public class Car {
List<String> features = new ArrayList<String>();
public List<String> getFeatures() {
return features;
}
public void setFeatures(List<String> features) {
this.features = features;
}
}
That's basically not the way Primefaces dynamic columns work. Your dynamic columns must be binded against a Managed Bean's property directly. There's no choice to dinamically stablish that value for each car iteration.
So, in short words, is not possible to have different columns for different table values. Table columns can be dinamically rendered, but this must be decided before PrimeFaces starts looping over the values.
If you have a look at Primefaces showcase, you'll find that.
However, it's possible to loop over car's features in the same columns using a ui:repeat, so you could have all its features in a single column:
<p:column>
<ui:repeat value="#{car.features}" var="feature">
#{feature}
</ui:repeat>
</p:column>
So I am struggling with getting a sample app to work. I'm using Primefaces 3.3M4-SNAPSHOT, JBOSS 7 web profile (CDI and JSF Mojarra).
I have my backing bean:
#Named
#ViewScoped
#URLMapping(id = "viewEditor", pattern = "/editor/e", viewId = "/editor/editor.jsf")
public class ViewEditor implements Serializable {
public void deleteNode() {
selectedNode.getChildren().clear();
selectedNode.getParent().getChildren().remove(selectedNode);
selectedNode.setParent(null);
selectedNode = null;
}
}
My xhtml:
<p:contextMenu for="docs">
<p:menuitem value="View" update="documentPanel"
icon="ui-icon ui-icon-search" oncomplete="documentDialog.show()" />
<p:menuitem value="Delete"
actionListener="#{viewEditor.deleteNode}" update="docs"
icon="ui-icon ui-icon-close" />
</p:contextMenu>
When I run my app, this is the exception I get:
javax.el.ELException: /editor/editor.xhtml: The class 'application.ViewEditor$Proxy$_$$_WeldClientProxy' does not have the property 'deleteNode'.
com.sun.faces.facelets.compiler.AttributeInstruction.write(AttributeInstruction.java:94)
com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)
com.sun.faces.facelets.compiler.UILeaf.encodeAll(UILeaf.java:183)
javax.faces.render.Renderer.encodeChildren(Renderer.java:168)
Did anyone come across the same issue as I did?
Okay got the answer. It turns out that the namespace for primefaces has changed from
xmlns:p="http://primefaces.prime.com.tr/ui"
to
xmlns:p="http://primefaces.org/ui"
By changing the namespace everything worked. Wow that was an elusive thing to track down.
In my case the reason was completely different.
I copied a class including serialVersionUID field:
private static final long serialVersionUID = 5443351151396868724L;
so I had two different classes and objects with the same serialVersionUID and this was the clue of the problem.
Has anybody used JSF2, PrimeFaces, and Highcharts together?
I am really confused on how I should put all these together, specially regarding the ajax request to get the data from the server to feed into Highcharts on the view to update the chart.
What I have right now is a servlet that handles the Ajax request, which is sent using JQuery.ajax() method and use JQuery to update the chart with the new data received as JSON object. And I am using GSon.toJSon to convert Java object into JSON object.
What I am trying to achieve here is that I want to replace that servlet with the JSF2. Instead of using a different servlet, I want to use JSF and have some backing bean to prepare and send the JSON object to the client.
Anybody?
In the example below the the p:commandButton starts the ajax request. The JSON object you want to use can be stored in the h:inputHidden field. When the p:commandButton completes the javascript function is called to update the chart. The javascript function will be able to access the JSON object from the h:inputHidden field.
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"
xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<script type="text/javascript">
function dosomething() {
var value = jQuery("#beanvalue").attr('value');
alert(value);
}
</script>
</h:head>
<h:body>
<h:form prependId="false" >
<p:commandButton value="update" action="#{testBean.update}" update="beanvalue" oncomplete="dosomething();" />
<h:inputHidden value="#{testBean.output}" id="beanvalue" />
</h:form>
</h:body>
</html>
Bean
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class TestBean {
private String output;
public TestBean() {
output = "1";
}
public void update() {
output += "1";
}
public String getOutput() {
return output;
}
public void setOutput(String output) {
this.output = output;
}
}