问题描述:

My web application is a CRUD web application based on JSF 2.0 / JPA using Java EE 5 and JDK 1.6. Running on Glassfish 3.1. The IDE is Netbeans 7.0. (I do not use EJB, nor CDI).

  1. THE PROBLEM

What I can achieve now is perform CRUD on my entities. Which is fine. For each entity I have:

  • List.xhtml (LIsting all Datamodel items for that entity in datatable)
  • Create.xhtml (A form to create a new item)
  • View.xhtml (a form to view an item)
  • Edit.xhtml (a form to edit an item)

Structure

  • entities package: entities.
  • jpa.controllers package: JPA controllers (Javax persistence..).
  • jsf package: a managed bean for each entity (session Scoped).

But the main problem is parent-leaf navigation. I want my webapp to do the same thing as the Demo application Agile ScrumToys that comes along shipped with Netbeans 7.0. or the demo webapp from SpringFuse, otherwise :

E.G: When you display a list of WRITERS in a you have the last <h:column> where you put three <h:commandLink /> for editing, viewing and deleting the selected row.

What I intend to do is to add another in the same column that allows me to view a collection of child objects related to that selected row.

Hence, I want to show the list of BOOKS written by a given WRITER.

WRITER 1 ---------- * BOOK (one-to-many) relationship.

When the user clicks on the

<h:commandButton action="#{someManagedBean.showBooksForWriter}" value="#{i18n.listBooks}" /> it forwards him to the /book/List.xhtml (list of the selected WRITEr row should appear). And so on, from the book datatable, from a given row, I click on <h:commandLink action="#{someManagedBean.showReferencesForBook}" value="List of Book References"/> to get the list of references for the given book.

A given hint by @Matt was to use a method in the book managed bean:

public showBooksForWriter(Writer writer) {

// TODO: get the selected writer

// Get the list of books for the selected writer

return "/book/List"; // Outcome

}

And in the view :

<h:datatable value="#{writerController.items}" var="w">

.....

<h:column>

<h:commandButton action="#{bookController.showBooksForWriter(w}" value="Show Books For Writer"/>

</h:column>

....

</h:datatable>

But I could not figure how to (DataModel is driving mad). So if anyone could help! It would be very appreciated!

Below is my code

the WRITER entity:

package entities;

import javax.persistence.*; // other imports

@Entity

@Table(name = "WRITER")

@XmlRootElement

@NamedQueries({

@NamedQuery(name = "Writer.findAll", query = "SELECT w FROM Writer w"),

@NamedQuery(name = "Writer.findByWriterid", query = "SELECT w FROM Writer w WHERE w.writerid = :writerid"),

@NamedQuery(name = "Writer.findByName", query = "SELECT w FROM Writer w WHERE w.name = :name"),

@NamedQuery(name = "Writer.findBySurname", query = "SELECT w FROM Writer w WHERE w.surname = :surname"),

@NamedQuery(name = "Writer.findByMiddlename", query = "SELECT w FROM Writer w WHERE w.middlename = :middlename"),

@NamedQuery(name = "Writer.findByIsRewarded", query = "SELECT w FROM Writer w WHERE w.isRewarded = :isRewarded")})

public class Writer implements Serializable {

private static final long serialVersionUID = 1L;

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

@Basic(optional = false)

@NotNull

@Column(name = "writerid")

private Integer writerid;

@Size(max = 45)

@Column(name = "name")

private String name;

@Size(max = 45)

@Column(name = "surname")

private String surname;

@Size(max = 45)

@Column(name = "middlename")

private String middlename;

@Column(name = "isRewarded")

private Boolean isRewarded;

@ManyToMany(mappedBy = "writerList")

private List<Topic> topicList;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "writer")

private List<Evaluation> evaluationList;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "writer")

private List<Book> bookList;

public Writer() {

}

public Writer(Integer writerid) {

this.writerid = writerid;

}

public Integer getWriterid() {

return writerid;

}

public void setWriterid(Integer writerid) {

this.writerid = writerid;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getSurname() {

return surname;

}

public void setSurname(String surname) {

this.surname = surname;

}

public String getMiddlename() {

return middlename;

}

public void setMiddlename(String middlename) {

this.middlename = middlename;

}

public Boolean getIsRewarded() {

return isRewarded;

}

public void setIsRewarded(Boolean isRewarded) {

this.isRewarded = isRewarded;

}

@XmlTransient

public List<Topic> getTopicList() {

return topicList;

}

public void setTopicList(List<Topic> topicList) {

this.topicList = topicList;

}

@XmlTransient

public List<Evaluation> getEvaluationList() {

return evaluationList;

}

public void setEvaluationList(List<Evaluation> evaluationList) {

this.evaluationList = evaluationList;

}

@XmlTransient

public List<Book> getBookList() {

return bookList;

}

public void setBookList(List<Book> bookList) {

this.bookList = bookList;

}

@Override

public int hashCode() {

int hash = 0;

hash += (writerid != null ? writerid.hashCode() : 0);

return hash;

}

@Override

public boolean equals(Object object) {

// TODO: Warning - this method won't work in the case the id fields are not set

if (!(object instanceof Writer)) {

return false;

}

Writer other = (Writer) object;

if ((this.writerid == null && other.writerid != null) || (this.writerid != null && !this.writerid.equals(other.writerid))) {

return false;

}

return true;

}

@Override

public String toString() {

return getMiddlename();

}

}

The Writer MANAGED BEAN

package jsf;

import entities.Writer;

import jsf.util.JsfUtil;

import jsf.util.PaginationHelper;

import jpa.controllers.WriterJpaController;

import javax.faces.bean.ManagedBean;

// other imports here

@ManagedBean(name = "writerController")

@SessionScoped

public class WriterController implements Serializable {

@Resource

private UserTransaction utx = null;

@PersistenceUnit(unitName = "writerPU")

private EntityManagerFactory emf = null;

private Writer current;

private DataModel items = null;

private WriterJpaController jpaController = null;

private PaginationHelper pagination;

private int selectedItemIndex;

public WriterController() {

}

public Writer getSelected() {

if (current == null) {

current = new Writer();

selectedItemIndex = -1;

}

return current;

}

private WriterJpaController getJpaController() {

if (jpaController == null) {

jpaController = new WriterJpaController(utx, emf);

}

return jpaController;

}

public PaginationHelper getPagination() {

if (pagination == null) {

pagination = new PaginationHelper(10) {

@Override

public int getItemsCount() {

return getJpaController().getWriterCount();

}

@Override

public DataModel createPageDataModel() {

return new ListDataModel(getJpaController().findWriterEntities(getPageSize(), getPageFirstItem()));

}

};

}

return pagination;

}

public String prepareList() {

recreateModel();

return "List";

}

public String prepareView() {

current = (Writer) getItems().getRowData();

selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();

return "View";

}

public String prepareCreate() {

current = new Writer();

selectedItemIndex = -1;

return "Create";

}

public String create() {

try {

getJpaController().create(current);

JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("WriterCreated"));

return prepareCreate();

} catch (Exception e) {

JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));

return null;

}

}

public String prepareEdit() {

current = (Writer) getItems().getRowData();

selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();

return "Edit";

}

public String update() {

try {

getJpaController().edit(current);

JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("WriterUpdated"));

return "View";

} catch (Exception e) {

JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));

return null;

}

}

public String destroy() {

current = (Writer) getItems().getRowData();

selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();

performDestroy();

recreateModel();

return "List";

}

public String destroyAndView() {

performDestroy();

recreateModel();

updateCurrentItem();

if (selectedItemIndex >= 0) {

return "View";

} else {

// all items were removed - go back to list

recreateModel();

return "List";

}

}

private void performDestroy() {

try {

getJpaController().destroy(current.getWriterid());

JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("WriterDeleted"));

} catch (Exception e) {

JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));

}

}

private void updateCurrentItem() {

int count = getJpaController().getWriterCount();

if (selectedItemIndex >= count) {

// selected index cannot be bigger than number of items:

selectedItemIndex = count - 1;

// go to previous page if last page disappeared:

if (pagination.getPageFirstItem() >= count) {

pagination.previousPage();

}

}

if (selectedItemIndex >= 0) {

current = getJpaController().findWriterEntities(1, selectedItemIndex).get(0);

}

}

public DataModel getItems() {

if (items == null) {

items = getPagination().createPageDataModel();

}

return items;

}

private void recreateModel() {

items = null;

}

public String next() {

getPagination().nextPage();

recreateModel();

return "List";

}

public String previous() {

getPagination().previousPage();

recreateModel();

return "List";

}

public SelectItem[] getItemsAvailableSelectMany() {

return JsfUtil.getSelectItems(getJpaController().findWriterEntities(), false);

}

public SelectItem[] getItemsAvailableSelectOne() {

return JsfUtil.getSelectItems(getJpaController().findWriterEntities(), true);

}

@FacesConverter(forClass = Writer.class)

public static class WriterControllerConverter implements Converter {

public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {

if (value == null || value.length() == 0) {

return null;

}

WriterController controller = (WriterController) facesContext.getApplication().getELResolver().

getValue(facesContext.getELContext(), null, "writerController");

return controller.getJpaController().findWriter(getKey(value));

}

java.lang.Integer getKey(String value) {

java.lang.Integer key;

key = Integer.valueOf(value);

return key;

}

String getStringKey(java.lang.Integer value) {

StringBuffer sb = new StringBuffer();

sb.append(value);

return sb.toString();

}

public String getAsString(FacesContext facesContext, UIComponent component, Object object) {

if (object == null) {

return null;

}

if (object instanceof Writer) {

Writer o = (Writer) object;

return getStringKey(o.getWriterid());

} else {

throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + WriterController.class.getName());

}

}

}

}

JSF Utility Class

package jsf.util;

import javax.faces.application.FacesMessage;

// Other imports here

public class JsfUtil {

public static SelectItem[] getSelectItems(List<?> entities, boolean selectOne) {

int size = selectOne ? entities.size() + 1 : entities.size();

SelectItem[] items = new SelectItem[size];

int i = 0;

if (selectOne) {

items[0] = new SelectItem("", "---");

i++;

}

for (Object x : entities) {

items[i++] = new SelectItem(x, x.toString());

}

return items;

}

public static void addErrorMessage(Exception ex, String defaultMsg) {

String msg = ex.getLocalizedMessage();

if (msg != null && msg.length() > 0) {

addErrorMessage(msg);

} else {

addErrorMessage(defaultMsg);

}

}

public static void addErrorMessages(List<String> messages) {

for (String message : messages) {

addErrorMessage(message);

}

}

public static void addErrorMessage(String msg) {

FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);

FacesContext.getCurrentInstance().addMessage(null, facesMsg);

}

public static void addSuccessMessage(String msg) {

FacesMessage facesMsg = new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg);

FacesContext.getCurrentInstance().addMessage("successInfo", facesMsg);

}

public static String getRequestParameter(String key) {

return FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get(key);

}

public static Object getObjectFromRequestParameter(String requestParameterName, Converter converter, UIComponent component) {

String theId = JsfUtil.getRequestParameter(requestParameterName);

return converter.getAsObject(FacesContext.getCurrentInstance(), component, theId);

}

}

JSF Pagination helper

package jsf.util;

import javax.faces.model.DataModel;

public abstract class PaginationHelper {

private int pageSize;

private int page;

public PaginationHelper(int pageSize) {

this.pageSize = pageSize;

}

public abstract int getItemsCount();

public abstract DataModel createPageDataModel();

public int getPageFirstItem() {

return page * pageSize;

}

public int getPageLastItem() {

int i = getPageFirstItem() + pageSize - 1;

int count = getItemsCount() - 1;

if (i > count) {

i = count;

}

if (i < 0) {

i = 0;

}

return i;

}

public boolean isHasNextPage() {

return (page + 1) * pageSize + 1 <= getItemsCount();

}

public void nextPage() {

if (isHasNextPage()) {

page++;

}

}

public boolean isHasPreviousPage() {

return page > 0;

}

public void previousPage() {

if (isHasPreviousPage()) {

page--;

}

}

public int getPageSize() {

return pageSize;

}

} // END of CLASS

The JPA Controller

package jpa.controllers;

import entities.Writer;

// other imports here

public class WriterJpaController implements Serializable {

public WriterJpaController(UserTransaction utx, EntityManagerFactory emf) {

this.utx = utx;

this.emf = emf;

}

private UserTransaction utx = null;

private EntityManagerFactory emf = null;

public EntityManager getEntityManager() {

return emf.createEntityManager();

}

public void create(Writer writer) throws RollbackFailureException, Exception {

if (writer.getTopicList() == null) {

writer.setTopicList(new ArrayList<Topic>());

}

if (writer.getEvaluationList() == null) {

writer.setEvaluationList(new ArrayList<Evaluation>());

}

if (writer.getBookList() == null) {

writer.setBookList(new ArrayList<Book>());

}

EntityManager em = null;

try {

utx.begin();

em = getEntityManager();

List<Topic> attachedTopicList = new ArrayList<Topic>();

for (Topic topicListTopicToAttach : writer.getTopicList()) {

topicListTopicToAttach = em.getReference(topicListTopicToAttach.getClass(), topicListTopicToAttach.getTopicname());

attachedTopicList.add(topicListTopicToAttach);

}

writer.setTopicList(attachedTopicList);

List<Evaluation> attachedEvaluationList = new ArrayList<Evaluation>();

for (Evaluation evaluationListEvaluationToAttach : writer.getEvaluationList()) {

evaluationListEvaluationToAttach = em.getReference(evaluationListEvaluationToAttach.getClass(), evaluationListEvaluationToAttach.getEvaluationPK());

attachedEvaluationList.add(evaluationListEvaluationToAttach);

}

writer.setEvaluationList(attachedEvaluationList);

List<Book> attachedBookList = new ArrayList<Book>();

for (Book bookListBookToAttach : writer.getBookList()) {

bookListBookToAttach = em.getReference(bookListBookToAttach.getClass(), bookListBookToAttach.getBookPK());

attachedBookList.add(bookListBookToAttach);

}

writer.setBookList(attachedBookList);

em.persist(writer);

for (Topic topicListTopic : writer.getTopicList()) {

topicListTopic.getWriterList().add(writer);

topicListTopic = em.merge(topicListTopic);

}

for (Evaluation evaluationListEvaluation : writer.getEvaluationList()) {

Writer oldWriterOfEvaluationListEvaluation = evaluationListEvaluation.getWriter();

evaluationListEvaluation.setWriter(writer);

evaluationListEvaluation = em.merge(evaluationListEvaluation);

if (oldWriterOfEvaluationListEvaluation != null) {

oldWriterOfEvaluationListEvaluation.getEvaluationList().remove(evaluationListEvaluation);

oldWriterOfEvaluationListEvaluation = em.merge(oldWriterOfEvaluationListEvaluation);

}

}

for (Book bookListBook : writer.getBookList()) {

Writer oldWriterOfBookListBook = bookListBook.getWriter();

bookListBook.setWriter(writer);

bookListBook = em.merge(bookListBook);

if (oldWriterOfBookListBook != null) {

oldWriterOfBookListBook.getBookList().remove(bookListBook);

oldWriterOfBookListBook = em.merge(oldWriterOfBookListBook);

}

}

utx.commit();

} catch (Exception ex) {

try {

utx.rollback();

} catch (Exception re) {

throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);

}

throw ex;

} finally {

if (em != null) {

em.close();

}

}

}

public void edit(Writer writer) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {

// remainder of code goes here

}

public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException, RollbackFailureException, Exception {

// remainder of code goes here

}

public List<Writer> findWriterEntities() {

return findWriterEntities(true, -1, -1);

}

public List<Writer> findWriterEntities(int maxResults, int firstResult) {

return findWriterEntities(false, maxResults, firstResult);

}

private List<Writer> findWriterEntities(boolean all, int maxResults, int firstResult) {

EntityManager em = getEntityManager();

try {

CriteriaQuery cq = em.getCriteriaBuilder().createQuery();

cq.select(cq.from(Writer.class));

Query q = em.createQuery(cq);

if (!all) {

q.setMaxResults(maxResults);

q.setFirstResult(firstResult);

}

return q.getResultList();

} finally {

em.close();

}

}

public Writer findWriter(Integer id) {

EntityManager em = getEntityManager();

try {

return em.find(Writer.class, id);

} finally {

em.close();

}

}

public int getWriterCount() {

EntityManager em = getEntityManager();

try {

CriteriaQuery cq = em.getCriteriaBuilder().createQuery();

Root<Writer> rt = cq.from(Writer.class);

cq.select(em.getCriteriaBuilder().count(rt));

Query q = em.createQuery(cq);

return ((Long) q.getSingleResult()).intValue();

} finally {

em.close();

}

}

}

相关阅读:
Top