jsf table repeats itself - java

another weird jsf problem. my code looks something like this:
Java Bean:
class Bean {
private ArrayList<OutageTableHeader> outageTableHeaderData;
public ArrayList<OutageTableHeader> getOutageTableHeaderData() {
return outageTableHeaderData;
}
public void setOutageTableHeaderData(ArrayList<OutageTableHeader> value) {
this.outageTableHeaderData = value;
}
public List<OutageRowData> getOutageDataForTable() {
createOutageTableHeader(); // method which populates outageTableHeaderData with data
...
return(); // returns a list of OutageRowData objects, each for every row
}
}
my xhtml file:
...
<h:form>
<rich:dataTable id="outageOverviewTable"
value="#{mapOverviewManager.getOutageDataForTable()}" var="outageRow"
rendered="#{mapOverviewManager.outageDataForTable.size() > 0}"
headerClass="overviewHeader" cellpadding="0" cellspacing="0"
rowClasses="areaRowOdd, areaRowEven" style="width: auto">
<f:facet name="header">
<rich:columnGroup style="background: #ffffff">
<rich:column>
<h:outputText>TEST</h:outputText>
</rich:column>
<c:forEach items="#{mapOverviewManager.outageTableHeaderData}"
var="outHeader">
<rich:column colspan="#{outHeader.colSpan}">
<h:outputText value="#{outHeader.displayName}" />
</rich:column>
</c:forEach>
</rich:columnGroup>
</f:facet>
</rich:dataTable>
</h:form>
mapOverviewManager is my bean. Now I'm confronted with two problems
1) when I initally load the page, only "TEST" appears (the entry that is hard coded)
2) every time I press F5 to reload the page, the table expands itself. That is, exactly 32 entries (always the same) are appended to the end of the table and I don't know why?
This is rather strange because on the same page is a similar table, from which I basically copied the whole structure. Any suggestions?

You did not provide any meaningful data (not the scope of the bean, not even the code outageDataForTable property, not to mention the code that fetches data). But let me play a psychic for a second: the bean is session (or view) scoped, and you fetch the data in your getter?

Related

What is the equivalent of JSTL <c:forTokens> in JSF or PrimeFaces?

Assume we have the following JSP code:
<c:forTokens items="${someBean.aStringOfIntNumbersSeparatedBySemicolons}"
delims=";"
var="item"
varStatus="stat">
${item}
<c:if test="${!stat.last}">;</c:if>
<c:if test="${stat.count %5 == 0}">
<br/>
</c:if>
</c:forTokens>
Of which the output is rendered in rows with 5 columns each, like so:
How can I possibly do this with the JSF or Primefaces tags?
There is no direct equivalent, you should transform your token into a list in the managed bean and consume the list in the framework components.
List<String> tokens = Arrays.asList("car1,car2,car3,car4".split(","));
For such simple scenario you might not need the primefaces components. When you go for a Object Oriented model, you can take advantage of PF components to iterate through the list and present its fields using data binding. For instance:
DataList - For each Car type in the cars1 list, a line will be added in the list.
<p:dataList value="#{dataListView.cars1}" var="car" type="ordered">
<f:facet name="header">
Basic
</f:facet>
#{car.brand}, #{car.year}
</p:dataList>
DataTable - For each car in cars list, a row is added to the table component.
<p:dataTable var="car" value="#{dtBasicView.cars}">
<p:column headerText="Id">
<h:outputText value="#{car.id}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Brand">
<h:outputText value="#{car.brand}" />
</p:column>
<p:column headerText="Color">
<h:outputText value="#{car.color}" />
</p:column>
</p:dataTable>
Using such component framework you might speed your development focusing on the business logic instead of UI design.
The only working solution I've found
For now, the only working solution I've found lies partly in the JSF and partly in the back-end code:
Edit the back-end code so that it adds a <br/> after every fifth element of that String field aStringOfIntNumbersSeparatedBySemicolons.
Add escape="false" to the <h:outputText> tag that holds the data on the front end. (The default value is escape="true", which renders <br/> as <br/>)

Parameter passing one page to another page in JSF-2.0?

I would like to pass a parameter from one page to another.
Each page will have a ViewScoped JSF Backing Bean.
Although, I try to use <f:param> I get the following error:
when I click <h:commandLink> will navigate to another page.
ERROR :
] Root cause of ServletException.
com.sun.faces.mgbean.ManagedBeanCreationException: Unable to create managed bean ReservationActionBean. The following problems were found:
- The scope of the object referenced by expression #{param.resvDataModel}, request, is shorter than the referring managed beans (ReservationActionBean) scope of view
at com.sun.faces.mgbean.BeanManager.create(BeanManager.java:265)
at com.sun.faces.el.ManagedBeanELResolver.resolveBean(ManagedBeanELResolver.java:244)
at com.sun.faces.el.ManagedBeanELResolver.getValue(ManagedBeanELResolver.java:116)
at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176)
at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203)
.........
page1.xhtml
<p:panelGrid style="margin-top:-1px;" id="dashboard">
<ui:repeat value="#{DashBoard.dayList}" var="day">
<p:row>
<p:column style="background:#C1CDCD;width:100px;">
<h:outputText value="#{day}" style="color:#333333;font-size:13px;">
<f:convertDateTime type="date" pattern="EEE, yyyy-MM-dd"/>
</h:outputText>
</p:column>
<ui:repeat value="#{DashBoard.timeSlot}" var="timeSlot">
<p:column style="background:#C1CDCD;text-align: center;">
<h:outputText value="#{timeSlot}" style="font-size:12px;"/>
</p:column>
</ui:repeat>
</p:row>
<ui:repeat value="#{DashBoard.resourceList}" var="res">
<p:row>
<p:column>
<h:outputText value="#{res.name}" style="font-size:12px;"/>
</p:column>
<ui:repeat value="#{DashBoard.getResvDataModelList(day, res)}" var="model">
<p:column style="background:#{model.colour};" colspan="#{model.section}">
<h:commandLink action="reservation" style="display:block;width:#{model.section * 50}px;height:20px;">
<f:param name="model" value="#{ReservationActionBean.resvDataModel}"/>
<!--h:outputText value="#{model.user}"rendered="#{model.resource.name == res.name ? true : false}"style="font-size:12px;"/-->
</h:commandLink>
</p:column>
</ui:repeat>
</p:row>
</ui:repeat>
</ui:repeat>
</p:panelGrid>
page2.xtml
<h:form id="reservationEntryFrom">
<f:metadata>
<f:viewParam name="resvDataModel" value="#{ReservationActionBean.resvDataModel}"/>
</f:metadata>
<!-- other -->
</h:form>
DashBoard.java
#ManagedBean(name = "DashBoard")
#ViewScoped
public class DashBoard extends BaseBean {
public List<ResvDataModel> getResvDataModelList(
Date date, MeetingRoom meetingRoom) {
// do operation
}
}
ReservationActionBean.java
#ManagedBean(name="ReservationActionBean")
#ViewScoped
public class ReservationActionBean extends BaseBean {
#ManagedProperty("#{param.resvDataModel}")
private ResvDataModel resvDataModel;
//other operations
}
ResvDataModel.java
public class ResvDataModel {
// attribute, getter and sertter
#Override
public boolean equals(Object object) {
return EqualsBuilder.reflectionEquals(this, object);
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
}
The #ManagedProperty is invoked only once during bean's construction. Imagine that the bean is in session scope and the managed property references a request scoped variable (e.g. a request parameter), then only the parameter of the very first request would be set and it would never be updated with changed request parameter values in subsequent requests after the session bean construction. This is considered undesired behaviour. Hence #ManagedProperty cannot reference something which has a narrower scope than the #ManagedBean itself.
In this particular case, you need <f:viewParam> instead. Put the following in page2.xhtml:
<f:metadata>
<f:viewParam name="resvDataModel" value="#{ReservationActionBean.resvDataModel}" />
</f:metadata>
See also:
ViewParam vs #ManagedProperty(value = "#{param.id}")
However, there's another problem with this approach. You're passing non-String object along as a request parameter. The value would be only com.example.ResvDataModel#hashcode (or whatever the toString() method of your ResvDataModel class returns). This information is insufficient to reconstruct exactly the desired ResvDataModel instance.
You need to pass some unique identifier or action parameter value along instead of a whole complex Java object which can't be uniquely represented as a String.

How Datatable holds my edited values

<h:dataTable value="#{studentBean2.studentList}" var="student">
<h:column>
<f:facet name="header">
<h:outputText value="STUDENT-ID" />
</f:facet>
<h:outputText value="#{student.studentId}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="STUDENT-NAME" />
</f:facet>
<h:inputText value="#{student.studentName}" />
</h:column>
.........
.........
</h:dataTable>
<h:commandButton type="submit" action="#{studentBean2.action}" value="ENTER" />
As from the above code, datatable values can be edited in <h:inputText> field and submitted. Those edited values are seen in action() method of bean StudentBean2.
As I followed the log, it showed that when I submit the page in the phase "Apply Request Values" the getStudentList() method is called. In this method I do the JDBC call to fetch students from the Database and set the newly fetched studentlist.
But in the "Invoke Application" phase, in method action() I get the edited data in the list which I have submitted. How exactly does this happen?
JSF has set them for you during the update model values phase. During this phase, the processUpdates() method of every component will be invoked. In case of the <h:dataTable> it's the UIData#processUpdates(). For every row it will then invoke the same method of the input component, which is in your case UIInput#processUpdates().
Basically:
get data model of UIData; // studentList = studentBean2.getStudentList()
for (every row of data model) {
get the current row item by index; // student = studentList.get(index)
for (every child UIInput component of UIData) {
set its value; // student.setStudentName(value)
}
}
Unrelated to the concrete problem, doing the JDBC call inside the getter method is a bad idea. The getter method will be called more than once during bean's life, so the JDBC call will be unnecessarily made too many times. You should make the JDBC call in bean's (post)constructor instead. See also Why JSF calls getters multiple times.

Richfaces 4 Datatable with onclick Event on row

I have a simple Richfaces 4 <rich:dataTable> with some <rich:column>s.
Now I want if I press on one row, that below the table the ID of the row should be displayed.
Here is what I did so far:
<rich:dataTable value="#{placeholder_control.lichtList}" var="licht" width="100%" id="lichtListe" columns="2">
<rich:column>
<f:facet name="header">
<h:outputText value="Beschreibung" />
</f:facet>
<h:outputText value="#{licht['beschreibung'].stringValue}" width="20" />
<a4j:ajax immediate="true" event="onclick" render="testingID" listener="#{placeholder_control.selectActiveLight}">
<f:attribute name="rowKey" value="#{licht['id'].stringValue}" />
</a4j:ajax>
</rich:column>
...
...
<h:outputText value="This is the id : #{placeholder_control.selectedLight}" id="testingID"></h:outputText>
The managed bean placeholder_control looks like this
#ManagedBean (name="placeholder_control")
#SessionScoped
public class ControlPlaceholder {
public void selectActiveLight(ActionEvent evt) {
String selectedRow = (String) evt.getComponent().getAttributes().get("rowKey");
System.out.println("Selected Light : " + selectedRow);
setSelectedLight(selectedRow);
}
Everything will be rendered correctly, but if I click on the row (on this column), nothing happens. I also tried to put a non existing method (on purpose) to the listener. I hoped that I get an error message but nothing happend.
If I look at the HTML source code, there is nothing with onclick at that <td> element.
Anyone has an idea?
hi friend take a look to rich:extended datatable, i used it to do a task that meet your requirements.
here is the showcase for richfaces 4 and explains the use of extended datatable: http://richfaces-showcase.appspot.com/richfaces/component-sample.jsf?demo=extendedDataTable&sample=exTableSelection&skin=blueSky
cheers

Passing Parameters With Seam, RichFaces & PopupPanel

I'm trying to get a little application working using Seam 3, RichFaces 4 and hitting a few troubles with passing some parameters around. I've tried a lot of different things but I keep falling at the final hurdle. I'm carrying through a customerId via a request parameter. But when I hit a RichFaces commandButton on a popupPanel, that customerId is no longer available to me.
I'm setting up an application to manage some data. Basically you select a customer from one screen, that will take you to another screen containing "repositories" where you then can create, edit etc. You can get to this second repositories page via the URL:
http://localhost:8080/media-manager/repositories.xhtml?customer=12
I then have a bean picking this value up:
#Named
#RequestScoped
public class RepositoryBean extends AbstractViewBean<Repository> {
// Various properties etc. here
private Long customerId;
public void init() {
log.info("Customer ID is "+ customerId);
}
}
I then set the customer ID via metadata on the repository page and call init:
<f:metadata>
<f:viewParam name="customer" value="#{repositoryBean.customerId}"/>
<f:event type="preRenderView" listener="#{repositoryBean.init}" />
</f:metadata>
This works well at the start. I can display information I need for the customer with the supplied ID. But when I try to create my popupPanel is goes a bit wrong. Here's a simplified version of the code first:
<rich:popupPanel id="repositoryModalPanel" modal="true" resizeable="true">
<f:facet name="header">Title</f:facet>
<f:facet name="controls">
<h:outputLink value="#" onclick="#{rich:component('repositoryModalPanel')}.hide(); return false;">X</h:outputLink>
</f:facet>
<h:form id="modalForm" class="modalForm">
<fieldset>
<ul class="layout form">
<li>
<label for="name" class="required">Name:</label>
<h:inputText id="name" value="#{repositoryBean.instance.name}" required="true">
<!-- rich:validator event="blur" / -->
</h:inputText>
<rich:message for="name" errorClass="error errormessage" />
</li>
<li class="last">
<a4j:commandButton id="create" value="Create" action="#{repositoryBean.saveRepository}" rendered="#{empty repositoryBean.instance.id}"/>
<a4j:commandButton id="save" value="Save" action="#{repositoryBean.saveRepository}" rendered="#{not empty repositoryBean.instance.id}"/>
<a4j:commandButton id="cancel" value="Cancel" action="#{repositoryBean.clearInstance}" immediate="true" />
</li>
</ul>
</fieldset>
</h:form>
Basically, whenever I hit the save commandButton, the init method is called but the customerId member is never populated. Does anyone have any insight into why?
I've read that viewParam is only for GET requests so maybe that's the problem? But if that's the case - what is the other solution? Lots of things I have seen suggested (e.g. using #ManagedProperty) does not seem to be applicable to Seam 3.
RepositoryBean is RequestScoped, and as such will be newly created on each request, especially if you hit the save button.
The straightforward solution is to promote RepositoryBean to be ConversationScoped, and to make it long running if you enter the page.
#Named
#ConversationScoped
public class RepositoryBean extends AbstractViewBean<Repository> {
// Various properties etc. here
#In
Conversation conversation
private Long customerId;
public void init() {
log.info("Customer ID is "+ customerId);
conversation.begin();
}
}
The easieast way for that is to dump the preRenderView and use seam 3 view-action instead.
<f:metadata>
<f:viewParam name="customer" value="#{repositoryBean.customerId}"/>
<s:viewAction action="#{repositoryBean.init}" if="#{conversation.transient}"/>
</f:metadata>

Categories