I'm a beginner in Java EE 6 and was recently playing with conversations. I was not able to find out how to start conversation immediately as JSF page is loaded (as in Seam). Is this doable?
It's doable.
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"
xmlns:f="http://java.sun.com/jsf/core">
<f:view contentType="text/html">
<f:metadata>
<f:event type="preRenderView" listener="#{myBean.preRenderView}"/>
</f:metadata>
<h:head>
<title>My Page</title>
</h:head>
<h:body>
<!-- Body here -->
</h:body>
</f:view>
</html>
Bean:
import java.io.Serializable;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.faces.event.ComponentSystemEvent;
import javax.inject.Inject;
import javax.inject.Named;
#Named
#ConversationScoped
public class MyBean implements Serializable {
public void preRenderView(ComponentSystemEvent e) {
String currentViewId = FacesContext.getCurrentInstance().getViewRoot().getViewId();
if (CONVERSATION_START_PAGE.equals(currentViewId)) {
conversation.begin();
}
#Inject
private Conversation conversation;
private static final String CONVERSATION_START_PAGE = "/foo/bar/start-page.xhtml";
}
Related
I want to pass selectedExamId from chooseexam page to exam page, what is the good way to do that? is it a good practice to use two baking bean for single jsf page?
One more thing is I am getting same Question list each time?
I have following jsf page
chooseExam.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 lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
<ui:composition template="/templates/admin/template.xhtml">
<ui:define name="content">
<h:selectOneRadio value="#{examBean.selectedExamId}">
<f:selectItems value="#{chooseExamBean.exams}" var="exam" itemValue="#{exam.examId}" itemLabel="#{exam.examName}"/>
</h:selectOneRadio>
<h:commandButton value="Submit" action="/user/exam?faces-redirect=true"/>
</ui:define>
</ui:composition>
</h:body>
</html>
and
exam.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 lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
</h:head>
<h:body>
<ui:composition template="/templates/admin/template.xhtml">
<ui:define name="content">
<ui:repeat value="#{examBean.questions}" var="question">
<h:outputLabel value="#{question.question}"/>
<h:selectOneRadio value="#{examBean.questionAnswerMap[question]}">
<f:selectItem itemValue="#{question.choice1}" itemLabel="#{question.choice1}"/>
<f:selectItem itemValue="#{question.choice2}" itemLabel="#{question.choice2}"/>
<f:selectItem itemValue="#{question.choice3}" itemLabel="#{question.choice3}"/>
<f:selectItem itemValue="#{question.choice4}" itemLabel="#{question.choice4}"/>
</h:selectOneRadio>
</ui:repeat>
<h:commandButton value="Submit" action="#{examBean.calculate}"/>
</ui:define>
</ui:composition>
</h:body>
</html>
following are the backing beans
ChooseExamBean.java
#Component
#ManagedBean
public class ChooseExamBean {
List<Exam> exams;
#Autowired
private ExamService examService;
#PostConstruct
public void init(){
exams = examService.getAllExams();
}
public List<Exam> getExams() {
return exams;
}
public void setExams(List<Exam> exams) {
this.exams = exams;
}
}
and
ExamBean.java
#Component
#ManagedBean
public class ExamBean {
private List<Question> questions;
private Map<Question, String> questionAnswerMap = new HashMap<>();
private int score;
private Long selectedExamId;
#Autowired
private QuestionService questionService;
#PostConstruct
public void init() {
if(selectedExamId != null)
questions = questionService.getQuestionsForExam(selectedExamId);
}
public Map<Question, String> getQuestionAnswerMap() {
return questionAnswerMap;
}
public void setQuestionAnswerMap(Map<Question, String> questionAnswerMap) {
this.questionAnswerMap = questionAnswerMap;
}
public List<Question> getQuestions() {
if(questions == null)
questions = questionService.getQuestionsForExam(selectedExamId);
return questions;
}
public void setQuestions(List<Question> questions) {
this.questions = questions;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public Long getSelectedExamId() {
return selectedExamId;
}
public void setSelectedExamId(Long selectedExamId) {
this.selectedExamId = selectedExamId;
}
public String calculate() {
score = questionAnswerMap.size();
return "result?faces-redirect=true";
}
}
Since you are using a RequestScope Beans for the (ExamBean and the ChooseExamBean) you cant keep the values after the response , so you should user the viewParam tag to pass the value from the first page to the second page.
you should make something like the following :
1- the ChooseExam.jsf , you have your radioButtons that will save its value in the chooseExamBean :
<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:selectOneRadio label="examType" value="#{chooseExamBean.examNumber}">
<f:selectItem itemLabel="exam1" itemValue="1"/>
<f:selectItem itemLabel="exam2" itemValue="2"/>
</h:selectOneRadio>
<h:commandButton value="commandButton1" action="#{chooseExamBean.navigateToExamPage}" />
</h:form>
</h:body>
</html>
</f:view>
2- in the action of the commandButton you will call a method in the bean to navigate , before navigation you will append a param to the url like the following in the navigateToExamPage method :
#ManagedBean(name = "chooseExamBean")
#RequestScoped
public class ChooseExamBean {
public ChooseExamBean() {
super();
}
private String examNumber;
public void setExamNumber(String examNumber) {
this.examNumber = examNumber;
}
public String getExamNumber() {
return examNumber;
}
public Object navigateToExamPage() {
return "exam?faces-redirect=true&examId="+getExamNumber();
}
}
3- in the exam.jsf page , you have to get the value of the parameter , here you will use the tag like the following :
<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>
<f:metadata>
<f:viewParam name="examId" value="#{examBean.examNumber}"/>
<f:event type="preRenderView" listener="#{examBean.onLoad}" />
</f:metadata>
<h:outputText value="#{examBean.examNumber}"/>
</h:form>
</h:body>
</html>
</f:view>
the view param have to attributes :
1- name :which is the name of the parameter that you want to get from the url.
2- value :which is where you want to set the value of the parameter.
so in our case the name is "examId" and we want to set the value in "examBean.examNumber" .
here you will find a problem if you didnt use tag , because you want to get the examId onPage Load in the postConstrct method , but the f:param will be called after the postConstruct , so we have to use the like the following :
<f:event type="preRenderView" listener="#{examBean.onLoad}" />
this will help us to perform custom task before a JSF page is displayed.
4- in you examBean :
#ManagedBean(name = "examBean")
#RequestScoped
public class ExamBean {
public ExamBean() {
super();
}
private String examNumber;
public void setExamNumber(String examNumber) {
this.examNumber = examNumber;
}
public String getExamNumber() {
return examNumber;
}
public void onLoad () {
System.out.println("onLoad = "+getExamNumber());
}
}
Please use this with your requirements and everything will go smooth.
Please refer to the following answer here, here and here .
Hope that Helps.
After a long time I'm using a4j:ajax to get simple text from h:inputText and render to h:outputText but it's not working
I found many examples like this but none of them worked for me.
this id my bean
import javax.faces.bean.*;
#ManagedBean(name="usertest")
#RequestScoped
public class UserBean {
private String name = "john";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and this is my index.xhtml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!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"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<h:head>
</h:head>
<body>
<h:form id="f1">
<h:inputText id="name1" value="#{usertest.name}">
<a4j:ajax event="keyup" render="name2" execute="#form"></a4j:ajax>
</h:inputText>
<h:outputText id="name2" value="#{usertest.name}"></h:outputText>
</h:form>
</body>
</html>
I'm using JSF 2.0 and RichFaces 4.0
Any solution would help me.
Tanks
I am building a web app based on ICEmobile with JSF 2.1 and Maven. I'm running into this problem when my jsf page doesn't look for its bean but I still can build and deploy the project with no errors, I deploy the project via run configuration in Eclipse: clean tomcat7:run-war. Even if I declare the bean via annotation or applicationContext.xml, the page still doesn't call the bean correctly. I can get the value of the field in the bean but cannot call the method within that bean System.out.println("Pressed"); gives no output to the console. I'm guessing it must be something to do with my configuration but I don't know where to look into. Please give me some hints. Thanks
<!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"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:util="http://java.sun.com/jsf/composite/components"
xmlns:mobi="http://www.icesoft.com/icefaces/mobile/component"
xmlns:ice="http://www.icesoft.com/icefaces/component"
xmlns:icecore="http://www.icefaces.org/icefaces/core">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
<meta name="viewport"
content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<title>ICEfaces Mobile Showcase</title>
<mobi:deviceStylesheet media="screen" />
</h:head>
<h:body>
<mobi:pagePanel>
<f:facet name="body">
<h:form>
<mobi:commandButton value="#{buttonBean.buttonName}" buttonType="important" actionListener="#{buttonBean.buttonPress}">
<f:attribute name="buttonState" value="change"/>
</mobi:commandButton>
</h:form>
</f:facet>
</mobi:pagePanel>
</h:body>
</html>
The Bean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.event.ActionEvent;
#ManagedBean(name = ButtonBean.BEAN_NAME)
#SessionScoped
public class ButtonBean implements Serializable {
private static final long serialVersionUID = 1L;
public static final String BEAN_NAME = "buttonBean";
private String buttonName = "0";
public String getButtonName() {
return buttonName;
}
public void setButtonName(String buttonName) {
this.buttonName = buttonName;
}
public void buttonPress(ActionEvent event){
System.out.println("Pressed");
String buttonState = (String)event.getComponent().getAttributes().get("buttonState");
if (buttonState.equals("change") && buttonName.equals("0")) buttonName = "1";
else if (buttonState.equals("change") && buttonName.equals("1")) buttonName = "0";
}
}
I found out that my web.xml was set as version 2.5. Change to version 3.0. All works now
I'm trying to make a partial rendering navigation for an application. The code bellow is a concept test that works well with exception of the commandbutton on x.xhtml file. It does't fire the actionListeneron a click. This is used to change the url for the included part.
index.xhtml
<!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:head>
<f:facet name="first">
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
<title>PrimeFaces</title>
</f:facet>
<style type="text/css">
.ui-layout-north {
z-index:20 !important;
overflow:visible !important;;
}
.ui-layout-north .ui-layout-unit-content {
overflow:visible !important;
}
</style>
</h:head>
<h:body>
<p:layout fullPage="true">
<p:layoutUnit position="north" size="100" header="Top" resizable="true" closable="true" collapsible="true">
<h:form>
<p:menubar>
<p:submenu label="File" icon="ui-icon-document">
<p:menuitem value="XXX" update=":wrapper" actionListener="#{tbean.doNav}">
<f:attribute name="xxx_page" value="x.xhtml" />
</p:menuitem>
<p:menuitem value="YYY" update=":wrapper" actionListener="#{tbean.doNav}">
<f:attribute name="xxx_page" value="y.xhtml" />
</p:menuitem>
</p:submenu>
</p:menubar>
</h:form>
</p:layoutUnit>
<p:layoutUnit position="center">
<p:outputPanel id="wrapper">
<ui:include src="#{tbean.url}"/>
</p:outputPanel>
</p:layoutUnit>
</p:layout>
</h:body>
</f:view>
</html>
x.xhtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<ui:component 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"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:form>
<p:commandButton value="zzz" update=":wrapper" actionListener="#{tbean.doNav}">
<f:attribute name="xxx_page" value="z.xhtml" />
</p:commandButton>
<p:dataTable var="car" value="#{tbean.cars}">
<p:column>
<f:facet name="header">
Name
</f:facet>
<h:outputText value="#{car.name}" />
</p:column>
</p:dataTable>
</h:form>
</ui:component>
y.xhtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<ui:component 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"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:outputText value="yyy"/>
</ui:component>
z.xhtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<ui:component 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"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:outputText value="zzz"/>
</ui:component>
tbean.java
package com.teste;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.event.ActionEvent;
#ManagedBean
#RequestScoped
public class tbean {
private String url = "y.xhtml";
private List<Car> cars = new ArrayList<>();
public tbean() {
for (int i = 0; i < 10; i++) {
cars.add(new Car(i));
}
}
public void setUrl(String url) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "setUrl :{0}", this.url);
this.url = url;
}
public String getUrl() {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "getUrl :{0}", this.url);
return this.url;
}
public void doNav(ActionEvent event) {
this.url = (String) event.getComponent().getAttributes().get("xxx_page");
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "doNav :{0}", this.url);
}
public List<Car> getCars() {
return cars;
}
}
Your backing bean is request scoped. This means that it's created on every HTTP request. So the url property will default to y.xhtml on every request.
Submitting the form by the command button creates a new HTTP request. So it gets a new instance of the request scoped bean with the url property defaulted to y.xhtml. When JSF needs to process the form submit, it can't figure the button pressed because it's not present in y.xhtml. So JSF cannot invoke the action associated with the button pressed.
Placing the bean in view scope should fix your problem.
#ManagedBean
#ViewScoped
public class tbean {
This will remember the url property properly across the HTTP requests on the very same view (by returning null or void on every action).
See also:
How to choose the right bean scope?
As to the whole design, you need to make absolutely sure that all the ajax actions are been invoked by PrimeFaces components, not by the standard JSF <f:ajax> ones, otherwise the commandbutton would still not be invoked due to a bug in JSF JS.
See also:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated (point 7)
I have just created a NetBeans project with JSF 2.0 and I have a problem with f:validateRequired. The bean
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean
#RequestScoped
public class TestBean {
private String value;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String action() {
return "test";
}
}
and the page
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.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">
<h:head>
<title>Test</title>
<h:outputStylesheet name="css/stylesheet.css" />
</h:head>
<h:body>
<h:form>
<div id="content">
Value:
<h:message for="test" />
<h:inputText value="#{testBean.value}" id="test">
<f:validateRequired />
</h:inputText>
<br/>
<h:commandButton action="#{testBean.action}" value="Action" />
</div>
</h:form>
</h:body>
</html>
seems to be allright, but the h:message isn't there until I supply the requered="true" attribute on the inputText. What I am missing? Why the validation does not occure whithout the requered="true" attribute?
I figured the answer: fields with empty input are not validated at all by default. If you wish to validate such field you have to set required=true. See UIInput.validateValue() JavaDoc
You can enable the validation of empty fields by setting the javax.faces.VALIDATE_EMPTY_FIELDS context parameter to true. See JavaDoc. After doing that the example above works as expected.
I know this post is kind of old, but I'm using MyFaces and apparently javax.faces.VALIDATE_EMPTY_FIELDS is set to false by default.