I'm writing a blog, and I want to display from database dataTable with 2 columns, in one column I would like to have post title, and in other I want post content, but when I try to implement that in my page, the only result I get is that in post title column is displayed all post titles for every row. I would like to ask you, how could I achieve my goal.
Now i have
title1 title2 ... | content1
title1 title2 ... | content2
etc
but I would like to have
title 1| content1 <br>
title2 | content2 <br>
Here is my index.xhtml code to display dataTable
<h:dataTable value="#{postView.postList}"
var="k"
styleClass="table"
headerClass="tableHeader"
rowClasses="tableContent"
>
<h:column>
<h:dataTable value="#{postView.postList}" var="t">
<h:column>
#{t.title}
</h:column>
</h:dataTable>
</h:column>
<h:column>
#{k.postContent}
</h:column>
</h:dataTable>
Here is my controller
package ManagePost;
import Entities.Post;
import FacadeDAO.PostFacade;
import FacadeDAO.UserFacade;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;
#Named
#ViewScoped
public class PostView implements Serializable {
#Inject
private PostFacade postDAO;
private List<Post> postList;
private String title;
private String content;
public PostView() {
}
public List<Post> getPostList() {
return postList;
}
public void setPostList(List<Post> postList) {
this.postList = postList;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
#PostConstruct
public void init() {
postList = postDAO.showAll();
}
public String validate() {
Post post = postDAO.checkIfExist(title);
if (post == null) {
Post newPost = new Post();
newPost.setTitle(title);
newPost.setPostContent(content);
try {
postDAO.add(newPost);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return "loginPage";
} else {
return null;
}
}
}
And the last, PostDao
public List<Post> showAll() {
List<Post> postList = new ArrayList<>();
List<Post> result = getEntityManager().createNamedQuery("Post.findAll", Post.class).getResultList();
postList.addAll(result);
return postList;
}
You are displaying all the titles in an embedded datatable. You should remove the nested datatable tag:
<h:dataTable value="#{postView.postList}"
var="k"
styleClass="table"
headerClass="tableHeader"
rowClasses="tableContent"
>
<h:column>
#{k.title}
</h:column>
<h:column>
#{k.postContent}
</h:column>
</h:dataTable>
Related
So, I want to display search result as I type the keyword and change the color of the search result text in JSF like when you use Google to search.
Search example (WhatsApp)
I've done the keyup part but still wonder how to apply highlight text using javascript in JSF.
Here is my xhtml code
<h:form>
<h:outputLabel value="Keyword "/>
<h:inputText id="key" value="#{bookList.keyword}" style="height: 22px">
<f:ajax event="keyup" render="search"/>
</h:inputText>
<h:commandButton value="SEARCH" action="index" styleClass="buttonSearch"/>
</h:form>
<br/>
<h:dataTable value="#{bookList.books}" var="book" id="search"
class="book-table"
headerClass="book-table-header">
<h:column>
#{book.title}
</h:column>
<h:column>
#{book.author}
</h:column>
</h:dataTable>
and this is my java code...
Constructor
public class Book {
private String title;
private String author;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Book(String title, String author){
this.title = title;
this.author = author;
}
}
Data
#ManagedBean
#RequestScoped
public class BookList {
private String keyword = "";
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
private List<Book> books = new ArrayList<Book>(
Arrays.asList(
new Book("My First Learn to Write Workbook", "Crystal Radke"),
new Book("Where the Crawdads Sing", "Delia Owens"),
new Book("Little Fires Everywhere: A Novel", "Celeste Ng"),
new Book("Fortitude: American Resilience in the Era", "Dan Crenshaw"),
new Book("Arguing the Socialists", "Glenn Beck"),
new Book("Hidden Valley Road: Inside the Mind of an American Family", "Robert Kolker")
)
);
public List<Book> getBooks() {
if (keyword.equals("")) {
return books;
} else {
List<Book> listSearch = new ArrayList<Book>();
for(Book book:books){
if(book.getAuthor().toLowerCase().contains(keyword.toLowerCase())
|| book.getTitle().toLowerCase().contains(keyword.toLowerCase())){
listSearch.add(book);
}
}
return listSearch;
}
}
}
Sorry, if my question isn't nice.
I have 2 classes Games and Fouls, there are lot of fouls in a game. The user sends a parameter with the game id to find the game he want and after that the currentGame variable is created.Its type is Game. I have a datatable which prints the fouls in the current game
The setCurentGame setter is called form the body of the page onload.
so far everything works okay, but when I add a new foul, is not added to the datatable, my assumption is that the game was already retrieved (because current game was created before) so the new foul is in the database and not in the Game currentGame.
Is there any way that i can update the currentGame every time a foul i added?
I have tried refreshing the page and even to call the seeter again after creating the foul but nothing worked
The datatable looks like this:
<p:dataTable id="datalist" value="#{gameController.currentGame.foulCollection}" var="item">
<f:facet name="{exporters}">
</f:facet>
<p:ajax event="rowSelect" update="createButton viewButton editButton deleteButton"/>
<p:ajax event="rowUnselect" update="createButton viewButton editButton deleteButton"/>
<p:column width="32" sortBy="#{item.id}" filterBy="#{item.id}">
<f:facet name="header">
<h:outputText value="#{bundle.ListFoulTitle_id}"/>
</f:facet>
<h:outputText value="#{item.id}"/>
</p:column>
<p:column sortBy="#{item.quarter}" filterBy="#{item.quarter}">
<f:facet name="header">
<h:outputText value="#{bundle.ListFoulTitle_quarter}"/>
</f:facet>
<h:outputText value="#{item.quarter}"/>
</p:column>
<p:column sortBy="#{item.foultime}" filterBy="#{item.foultime}">
<f:facet name="header">
<h:outputText value="#{bundle.ListFoulTitle_foultime}"/>
</f:facet>
<h:outputText value="#{item.foultime}"/>
</p:column>
<f:facet name="footer">
<p:commandButton id="createButton" icon="ui-icon-plus" value="#{bundle.Create}" actionListener="#{foulController.prepareCreate}" update=":FoulCreateForm" oncomplete="PF('FoulCreateDialog').show()"/>
</f:facet>
</p:dataTable>
GameController bean:
package onisiforos.fouls.classes;
import onisiforos.fouls.db.Game;
import onisiforos.fouls.classes.util.JsfUtil;
import onisiforos.fouls.classes.util.JsfUtil.PersistAction;
import onisiforos.fouls.bean.GameFacade;
import java.io.Serializable;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import javax.faces.bean.ManagedProperty;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
#Named("gameController")
#SessionScoped
public class GameController implements Serializable {
#EJB
private onisiforos.fouls.bean.GameFacade ejbFacade;
private List<Game> items = null;
private Game selected;
private Game currentGame;
public Game getCurrentGame() {
return currentGame;
}
public void setCurrentGame() {
int gid =
Integer.parseInt(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("gameid"));
Game cg = getGame(gid);
this.currentGame = cg;
}
public GameController() {
}
public Game getSelected() {
return selected;
}
public void setSelected(Game selected) {
this.selected = selected;
}
protected void setEmbeddableKeys() {
}
protected void initializeEmbeddableKey() {
}
private GameFacade getFacade() {
return ejbFacade;
}
public Game prepareCreate() {
selected = new Game();
initializeEmbeddableKey();
return selected;
}
public void create() {
setCurrentGame()
persist(PersistAction.CREATE, ResourceBundle.getBundle("/Bundle").getString("GameCreated"));
updateCurrentGame();
if (!JsfUtil.isValidationFailed()) {
items = null;
}
}
public void update() {
persist(PersistAction.UPDATE, ResourceBundle.getBundle("/Bundle").getString("GameUpdated"));
}
public void destroy() {
persist(PersistAction.DELETE, ResourceBundle.getBundle("/Bundle").getString("GameDeleted"));
if (!JsfUtil.isValidationFailed()) {
selected = null; // Remove selection
items = null;
}
}
public List<Game> getGames() {
if (items == null) {
items = getFacade().findAll();
}
return items;
}
private void persist(PersistAction persistAction, String successMessage) {
if (selected != null) {
setEmbeddableKeys();
try {
if (persistAction != PersistAction.DELETE) {
getFacade().edit(selected);
} else {
getFacade().remove(selected);
}
JsfUtil.addSuccessMessage(successMessage);
} catch (EJBException ex) {
String msg = "";
Throwable cause = ex.getCause();
if (cause != null) {
msg = cause.getLocalizedMessage();
}
if (msg.length() > 0) {
JsfUtil.addErrorMessage(msg);
} else {
JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
}
} catch (Exception ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
}
}
}
public Game getGame(java.lang.Integer id) {
return getFacade().find(id);
}
public List<Game> getItemsAvailableSelectMany() {
return getFacade().findAll();
}
public List<Game> getItemsAvailableSelectOne() {
return getFacade().findAll();
}
#FacesConverter(forClass = Game.class)
public static class GameControllerConverter implements Converter {
#Override
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if (value == null || value.length() == 0) {
return null;
}
GameController controller = (GameController) facesContext.getApplication().getELResolver().
getValue(facesContext.getELContext(), null, "gameController");
return controller.getGame(getKey(value));
}
java.lang.Integer getKey(String value) {
java.lang.Integer key;
key = Integer.valueOf(value);
return key;
}
String getStringKey(java.lang.Integer value) {
StringBuilder sb = new StringBuilder();
sb.append(value);
return sb.toString();
}
#Override
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof Game) {
Game o = (Game) object;
return getStringKey(o.getId());
} else {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, "object {0} is of type {1}; expected type: {2}", new Object[]{object, object.getClass().getName(), Game.class.getName()});
return null;
}
}
}
}
It seems your setCurrentGame method will not be called, you can manually call it in your create() method to update the current game object from the database after the foul is created.
How to implement a simple add/remove dynamic <rich:tabPanel>?
(I've seen people asking this around so I thought postin a Q&A of a simple implementation)
The implementation has 3 custom classes:
Content: contains the values to be displayed in a tab;
ItemTab: contais an UITab object and a Content object;
MyTabs: EJB managed bean that provides access to the tabs and adding/removal methods.
The code is:
Content:
public class Content {
String name;
String job;
String dept;
public Content() {
name = "John Doe";
job = "None";
dept = "None";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public String getDept() {
return dept;
}
public void setDept(String dept) {
this.dept = dept;
}
}
TabItem:
public class TabItem {
UITab component;
Content content;
public TabItem() {
component = new UITab();
content = new Content();
}
public UITab getComponent() {
return component;
}
public void setComponent(UITab tab) {
this.component = tab;
}
public Content getContent() {
return content;
}
public void setContent(Content content) {
this.content = content;
}
}
MyTabs:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named
#SessionScoped
public class MyTabs implements Serializable {
private List<TabItem> tabs;
public MyTabs() {
tabs = new ArrayList<TabItem>();
}
#PostConstruct
private void init() {
createTab();
createTab();
createTab();
}
public void createTab() {
TabItem tab = new TabItem();
tab.getComponent().setId("Tab" + (tabs.size()+1));
tab.getComponent().setHeader("Tab " + (tabs.size()+1));
tab.getContent().setName("John Doe " + (tabs.size()+1));
tab.getContent().setJob("Salesman " + (tabs.size()+1));
tab.getContent().setDept("Sales " + (tabs.size()+1));
tabs.add(tab);
}
public void removeTab(TabItem tab) {
tabs.remove(tab);
}
public List<TabItem> getTabs() {
return tabs;
}
public void setTabs(List<TabItem> tabs) {
this.tabs = tabs;
}
}
tabview.xhtml:
<h:commandLink value="Add Tab"
actionListener="#{myTabs.createTab()}"/>
<rich:tabPanel switchType="client">
<c:forEach items="#{myTabs.tabs}" var="tab">
<rich:tab value="#{tab.component}">
<f:facet name="header">
<h:outputLabel value="#{tab.component.header}"/>
<h:commandLink value=" X" actionListener="#{myTabs.removeTab(tab)}"/>
</f:facet>
<h:panelGrid columns="2">
<h:outputLabel value="Name: "/>
<h:outputLabel value="#{tab.content.name}"/>
<h:outputLabel value="Dept: "/>
<h:outputLabel value="#{tab.content.dept}"/>
<h:outputLabel value="Job: "/>
<h:outputLabel value="#{tab.content.job}"/>
</h:panelGrid>
</rich:tab>
</c:forEach>
</rich:tabPanel>
I have this problem.
I wanted to create selectOneMenu for custom select some data. But it's not working and i really don't know why. I spent cca 5 hours with this problem. I'm so desperate.
So some my code:
But when i will pick some item from selectonemenu, selected_id is still 0. Still, still. I tried to do almost everything but without result.
I tried this:
<p:selectOneMenu value="#{medicinesBean.selectedBranch}" required="true" effect="fade" id="listComboBox">
<f:selectItems value="#{medicinesBean.branchesForComboBox}" var="itm" itemLabel="#{itm.name}" itemValue="#{itm.id}" />
</p:selectOneMenu>
Backing Bean class:
/* private members */
private ArrayList<BranchDTO> branchesForComboBox = new ArrayList<BranchDTO>();
private BranchDTO selectedBranch;
/* getter and setters ... */
also i tried this with SelectItem[] model but result was same. NOT WORK.
Then i tried it like:
<p:selectOneMenu value="#{medicinesBean.selected_id}" required="true" effect="fade" id="listComboBox">
<f:selectItem itemLabel="First" itemValue="1"/>
<f:selectItem itemLabel="Second" itemValue="2"/>
<f:selectItem itemLabel="Third" itemValue="3"/>
<f:selectItem itemLabel="Fouth" itemValue="4"/>
</p:selectOneMenu>
/* private members */
private int selected_id;
But still 0. When i used object like value for selectonemenu, always null exception was always returned. So i will be glad for any advice for this.
Thanks
brw. backing bean is ViewScoped and data from DAO are correctly returned so some bug will be in component selectonemenu.
Thanks BalusC, so here is my implementation
Backing Bean
/**
* #author Sajmon
*/
package OraclBeans;
import DTOs.PobockaDTO;
import DTOs.ZoznamLiekovDTO;
import EJBs.ZoznamLiekovEJB;
import java.io.Serializable;
import java.util.ArrayList;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name="zoznamLiekovBean")
#ViewScoped
public class ZoznamLiekovBean implements Serializable {
#EJB
private ZoznamLiekovEJB listOfMedicineEJB;
/* private members */
private ArrayList<ZoznamLiekovDTO> listOfMedicines;
private ArrayList<PobockaDTO> branchesForCombobox = new ArrayList<PobockaDTO>();
private ZoznamLiekovDTO selectedItem;
private PobockaDTO selectedBranch;
//private SelectItem[] branchesOptions;
//private SelectItem selectedOption;
private int selected_id;
public ZoznamLiekovBean() {
}
#PostConstruct
private void init() {
branchesForCombobox = listOfMedicineEJB.getBranches();
listOfMedicines = listOfMedicineEJB.getLists();
}
public void test() {
System.out.println("ID: " + selected_id);
}
/*
private SelectItem[] addItemsToOptions() {
SelectItem[] data = new SelectItem[branchesForCombobox.size()];
for (int i = 0; i < branchesForCombobox.size(); i++) {
data[i] = new SelectItem(branchesForCombobox.get(i).getId(), branchesForCombobox.get(i).getNazov());
}
return data;
}
*/
/* getters and setters */
/*
public SelectItem[] getBranchesOptions() {
return branchesOptions;
}
public void setBranchesOptions(SelectItem[] branchesOptions) {
this.branchesOptions = branchesOptions;
}
public void setSelectedOption(SelectItem selectedOption) {
this.selectedOption = selectedOption;
}
public SelectItem getSelectedOption() {
return selectedOption;
}
*/
public ArrayList<PobockaDTO> getBranchesForCombobox() {
return branchesForCombobox;
}
public void setBranchesForCombobox(ArrayList<PobockaDTO> branchesForCombobox) {
this.branchesForCombobox = branchesForCombobox;
}
public ArrayList<ZoznamLiekovDTO> getListOfMedicines() {
return listOfMedicines;
}
public void setListOfMedicines(ArrayList<ZoznamLiekovDTO> listOfMedicines) {
this.listOfMedicines = listOfMedicines;
}
public PobockaDTO getSelectedBranch() {
return selectedBranch;
}
public void setSelectedBranch(PobockaDTO selectedBranch) {
this.selectedBranch = selectedBranch;
}
public ZoznamLiekovDTO getSelectedItem() {
return selectedItem;
}
public void setSelectedItem(ZoznamLiekovDTO selectedItem) {
this.selectedItem = selectedItem;
}
public int getSelected_id() {
return selected_id;
}
public void setSelected_id(int selected_id) {
this.selected_id = selected_id;
}
}
EJB:
/**
* #author Sajmon
*/
package EJBs;
import DTOs.PobockaDTO;
import DTOs.ZoznamLiekovDTO;
import OraclDAO.OracleZoznamLiekovDAO;
import java.io.Serializable;
import java.util.ArrayList;
import javax.ejb.Stateless;
#Stateless
public class ZoznamLiekovEJB implements Serializable {
private OracleZoznamLiekovDAO dao = new OracleZoznamLiekovDAO();
public ArrayList<ZoznamLiekovDTO> getLists() {
return dao.getListOfMedicines();
}
public ArrayList<PobockaDTO> getBranches() {
return dao.getBranchesForCombobox();
}
}
DAO:
/**
* #author Sajmon
*/
package OraclDAO;
import DTOs.PobockaDTO;
import DTOs.ZoznamLiekovDTO;
import OraclDAOFactory.OracleDAOFactory;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
public class OracleZoznamLiekovDAO implements Serializable {
private String SELECT_ALL = "SELECT Z.id_zoznamu, P.nazov_pobocky, L.nazov_lieku FROM Zoznam_liekov Z "
+ "JOIN Pobocka P ON (Z.id_pobocky = P.id_pobocky)"
+ "JOIN Liek L ON (Z.id_lieku = L.id_lieku)";
private String SELECT_BRANCHES = "SELECT DISTINCT P.id_pobocky, P.nazov_pobocky FROM Zoznam_liekov Z JOIN Pobocka P ON (Z.id_pobocky = P.id_pobocky)";
public OracleZoznamLiekovDAO() {
}
public ArrayList<PobockaDTO> getBranchesForCombobox() {
ArrayList<PobockaDTO> data = new ArrayList<PobockaDTO>();
PobockaDTO item;
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = OracleDAOFactory.getOracleDatabaseConnection();
ps = con.prepareStatement(SELECT_BRANCHES);
rs = ps.executeQuery();
while (rs.next()) {
item = new PobockaDTO();
item.setId(rs.getInt(1));
item.setNazov(rs.getString(2));
data.add(item);
}
System.out.println("Data imported to list successfully.");
}
catch (SQLException ex) {
Logger.getLogger(OracleZoznamLiekovDAO.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
if (con != null) {
try {
con.close();
}
catch (SQLException ex) {
Logger.getLogger(OracleZoznamLiekovDAO.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
return data;
}
public ArrayList<ZoznamLiekovDTO> getListOfMedicines() {
ArrayList<ZoznamLiekovDTO> data = new ArrayList<ZoznamLiekovDTO>();
ZoznamLiekovDTO item;
Connection con = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
con = OracleDAOFactory.getOracleDatabaseConnection();
ps = con.prepareStatement(SELECT_ALL);
rs = ps.executeQuery();
while (rs.next()) {
item = new ZoznamLiekovDTO();
item.setId(rs.getInt(1));
item.getPobocka().setNazov(rs.getString(2));
item.getLiek().setNazov(rs.getString(3));
data.add(item);
}
System.out.println("List of Medicines imported successfully.");
}
catch (SQLException ex) {
Logger.getLogger(OracleZoznamLiekovDAO.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
if (con != null) {
try {
con.close();
}
catch (SQLException ex) {
Logger.getLogger(OracleZoznamLiekovDAO.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
return data;
}
}
And XHTML:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Zoznam liekov - prehľad</title>
<link rel="stylesheet" type="text/css" href="../style.css" />
</h:head>
<h:body>
<div id="out">
<h:form id="mainForm">
<p:selectOneMenu value="#{zoznamLiekovBean.selected_id}" required="true" effect="fade" id="zoznamComboBox">
<f:selectItems value="#{zoznamLiekovBean.branchesForCombobox}" var="itm" itemLabel="#{itm.nazov}" itemValue="#{itm.id}"/>
</p:selectOneMenu>
<p:commandButton immediate="true" styleClass="submitClass" value="Generuj zoznam" update="dialogText" actionListener="#{zoznamLiekovBean.test()}"/>
<p:dataTable style="width: 1100px" widgetVar="zoznamLiekovTable" selection="#{zoznamLiekovBean.selectedItem}" selectionMode="single" rowKey="#{item.id}" var="item" value="#{zoznamLiekovBean.listOfMedicines}" rows="5" rowsPerPageTemplate="5,10,15,20"
paginator="true" paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink}">
<p:column>
<f:facet name="header">ID:</f:facet>
<h:outputText value="#{item.id}"/>
</p:column>
<p:column>
<f:facet name="header">Pobočka:</f:facet>
<h:outputText value="#{item.pobocka.nazov}"/>
</p:column>
<p:column>
<f:facet name="header">Liek:</f:facet>
<h:outputText value="#{item.liek.nazov}"/>
</p:column>
</p:dataTable>
<p:dialog widgetVar="test" showEffect="explode" hideEffect="explode">
<h:outputText id="dialogText" value="#{zoznamLiekovBean.selected_id}"/>
</p:dialog>
</h:form>
</div>
</h:body>
</html>
Remove immediate="true" from the commandButton. You are skipping the whole Apply Request Value phase - Update Model value phase with that. That's why your value is always null or 0.
Check this out
I am working with Eclipse and Glassfish 3.0. Pretty new to this technology although I have done similar things before. Very simple really got a datatable bound to a backing bean. Add methods and remove methods i have covered - the problem lies with the update method I am calling. I cannot seem to see the changes being picked up in the component (HtmlInputText) never mind passing the data back to the table.
My code for the data table is below (and the jsf page)
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<f:loadBundle basename="resources.application" var="msg"/>
<head>
<title><h:outputText value="#{msg.welcomeTitle}" /></title>
</head>
<body>
<h:form id="mainform">
<h:dataTable var="row" border="0" value="#{beanCategory.collection}" binding="#{beanCategory.datatable}">
<f:facet name="header">
<h:outputText value="Categories"/>
</f:facet>
<h:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:inputText id="input1" value="#{row.description}" valueChangeListener="#{row.inputChanged}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Id"/>
</f:facet>
<h:outputText id="id" value="#{row.id}"/>
</h:column>
<h:column>
<h:commandButton value="Delete" type="submit" action="#{beanCategory.remove}">
<f:setPropertyActionListener target="#{beanCategory.selectedcategory}" value="#{row}"/>
</h:commandButton>
<h:commandButton value="Save" action="#{beanCategory.update}"
>
<f:setPropertyActionListener
target="#{beanCategory.selectedcategory}" value="#{row}" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:inputText id="text1"></h:inputText> <h:commandButton action="#{beanCategory.addCategory}" value="Add" type="submit" id="submitbutton">
</h:commandButton>
<br/><br/>
Messages
<h:messages></h:messages><br /><br />
</h:form>
</body>
</html>
Backing Bean is here
package net.bssuk.timesheets.controller;
import java.io.Serializable;
import java.util.List;
import javax.faces.component.UIInput;
import javax.faces.component.html.HtmlDataTable;
import javax.faces.context.FacesContext;
import javax.persistence.*;
import net.bssuk.timesheets.model.Category;
#javax.inject.Named("beanCategory")
#javax.enterprise.context.SessionScoped
public class BeanCategory implements Serializable {
private List<Category> collection;
private EntityManagerFactory emf;
private EntityManager em;
private int selectedid;
private Category selectedcategory;
private HtmlDataTable datatable;
private static final long serialVersionUID = 1L;
public BeanCategory() {
// TODO Auto-generated constructor stub
System.out.println("Bean Constructor");
}
public String addCategory() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Changed - Now attempting to add");
System.out.println("Ready to do cateogory");
Category category = new Category();
FacesContext context = FacesContext.getCurrentInstance();
UIInput input = (UIInput) context.getViewRoot().findComponent(
"mainform:text1");
String value = input.getValue().toString();
if (value != null) {
category.setDescription(input.getValue().toString());
} else {
category.setDescription("Was null");
}
this.em = this.emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(category);
tx.commit();
em.close();
emf.close();
// return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
}
return "return.html";
}
public String remove() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Getting Collection");
this.em = this.emf.createEntityManager();
FacesContext context = FacesContext.getCurrentInstance();
System.out.println("Number found is " + this.selectedid);
if (selectedcategory != null) {
System.out.println("removing "+selectedcategory.getId()+" - " +selectedcategory.getDescription());
EntityTransaction tx = em.getTransaction();
tx.begin();
System.out.println("Merging..");
this.em.merge(selectedcategory);
System.out.println("removing...");
this.em.remove(selectedcategory);
tx.commit();
em.close();
emf.close();
}else{
System.out.println("Not found");
}
return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
return "index.xhtml";
}
}
public String update() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Update Getting Collection");
Category category = (Category) getDatatable().getRowData();
FacesContext context = FacesContext.getCurrentInstance();
System.out.println("PHASE ID="+context.getCurrentPhaseId().toString());
if (category != null) {
// DESCRIPTION VALUE BELOW IS ALWAYS OLD VALUE (IE DATA IN DATABASE)
System.out.println("updating "+category.getId()+" - " +category.getDescription());
this.em = this.emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.merge(category);
tx.commit();
em.close();
emf.close();
}else{
System.out.println("Not found");
}
return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public void setCollection(List<Category> collection) {
this.collection = collection;
}
public List<Category> getCollection() {
// this.emf=Persistence.createEntityManagerFactory("timesheets1");
// System.out.println("Getting Collection");
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
this.em = this.emf.createEntityManager();
Query query = this.em.createNamedQuery("findAll");
this.collection = query.getResultList();
return this.collection;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void setSelectedid(int id) {
this.selectedid=id;
}
public void setSelectedcategory(Category selectedcategory) {
this.selectedcategory = selectedcategory;
}
public HtmlDataTable getDatatable() {
return datatable;
}
public void setDatatable(HtmlDataTable datatable) {
this.datatable = datatable;
}
public Category getSelectedcategory() {
return selectedcategory;
}
}
My Mapped entity for JPA is here
package net.bssuk.timesheets.model;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the CATEGORIES database table.
*
*/
#Entity
#Table(name="CATEGORIES")
#NamedQuery(name="findAll", query = "SELECT c from Category c")
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
private String description;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
public Category() {
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
}
OK - Updated my code to follow example. I have tried to incorporate an EJB into the scenario as follows
package net.bssuk.timesheets.ejb;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import net.bssuk.timesheets.model.Category;
#Stateless
public class CategoryEJB implements CategoryEJBRemote {
#PersistenceContext(unitName="timesheets1")
private EntityManager em;
#Override
public List<Category> findCategories() {
// TODO Auto-generated method stub
System.out.println("find categories");
Query query = em.createNamedQuery("findAll");
return query.getResultList();
}
#Override
public Category createCategory(Category category) {
// TODO Auto-generated method stub
em.persist(category);
return category;
}
#Override
public Category udpateCategory(Category category) {
// TODO Auto-generated method stub
return em.merge(category);
}
#Override
public void deleteCategory(Category category) {
// TODO Auto-generated method stub
em.remove(em.merge(category));
}
}
My EJB is below
package net.bssuk.timesheets.ejb;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import net.bssuk.timesheets.model.Category;
#Stateless
public class CategoryEJB implements CategoryEJBRemote {
#PersistenceContext(unitName="timesheets1")
private EntityManager em;
#Override
public List<Category> findCategories() {
// TODO Auto-generated method stub
System.out.println("find categories");
Query query = em.createNamedQuery("findAll");
return query.getResultList();
}
#Override
public Category createCategory(Category category) {
// TODO Auto-generated method stub
em.persist(category);
return category;
}
#Override
public Category udpateCategory(Category category) {
// TODO Auto-generated method stub
return em.merge(category);
}
#Override
public void deleteCategory(Category category) {
// TODO Auto-generated method stub
em.remove(em.merge(category));
}
}
Can anyone suggest if this sort of looks ok? Or have I completely lost the plot with it!
Look,
<h:dataTable var="row" border="0" value="#{beanCategory.collection}" binding="#{beanCategory.datatable}">
and
public List<Category> getCollection() {
// this.emf=Persistence.createEntityManagerFactory("timesheets1");
// System.out.println("Getting Collection");
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
this.em = this.emf.createEntityManager();
Query query = this.em.createNamedQuery("findAll");
this.collection = query.getResultList();
return this.collection;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
You're loading the list inside a getter method. This is a very bad idea. A getter should solely be an access point to the bean property, not to do some business job. A getter can be called multiple times during bean's life. The DB will be hit on every call and the local collection property which was been updated by JSF during form submit will be overwritten again at a later point. This makes no sense.
Do the business job in the (post)constructor method or action(listener) methods. Definitely not in a getter. Here's a minimum kickoff example with some code improvements:
<h:dataTable value="#{bean.categories}" var="category">
<h:column>
<h:inputText value="#{category.description}" />
</h:column>
<h:column>
<h:outputText value="#{category.id}" />
</h:column>
<h:column>
<h:commandButton value="Delete" action="#{bean.delete(category)}" />
<h:commandButton value="Save" action="#{bean.update(category)}" />
</h:column>
</h:dataTable>
<h:inputText value="#{bean.newCategory.description}" />
<h:commandButton value="Add" action="#{bean.add}" />
(note that passing arguments in EL is supported since EL 2.2 (part of Servlet 3.0), Glassfish 3 is a Servlet 3.0 container, so it should definitely support it when web.xml is properly declared conform Servlet 3.0 spec)
with
#ManagedBean
#ViewScoped // Definitely don't use session scoped. I'm not sure about CDI approach, so here's JSF example.
public class Bean {
private List<Category> categories;
private Category newCategory;
#EJB
private CategoryService categoryService;
#PostConstruct
public void init() {
categories = categoryService.list();
newCategory = new Category();
}
public void add() {
categoryService.add(newCategory);
init();
}
public void delete(Category category) {
categoryService.delete(category);
init();
}
public void update(Category category) {
categoryService.update(category);
init();
}
public List<Category> getCategories() {
return categories;
}
public Category getNewCategory() {
return newCategory;
}
}
That should be it. See also:
Why JSF calls getters multiple times
Help understanding JSF's multiple calls to managed bean
<h:dataTable value=#{myBean.xxx}>: getXxx() get called so many times, why?
As I see, you have forgotten the <h:form>. This is very necessary to save inputs.