PrimeFaces add row to DataTable - primefaces

I want to make a Log-File-Reader. I have a Upload field, and a dataTable. First I choose the Log-File an Upload it. Then the program Split each line of the Log-File in the separate variables. Now the Log-File should be printet line for line into the table. But I dont know, how i should put the Lines in the Table. It works, when I define the Lines Static bevore. But now when the lines are not defined static it don't update the Table.
Here is my index.xhtml:
<h:form 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>
<title>LogReader</title>
</h:head>
<h:body>
<p:accordionPanel dynamic="true" cache="true" activeIndex="1" multiple="false">
<p:tab title="Upload File">
<h:panelGrid>
<p:fileUpload fileUploadListener="#{fileUploadController.handleFileUpload}" mode="advanced" dragDropSupport="false"
update="messages" fileLimit="1" allowTypes="/(\.|\/)(log|txt|)$/" />
<p:growl id="messages" showDetail="true"/>
</h:panelGrid>
</p:tab>
</p:accordionPanel>
<p:dataTable id="dataTable" var="log" value="#{fileUpload.logsSmall}" widgetVar="dataTable"
emptyMessage="No Log found with given criteria" filteredValue="#{tableBean.filteredLogs}"
rowKey="#{log.datetime}" paginator="true" rows="20" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" rowsPerPageTemplate="5,10,15,20,50,100" selection="#{tableBean.selectedLog}" selectionMode="single">
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Search all fields:" />
<p:inputText id="globalFilter" onkeyup="dataTable.filter();" style="width:150px" />
</p:outputPanel>
</f:facet>
<p:column id="datetimeColumn" filterBy="datetime" sortBy="datetime"
headerText="DateTime" footerText=""
filterMatchMode="contains">
<h:outputText value="#{log.datetime}" />
</p:column>
<p:column id="levelColumn" filterBy="level"
headerText="LogLevel" footerText=""
filterOptions="#{tableBean.levelOptions}"
filterMatchMode="exact" sortBy="level">
<h:outputText value="#{log.level}" />
</p:column>
<p:column id="categoryColumn" filterBy="category" sortBy="category"
headerText="Category" footerText=""
filterMatchMode="contains">
<h:outputText value="#{log.category}" />
</p:column>
<p:column id="messageColumn" filterBy="message" sortBy="message"
headerText="Message" footerText="" filterMatchMode="contains">
<h:outputText value="#{log.message}" />
</p:column>
</p:dataTable>
</h:body>
Here my TableBean:
package com.rausch.logreader;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ViewScoped;
import javax.faces.model.SelectItem;
import com.rausch.logreader.Log;
#ViewScoped
#ManagedBean(name = "tableBean")
#SessionScoped
public class TableBean implements Serializable {
private final static String[] level;
private SelectItem[] levelOptions;
private List<Log> filteredLogs;
private int i = 0;
private Log selectedLog;
private Log[] selectedLogs;
static {
level = new String[5];
level[0] = "DEBUG";
level[1] = "INFO";
level[2] = "WARN";
level[3] = "ERROR";
level[4] = "FATAL";
}
public TableBean() {
levelOptions = createLevelOptions(level);
}
public Log getSelectedLog() {
return selectedLog;
}
public void setSelectedLog(Log selectedLog) {
this.selectedLog = selectedLog;
}
public void listAdd(List<Log> list, String datetime, String level, String category, String message){
list.add(new Log(datetime, level, category, message));
}
public List<Log> getFilteredLogs() {
return filteredLogs;
}
public void setFilteredLogs(List<Log> filteredCars) {
this.filteredLogs = filteredCars;
}
private SelectItem[] createLevelOptions(String[] data) {
SelectItem[] options = new SelectItem[data.length + 1];
options[0] = new SelectItem("", "Select");
for(int i = 0; i < data.length; i++) {
options[i + 1] = new SelectItem(data[i], data[i]);
}
return options;
}
public SelectItem[] getLevelOptions() {
return levelOptions;
}
}
And here my FileUploadController:
import java.util.List;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.UploadedFile;
#ViewScoped
#ManagedBean(name = "fileUploadController")
#SessionScoped
public class FileUploadController {
public List<Log> logsSmall;
public void handleFileUpload(FileUploadEvent event) {
FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");
FacesContext.getCurrentInstance().addMessage(null, msg);
try {
copyFile(event.getFile().getFileName(), event.getFile().getInputstream());
} catch (IOException e) {
e.printStackTrace();
}
}
private String destination="C:\\Java\\";
public void copyFile(String fileName, InputStream in) {
try {
// write the inputStream to a FileOutputStream
OutputStream out = new FileOutputStream(new File(destination + fileName));
int read;
byte[] bytes = new byte[1024];
while ((read = in.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
in.close();
out.flush();
out.close();
readFile(destination + fileName);
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
public void readFile(String filePath){
try
{
String sCurrentLine;
BufferedReader br = new BufferedReader(new FileReader(filePath));
String output;
String datetime = "";
String level = "";
String category = "";
String message;
TableBean table = new TableBean();
while ((sCurrentLine = br.readLine()) != null) {
//System.out.println(sCurrentLine.charAt(4) + "" + sCurrentLine.charAt(7) + sCurrentLine.charAt(13) + "" +sCurrentLine.charAt(16));
if(sCurrentLine.length()<1){
}
else{
if (sCurrentLine.length() >= 16 && sCurrentLine.charAt(4)=='-' && sCurrentLine.charAt(7)=='-' && sCurrentLine.charAt(13)==':' && sCurrentLine.charAt(16)==':'){
output = "";
message = "";
String[] leerzeichen = sCurrentLine.split(" ");
datetime = leerzeichen[0] + " " + leerzeichen[1];
level = leerzeichen[2];
category = leerzeichen[4];
int arraylength = leerzeichen.length;
for (int l=5; l<arraylength; l++){
message = message.concat(leerzeichen[l] + " ");
}
output = datetime + level + category + message;
} else {
message = sCurrentLine;
output = message;
}
logsSmall = new ArrayList<Log>();
table.listAdd(logsSmall, datetime, level, category, message);
System.out.println(output);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Sorry for my bad English. I try to Ask an other way:
I want to have a program, where I can upload a *.log File and read it in a table. I open the xhtml, and there is a empty table. Than I Upload the File with the <:pFileUpload. The File Upload Controller takes the Log-File and split each line in the values (datetime, Level, Category and message). Then the Script should add a new row to the table width the datas of the Log-File-Line. Then it goes to the next Line and parses the Text. At the End the Table should show the content of the Log-File.
The Problem is, that the Table don't Reload. Or i don't know how i should reload it. When I upload the File, the script correctly read each Line of the Log-File. But the table keeps empty.

I quite don't understand what is yourt question what i see some lack of understanding on how to use the beans to manage the view.
First, you have #ViewScoped and #SessionScoped declared at the same time. There must be only one.
Second, the thing about defining managed beans it's that you don't have to manage the creation or destruction on them, the system does. Thats why they are called managed. So doing this:
TableBean table = new TableBean();
is useless. You are creating and instance of an object inside a funcion. Outside that function the object is unreacheable, as the annotations aren't considered if you create the object in your code.
I would have one managed bean that handles the events on the view, like this:
#ViewScoped
#ManagedBean(name = "logViewController")
public class LogViewController{
private List<Log> filteredLogs;
private List<Log> logsSmall;
public void handleFileUpload(FileUploadEvent event) {....}
// other private functions
//public getters and setters
}
Also, if you are working with java 7, maybe you want to look at the new file
I/O.

Related

RowKey of DataTable is null when calling onCellEdit

I have a Primefaces 6.0 DataTable working with a LazyDataModel bean. After I changed to the lazy implementation, the cell edition stopped working.
The reason for that is whenever I call my onCellEdit method, and try to get the clicked row contents by calling event.getRowkey() , I get a null object.
As per Primefaces Documentation I'm have a rowKey attribute to bind the tuple with the bean value, but it doesn't seems to work.
EDIT: I can update the value now, but the dataTable doesn't reload the cell UiElement. To see the changes i have to F5 the page.
Here is my ata.xhtml DATATABLE(Sanitized)
<p:tabView id="tab" value="#{setorMB.listaSetor}" var="tabView"
activeIndex="#{ataGerencialMB.activeTabIndex}">
<p:ajax event="tabChange" listener="#{ataGerencialMB.onTabChange}"
update="tab ,formListagemCapacitacao" />
<p:tab title="#{tabView.sigla}">
<p:dataTable id="dtCapacitacao"
value="#{ataGerencialMB.lazyModelAtaGerencial}"
var="gerencial"
lazy="true"
paginator="true"
rows="#{Config.NUM_ROWS}"
currentPageReportTemplate="#{Config.CURRENT_PAGE_REPORT_TEMPLATE}"
paginatorTemplate="#{Config.PAGINATOR_TEMPLATE}"
rowsPerPageTemplate="#{Config.ROWS_PER_PAGE_TEMPLATE}"
sortBy="#{gerencial.idAta}"
sortOrder="ascending"
reflow="true"
editable="true"
editMode="cell"
rowKey="#{gerencial.idAta}">
<p:ajax event="cellEdit"
listener="#{ataGerencialMB.onCellEdit}" oncomplete="onCellEdit()"/>
<p:column>
<p:rowToggler/>
</p:column>
<p:column headerText="Tipo Assunto" >
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{gerencial.tipo}"
rendered="true" />
</f:facet>
<f:facet name="input">
<p:inputTextarea id="tipo"
value="#{gerencial.tipo}"
style="width:96%" />
</f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
</p:tab>
</p:tabView>
Class that extends the LazyDataModel AtaGerencialLazyDataModel
public class AtaGerencialLazyDataModel extends LazyDataModel<AtaGerencialBean> {
AtaGerencialBusiness ataBusiness = new AtaGerencialBusiness();
Map<String, Object> customFilters = new HashMap<String, Object>();
private List<AtaGerencialBean> listaAtaGerencialBean = new ArrayList<AtaGerencialBean>();
public AtaGerencialLazyDataModel(){
this.setRowCount(ataBusiness.getAtaGerencialTotalCount(null));
}
public AtaGerencialLazyDataModel(SetorBean setor){
customFilters.put("setor", setor);
this.setRowCount(ataBusiness.getAtaGerencialTotalCount(customFilters));
}
#Override
public List<AtaGerencialBean> load(int first, int pageSize, String sortField,
SortOrder sortOrder, Map<String, Object> filters){
List<AtaGerencialBean> list = ataBusiness.fetchLazyAtaGerencial(first, pageSize, sortField, sortOrder, customFilters);
this.setRowCount(ataBusiness.getAtaGerencialTotalCount(customFilters));
setListaAtaGerencialBean(list);
setWrappedData(list);
return list;
}
#Override
public AtaGerencialBean getRowData(String rowKey){
try{
long id = Long.parseLong(rowKey);
for (AtaGerencialBean bean : listaAtaGerencialBean) {
if (bean.getIdAta() == id){
return bean;
}
}
}catch(Exception e){
System.out.println(e.getMessage());
}
return null;
}
#Override
public Object getRowKey(AtaGerencialBean p) {
return p.getIdAta();
}
public List<AtaGerencialBean> getListaAtaGerencialBean() {
return listaAtaGerencialBean;
}
public void setListaAtaGerencialBean(
List<AtaGerencialBean> listaAtaGerencialBean) {
this.listaAtaGerencialBean = listaAtaGerencialBean;
}
}
The onCellEdit method
#ManagedBean
#ViewScoped
public class AtaGerencialMB extends MB<AtaGerencialBean,
AtaGerencialBusiness> {
private LazyDataModel<AtaGerencialBean> lazyModelAtaGerencial;
#SuppressWarnings("unused")
public void onCellEdit(CellEditEvent event) {
try{
DataTable controladorTabela = (DataTable) event.getComponent();
//rowindex is fine, it brings the index of the edited row in the
datatable (from 0 onwards)
Integer rowIndex = event.getRowIndex();
String rowKey = event.getRowKey();
//rowKey is always null
System.out.println("rowKey value:" + rowKey);
AtaGerencialBean entity = (AtaGerencialBean) controladorTabela.getRowData(event.getRowKey());
this.setRegistroDefinido(entity);
super.atualizar();
}catch(NullPointerException ex){
System.out.println(ex.getMessage());
}
}
}
EDIT
I was able to circumvent the problem by NOT using the rowKey to retrieve the data and modifying the onCellEdit method to get the data from the Datamodel inside the Datatable.
I am not sure whether it is a good/bad practice, or if that's how you're supposed to retrieve the row when using LazyLoading.
Also, following #Kukeltje suggestion, I am now using PRIMEFACES 6.2
Modified onCellEdit method
#ManagedBean
#ViewScoped
public class AtaGerencialMB extends MB<AtaGerencialBean, AtaGerencialBusiness> {
private LazyDataModel<AtaGerencialBean> lazyModelAtaGerencial;
#SuppressWarnings("unused")
public void onCellEdit(CellEditEvent event) {
try{
DataTable controladorTabela = (DataTable) event.getComponent();
DataModel dm = (DataModel) controladorTabela.getValue();
AtaGerencialBean entity = (AtaGerencialBean) dm.getRowData();
this.setRegistroDefinido(entity);
super.atualizar();
}catch(NullPointerException ex){
System.out.println(ex.getMessage());
}
}
}
I was able to circumvent the problem by NOT using the rowKey to retrieve the data and modifying the onCellEdit method to get the data from the Datamodel inside the Datatable.
I am not sure whether it is a good/bad practice, or if that's how you're supposed to retrieve the row when using LazyLoading.
Also, following #Kukeltje suggestion, I am now using PRIMEFACES 6.2
Modified onCellEdit method
#SuppressWarnings("unused")
public void onCellEdit(CellEditEvent event) {
try{
DataTable controladorTabela = (DataTable) event.getComponent();
DataModel dm = (DataModel) controladorTabela.getValue();
AtaGerencialBean entity = (AtaGerencialBean) dm.getRowData();
this.setRegistroDefinido(entity);
super.atualizar();
}catch(NullPointerException ex){
System.out.println(ex.getMessage());
}
}
https://github.com/primefaces/primefaces/issues/2688
You may refer to this issue on github. You should enable selection for your datatable

liveScroll appended page refresh on selecting row Primefaces dataTable

I think i found a bug with livescroll in dataTable in Primefaces 6.1.
I have command link in second column that is saving row/rownumber to variables and calling method to save a file. It works on first 10 elements (size of page), but dont work on any other element that is appended by live pagination - instead something happens to invoke load with first set to 0. I dont see any errors in browser console or tomcat console. On my main project also page is losing all css elements, only text stays, but it could be liferay 6.2 issue.
If i disable liveScroll by replacing
scrollRows="10" liveScroll="true" scrollHeight="90%" scrollable="true"
with
paginatorTemplate="{PreviousPageLink} {NextPageLink}" paginator="true"
everything works. I have run out of ideas how to debug and fix it, any suggestions?
xhtml datatable:
<p:dataTable var="live" value="#{LiveLazyModel}" rows="10" lazy="true"
scrollRows="10" liveScroll="true" scrollHeight="90%" scrollable="true"
style="width: 1000px">
<p:column headerText="Id">
<h:outputText value="#{live.id}" id="idlive"/>
</p:column>
<p:column headerText=".txt" style="width: 80px" exportable="false">
<h:commandLink>
<h:outputText value="download"/>
<f:param name="liveId" value="#{live.id}" />
<f:setPropertyActionListener value="#{live}" target="#{LiveLazyModel.selectedRow}"/>
<p:fileDownload value="#{LiveLazyModel.liveStreamedContent}"/>
</h:commandLink>
</p:column>
</p:dataTable>
bean:
#ManagedBean(name = "LiveLazyModel")
#ViewScoped
public class LiveLazyModel extends LazyDataModel {
private Live selectedRow;
#Override
public List load(int first, int pageSize, String sortField, SortOrder sortOrder, Map filters) {
List list = addToList(first, pageSize);
this.setRowCount(100);
this.setPageSize(pageSize);
return list;
}
private List addToList(int first, int pageSize) {
List list = new ArrayList();
for (Integer i = first; i < first + pageSize; i++) {
list.add(new Live(i));
}
return list;
}
public StreamedContent getliveStreamedContent() throws IOException {
String idFrom = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("liveId");
if(selectedRow != null){
InputStream targetStream = IOUtils.toInputStream(selectedRow.id + (Double.toString(Math.random()).substring(1)));
return new DefaultStreamedContent(targetStream, "txt", "idLiveFromSelectedRow" + selectedRow.id + ".txt");
}
if (idFrom != null) {
InputStream targetStream = IOUtils.toInputStream(idFrom + (Double.toString(Math.random()).substring(1)));
return new DefaultStreamedContent(targetStream, "txt", "idLiveFromFacesContext" + idFrom + ".txt");
}
throw new RuntimeException("liveId is null & selectedRow is null ");
}
public void setSelectedRow(Live selectedRow) {
this.selectedRow = selectedRow;
}
}
Working barebone code could be found on:
https://github.com/TomaszKocinski/jsfPFLiveScrollBugPagination
to run it: mvn tomcat7:run should be enough, localhost:9966/live

Allowing user inputs that have spaces (" ")

I am creating a program that takes an address that the user inputs, and using GeoCoder, places that address on a map. This is done through oracle adf thematic map and java for the backing bean. The issue I'm getting is that the input works, but only if there are no spaces in the user's input. When an input is entered that DOES have a space, I get this error:
<oracle.adf.view> <PartialResponseUtils> <handleError> <ADF_FACES-60096:Server Exception during PPR, #1>
javax.el.ELException: .../map.jsf #76,86 pointX="#{row.lattitude}": java.lang.NullPointerException
Since GeoCoder doesn't care about spaces, I'm guessing the error is in the map code? Here's the code for the map jsf page:
<af:form id="f1">
<af:panelStretchLayout topHeight="50px" id="psl1">
<f:facet name="top">
<af:panelHeader text="Regional Map" id="ph1">
<f:facet name="context"/>
<f:facet name="menuBar"/>
<f:facet name="toolbar"/>
<f:facet name="legend"/>
<f:facet name="info"/>
</af:panelHeader>
</f:facet>
<f:facet name="center">
<af:panelSplitter id="ps1" splitterPosition="289">
<f:facet name="first">
<af:decorativeBox id="db1">
<f:facet name="center">
<af:panelGroupLayout layout="scroll" id="pgl1">
<af:panelFormLayout id="pfl1">
<f:facet name="footer">
<af:commandButton text="Add Location" id="cb1" partialSubmit="true"
actionListener="#{locationsCollector.addCurrentLocation}"/>
</f:facet>
<af:inputText label="Label" id="it1" autoSubmit="true"
value="#{currentLocation.label}"/>
<af:inputText label="Description" id="it1a" autoSubmit="true"
value="#{currentLocation.description}"/>
<af:inputText label="Location (NO SPACES)" id="it2" autoSubmit="true"
value="#{currentLocation.location}"/>
</af:panelFormLayout>
<af:spacer id="spac1" height="40"/>
<af:table value="#{locationsCollector.locations}" var="row"
rowBandingInterval="0" id="t1" partialTriggers="::cb1">
<af:column sortable="false" headerText="Label" align="start" id="c1">
<af:outputText value="#{row.label}" id="ot1"
shortDesc="#{row.description}"/>
</af:column>
<af:column sortable="false" headerText="Description" align="start" id="c2">
<af:outputText value="#{row.description}" id="ot2"/>
</af:column>
<!--<af:column sortable="false" headerText="Country" align="start" id="c3">
<af:outputText value="#{row.country}" id="ot3"/>
</af:column>-->
</af:table>
</af:panelGroupLayout>
</f:facet>
<!--<f:facet name="top">
<af:panelHeader text="Enter location details" id="ph2">
<f:facet name="context"/>
<f:facet name="menuBar"/>
<f:facet name="toolbar"/>
<f:facet name="legend"/>
<f:facet name="info"/>
</af:panelHeader>
</f:facet>-->
</af:decorativeBox>
</f:facet>
<f:facet name="second">
<dvt:thematicMap basemap="usa" id="tm1" partialTriggers="::cb1" summary="map">
<dvt:areaLayer layer="states" id="al1" rendered="true">
<dvt:pointDataLayer id="pdl1c" value="#{locationsCollector.locations}" var="row">
<dvt:pointLocation id="pl1c" type="pointXY" pointX="#{row.lattitude}"
pointY="#{row.longitude}">
<dvt:marker id="m1c" labelDisplay="on" value="#{row.label}"
labelPosition="top"
shortDesc="#{row.description} #{row.location} "/>
</dvt:pointLocation>
</dvt:pointDataLayer>
</dvt:areaLayer>
</dvt:thematicMap>
</f:facet>
</af:panelSplitter>
<!-- id="af_one_column_header_stretched" -->
</f:facet>
</af:panelStretchLayout>
</af:form>
And here is the bean for getting the latitude and longitude from Geocoder to add to the map's point detail:
public class Location {
private String location;
private String country;
private String label;
private String description;
private float[] coordinates;
private static float[] getCoordinatesForLocation(String location) {
URL geoCodeUrl;
String url = "http://maps.googleapis.com/maps/api/geocode/json?address=" + location
+ "&oe=utf8&sensor=false";
try {
geoCodeUrl
= new URL(url);
} catch (MalformedURLException e) {
System.out.println(e.getMessage() + " url=" + url);
return null;
}
BufferedReader in;
String coord = null;
try {
in = new BufferedReader(new InputStreamReader(geoCodeUrl.openStream()));
char[] buf = new char[8000];
in.read(buf);
coord = new StringBuilder().append(buf).toString();
in.close();
} catch (IOException e) {
System.out.println(e.getMessage() + " IO Exception ");
return null;
}
if (coord != null) {
float[] coordinates;
try {
// find first occurrence of lat
int posLAT = coord.indexOf("\"lat\"");
String latString = coord.substring(posLAT, posLAT + 21);
String lat = latString.split(":")[1].replaceAll(" ", "").replaceAll(",", "");
// find first occurrence of lng
int posLNG = coord.indexOf("\"lng\"");
String lngString = coord.substring(posLNG, posLNG + 21);
String lng = lngString.split(":")[1].replaceAll(" ", "").replaceAll(",", "");
coordinates
= new float[]{Float.parseFloat(lat), Float.parseFloat(lng)};
return coordinates;
} catch (Exception e) {
System.out.println("Coordinates stank " + coord);
}
}
System.out.println("Failed to create proper coordinates; sorry!");
return null;
}
public void setLocation(String location) {
this.location = location;
}
public String getLocation() {
return location;
}
public void setCountry(String country) {
this.country = country;
}
public String getCountry() {
return country;
}
public void setLabel(String label) {
this.label = label;
}
public String getLabel() {
return label;
}
public void setCoordinates(float[] coordinates) {
this.coordinates = coordinates;
}
public float[] getCoordinates() {
if (coordinates == null) {
coordinates = getCoordinatesForLocation(location);
}
return coordinates;
}
public float getLongitude() {
return getCoordinates()[0];
}
public float getLattitude() {
return getCoordinates()[1];
}
public void setDescription(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
All I'm looking for is the ability for the program to accept an address with spaces so the program is more user friendly. Thanks for looking this over!

primefaces selectOneMenu not outputting correctly

I am creating a SelectOneMenu. The menu outputs correctly. However, along with the menu being outputted is an InputBox and then all the items of the menu being printed as text. I don't know what is causing it. I have included a image of the output below.
Here is my JSF code:
<p:panelGrid columns="2">
<h:outputLabel for="trader" value="Trader:" />
<p:selectOneMenu id="trader" value="#{fixBean.trader}">
<f:selectItem itemLabel="Select" itemValue="0" />
<f:selectItems value="#{fixBean.traderOption}" />
</p:selectOneMenu>
</p:panelGrid>
Below is the code to my Bean:
private SelectItem[] traderOption = createFilterOptions(traders);
private final static String[] traders;
private static String trader = "";
static {
traders = new String[9];
traders[0] = "Dowd";
traders[1] = "Dwyer";
traders[2] = "Edelman";
traders[3] = "Hughes";
traders[4] = "Kelley";
traders[5] = "Nauyokas";
traders[6] = "Options";
traders[7] = "Rafferty";
traders[8] = "Russillo";
}
public String getTrader() {
return trader;
}
public void setTrader(String trader) {
this.traderOption = trader;
}
public void setTraderOption() {
traderOption = createFilterOptions(traders);
}
private SelectItem[] createFilterOptions(String[] data) {
SelectItem[] options = new SelectItem[data.length + 1];
options[0] = new SelectItem("", "Select");
for(int i = 0; i < data.length; i++) {
options[i + 1] = new SelectItem(data[i], data[i]);
}
return options;
}
public SelectItem[] getTraderOption() {
return traderOption;
}
The SelectMenu has the correct options in it however, I don't know why the rest of the output is being create (i.e. InputBox and text list).
****update****
I rebuilt the page using the primfaces SelectOneMenu example and built out from there. That resolved the issue. Though still not sure what was causing the issue

Primefaces tabview tabChange event fired after displaying tab

I am working on a project using Primefaces 3.5 & JSF2.1 (Mojarra)
I have created a primefaces <p:tabView id="tabsVw" dynamic="false"> with two tabs inside and each tab has a primefaces datatable
<h:form>
<p:tabView dynamic="false">
<p:ajax event="tabChange" listener="#{tstTab.onDtlTabChanged}" />
<p:tab title="tab1">
<p:dataTable value="#{tstTab.list1}" var="v1">
<p:column>
<h:outputText value="#{v1}"/>
</p:column>
</p:dataTable>
</p:tab>
<p:tab title="tab2">
<p:dataTable value="#{tstTab.list2}" var="v2">
<p:column>
<h:outputText value="#{v2}"/>
</p:column>
</p:dataTable>
</p:tab>
</p:tabView>
</h:form>
and inside the bean (view scoped)
#ManagedBean
#ViewScoped
public class TstTab {
private List<String> list1;
private List<String> list2;
public TstTab(){
list1 = new ArrayList<String>();
list2 = new ArrayList<String>();
list1.add("List 1 - Str 1");
list1.add("List 1 - Str 2");
list1.add("List 1 - Str 3");
list1.add("List 1 - Str 4");
list1.add("List 1 - Str 5");
list2.add("List 2 - Str 1");
list2.add("List 2 - Str 2");
list2.add("List 2 - Str 3");
list2.add("List 2 - Str 4");
list2.add("List 2 - Str 5");
}
public void onDtlTabChanged(TabChangeEvent event) {
System.out.println("000000000000000000");
}
public List<String> getList1() {
System.out.println("11111111111111");
return list1;
}
public List<String> getList2() {
System.out.println("222222222222222222");
return list2;
}
}
now the problem is when run the application and try to navigate (change) between tabs, but I can see that the onDtlTabChanged is called after calling getters, so that is a big problem.
and if change the tabView from static to dynamic, then the behavior is random, in other words the calling to the change event is happening somewhere in the middle of getters.
Thank you in advance.
Well I think that its a primefaces BUG, I found a workaround which as the following
Do not use a global form (form for the tabView itself) instead use a form for each tab (inside it that surround the datatable)
You have to add a dummy tab to be the first one that must include a form which some static data or pre-loaded data inside
Thats all,
the problem was that the ajax request is inside the global form and it cause the datatables to get their data first before ajax request,
the strange thing with Primefaces that if you do not add the first dummy tab it will always execute the first form inside the tabs and get its data and this will cause a problem
regards ,
I think the answer of ali saleh is right.
If you get problems with the tabchangelistener perhaps this can help you:
I had a similar problem with Primefaces 5.1
As long as i put the tabview into a form everything worked fine.
But because i wanted to use seperate forms in my tabs i had to remove the surrounding form of the tabview to avoid nested forms.
Without the surrounding form the ajax event didnĀ“t get triggered any more when changing the tab.
My solution was to use a remotecommand in a form parallel to the tabview.
The remotecommand is triggered by the onTabChange attribute of the tabview element.
At that call i forwarded the index parameter to the global request parameters.
<p:tabView id="rootTabMenu" styleClass="tabcontainer" prependId="false"
activeIndex="#{sessionData.activeTabIndex}" widgetVar="rootTabMenu"
onTabChange="tabChangeHelper([{name: 'activeIndex', value: index}])">
// Tabs...
</p:tabView>
<h:form id="tabChangeHelperForm">
<p:remoteCommand name="tabChangeHelper" actionListener="#{sessionData.onTabChange()}" />
</h:form>
In the backing bean i catched the value again from the request parameter map and set the active index.
public void onTabChange()
{
FacesContext context = FacesContext.getCurrentInstance();
Map<String, String> paramMap = context.getExternalContext().getRequestParameterMap();
String paramIndex = paramMap.get("activeIndex");
setActiveTabIndex(Integer.valueOf(paramIndex));
System.out.println("Active index changed to " + activeTabIndex);
}
Hope that can help you
It work fine in Primefaces 3.5 and mojarra 2.1.20, my code:
bean:
#ManagedBean(name = "tabview")
#ViewScoped
public class TabView implements Serializable {
private static final long serialVersionUID = 1L;
private List<Car> l1;
private List<Car> l2;
private List<Car> l3;
public TabView() {
l1 = new ArrayList<Car>();
l2 = new ArrayList<Car>();
l3 = new ArrayList<Car>();
Car c1 = new Car("c1", "a1");
Car c2 = new Car("c21", "a21");
Car c3 = new Car("c31", "a31");
Car c4 = new Car("c41", "a41");
Car c5 = new Car("c51", "a51");
Car c6 = new Car("c61", "a61");
Car c7 = new Car("c71", "a71");
Car c8 = new Car("c81", "a81");
Car c9 = new Car("c91", "a91");
l1.add(c1);
l1.add(c2);
l1.add(c3);
l2.add(c4);
l2.add(c5);
l2.add(c6);
l3.add(c7);
l3.add(c8);
l3.add(c9);
}
public void hand(TabChangeEvent event) {
Car c1 = new Car("c1", "a1");
Car c2 = new Car("c1", "a1");
Car c3 = new Car("c1", "a1");
Car c4 = new Car("c1", "a1");
Car c5 = new Car("c1", "a1");
Car c6 = new Car("c1", "a1");
Car c7 = new Car("c1", "a1");
Car c8 = new Car("c1", "a1");
Car c9 = new Car("c1", "a1");
l1.add(c1);
l1.add(c2);
l1.add(c3);
l2.add(c4);
l2.add(c5);
l2.add(c6);
l3.add(c7);
l3.add(c8);
l3.add(c9);
}
public List<Car> getL1() {
return l1;
}
public void setL1(List<Car> l1) {
this.l1 = l1;
}
public List<Car> getL2() {
return l2;
}
public void setL2(List<Car> l2) {
this.l2 = l2;
}
public List<Car> getL3() {
return l3;
}
public void setL3(List<Car> l3) {
this.l3 = l3;
}
}
xhtml:
<p:tabView id="mtrlDtlTabs" dynamic="true" cache="false">
<p:ajax event="tabChange" update="t1 t2 t3" listener="#{tabview.hand}"/>
<p:tab id="t1" title="1">
<p:dataTable id="l1" value="#{tabview.l1}" var="l1">
<p:column headerText="l1">#{l1.manufacturer}</p:column>
<p:column headerText="l2">#{l1.model}</p:column>
</p:dataTable>
</p:tab>
<p:tab id="t2" title="2">
<p:dataTable id="l2" value="#{tabview.l2}" var="l2">
<p:column headerText="l2">#{l2.manufacturer}</p:column>
<p:column headerText="l22">#{l2.model}</p:column>
</p:dataTable>
</p:tab>
<p:tab id="t3" title="3">
<p:dataTable id="l3" value="#{tabview.l3}" var="l3">
<p:column headerText="l3">#{l3.manufacturer}</p:column>
<p:column headerText="l33">#{l3.model}</p:column>
</p:dataTable>
</p:tab>
</p:tabView>