ui repeat to show one more value and method is not invoking in managed Bean in JSF2.2 - jsf-2.2

<ui:repeat value="#{cc.attrs.bean.foo.foo1}" var="test" varStatus="test1">
<h:outputText value="#{test.prime}" title="#{test.primeNumber}" />
<h:outputText value="," rendered="#{!test1.last}" />
</ui:repeat>
I am getting a value example1,example2
Now after adding a new line:
<ui:repeat value="#{cc.attrs.bean.foo.foo1}" var="test" varStatus="test1">
<h:outputText value="#{cc.attrs.bean.testNo(test)}" rendered="#{test1.first}" />
<h:outputText value="#{test.prime}" title="#{test.primeNumber}" />
<h:outputText value="," rendered="#{!test1.last}" />
</ui:repeat>
I want my output something like this Hello- example1,example2......
But I am not able to get this output. In fact testNo(test) method is not invoked. What exactly is getting wrong over here. Thank you in advance
Manage bean method
private String testNo(Test test) {
List<Test11> type = Lists.newArrayList();
String some = someService.findTestNumber(test.getSomeNumber());
return some;
}

You need to make a basic MVC webapp. There are many tutorials about this, but example always helps: Your model is simple, two entities for a CompletedTest:
#Entity
public class CompletedTest {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
#OneToMany(fetch=FetchType.EAGER)
private List<TestResult> results;
// getters and setters
}
and a TestResult:
#Entity
public class TestResult {
#Id #GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String result;
// constructors, getters, setters
}
Access your model through a service layer
#Stateless
public class TestService {
#Inject
private EntityManager em;
public CompletedTest findTestResultByName(String name) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<CompletedTest> q = cb.createQuery(CompletedTest.class);
Root<CompletedTest> tr = q.from(CompletedTest.class);
q.select(tr).where(cb.equal(tr.get("name"), name));
List<CompletedTest> testResults = em.createQuery(q).getResultList();
if ( testResults.size() > 0 ) return testResults.get(0);
else return null;
}
The create a controller to interface to your view:
#Model
public class TestResultController {
#Inject
private TestService testResultService;
private CompletedTest testResult;
#PostConstruct
public void init() {
testResult = testResultService.findTestResultByName("Test #1");
}
and finally your view is your JSF page:
<ui:repeat var="r" value="#{testResultController.testResult.results}" varStatus="tSt">
<h:outputText value="#{testResultController.testResult.name}: " rendered="#{tSt.first}" />
<h:outputText value="#{r.result}"/>
<h:outputText value=", " rendered="#{!tSt.last}" />
</ui:repeat>
As you can see, the JSF page accesses the Controller bean. In that bean is a PostConstruct annotation, which gets executed when the JSF page references the bean. The PostConstruct executes any code you need to initialize the bean, in this case a call to the service layer which loads a test result from the database. Of course, there is a bit of code I didn't include, such as creating a test or showing a list of CompletedTests so the user can choose which one he or she wants. You can do all that on a single page with a form and a drop-down list. Further, calling to the database every time the JSF page is loaded will result in poor performance, so there are more sophisticated mechanisms for caching Entities in memory, but that is beyond this simple answer.

Related

JSF Primefaces: Update a dataTable open in another tab?

I have a simple webapp which allows the user to create transactions, and on another page the user can see all past transactions. I would like:
To have the dataTable be up-to-date when I open the past transaction page
To update the dataTable when I create a transaction on the creation page
I am not sure if this can be covered by one or two functionalities. Also, I am not sure how to decouple the functionalities. Should the creation of a transaction trigger the refresh of the dataTable, or should the dataTable itself find new entries in the DB ?
The past transactions page:
My TransactionListModel
package model;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import entity.Transaction;
#Named
#SessionScoped
public class TransactionListModel implements Serializable {
private static final long serialVersionUID = 1L;
private List<Transaction> txList;
#PostConstruct
public void init() {
txList = new ArrayList<Transaction>();
}
public List<Transaction> getTxList() {
return txList;
}
public void clearList(){
txList = new ArrayList<Transaction>();
}
}
My Transaction view
<!-- Fill the table before rendering -->
<f:event type="preRenderView" listener="# {transactionListController.findAllTx()}" />
<h:form id="alltxform">
<p:dataTable id="tableAllTransactions" var="transaction"
value="#{transactionListModel.txList}">
<f:facet name="header">Transactions</f:facet>
<p:column headerText="Id">
<h:outputText value="#{transaction.id}" />
</p:column>
</p:dataTable>
</h:form>
My TransactionList Controller
#Named
#RequestScoped
public class TransactionListController implements Serializable {
private static final long serialVersionUID = 1L;
#Inject
private Logger log;
#Inject
private TransactionService txService;
#Inject
private TransactionListModel txListModel;
public void findAllTx() {
txListModel.clearList();
txListModel.getTxList().addAll(txService.findAllTx());
}
public void reset() {
if (txListModel.getTxList() != null) {
txListModel.clearList();
}
}
}
The creation page
There is a simple textInputField (bound to a model) with a button:
<h:commandButton id="sendtx" value="Send" styleClass="ui-priority-primary">
<f:actionListener binding="#{transactionXmlController.sendTx()}" />
</h:commandButton>
The called method:
public void sendTx() {
FacesMessage message;
if (!transactionService.sendTx(transactionXmlEditableModel.getXml()).equals("OK"))
message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "KO");
else {
message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Success", "OK");
}
fc.addMessage(null, message);
}
So far, this works.
My Questions
How do I reload the dataTable with AJAX ?
I would like the dataTable to update even if it has been opened in another tab before the creation of a new transaction. How to do this ?
How to replace my "f:event type="preRenderView" with a viewAction in order to fill the dataTable before rendering the page ?
I'm not sure how you would update the table in another tab, without something like <p:poll> but to update your table with Ajax you can do something like:
<h:commandButton id="sendtx" value="Send" styleClass="ui-priority-primary">
<f:ajax listener = '#{transactionXmlController.sendTx()}' render="alltxform:tableAllTransactions" />
</h:commandButton>

JSF2.2, RequestScope and component persistence

My actual scenario is a simple JSF project that uses Mojarra 2.2.5.
I'm trying to get programmatically a component instance (via "findComponent" method or binding ...) and set some attributes (click on "ChangeColor" button).
After that, using any other action (for example clicking on "Send" button), the previous changes are ignored !!
It seems that changeColor method don't update the ViewState !
The sample code is the following:
<h:form id="form">
<h:panelGrid columns="1">
<h:inputText id="input" binding="#{page9.input}"/>
<h:commandButton value="Change BackColor" action="#{page9.changeColor}"/>
<h:commandButton value="Send" action="#{page9.dummy}" />
</h:panelGrid>
</h:form>
And the relative RequestScope bean
#ManagedBean(name="page9")
#RequestScoped
public class Page9 implements Serializable {
private static final long serialVersionUID = 1L;
private HtmlInputText input;
public HtmlInputText getInput() {
return input;
}
public void setInput(HtmlInputText input) {
this.input = input;
}
public void changeColor(){
FacesContext fc = FacesContext.getCurrentInstance();
HtmlInputText hit = (HtmlInputText) fc.getViewRoot().findComponent(":form:input");
hit.setStyle("background-color:blue");
}
public void dummy(){
}
}
Some important considerations:
1) I must use RequestScope for compatibility reasons.
2) Setting javax.faces.PARTIAL_STATE_SAVING to "false" all works fine (!).
3) Trying to use MyFaces 2.2.3 libraries all works fine (!).
What do you think about ?
Thanks.

Use single p:ajax to execute multiple actions

I have a p:selectOneMenu in my application, and when the selection takes place I need to call multiple back-end methods from different managed beans in order to perform different actions.
XHTML code:
<p:selectOneMenu id="selectMenu" value="#{userBean.selectedSite}"
converter="siteConverter" style="width:150px">
<p:ajax event="change" listener="#{bean2.changeSite}"
render="#form :comp1 :comp2 :comp3 :comp4" />
<f:selectItems value="#{userBean.sites}" var="site"
itemValue="#{site}" itemLabel="#{site.description}" />
<p:ajax event="change" listener="#{bean1.reset}"
update="#form :comp1 :comp2 :comp3 :comp4" />
</p:selectOneMenu>
Managed bean 1:
#ManagedBean(name="bean1")
#ViewScoped
public class Bean1 implements Serializable {
// ...
public void reset() {
loadEvents();
resetEvent();
}
}
Managed bean 2:
#ManagedBean(name="bean2")
#SessionScoped
public class Bean2 implements Serializable {
// ...
public void changeSite() {
FacesContext context = FacesContext.getCurrentInstance();
Bean1 bean = (Bean1) context.getApplication().evaluateExpressionGet(context, "#{bean1}", Bean1.class);
reload();
bean.loadEvents();
}
}
If, instead of using two different p:ajax components, I use a single p:ajax that calls a single method from Bean1, the page components listed under "update" are not correctly updated.
XHTML:
<p:ajax event="change" listener="#{bean1.singleMethod}"
update="#form :comp1 :comp2 :comp3 :comp4" />
Managed bean 1:
#ManagedBean(name="bean1")
#ViewScoped
public class Bean1 implements Serializable {
// ...
public void () singleMethod() {
FacesContext context = FacesContext.getCurrentInstance();
Bean2 bean = (Bean2) context.getApplication().evaluateExpressionGet(context, "#{bean2}", Bean2.class);
bean2.changeSite();
reset();
}
}
Changing the selected values updates the server side objects, but the page is not updated: if I press F5, the page shows the actual situation.
Moving the single global method to the session scoped bean (Bean2) does the job.

JSF/AJAX Dynamic Menu - 404 issue

I am trying to make a dynamic menu such that when something is selected in the first selector, the second one is populated from the database based on the selection in the first one. Here is the .xhtml:
<f:view>
<h:form>
<h:selectOneMenu id="seasonSelector" value ="#{selector_bean.season}">
<f:ajax event="valueChange" listener="#{selector_bean.genEvents}"
execute="seasonSelector" render="eventSelector" />
<f:selectItems value ="#{selector_bean.seasons}" var ="s"
itemLabel="#{s.getRange()}"
itemValue="#{s}"></f:selectItems>
</h:selectOneMenu>
<h:selectOneMenu id="eventSelector">
<f:selectItems value ="#{selector_bean.events}" var ="e"
itemLabel="#{e.event_Name}"
itemValue="#{e}"></f:selectItems>
</h:selectOneMenu>
</h:form>
</f:view>
Here is the bean:
#ManagedBean(name = "selector_bean")
#Stateless
public class selector_bean implements Serializable{
#EJB
SeasonFacade sf;
#EJB
EventFacade ef;
#EJB
WrestlerFacade wf;
private Season season;
private Event event;
private List<Event> events;
private Match match;
private Wrestler wrestler;
public List<Season> getSeasons(){
return sf.findAll();
}
public void genEvents(AjaxBehaviorEvent event){
events = (ef.findBySeason(season));
}
// setters and getters after this
When I change the value of the first selectOneMenu, a popup box appears with this message:
httpError: There was an error communicating with the server, status: 404
I am new to both JSF and AJAX so feel free to tear me apart if I am doing it wrong. Thanks for any help!
Your #ManagedBean is behaving as an EJB with the #Stateless annotation. Remove it and instead set the scope of your bean to #ViewScoped:
#ManagedBean(name = "selectorBean")
#ViewScoped
public class SelectorBean implements Serializable{
//your implementation...
}
Also, make sure to follow the JavaBean naming conventions. I've changed the name of your class to start with capital letter.

JSF2 - what scope for f:ajax elements?

I have this form:
<h:form>
<h:outputText value="Tag:" />
<h:inputText value="#{entryRecorder.tag}">
<f:ajax render="category" />
</h:inputText>
<h:outputText value="Category:" />
<h:inputText value="#{entryRecorder.category}" id="category" />
</h:form>
What I'm trying to achieve: When you type in the "tag" field, the entryRecorder.tag field is updated with what was typed. By some logic upon this action the bean also updates its category field. This change should be reflected in the form.
Questions:
What scope shall I use for EntryRecorder? Request may not be satisfactory for multiple AJAX requests, while session will not work with multiple browser windows per one session.
How can I register my updateCategory() action in EntryRecorder so that it is triggered when the bean is updated?
Answering point 2:
<h:inputText styleClass="id_tag" value="#{entryRecorder.tag}"
valueChangeListener="#{entryRecorder.tagUpdated}">
<f:ajax render="category" event="blur" />
</h:inputText>
Bean:
#ManagedBean
#ViewScoped
public class EntryRecorder {
private String tag;
private String category;
#EJB
private ExpenseService expenseService;
public void tagUpdated(ValueChangeEvent e) {
String value = (String) e.getNewValue();
setCategory(expenseService.getCategory(value));
}
}
Number 1, anybody?
To point 1, I'll use Request since there is no need to use View and Session is, as you well pointed, completely unnecessary.
For point 2, since you are using <f:ajax/> I suggest making full use of it. Here is my proposal:
xhtml:
<h:form>
<h:outputText value="Tag:" />
<h:inputText value="#{entryRecorder.tag}">
<f:ajax render="category" event="valueChange"/>
</h:inputText>
<h:outputText value="Category:" />
<h:inputText value="#{entryRecorder.category}" id="category" />
</h:form>
Note the use of valueChange event instead of blur (not that blur doesn't work but I find valueChange more 'proper' for a value holder component).
bean:
#ManagedBean
#RequestScoped
public class EntryRecorder {
private String tag;
private String category;
public String getCategory() {
return category;
}
public String getTag() {
return tag;
}
public void setCategory(String category) {
this.category = category;
}
public void setTag(String tag) {
this.tag = tag;
tagUpdated();
}
private void tagUpdated() {
category = tag;
}
}
Unless you really want the tagUpdated method executed only when tag is updated through the view, my proposal looks more clear. You don't have to deal with the events (nor casting) and the tagUpdated method can be private hiding it's functionality from possible misuses.

Resources