Commits

vmorsiani committed 85ac9a1

TicketMessage persistence base support
few improvements from web frontend

  • Participants
  • Parent commits 9abf91c

Comments (0)

Files changed (18)

File jticketing-core/src/main/java/org/wanna/jticketing/persistence/dao/TicketMessageDao.java

+package org.wanna.jticketing.persistence.dao;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.wanna.jticketing.persistence.entity.TicketMessageEntity;
+
+public interface TicketMessageDao extends JpaRepository<TicketMessageEntity,Long>, JpaSpecificationExecutor<TicketMessageEntity> {
+}

File jticketing-core/src/main/java/org/wanna/jticketing/persistence/dao/specification/ticket/TicketMessageSpecifications.java

+package org.wanna.jticketing.persistence.dao.specification.ticket;
+
+import org.springframework.data.jpa.domain.Specification;
+import org.wanna.jticketing.persistence.entity.TicketEntity;
+import org.wanna.jticketing.persistence.entity.TicketMessageEntity;
+import org.wanna.jticketing.persistence.entity.TicketMessageEntity_;
+
+import javax.persistence.criteria.*;
+
+public class TicketMessageSpecifications {
+    public static Specification<TicketMessageEntity> fromTicket(final TicketEntity ticket) {
+        return new Specification<TicketMessageEntity>() {
+            @Override
+            public Predicate toPredicate(Root<TicketMessageEntity> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
+                return builder.equal(root.get(TicketMessageEntity_.ticket),ticket);
+            }
+        };
+    }
+}

File jticketing-core/src/main/java/org/wanna/jticketing/persistence/entity/TicketEntity.java

 import org.apache.commons.lang.builder.ToStringBuilder;
 
 import javax.persistence.*;
+import java.util.HashSet;
 import java.util.Set;
 
 @Entity
     private UserEntity reporter,account;
     @ManyToOne
     private UserEntity assignee;
-    @ManyToMany
-    private Set<TicketMessage> messages;
+    @OneToMany(mappedBy = "ticket")
+    private Set<TicketMessageEntity> messages = new HashSet<TicketMessageEntity>();
     @Column(nullable = false)
     private String subject;
     @Lob
         this.description = description;
     }
 
-    public Set<TicketMessage> getMessages() {
-        return messages;
-    }
-
-    public void setMessages(Set<TicketMessage> messages) {
-        this.messages = messages;
-    }
-
     public TicketCategoryEntity getCategory() {
         return category;
     }
                 append("reference", reference).
                 toString();
     }
+
+    public Set<TicketMessageEntity> getMessages() {
+        return messages;
+    }
+
+    public void setMessages(Set<TicketMessageEntity> messages) {
+        this.messages = messages;
+    }
 }

File jticketing-core/src/main/java/org/wanna/jticketing/persistence/entity/TicketMessage.java

-package org.wanna.jticketing.persistence.entity;
-
-import javax.persistence.*;
-
-@Entity
-@Table(name="messages")
-public class TicketMessage implements BaseEntity<Long>{
-    @Id
-    @GeneratedValue(strategy = GenerationType.AUTO)
-    private Long id;
-    @Lob
-    private String text;
-    @ManyToOne
-    private UserEntity author;
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public String getText() {
-        return text;
-    }
-
-    public void setText(String text) {
-        this.text = text;
-    }
-
-    public UserEntity getAuthor() {
-        return author;
-    }
-
-    public void setAuthor(UserEntity author) {
-        this.author = author;
-    }
-
-
-}

File jticketing-core/src/main/java/org/wanna/jticketing/persistence/entity/TicketMessageEntity.java

+package org.wanna.jticketing.persistence.entity;
+
+import javax.persistence.*;
+
+@Entity
+@Table(name="messages")
+public class TicketMessageEntity implements BaseEntity<Long>{
+    @Id
+    @GeneratedValue(strategy = GenerationType.AUTO)
+    private Long id;
+    @Lob
+    private String text;
+    @ManyToOne
+    private UserEntity author;
+
+    @ManyToOne
+    private  TicketEntity ticket;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+
+    public UserEntity getAuthor() {
+        return author;
+    }
+
+    public void setAuthor(UserEntity author) {
+        this.author = author;
+    }
+    public TicketEntity getTicket() {
+        return ticket;
+    }
+
+    public void setTicket(TicketEntity ticket) {
+        this.ticket = ticket;
+    }
+}

File jticketing-core/src/main/java/org/wanna/jticketing/persistence/service/ticket/TicketService.java

 
 import org.wanna.jticketing.persistence.entity.TicketCategoryEntity;
 import org.wanna.jticketing.persistence.entity.TicketEntity;
+import org.wanna.jticketing.persistence.entity.TicketMessageEntity;
 import org.wanna.jticketing.persistence.entity.UserEntity;
 
 import java.util.List;
+import java.util.Set;
 
 public interface TicketService {
     List<TicketEntity> findAll();
     TicketEntity createTicket(TicketEntity ticket);
     TicketEntity findByReference(String reference);
     List<TicketCategoryEntity> getAvailableTicketCategory(UserEntity userEntity);
+    List<TicketMessageEntity> getMessages(TicketEntity ticket, UserEntity user);
+    void addMessage(TicketMessageEntity message, TicketEntity ticket);
 }

File jticketing-core/src/main/java/org/wanna/jticketing/persistence/service/ticket/TicketServiceImpl.java

 import org.springframework.transaction.annotation.Transactional;
 import org.wanna.jticketing.persistence.dao.TicketCategoryDao;
 import org.wanna.jticketing.persistence.dao.TicketDao;
+import org.wanna.jticketing.persistence.dao.TicketMessageDao;
+import org.wanna.jticketing.persistence.dao.specification.ticket.TicketMessageSpecifications;
 import org.wanna.jticketing.persistence.dao.specification.ticket.TicketSpecifications;
-import org.wanna.jticketing.persistence.entity.TicketCategoryEntity;
-import org.wanna.jticketing.persistence.entity.TicketEntity;
-import org.wanna.jticketing.persistence.entity.TicketStatusEntity;
-import org.wanna.jticketing.persistence.entity.UserEntity;
+import org.wanna.jticketing.persistence.entity.*;
 import org.wanna.jticketing.persistence.service.ticket.reference.DefaultReferenceGenerator;
 import org.wanna.jticketing.persistence.service.ticket.reference.TicketReferenceGenerator;
 
 import javax.annotation.Resource;
 import java.util.List;
+import java.util.Set;
 
 @Service
 public class TicketServiceImpl implements TicketService{
     TicketDao ticketDao;
     @Resource
     TicketCategoryDao ticketCategoryDao;
+    @Resource
+    TicketMessageDao ticketMessageDao;
 
     TicketReferenceGenerator ticketReferenceGenerator = new DefaultReferenceGenerator();
 
         return ticketCategoryDao.findAll();
     }
 
+    @Override
+    public List<TicketMessageEntity> getMessages(TicketEntity ticket, UserEntity user) {
+        return ticketMessageDao.findAll(TicketMessageSpecifications.fromTicket(ticket));
+    }
 
+    @Override
+    public void addMessage(TicketMessageEntity message, TicketEntity ticket) {
+        ticket.getMessages().add(message);
+        ticketDao.save(ticket);
+    }
 }

File jticketing-core/src/test/java/org/wanna/jticketing/persistence/service/ticket/TicketServiceTest.java

 import org.junit.Test;
 import org.wanna.jticketing.persistence.entity.TicketCategoryEntity;
 import org.wanna.jticketing.persistence.entity.TicketEntity;
+import org.wanna.jticketing.persistence.entity.TicketMessageEntity;
 import org.wanna.jticketing.persistence.entity.UserEntity;
 import org.wanna.jticketing.persistence.service.AbstractServiceTestCase;
 
         Assert.assertNotNull(ticket.getReference());
         LOG.debug(ticket.getReference());
     }
+
+    @Test
+    public void addMessage(){
+        ticket = ticketService.createTicket(ticket);
+        TicketMessageEntity message = new TicketMessageEntity();
+        message.setAuthor(reporter);
+        message.setText("This is a message from unit test");
+        ticketService.addMessage(message,ticket);
+    }
 }

File jticketing-webapp/src/main/java/org/wanna/jticketing/web/beans/ticket/QuickSearchBean.java

 import javax.faces.bean.ManagedBean;
 import javax.faces.bean.ManagedProperty;
 import javax.faces.bean.RequestScoped;
+import javax.faces.context.FacesContext;
 import javax.faces.event.AjaxBehaviorEvent;
 
 @ManagedBean

File jticketing-webapp/src/main/java/org/wanna/jticketing/web/beans/ticket/TicketEditorBean.java

 
 import org.wanna.jticketing.persistence.entity.TicketCategoryEntity;
 import org.wanna.jticketing.persistence.entity.TicketEntity;
+import org.wanna.jticketing.persistence.entity.TicketMessageEntity;
 import org.wanna.jticketing.persistence.entity.UserEntity;
 import org.wanna.jticketing.persistence.service.ticket.TicketService;
 import org.wanna.jticketing.web.beans.AbstractUIBean;
     public List<TicketCategoryEntity> getCategories(){
         return ticketService.getAvailableTicketCategory(super.getCurrentUser());
     }
+
+    public List<TicketMessageEntity> getMessages(){
+        return ticketService.getMessages(ticket, super.getCurrentUser());
+    }
+
 }

File jticketing-webapp/src/main/java/org/wanna/jticketing/web/faces/converter/entity/AbstractEntityConverter.java

 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 
-public abstract class AbstractEntityConverter implements Converter {
+public abstract class AbstractEntityConverter extends AbstractSpringAwareConverter {
     private Class<? extends BaseEntity> clazz;
     public final Log LOG = LogFactory.getLog(this.getClass());
 
     }
 
     private EntityManager getEntityManager(FacesContext context){
-        EntityManagerFactory factory = (EntityManagerFactory)
-                FacesContextUtils.getWebApplicationContext(context).getBean("entityManagerFactory");
+        EntityManagerFactory factory = (EntityManagerFactory)super.getBean(context,"entityManagerFactory");
         return factory.createEntityManager();
     }
 }

File jticketing-webapp/src/main/java/org/wanna/jticketing/web/faces/converter/entity/AbstractSpringAwareConverter.java

+package org.wanna.jticketing.web.faces.converter.entity;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.web.jsf.FacesContextUtils;
+
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+
+public abstract class AbstractSpringAwareConverter implements Converter {
+    public final Log LOG = LogFactory.getLog(this.getClass());
+
+    public Object getBean(FacesContext context, String bean){
+        return FacesContextUtils.getWebApplicationContext(context).getBean(bean);
+    }
+}

File jticketing-webapp/src/main/java/org/wanna/jticketing/web/faces/converter/entity/TicketReferenceConverter.java

+package org.wanna.jticketing.web.faces.converter.entity;
+
+import org.wanna.jticketing.persistence.entity.BaseEntity;
+import org.wanna.jticketing.persistence.entity.TicketEntity;
+import org.wanna.jticketing.persistence.service.ticket.TicketService;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.FacesConverter;
+
+@FacesConverter("ticketReferenceConverter")
+public class TicketReferenceConverter extends AbstractSpringAwareConverter{
+
+    @Override
+    public Object getAsObject(FacesContext context, UIComponent component, String value) {
+        LOG.trace("converting ticket for reference "+value);
+        return getTicketService(context).findByReference(value);
+    }
+
+    @Override
+    public String getAsString(FacesContext context, UIComponent component, Object value) {
+        if(value != null && value instanceof TicketEntity) {
+            TicketEntity ticket = (TicketEntity)value;
+            return ticket.getReference();
+        }else{
+            return null;
+        }
+    }
+
+    private TicketService getTicketService(FacesContext context){
+        return (TicketService)super.getBean(context,"ticketServiceImpl");
+    }
+}

File jticketing-webapp/src/main/webapp/includes/navigation.xhtml

         <p:menubar>
             <p:menuitem value="#{message['navigation.dashboard']}" url="/secured/dashboard/view.html"/>
             <p:submenu label="#{message['navigation.ticket']}">
-                <p:menuitem value="#{message['navigation.ticket.search']}" url="/secured/ticket/view.html"/>
+                <p:menuitem value="#{message['navigation.ticket.search']}" url="/secured/ticket/search.html"/>
                 <p:menuitem value="#{message['navigation.ticket.create']}" url="/secured/ticket/edit.html"/>
             </p:submenu>
 

File jticketing-webapp/src/main/webapp/resources/components/tickets/editor.xhtml

                              type="org.wanna.jticketing.persistence.entity.TicketEntity"
 
                              required="true"/>
+        <composite:attribute name="edit" type="java.lang.Boolean" default="false"/>
     </composite:interface>
 
     <composite:implementation>
         <h:form>
-
             <p:panelGrid columns="2">
                 <p:outputLabel value="#{message['ticket.subject']}" for="subject"/>
-                <p:inputText id="subject"  value="#{cc.attrs.value.subject}"/>
+                <h:outputText value="#{cc.attrs.value.subject}" rendered="#{not cc.attrs.edit}"/>
+                <p:inputText id="subject"  value="#{cc.attrs.value.subject}" rendered="#{cc.attrs.edit}"/>
 
                 <p:outputLabel value="#{message['ticket.description']}" for="description"/>
-                <p:inputTextarea id="description"  value="#{cc.attrs.value.description}"/>
+                <h:outputText value="#{cc.attrs.value.description}" rendered="#{not cc.attrs.edit}"/>
+                <p:inputTextarea id="description"  value="#{cc.attrs.value.description}" rendered="#{cc.attrs.edit}"/>
 
                 <p:outputLabel value="#{message['ticket.category']}" for="category"/>
-                <p:selectOneMenu id="category" value="#{cc.attrs.value.category}">
+                <h:outputText value="#{cc.attrs.value.category.name}" rendered="#{not cc.attrs.edit}"/>
+                <p:selectOneMenu id="category" value="#{cc.attrs.value.category}"
+                        rendered="#{cc.attrs.edit}">
                     <f:selectItems value="#{ticketEditorBean.categories}"
                                    var="category"
                                    itemLabel="#{category.name}"

File jticketing-webapp/src/main/webapp/secured/ticket/edit.xhtml

 <h:body>
     <ui:composition template="/WEB-INF/templates/layout.xhtml">
         <ui:define name="content">
-            <ticket:editor value="#{ticketEditorBean.ticket}"/>
+            <ticket:editor value="#{ticketEditorBean.ticket}" edit="true"/>
         </ui:define>
     </ui:composition>
 </h:body>

File jticketing-webapp/src/main/webapp/secured/ticket/search.xhtml

+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE html
+        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"
+      xmlns:jtt="http://java.sun.com/jsf/composite/components/tickets" xmlns:f="http://java.sun.com/jsf/core">
+
+<h:head>
+    <title>Simple JSF Facelets page</title>
+</h:head>
+
+<h:body>
+    <ui:composition template="/WEB-INF/templates/layout.xhtml">
+        <ui:define name="content">
+            <jtt:ticketTable tickets="#{ticketViewBean.tickets}"/>
+        </ui:define>
+    </ui:composition>
+</h:body>
+
+</html>

File jticketing-webapp/src/main/webapp/secured/ticket/view.xhtml

 
 <html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"
-      xmlns:jtt="http://java.sun.com/jsf/composite/components/tickets">
+      xmlns:jtt="http://java.sun.com/jsf/composite/components/tickets" xmlns:f="http://java.sun.com/jsf/core"
+      xmlns:p="http://java.sun.com/jsf/html">
 
 <h:head>
     <title>Simple JSF Facelets page</title>
 
 <h:body>
     <ui:composition template="/WEB-INF/templates/layout.xhtml">
+        <f:metadata>
+            <f:viewParam name="ref" value="#{ticketEditorBean.ticket}"
+                         required="true"
+                         requiredMessage="Ticket Reference is required"
+                         converter="ticketReferenceConverter">
+            </f:viewParam>
+        </f:metadata>
+
         <ui:define name="content">
-            <jtt:ticketTable tickets="#{ticketViewBean.tickets}"/>
+            <!-- Ticket Summary -->
+            <h:form>
+                <h:outputText value="This is the ticket viewer"/>
+                <jtt:editor value="#{ticketEditorBean.ticket}" edit="false"/>
+            </h:form>
+
+            <!-- Ticket Messages -->
+            <p:dataTable value="#{ticketEditorBean.messages}" var="message">
+                <h:column>
+                    <h:outputText value="#{message.text}"/>
+                </h:column>
+            </p:dataTable>
         </ui:define>
     </ui:composition>
 </h:body>