I have two entities , Employee and publication :
I want to show in a data table the publication title, date, and it's author stored in database :
this is my query using JPQL :
private static EntityManager em;
private static EntityManagerFactory factory;
public PublicationDAO() {
if(factory==null)
factory=Persistence.createEntityManagerFactory("mavenTest");
if(em==null)
em=factory.createEntityManager();
}
public List<Object[]> getAllPublication() {
em.getTransaction().begin();
List<Object[]> pubs = em.createQuery("SELECT c.titrePublication, p.login FROM Publication c JOIN c.employee p ").getResultList();
em.getTransaction().commit();
return pubs;
}
so I want to show this information in XHTML page's data table.
Currently the query would return Array and what you need is a Construct return type..
create custom class (this will be your return type and it must have constructor which takes result values you define in query string. )
public class publicationModel
{
public String publicationName;
public String author;
public publicationModel (String publicationName, String author)
{
this.publicationName= publicationName;
this.author= author;
}
}
use typedQuery
String queryStr ="SELECT NEW example.publicationModel (c.titrePublication, p.login) " +
"FROM Publication c JOIN c.employee p ";
TypedQuery query =
em.createQuery(queryStr, publicationModel .class);
List <publicationModel> results = query.getResultList();
m not able to format the answer.. but i hope this helps..
I wonder why you make the type of the list "array of objects". Rendering it as type of your entity class is enough :
public List<Publication> getAllPublication() {
...
List<Publication> pubs = ...
...
}
Specify a managedBean class in your presentation tier, to do the job :
#RequestScoped
#ManagedBean
public class PublicationBean {
// Inject your PublicationDAO here
private PublicationDAO publicationDao;
private List<Publication> publications;
#PostConstruct
public retrievePublications () {
try {
publications = publicationDao.getAllPublication();
} catch (Exception e) {
}
}
public List<Publication> getPublications() {
return this.publications;
}
public void setPublications(List<Publication> publications) {
this.publications= publications;
}
// getters/setters
}
Then, display the data with <h:dataTable> like this :
<h:dataTable value="#{publicationBean.publications}" var="p" rules="all">
<h:column>
<f:facet name="header">Publication title</f:facet>
#{p.titrePublication}
</h:column>
<h:column>
<f:facet name="header">Publication author</f:facet>
#{p.employee.name}
</h:column>
</h:dataTable>
hi finally I find the solution :
the correct query should be :
List<Publication>=em.createQuery("select p from Publication p",Publication.Class).getResultList();
in the managed bean I should declare The author which is The Employee entity with getter and setter.
then create a method called getAllpublications as :
public List<Publication> getAllpublications (){
publicationDao.getAllPublication();//this method is declared and specified in the DAO class
}
after that the xhtml page should look like:
<h:dataTable value="#{publicationBean.publications}" var="p" rules="all">
<h:column>
<f:facet name="header">Publication title</f:facet>
<h:outputText value="#{p.titrePublication}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">Publication author</f:facet>
<h:outputText value="#{p.employee.name}"></h:outputText>
</h:column>
</h:dataTable>
so the solution is very close to your answer Omar thanks a lot for your help.
Related
My JSF application is behaving strangely, and I ask colleagues to help me identify a solution.
The application fetches data from the database through Facade+DAO classes, and through debug and println I can state that the object collection is correct (in the example below, the collection contains the 5 objects and their attributes), however, when passing this collection to the Primefaces page, dataTable does not display the attributes, it becomes clear that the the amount of rows is correct but the attributes are not displayed as shown in the figure.
I researched other posts, but the errors described do not resemble mine:
after filtering Empty rows blank rows displayed while paging in the datatable using Primefaces
primefaces datatable is showing blank rows. Showing the same number of rows as the records in backed list
Since the managed bean is reposting the collection correctly, I figured the issue should be on display (ie on the JSF page), and to try to find where the fault could be, I created a page without using Primefaces or Facelets, just pure JSF components, but the failure persisted. The basic code looks like this:
Here are the code snippets:
simple page
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<link href="scripts/teste.css" rel="stylesheet" type="text/css" media="all" />
</h:head>
<h:body>
<h:form>
<h:dataTable value="#{coletaMB.coletas}" var="coleta"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row">
<h:column>
<f:facet name="header">Nr. Setor</f:facet>
<h:outputText value="#{coleta.setor.numero}"/>
---- #{coleta.setor.numero} ----
</h:column>
</h:dataTable>
</h:form>
With this simple code, the page looks like this:
managed bean
#ManagedBean(name="coletaMB")
#SessionScoped
public class ColetaMB{
#ManagedProperty(name="coleta", value="#{coleta}")
private Coleta coleta;
#ManagedProperty(name="coletaFacade", value="#{coletaFacade}")
private ColetaFacade coletaFacade;
private List<Coleta> coletas;
public List<Coleta> getColetas(){
if(coletas == null){
coletas = getListColetas();
}
return coletas;
}
private List<Coleta> getListColetas(){
coletas = new ArrayList<Coleta>();
try {
coletas = coletaFacade.getColetas();
return coletas;
} catch (DAOException e) {
(...)
}
}
(...)
}
Coleta.java
public class Coleta {
private int ano;
private Setor setor;
private int mes;
private int semana;
private int numeroEntrevista;
(*)getters and setter
}
Setor.java
public class Setor {
private Agencia agencia;
private String numero;
private String upa;
(*)getters and setters
}
Agencia.java
public class Agencia {
private int idAgencia;
private String nome;
(*)getters and setters
}
Facade
public List<Coleta> getColetas() throws DAOException {
return dao.getColetas();
}
DAO
#Value("#{queries.sql01}")
private String sql01;
public List<Coleta> getColetas() throws DAOException {
try{
RowMapper<Coleta> mapper = getRowMapper();
return getJdbcTemplate().query(sql01, mapper);
} catch (DataAccessException de) {
de.printStackTrace();
throw new DAOException(de.getMessage());
}
}
private RowMapper<Coleta> getRowMapper() {
return new RowMapper<Coleta>() {
public Coleta mapRow(ResultSet rs, int rowNum) throws SQLException {
Agencia ag = new Agencia();
ag.setIdAgencia(rs.getInt(1));
ag.setNome(rs.getString(2));
Setor s = new Setor();
s.setAgencia(ag);
s.setUpa(rs.getString(3));
s.setNumero(rs.getString(4));
Coleta c = new Coleta();
c.setSetor(s);
c.setAno(rs.getInt(5));
c.setMes(rs.getInt(6));
c.setSemana(rs.getInt(7));
c.setNumeroEntrevista(rs.getInt(8));
return c;
}
};
}
In getListColetas, I inserted a println to verify the collection and it is complete, that is, each object 'coleta' has the object 'setor' and each 'setor' has the object 'agencia'. But, following the suggestion of using 'empty' on the JSF page,
<h:outputText value="#{empty coleta} - #{empty coleta.setor} - #{empty coleta.setor.numero}"/>
the return was false - true - true, and I don't know why.
My complete application is using the following libraries and dependencies (Spring is only used for DI and DAO classes):
Resolved: in dataTable tag, I changed the attribute var="coleta" to var="c", like this:
<h:dataTable value="#{coletaMB.coletas}" var="c"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row">
<h:column>
<f:facet name="header">Nr. Setor</f:facet>
<h:outputText value="#{c.setor.numero}"/>
---- #{c.setor.numero} ----
</h:column>
</h:dataTable>
I imagine JSF was conflicting with the #ManagedProperty 'coleta' in ColetaMB, although I understand that the var attribute is specific to varying collection objects delivered to dataTable.
This question already has answers here:
How can I pass selected row to commandLink inside dataTable or ui:repeat?
(4 answers)
Closed 7 years ago.
I am new to java ee and dont have much idea about jsf and all. I am making a simple java web application that fetches data from database and shows in dataTable. I need to edit data selected by user from dataTable for which i need to get value of the row selected/clicked. But i havent been able to do it. Can any one please help me with my code ? I hope someone would tell me how can i do it with my following codes.
showRecords.xhtml
h:dataTable value="#{studentList.studentL()}" var="student" styleClass="studentTable"
columnClasses=",,,fixedWidth">
<h:column>
<f:facet name="header">Student ID</f:facet>
<h:outputText value="#{student.studentId}"></h:outputText>
</h:column>
<h:column>
<f:facet name="header">Name</f:facet>
<h:outputText value="#{student.fname}"></h:outputText>
</h:column>
Student.java
#ManagedBean(name="student")
public class student {
#Id private String StudentId;
private String Fname, Lname, Mname="noname";
/*******getters and setters** and database transaction****/
}
studentList.java
#ManagedBean(name="studentList")
#SessionScoped
public class studentList {
public List<student> studentL(){
List<student> list = new ArrayList<student>();
PreparedStatement ps = null;
ResultSet rs = null;
Connection con = null;
try{
Class.forName("org.apache.derby.jdbc.ClientDriver");
con = DriverManager.getConnection("jdbc:derby://localhost:1527/tourManager","administrator","pass");
String sql = "Select * from student";
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
while(rs.next()){
student student1 = new student();
student1.setFname(rs.getString("FNAME"));
student1.setLname(rs.getString("LNAME"));
student1.setStudentId(rs.getString("STUDENTID"));
list.add(student1);
// return list;
}
}catch(Exception e){
e.printStackTrace();
}
return list;
}
public void editStudent() throws IOException{
int index = Integer.parseInt(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("index").toString());
System.out.println(" the selected row is "+index);
}
}
You can pass a parameter using expression language.
In your bean, have a function like
public void editStudent(String studentId)
{
// do something with id
}
Now, using expression language, you can call that method using #{yourbean.editStudent('id')}
Since you are iterating through your data using a datatable, you can access the student's id from the var variable.
<h:dataTable value="#{studentList.studentL()}" var="student" ...>
...
<h:commandButton value="Edit" action="#{studentList.editStudent(student.studentId)}" />
...
</h:dataTable>
The expression language will access the getStudentId() (getter method from studentId) method from the specific student.
I've got a list of orders on a database, and I want to show two separate datatables in two JSF pages: one table regarding all orders, and one table regarding the current logged user.
Problem is, only the first one is actually showed on the page.
JSF page with the datatable links
<h:commandLink action="#{ordineController.listaOrdini}"
value="Consulta gli ordini esistenti" rendered="#{not empty loginAdmin.admin.email}"/>
<div>
<h:commandLink
action="#{ordineController.listaOrdiniCliente}"
value="Controlla i tuoi ordini"
rendered="#{not empty loginCliente.clienteLoggato.email}">
<f:setPropertyActionListener target="#{ordineController.clienteCorrente}"
value="#{loginCliente.clienteLoggato}" />
</h:commandLink>
</div>
ViewScoped bean
#ManagedBean(name="ordineController")
#ViewScoped
public class OrdineController implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#PostConstruct
public void init() {
ordini = oFacade.getListaOrdini();
listaOrdiniCliente();
}
public String listaOrdini() {
this.ordini = oFacade.getListaOrdini();
return "showOrdini";
}
public String listaOrdiniCliente() {
this.ordiniCliente = oFacade.getOrdiniCliente(clienteCorrente);
return "showOrdiniCliente";
}
/*Getters and setters*
The JSF page that doesn't work (showOrdiniCliente.xhtml)
<h:outputText value="Non c'è nessun ordine."
rendered="#{empty ordineController.ordiniCliente}" />
<h:dataTable id="lista" value="#{ordineController.ordiniCliente}"
var="ordine" rendered="#{not empty ordineController.ordiniCliente}">
The JSF page that does work (showOrdini.xhtml)
<h:outputText value="Non c'è nessun ordine."
rendered="#{empty ordineController.ordini}" />
<h:form rendered="#{not empty ordineController.ordini}">
<h:dataTable id="lista" value="#{ordineController.ordini}"
var="ordine">
Why is the #{ordineController.ordiniCliente} empty?
Shouldn't it be builded along with the "ordini" variable in the #PostConstruct?
edit
Facade method (it retrieves all the orders of a customer)
public List<Ordine> getOrdiniCliente (Cliente cliente) {
try {
TypedQuery<Ordine> q = em.createQuery("SELECT ord FROM Ordine ord WHERE ord.cliente = :cliente", Ordine.class);
q.setParameter("cliente", cliente);
return q.getResultList();
}
catch (Exception e) {
String q = "Il cliente " +cliente.getNickname()+ " non ha creato degli ordini";
System.out.println(q);
return null;
}
}
I am using RichFaces's ordering list to display a table custom Command objects to the user. The user uses a form to create new commands which are then added to the list. Here is the orderingList implementation:
app.xhtml
<rich:orderingList id="oList" value="#{commandBean.newBatch}" var="com"
listHeight="300" listWidth="350" converter="commandConverter">
<f:facet name="header">
<h:outputText value="New Batch Details" />
</f:facet>
<rich:column width="180">
<f:facet name="header">
<h:outputText value="Command Type" />
</f:facet>
<h:outputText value="#{com.commandType}"></h:outputText>
</rich:column>
<rich:column>
<f:facet name="header">
<h:outputText value="Parameters" />
</f:facet>
<h:outputText value="#{com.parameters}"></h:outputText>
</rich:column>
<rich:column>
<h:commandButton value="Remove #{com.id} : #{com.seqNo}"
action="#{commandBean.remove(com.id,com.seqNo)}"
onclick="alert('id:#{com.id} seqNo:#{com.seqNo}');"/>
</rich:column>
My troubles began when I tried to implement a remove button which would send a command's ID and seqNo to the backing bean (cb) to be removed from the list. Here is the backing bean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class CommandBean implements Serializable{
private static final long serialVersionUID = 1L;
private CommandType type;
private String parameters;
private List<Command> newBatch = new ArrayList<Command>();
private Set<Command> commandSet = new HashSet<Command>();
private String msg = "not removed";
public CommandType[] getCommandTypes() {
return CommandType.values();
}
public void addCommand(CommandType type, String parameters) {
newBatch.add(new Command(type, parameters));
}
CommandType getType() {
return type;
}
void setType(CommandType type) {
this.type = type;
}
String getParameters() {
return parameters;
}
void setParameters(String parameters) {
this.parameters = parameters;
}
public List<Command> getNewBatch() {
return newBatch;
}
public void setNewBatch(List<Command> newBatch) {
this.newBatch = newBatch;
}
public Set<Command> getCommandSet() {
return commandSet;
}
public void setCommandSet(Set<Command> commandSet) {
this.commandSet = commandSet;
}
String getMsg() {
return msg;
}
public void remove(Integer id, Integer seqNo) {
for(Command c : newBatch) {
if(c.getId() == id && c.getSeqNo() == seqNo) {
newBatch.remove(c);
msg = "removed " + c;
return;
}
}
msg = String.format("%d : %d", id,seqNo);
}
}
When the Command (com)'s id and seqNo are passed via #{cb.remove(com.id,com.seqNo)} they are both 0. I also read somewhere that null values are transformed to 0's, so that would explain it. I also tried to pass the Command object directly via #{cb.remove(com)} but the Command was null when bean tried to process it.
I'm betting there is something off with the scoping, but I am too new to JSF to figure it out...
UPDATE
I have eliminated the conflicting #Named tag and have updated the html to reflect the new name of the bean, namely commandBean. Still having issues though.
you can pass the two values as request parameters:
<h:commandButton ... >
<f:param name="id" value="#{com.id}"/>
<f:param name="seqNo" value="#{com.seqNo}"/>
</h:commandButton>
and get retrieve them in managed bean like this:
HttpServletRequest request = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest());
System.out.println(request.getParameter("id"));
System.out.println(request.getParameter("seqNo"));
You're trying to get a value from a variable that is used in a for-cycle after the cycle is over. The #action is being resolved on the server side, by the time the #var is null.
You can do this:
<a4j:commandButton action="#{commandBean.remove()}" … >
<a4j:param assignTo="#{commandBean.idToRemove}" value="#{com.id}"/>
</a4j:commandButton>
The a4j:param resolves the value on client side, when the button is clicked it sends it to the server.
I have a table displayed. When the user clicks on the headers i want the table to reorganise itself, sorted according to the selected header. Clicking on the same header again, swaps the order of sorting
Within the table, there are several commandLinks.
Now, the problems are as follows
the first update to the sorting order happens, but clicking on the header again will not swap the order.
When the table is refreshed, the links have their value changed, but the link still maps to the object that was previously there
Code:
Table:
<h:form title="table">
<h:dataTable value="#{employee.employeeList}" var="a"
styleClass="order-table" headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row"
style="width:100%">
<h:column>
<f:facet name="header"><h:commandLink value="Number" action="#{employee.sortByNumber()}" /></f:facet>
<h:commandLink value="#{a.number}" action="#{employee.setEmp(a)}" />
</h:column>
...
...
...
</h:dataTable>
</h:form>
Employee Bean:
public String filter = ""; //has getters and setters
public String order = ""; //has getters and setters
public static final String ORDER_ASCENDING = "asc";
public static final String ORDER_DESCENDING = "desc";
public static final String FILTER_NUMBER = "number";
public void sortByNumber(){
if(filter.equals(FILTER_NUMBER)){
swapOrder();
}else{
filter = FILTER_NUMBER;
order = ORDER_ASCENDING;
}
refreshPage();
}
public void swapOrder(){
if(order.equals(ORDER_ASCENDING)){
order = ORDER_DESCENDING;
}else{
order = ORDER_ASCENDING;
}
}
public void refreshPage(){
FacesContext context = FacesContext.getCurrentInstance();
String viewId = context.getViewRoot().getViewId();
ViewHandler handler = context.getApplication().getViewHandler();
UIViewRoot root = handler.createView(context, viewId);
root.setViewId(viewId);
context.setViewRoot(root);
}
public String setEmp(Employee employee) {
this.employee = employee;
return "details"; //redirects to the details page where the employee set in the previous line is used
}