From 68a999f4232290701c631db3fb824bc89e7f5115 Mon Sep 17 00:00:00 2001 From: George Gastaldi Date: Tue, 4 Mar 2014 18:41:40 -0300 Subject: [PATCH] Scaffolded Addon entity --- .../java/org/jboss/forge/view/AddonBean.java | 319 ++++++++++++++++++ .../java/org/jboss/forge/view/ViewUtils.java | 86 +++++ .../org/jboss/forge/website/model/Addon.java | 97 ++++++ src/main/resources/META-INF/persistence.xml | 8 + .../WEB-INF/classes/META-INF/forge.taglib.xml | 22 ++ src/main/webapp/WEB-INF/web.xml | 39 ++- src/main/webapp/addon/create.xhtml | 70 ++++ src/main/webapp/addon/search.xhtml | 79 +++++ src/main/webapp/addon/view.xhtml | 43 +++ .../resources/scaffold/pageTemplate.xhtml | 22 +- 10 files changed, 757 insertions(+), 28 deletions(-) create mode 100644 src/main/java/org/jboss/forge/view/AddonBean.java create mode 100644 src/main/java/org/jboss/forge/view/ViewUtils.java create mode 100644 src/main/java/org/jboss/forge/website/model/Addon.java create mode 100644 src/main/resources/META-INF/persistence.xml create mode 100644 src/main/webapp/WEB-INF/classes/META-INF/forge.taglib.xml create mode 100644 src/main/webapp/addon/create.xhtml create mode 100644 src/main/webapp/addon/search.xhtml create mode 100644 src/main/webapp/addon/view.xhtml diff --git a/src/main/java/org/jboss/forge/view/AddonBean.java b/src/main/java/org/jboss/forge/view/AddonBean.java new file mode 100644 index 0000000..956fadf --- /dev/null +++ b/src/main/java/org/jboss/forge/view/AddonBean.java @@ -0,0 +1,319 @@ +package org.jboss.forge.view; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import javax.annotation.Resource; +import javax.ejb.SessionContext; +import javax.ejb.Stateful; +import javax.enterprise.context.Conversation; +import javax.enterprise.context.ConversationScoped; +import javax.faces.application.FacesMessage; +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; +import javax.faces.convert.Converter; +import javax.inject.Inject; +import javax.inject.Named; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceContextType; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import org.jboss.forge.website.model.Addon; + +/** + * Backing bean for Addon entities. + *

+ * This class provides CRUD functionality for all Addon entities. It focuses + * purely on Java EE 6 standards (e.g. @ConversationScoped for + * state management, PersistenceContext for persistence, + * CriteriaBuilder for searches) rather than introducing a CRUD framework or + * custom base class. + */ + +@Named +@Stateful +@ConversationScoped +public class AddonBean implements Serializable +{ + + private static final long serialVersionUID = 1L; + + /* + * Support creating and retrieving Addon entities + */ + + private Long id; + + public Long getId() + { + return this.id; + } + + public void setId(Long id) + { + this.id = id; + } + + private Addon addon; + + public Addon getAddon() + { + return this.addon; + } + + @Inject + private Conversation conversation; + + @PersistenceContext(unitName = "website-persistence-unit", type = PersistenceContextType.EXTENDED) + private EntityManager entityManager; + + public String create() + { + + this.conversation.begin(); + return "create?faces-redirect=true"; + } + + public void retrieve() + { + + if (FacesContext.getCurrentInstance().isPostback()) + { + return; + } + + if (this.conversation.isTransient()) + { + this.conversation.begin(); + } + + if (this.id == null) + { + this.addon = this.example; + } + else + { + this.addon = findById(getId()); + } + } + + public Addon findById(Long id) + { + + return this.entityManager.find(Addon.class, id); + } + + /* + * Support updating and deleting Addon entities + */ + + public String update() + { + this.conversation.end(); + + try + { + if (this.id == null) + { + this.entityManager.persist(this.addon); + return "search?faces-redirect=true"; + } + else + { + this.entityManager.merge(this.addon); + return "view?faces-redirect=true&id=" + this.addon.getId(); + } + } + catch (Exception e) + { + FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(e.getMessage())); + return null; + } + } + + public String delete() + { + this.conversation.end(); + + try + { + Addon deletableEntity = findById(getId()); + + this.entityManager.remove(deletableEntity); + this.entityManager.flush(); + return "search?faces-redirect=true"; + } + catch (Exception e) + { + FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(e.getMessage())); + return null; + } + } + + /* + * Support searching Addon entities with pagination + */ + + private int page; + private long count; + private List pageItems; + + private Addon example = new Addon(); + + public int getPage() + { + return this.page; + } + + public void setPage(int page) + { + this.page = page; + } + + public int getPageSize() + { + return 10; + } + + public Addon getExample() + { + return this.example; + } + + public void setExample(Addon example) + { + this.example = example; + } + + public void search() + { + this.page = 0; + } + + public void paginate() + { + + CriteriaBuilder builder = this.entityManager.getCriteriaBuilder(); + + // Populate this.count + + CriteriaQuery countCriteria = builder.createQuery(Long.class); + Root root = countCriteria.from(Addon.class); + countCriteria = countCriteria.select(builder.count(root)).where( + getSearchPredicates(root)); + this.count = this.entityManager.createQuery(countCriteria) + .getSingleResult(); + + // Populate this.pageItems + + CriteriaQuery criteria = builder.createQuery(Addon.class); + root = criteria.from(Addon.class); + TypedQuery query = this.entityManager.createQuery(criteria + .select(root).where(getSearchPredicates(root))); + query.setFirstResult(this.page * getPageSize()).setMaxResults( + getPageSize()); + this.pageItems = query.getResultList(); + } + + private Predicate[] getSearchPredicates(Root root) + { + + CriteriaBuilder builder = this.entityManager.getCriteriaBuilder(); + List predicatesList = new ArrayList(); + + String groupId = this.example.getGroupId(); + if (groupId != null && !"".equals(groupId)) + { + predicatesList.add(builder.like(builder.lower(root. get("groupId")), '%' + groupId.toLowerCase() + '%')); + } + String artifactId = this.example.getArtifactId(); + if (artifactId != null && !"".equals(artifactId)) + { + predicatesList.add(builder.like(builder.lower(root. get("artifactId")), '%' + artifactId.toLowerCase() + '%')); + } + + return predicatesList.toArray(new Predicate[predicatesList.size()]); + } + + public List getPageItems() + { + return this.pageItems; + } + + public long getCount() + { + return this.count; + } + + /* + * Support listing and POSTing back Addon entities (e.g. from inside an + * HtmlSelectOneMenu) + */ + + public List getAll() + { + + CriteriaQuery criteria = this.entityManager + .getCriteriaBuilder().createQuery(Addon.class); + return this.entityManager.createQuery( + criteria.select(criteria.from(Addon.class))).getResultList(); + } + + @Resource + private SessionContext sessionContext; + + public Converter getConverter() + { + + final AddonBean ejbProxy = this.sessionContext.getBusinessObject(AddonBean.class); + + return new Converter() + { + + @Override + public Object getAsObject(FacesContext context, + UIComponent component, String value) + { + + return ejbProxy.findById(Long.valueOf(value)); + } + + @Override + public String getAsString(FacesContext context, + UIComponent component, Object value) + { + + if (value == null) + { + return ""; + } + + return String.valueOf(((Addon) value).getId()); + } + }; + } + + /* + * Support adding children to bidirectional, one-to-many tables + */ + + private Addon add = new Addon(); + + public Addon getAdd() + { + return this.add; + } + + public Addon getAdded() + { + Addon added = this.add; + this.add = new Addon(); + return added; + } +} \ No newline at end of file diff --git a/src/main/java/org/jboss/forge/view/ViewUtils.java b/src/main/java/org/jboss/forge/view/ViewUtils.java new file mode 100644 index 0000000..b31311f --- /dev/null +++ b/src/main/java/org/jboss/forge/view/ViewUtils.java @@ -0,0 +1,86 @@ +package org.jboss.forge.view; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import javax.persistence.Id; + +/** + * Utilities for working with Java Server Faces views. + */ + +public final class ViewUtils +{ + + public static List asList(Collection collection) + { + + if (collection == null) + { + return null; + } + + return new ArrayList(collection); + } + + public static String display(Object object) + { + + if (object == null) + { + return null; + } + + try + { + // Invoke toString if declared in the class. If not found, the NoSuchMethodException is caught and handled + object.getClass().getDeclaredMethod("toString"); + return object.toString(); + } + catch (NoSuchMethodException noMethodEx) + { + try + { + for (Field field : object.getClass().getDeclaredFields()) + { + // Find the primary key field and display it + if (field.getAnnotation(Id.class) != null) + { + // Find a matching getter and invoke it to display the key + for (Method method : object.getClass().getDeclaredMethods()) + { + if (method.equals(new PropertyDescriptor(field.getName(), object.getClass()).getReadMethod())) + { + return method.invoke(object).toString(); + } + } + } + } + for (Method method : object.getClass().getDeclaredMethods()) + { + // Find the primary key as a property instead of a field, and display it + if (method.getAnnotation(Id.class) != null) + { + return method.invoke(object).toString(); + } + } + } + catch (Exception ex) + { + // Unlikely, but abort and stop view generation if any exception is thrown + throw new RuntimeException(ex); + } + } + + return null; + } + + private ViewUtils() + { + + // Can never be called + } +} diff --git a/src/main/java/org/jboss/forge/website/model/Addon.java b/src/main/java/org/jboss/forge/website/model/Addon.java new file mode 100644 index 0000000..a9277de --- /dev/null +++ b/src/main/java/org/jboss/forge/website/model/Addon.java @@ -0,0 +1,97 @@ +package org.jboss.forge.website.model; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Version; +import java.lang.Override; + +@Entity +public class Addon implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "id", updatable = false, nullable = false) + private Long id; + + @Version + @Column(name = "version") + private int version; + + @Column + private String groupId; + + @Column + private String artifactId; + + public Long getId() { + return this.id; + } + + public void setId(final Long id) { + this.id = id; + } + + public int getVersion() { + return this.version; + } + + public void setVersion(final int version) { + this.version = version; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof Addon)) { + return false; + } + Addon other = (Addon) obj; + if (id != null) { + if (!id.equals(other.id)) { + return false; + } + } + return true; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((id == null) ? 0 : id.hashCode()); + return result; + } + + public String getGroupId() { + return this.groupId; + } + + public void setGroupId(final String groupId) { + this.groupId = groupId; + } + + public String getArtifactId() { + return this.artifactId; + } + + public void setArtifactId(final String artifactId) { + this.artifactId = artifactId; + } + + @Override + public String toString() { + String result = getClass().getSimpleName() + " "; + if (groupId != null && !groupId.trim().isEmpty()) + result += "groupId: " + groupId; + if (artifactId != null && !artifactId.trim().isEmpty()) + result += ", artifactId: " + artifactId; + return result; + } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000..4fa6b17 --- /dev/null +++ b/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,8 @@ + + + + Forge Persistence Unit + java:jboss/datasources/PostgreSQLDS + false + + diff --git a/src/main/webapp/WEB-INF/classes/META-INF/forge.taglib.xml b/src/main/webapp/WEB-INF/classes/META-INF/forge.taglib.xml new file mode 100644 index 0000000..ed44fb7 --- /dev/null +++ b/src/main/webapp/WEB-INF/classes/META-INF/forge.taglib.xml @@ -0,0 +1,22 @@ + + + + http://jboss.org/forge/view + + + asList + org.jboss.forge.view.ViewUtils + + java.util.List asList(java.util.Collection) + + + + + display + org.jboss.forge.view.ViewUtils + + java.lang.String display(java.lang.Object) + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 0a9d908..e41bea0 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -1,19 +1,24 @@ - - website - - 30 - - - 404 - /faces/error.xhtml - - - 500 - /faces/error.xhtml - - - javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE - true - + + website + + 30 + + + 404 + /faces/error.xhtml + + + 500 + /faces/error.xhtml + + + javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE + true + + + index.html + diff --git a/src/main/webapp/addon/create.xhtml b/src/main/webapp/addon/create.xhtml new file mode 100644 index 0000000..c1ced7a --- /dev/null +++ b/src/main/webapp/addon/create.xhtml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + Addon + + + + + + Edit existing Addon + + + Create a new Addon + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/src/main/webapp/addon/search.xhtml b/src/main/webapp/addon/search.xhtml new file mode 100644 index 0000000..51b1f39 --- /dev/null +++ b/src/main/webapp/addon/search.xhtml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + Addon + + + + Search Addon entities + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/addon/view.xhtml b/src/main/webapp/addon/view.xhtml new file mode 100644 index 0000000..8d3fd4d --- /dev/null +++ b/src/main/webapp/addon/view.xhtml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + Addon + + + + View existing Addon + + + + + + + + + + + + + + +
+ + + +
+
+ +
\ No newline at end of file diff --git a/src/main/webapp/resources/scaffold/pageTemplate.xhtml b/src/main/webapp/resources/scaffold/pageTemplate.xhtml index 7601f9d..78a4c4a 100644 --- a/src/main/webapp/resources/scaffold/pageTemplate.xhtml +++ b/src/main/webapp/resources/scaffold/pageTemplate.xhtml @@ -5,21 +5,20 @@ #{empty pageTitle ? 'Page Title' : pageTitle} - + +