From b9209f6413cb6985c0089f9677f4db9b52ca1395 Mon Sep 17 00:00:00 2001
From: Ravi Srinivasan <rsriniva@redhat.com>
Date: Tue, 11 Sep 2018 07:41:08 +0200
Subject: [PATCH] Chap 6 lab code

---
 solutions/hello-rest/src/main/java/com/redhat/training/messaging/QueueListener.java |   59 ++
 solutions/hello-rest/src/main/java/com/redhat/training/servlet/PingServlet.java     |   60 +++
 labs/hello-rest/src/main/java/com/redhat/training/ui/Hello.java                     |   51 ++
 solutions/hello-rest/pom.xml                                                        |  148 +++++++
 labs/hello-rest/src/main/java/com/redhat/training/rest/PersonService.java           |  154 +++++++
 solutions/hello-rest/src/main/java/com/redhat/training/rest/PersonService.java      |  144 +++++++
 labs/hello-rest/.gitignore                                                          |    5 
 labs/hello-rest/src/main/java/com/redhat/training/servlet/PingServlet.java          |   60 +++
 labs/hello-rest/src/main/resources/META-INF/persistence.xml                         |   15 
 solutions/hello-rest/src/main/java/com/redhat/training/model/Person.java            |   62 +++
 labs/hello-rest/README.md                                                           |   12 
 labs/hello-rest/src/main/java/com/redhat/training/messaging/JMSUtil.java            |   28 +
 labs/hello-rest/src/main/java/com/redhat/training/messaging/QueueListener.java      |   59 ++
 solutions/hello-rest/.gitignore                                                     |    5 
 solutions/hello-rest/src/main/java/com/redhat/training/ui/Hello.java                |   51 ++
 solutions/hello-rest/README.md                                                      |   12 
 solutions/hello-rest/src/main/java/com/redhat/training/rest/Service.java            |    9 
 labs/hello-rest/src/main/java/com/redhat/training/model/Person.java                 |   62 +++
 solutions/hello-rest/src/main/resources/META-INF/persistence.xml                    |   15 
 labs/hello-rest/pom.xml                                                             |  148 +++++++
 solutions/hello-rest/src/main/java/com/redhat/training/messaging/JMSUtil.java       |   28 +
 21 files changed, 1,187 insertions(+), 0 deletions(-)

diff --git a/labs/hello-rest/.gitignore b/labs/hello-rest/.gitignore
new file mode 100644
index 0000000..d0152b8
--- /dev/null
+++ b/labs/hello-rest/.gitignore
@@ -0,0 +1,5 @@
+.classpath
+.project
+.tern-project
+.settings
+target
diff --git a/labs/hello-rest/README.md b/labs/hello-rest/README.md
new file mode 100644
index 0000000..56cae66
--- /dev/null
+++ b/labs/hello-rest/README.md
@@ -0,0 +1,12 @@
+# JB125 Java EE 7 Hello World web App
+
+##This app is composed of the following architecture:
+
+* Maven Project - builds a WAR
+* Using JSF 2.2 for web interface, HTML5 facelets page, JSF backing beans, CDI scopes on beans, @Named
+* Statelss EJB for services - uses JPA entity beans - exposes appropriate method as REST API using JAX-RS annotations
+* JAX-RS Application class
+* JPA entity bean to store names - uses H2 in-memory database
+* Use EJB Singleton to lookup messaging connection and queue destination and inject into stateless EJB - lookup should only occur once on startup
+* Servlet that returns "OK" - this is a health check - path should be [context]/health
+* H2 (embedded in-memory DB) backend
diff --git a/labs/hello-rest/pom.xml b/labs/hello-rest/pom.xml
new file mode 100644
index 0000000..50d0517
--- /dev/null
+++ b/labs/hello-rest/pom.xml
@@ -0,0 +1,148 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>hello-rest</artifactId>
+  <packaging>war</packaging>
+  <name>Hello World REST app Project</name>
+  <description>This is the hello-rest project</description>
+  <parent>
+  	<groupId>com.redhat.training</groupId>
+  	<artifactId>parent-pom</artifactId>
+  	<version>1.0</version>
+  	<relativePath>../pom.xml</relativePath>
+  </parent>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+    <dependencies>
+
+        <!-- First declare the APIs we depend on and need for compilation. All
+            of them are provided by JBoss EAP -->
+
+        <!-- Import the CDI API, we use provided scope as the API is included in
+            JBoss EAP -->
+        <dependency>
+            <groupId>javax.enterprise</groupId>
+            <artifactId>cdi-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Import the Common Annotations API (JSR-250), we use provided scope
+            as the API is included in JBoss EAP -->
+        <dependency>
+            <groupId>org.jboss.spec.javax.annotation</groupId>
+            <artifactId>jboss-annotations-api_1.2_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Import the JAX-RS API, we use provided scope as the API is included
+            in JBoss EAP -->
+        <dependency>
+            <groupId>org.jboss.spec.javax.ws.rs</groupId>
+            <artifactId>jboss-jaxrs-api_2.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Import the JPA API, we use provided scope as the API is included in
+            JBoss EAP -->
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.1-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Import the EJB API, we use provided scope as the API is included in
+            JBoss EAP -->
+        <dependency>
+            <groupId>org.jboss.spec.javax.ejb</groupId>
+            <artifactId>jboss-ejb-api_3.2_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jboss.spec.javax.jms</groupId>
+            <artifactId>jboss-jms-api_2.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Bean Validation Implementation -->
+        <!-- Provides portable constraints such as @Email -->
+        <!-- Hibernate Validator is shipped in JBoss EAP -->
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-validator</artifactId>
+            <scope>provided</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+            <dependency>
+                <groupId>org.hibernate</groupId>
+                <artifactId>hibernate-search-orm</artifactId>
+                 <scope>provided</scope>
+            </dependency>
+
+             <dependency>
+                <groupId>org.hibernate</groupId>
+                <artifactId>hibernate-entitymanager</artifactId>
+                 <scope>provided</scope>
+            </dependency>
+
+        <!-- Import the JSF API, we use provided scope as the API is included in
+            JBoss EAP -->
+        <dependency>
+            <groupId>org.jboss.spec.javax.faces</groupId>
+            <artifactId>jboss-jsf-api_2.2_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+	  		<groupId>org.jboss.spec.javax.servlet</groupId>
+	  		<artifactId>jboss-servlet-api_3.1_spec</artifactId>
+			<scope>provided</scope>
+	  	</dependency>
+
+        <!-- Annotation processor to generate the JPA metamodel classes for
+            typesafe criteria queries -->
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-jpamodelgen</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Annotation processor that raising compilation errors whenever constraint
+            annotations are incorrectly used. -->
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-validator-annotation-processor</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <finalName>hello-rest</finalName>
+        <plugins>
+            <plugin>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>${version.war.plugin}</version>
+                <extensions>false</extensions>
+                <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                    <archive>
+                        <manifestEntries>
+                            <Dependencies>com.google.guava,org.slf4j
+                            </Dependencies>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/labs/hello-rest/src/main/java/com/redhat/training/messaging/JMSUtil.java b/labs/hello-rest/src/main/java/com/redhat/training/messaging/JMSUtil.java
new file mode 100644
index 0000000..14c1421
--- /dev/null
+++ b/labs/hello-rest/src/main/java/com/redhat/training/messaging/JMSUtil.java
@@ -0,0 +1,28 @@
+package com.redhat.training.messaging;
+
+import javax.ejb.Singleton;
+import javax.ejb.Startup;
+import javax.annotation.Resource;
+import javax.jms.Queue;
+import javax.jms.JMSContext;
+import javax.inject.Inject;
+
+@Startup
+@Singleton
+public class JMSUtil {
+
+    @Resource(mappedName = "java:jboss/jms/queue/helloWorldQueue")
+    private Queue helloWorldQueue;
+
+    @Inject
+    JMSContext context;
+
+    public void sendMessage(String msg) {
+        try {
+            context.createProducer().send(helloWorldQueue, msg);
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/labs/hello-rest/src/main/java/com/redhat/training/messaging/QueueListener.java b/labs/hello-rest/src/main/java/com/redhat/training/messaging/QueueListener.java
new file mode 100644
index 0000000..169c4be
--- /dev/null
+++ b/labs/hello-rest/src/main/java/com/redhat/training/messaging/QueueListener.java
@@ -0,0 +1,59 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.redhat.training.messaging;
+
+import org.jboss.logging.Logger;
+import javax.ejb.ActivationConfigProperty;
+import javax.ejb.MessageDriven;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.TextMessage;
+
+/**
+ * <p>
+ * A simple Message Driven Bean that asynchronously receives and processes the messages that are sent to the queue.
+ * </p>
+ *
+ * @author Serge Pagop (spagop@redhat.com)
+ *
+ */
+@MessageDriven(name = "QueueListener", activationConfig = {
+    @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "queue/helloWorldQueue"),
+    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
+    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })
+public class QueueListener implements MessageListener {
+
+    private final static Logger LOGGER = Logger.getLogger(QueueListener.class.getName());
+
+    /**
+     * @see MessageListener#onMessage(Message)
+     */
+    public void onMessage(Message rcvMessage) {
+        TextMessage msg = null;
+        try {
+            if (rcvMessage instanceof TextMessage) {
+                msg = (TextMessage) rcvMessage;
+                LOGGER.info("Received Message from helloWorldQueue ===> " + msg.getText());
+            } else {
+                LOGGER.warn("Message of wrong type: " + rcvMessage.getClass().getName());
+            }
+        } catch (JMSException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/labs/hello-rest/src/main/java/com/redhat/training/model/Person.java b/labs/hello-rest/src/main/java/com/redhat/training/model/Person.java
new file mode 100644
index 0000000..163204a
--- /dev/null
+++ b/labs/hello-rest/src/main/java/com/redhat/training/model/Person.java
@@ -0,0 +1,62 @@
+package com.redhat.training.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+@Entity
+public class Person {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @NotNull
+    @Size(min=2,max=50)
+    private String name;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((id == null) ? 0 : id.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		Person other = (Person) obj;
+		if (id == null) {
+			if (other.id != null)
+				return false;
+		} else if (!id.equals(other.id))
+			return false;
+		return true;
+	}
+
+    
+}
diff --git a/labs/hello-rest/src/main/java/com/redhat/training/rest/PersonService.java b/labs/hello-rest/src/main/java/com/redhat/training/rest/PersonService.java
new file mode 100644
index 0000000..0c309c3
--- /dev/null
+++ b/labs/hello-rest/src/main/java/com/redhat/training/rest/PersonService.java
@@ -0,0 +1,154 @@
+package com.redhat.training.rest;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+import javax.annotation.Resource;
+import javax.ejb.EJBException;
+import javax.ejb.Stateless;
+import javax.ejb.TransactionManagement;
+import javax.ejb.TransactionManagementType;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.TypedQuery;
+import javax.transaction.UserTransaction;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import com.redhat.training.messaging.JMSUtil;
+import com.redhat.training.model.Person;
+
+//TODO Add the stateless annotation
+
+//TODO Add a Path for persons
+
+//TODO Add a Consumes annotation for JSON
+
+//TODO Add a Produces annotation for JSON
+
+@TransactionManagement(TransactionManagementType.BEAN)
+public class PersonService {
+
+	@PersistenceContext
+	private EntityManager entityManager;
+
+	@Resource
+	UserTransaction tx;
+
+	@Inject
+	JMSUtil jmsUtil;
+
+	// Simple non-RESTy method for JSF bean invocation
+	public String hello(String name) {
+		try {
+			try {
+				// start a new transaction
+				tx.begin();
+
+				// let's grab the current date and time on the server
+				LocalDateTime today = LocalDateTime.now();
+
+				// format it nicely for on-screen display
+				DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy hh:mm:ss a");
+				String fdate = today.format(format);
+
+				// Create a new Person object and persist to database
+				Person p = new Person();
+				p.setName(name);
+				entityManager.persist(p);
+
+				// Send a JMS message to the 'helloWorldQueue'
+				jmsUtil.sendMessage("Said Hello to " + name.toUpperCase() + " at " + fdate);
+
+				// respond back with Hello and convert the name to UPPERCASE. Also, send the
+				// current time on the server.
+				return "Hello " + name.toUpperCase() + "!. " + "Time on the server is: " + fdate;
+			} finally {
+				// commit the transaction
+				tx.commit();
+			}
+		} catch (Exception e) {
+			throw new EJBException(e);
+		}
+	}
+
+	// CRUD RESTful methods below
+
+	// fetch result by Person id
+	//TODO add GET annotation
+
+	//TODO add path for ID
+
+	public Person getPerson(Long id) {
+		return entityManager.find(Person.class, id);
+	}
+
+	// Dump all Person objects in the Database
+	//TODO add GET annotation
+
+	public List<Person> getAllPersons() {
+		TypedQuery<Person> query = entityManager.createQuery("SELECT p FROM Person p", Person.class);
+		List<Person> persons = query.getResultList();
+
+		return persons;
+	}
+
+	// delete an object by Person id
+	//TODO add DELETE annotation
+
+	//TODO add Path for ID
+
+    public void deletePerson(Long id) {
+			try {
+				try {
+					tx.begin();
+					entityManager.remove(getPerson(id));
+				} finally {
+					tx.commit();
+				}
+			} catch (Exception e) {
+				throw new EJBException();
+			}
+    }
+
+	// Save a Person object to Database
+	//TODO add POST annotation
+
+	public Response savePerson(Person person) {
+		try {
+			try {
+			ResponseBuilder builder;
+			if (person.getId() == null) {
+				Person newPerson = new Person();
+				newPerson.setName(person.getName());
+				tx.begin();
+				entityManager.persist(newPerson);
+				builder = Response.ok();
+			} else {
+				Person uPerson;
+				Person updatePerson = getPerson(person.getId());
+				updatePerson.setName(person.getName());
+				uPerson = entityManager.merge(updatePerson);
+				builder = Response.ok(uPerson);
+			}
+
+			return builder.build();
+			}finally {
+				tx.commit();
+			}
+		}catch (Exception e) {
+			throw new EJBException(e);
+		}
+	}
+
+}
diff --git a/labs/hello-rest/src/main/java/com/redhat/training/servlet/PingServlet.java b/labs/hello-rest/src/main/java/com/redhat/training/servlet/PingServlet.java
new file mode 100644
index 0000000..d413cdf
--- /dev/null
+++ b/labs/hello-rest/src/main/java/com/redhat/training/servlet/PingServlet.java
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.redhat.training.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * <p>
+ * A simple servlet taking advantage of features added in 3.0.
+ * </p>
+ *
+ * <p>
+ * The servlet is registered and mapped to /HelloServlet using the {@linkplain WebServlet
+ * @HttpServlet}.
+ * </p>
+ *
+ * @author Pete Muir
+ *
+ */
+@SuppressWarnings("serial")
+@WebServlet("/health")
+public class PingServlet extends HttpServlet {
+
+    static String PAGE_HEADER = "<html><head><title>Ping Servlet</title></head><body>";
+
+    static String PAGE_FOOTER = "</body></html>";
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        resp.setContentType("text/html");
+        PrintWriter writer = resp.getWriter();
+        writer.println(PAGE_HEADER);
+        writer.println("<h1>OK.</h1>");
+        writer.println("It is now " + new java.util.Date().toString() + " at the server.");
+        writer.println(PAGE_FOOTER);
+        writer.close();
+    }
+
+}
diff --git a/labs/hello-rest/src/main/java/com/redhat/training/ui/Hello.java b/labs/hello-rest/src/main/java/com/redhat/training/ui/Hello.java
new file mode 100755
index 0000000..fd1d43f
--- /dev/null
+++ b/labs/hello-rest/src/main/java/com/redhat/training/ui/Hello.java
@@ -0,0 +1,51 @@
+package com.redhat.training.ui;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.inject.Inject;
+
+import com.redhat.training.rest.PersonService;
+
+@RequestScoped
+@Named("hello")
+public class Hello {
+	private String name;
+
+	@Inject
+	private PersonService personService;
+
+	public void sayHello() {
+		try {
+			String response = personService.hello(name);
+			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(response));
+		}catch(Exception e){
+			System.out.println(e.getCause());
+			if(e.getCause() != null && e.getCause() instanceof ConstraintViolationException) {
+				ConstraintViolationException ex = (ConstraintViolationException) e.getCause();
+				String violations = "";
+				for(ConstraintViolation<?> cv: ex.getConstraintViolations()) {
+					
+					violations += cv.getMessage() + "\n";
+					
+					System.out.println("Violations: "+violations);
+				}
+				FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(violations));
+			}
+			
+		}
+		
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+}
diff --git a/labs/hello-rest/src/main/resources/META-INF/persistence.xml b/labs/hello-rest/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000..41466e2
--- /dev/null
+++ b/labs/hello-rest/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence version="2.1"
+             xmlns="http://xmlns.jcp.org/xml/ns/persistence"
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
+    <persistence-unit name="hello" transaction-type="JTA">
+        <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
+        <properties>
+    			<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
+    			<property name="hibernate.hbm2ddl.auto" value="create-drop" />
+    			<property name="hibernate.show_sql" value="true" />
+    			<property name="hibernate.format_sql" value="true" />
+	</properties>
+    </persistence-unit>
+</persistence>
diff --git a/solutions/hello-rest/.gitignore b/solutions/hello-rest/.gitignore
new file mode 100644
index 0000000..d0152b8
--- /dev/null
+++ b/solutions/hello-rest/.gitignore
@@ -0,0 +1,5 @@
+.classpath
+.project
+.tern-project
+.settings
+target
diff --git a/solutions/hello-rest/README.md b/solutions/hello-rest/README.md
new file mode 100644
index 0000000..56cae66
--- /dev/null
+++ b/solutions/hello-rest/README.md
@@ -0,0 +1,12 @@
+# JB125 Java EE 7 Hello World web App
+
+##This app is composed of the following architecture:
+
+* Maven Project - builds a WAR
+* Using JSF 2.2 for web interface, HTML5 facelets page, JSF backing beans, CDI scopes on beans, @Named
+* Statelss EJB for services - uses JPA entity beans - exposes appropriate method as REST API using JAX-RS annotations
+* JAX-RS Application class
+* JPA entity bean to store names - uses H2 in-memory database
+* Use EJB Singleton to lookup messaging connection and queue destination and inject into stateless EJB - lookup should only occur once on startup
+* Servlet that returns "OK" - this is a health check - path should be [context]/health
+* H2 (embedded in-memory DB) backend
diff --git a/solutions/hello-rest/pom.xml b/solutions/hello-rest/pom.xml
new file mode 100644
index 0000000..c75812b
--- /dev/null
+++ b/solutions/hello-rest/pom.xml
@@ -0,0 +1,148 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>hello-rest-solution</artifactId>
+  <packaging>war</packaging>
+  <name>Hello World REST app Project -Solution</name>
+  <description>This is the hello-rest solution project</description>
+  <parent>
+  	<groupId>com.redhat.training</groupId>
+  	<artifactId>parent-pom</artifactId>
+  	<version>1.0</version>
+  	<relativePath>../pom.xml</relativePath>
+  </parent>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+    <dependencies>
+
+        <!-- First declare the APIs we depend on and need for compilation. All
+            of them are provided by JBoss EAP -->
+
+        <!-- Import the CDI API, we use provided scope as the API is included in
+            JBoss EAP -->
+        <dependency>
+            <groupId>javax.enterprise</groupId>
+            <artifactId>cdi-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Import the Common Annotations API (JSR-250), we use provided scope
+            as the API is included in JBoss EAP -->
+        <dependency>
+            <groupId>org.jboss.spec.javax.annotation</groupId>
+            <artifactId>jboss-annotations-api_1.2_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Import the JAX-RS API, we use provided scope as the API is included
+            in JBoss EAP -->
+        <dependency>
+            <groupId>org.jboss.spec.javax.ws.rs</groupId>
+            <artifactId>jboss-jaxrs-api_2.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Import the JPA API, we use provided scope as the API is included in
+            JBoss EAP -->
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.1-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Import the EJB API, we use provided scope as the API is included in
+            JBoss EAP -->
+        <dependency>
+            <groupId>org.jboss.spec.javax.ejb</groupId>
+            <artifactId>jboss-ejb-api_3.2_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.jboss.spec.javax.jms</groupId>
+            <artifactId>jboss-jms-api_2.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Bean Validation Implementation -->
+        <!-- Provides portable constraints such as @Email -->
+        <!-- Hibernate Validator is shipped in JBoss EAP -->
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-validator</artifactId>
+            <scope>provided</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+            <dependency>
+                <groupId>org.hibernate</groupId>
+                <artifactId>hibernate-search-orm</artifactId>
+                 <scope>provided</scope>
+            </dependency>
+
+             <dependency>
+                <groupId>org.hibernate</groupId>
+                <artifactId>hibernate-entitymanager</artifactId>
+                 <scope>provided</scope>
+            </dependency>
+
+        <!-- Import the JSF API, we use provided scope as the API is included in
+            JBoss EAP -->
+        <dependency>
+            <groupId>org.jboss.spec.javax.faces</groupId>
+            <artifactId>jboss-jsf-api_2.2_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+	  		<groupId>org.jboss.spec.javax.servlet</groupId>
+	  		<artifactId>jboss-servlet-api_3.1_spec</artifactId>
+			<scope>provided</scope>
+	  	</dependency>
+
+        <!-- Annotation processor to generate the JPA metamodel classes for
+            typesafe criteria queries -->
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-jpamodelgen</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- Annotation processor that raising compilation errors whenever constraint
+            annotations are incorrectly used. -->
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-validator-annotation-processor</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <finalName>hello-rest</finalName>
+        <plugins>
+            <plugin>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>${version.war.plugin}</version>
+                <extensions>false</extensions>
+                <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                    <archive>
+                        <manifestEntries>
+                            <Dependencies>com.google.guava,org.slf4j
+                            </Dependencies>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/solutions/hello-rest/src/main/java/com/redhat/training/messaging/JMSUtil.java b/solutions/hello-rest/src/main/java/com/redhat/training/messaging/JMSUtil.java
new file mode 100644
index 0000000..14c1421
--- /dev/null
+++ b/solutions/hello-rest/src/main/java/com/redhat/training/messaging/JMSUtil.java
@@ -0,0 +1,28 @@
+package com.redhat.training.messaging;
+
+import javax.ejb.Singleton;
+import javax.ejb.Startup;
+import javax.annotation.Resource;
+import javax.jms.Queue;
+import javax.jms.JMSContext;
+import javax.inject.Inject;
+
+@Startup
+@Singleton
+public class JMSUtil {
+
+    @Resource(mappedName = "java:jboss/jms/queue/helloWorldQueue")
+    private Queue helloWorldQueue;
+
+    @Inject
+    JMSContext context;
+
+    public void sendMessage(String msg) {
+        try {
+            context.createProducer().send(helloWorldQueue, msg);
+        }
+        catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/solutions/hello-rest/src/main/java/com/redhat/training/messaging/QueueListener.java b/solutions/hello-rest/src/main/java/com/redhat/training/messaging/QueueListener.java
new file mode 100644
index 0000000..169c4be
--- /dev/null
+++ b/solutions/hello-rest/src/main/java/com/redhat/training/messaging/QueueListener.java
@@ -0,0 +1,59 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.redhat.training.messaging;
+
+import org.jboss.logging.Logger;
+import javax.ejb.ActivationConfigProperty;
+import javax.ejb.MessageDriven;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.TextMessage;
+
+/**
+ * <p>
+ * A simple Message Driven Bean that asynchronously receives and processes the messages that are sent to the queue.
+ * </p>
+ *
+ * @author Serge Pagop (spagop@redhat.com)
+ *
+ */
+@MessageDriven(name = "QueueListener", activationConfig = {
+    @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "queue/helloWorldQueue"),
+    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
+    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") })
+public class QueueListener implements MessageListener {
+
+    private final static Logger LOGGER = Logger.getLogger(QueueListener.class.getName());
+
+    /**
+     * @see MessageListener#onMessage(Message)
+     */
+    public void onMessage(Message rcvMessage) {
+        TextMessage msg = null;
+        try {
+            if (rcvMessage instanceof TextMessage) {
+                msg = (TextMessage) rcvMessage;
+                LOGGER.info("Received Message from helloWorldQueue ===> " + msg.getText());
+            } else {
+                LOGGER.warn("Message of wrong type: " + rcvMessage.getClass().getName());
+            }
+        } catch (JMSException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/solutions/hello-rest/src/main/java/com/redhat/training/model/Person.java b/solutions/hello-rest/src/main/java/com/redhat/training/model/Person.java
new file mode 100644
index 0000000..163204a
--- /dev/null
+++ b/solutions/hello-rest/src/main/java/com/redhat/training/model/Person.java
@@ -0,0 +1,62 @@
+package com.redhat.training.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+@Entity
+public class Person {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @NotNull
+    @Size(min=2,max=50)
+    private String name;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((id == null) ? 0 : id.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		Person other = (Person) obj;
+		if (id == null) {
+			if (other.id != null)
+				return false;
+		} else if (!id.equals(other.id))
+			return false;
+		return true;
+	}
+
+    
+}
diff --git a/solutions/hello-rest/src/main/java/com/redhat/training/rest/PersonService.java b/solutions/hello-rest/src/main/java/com/redhat/training/rest/PersonService.java
new file mode 100644
index 0000000..9a76af5
--- /dev/null
+++ b/solutions/hello-rest/src/main/java/com/redhat/training/rest/PersonService.java
@@ -0,0 +1,144 @@
+package com.redhat.training.rest;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.List;
+
+import javax.annotation.Resource;
+import javax.ejb.EJBException;
+import javax.ejb.Stateless;
+import javax.ejb.TransactionManagement;
+import javax.ejb.TransactionManagementType;
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.TypedQuery;
+import javax.transaction.UserTransaction;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+
+import com.redhat.training.messaging.JMSUtil;
+import com.redhat.training.model.Person;
+
+@Stateless
+@Path("persons")
+@Consumes(MediaType.APPLICATION_JSON)
+@Produces(MediaType.APPLICATION_JSON)
+@TransactionManagement(TransactionManagementType.BEAN)
+public class PersonService {
+
+	@PersistenceContext
+	private EntityManager entityManager;
+
+	@Resource
+	UserTransaction tx;
+
+	@Inject
+	JMSUtil jmsUtil;
+
+	// Simple non-RESTy method for JSF bean invocation
+	public String hello(String name) {
+		try {
+			try {
+				// start a new transaction
+				tx.begin();
+
+				// let's grab the current date and time on the server
+				LocalDateTime today = LocalDateTime.now();
+
+				// format it nicely for on-screen display
+				DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM dd yyyy hh:mm:ss a");
+				String fdate = today.format(format);
+
+				// Create a new Person object and persist to database
+				Person p = new Person();
+				p.setName(name);
+				entityManager.persist(p);
+
+				// Send a JMS message to the 'helloWorldQueue'
+				jmsUtil.sendMessage("Said Hello to " + name.toUpperCase() + " at " + fdate);
+
+				// respond back with Hello and convert the name to UPPERCASE. Also, send the
+				// current time on the server.
+				return "Hello " + name.toUpperCase() + "!. " + "Time on the server is: " + fdate;
+			} finally {
+				// commit the transaction
+				tx.commit();
+			}
+		} catch (Exception e) {
+			throw new EJBException(e);
+		}
+	}
+
+	// CRUD RESTful methods below
+
+	// fetch result by Person id
+	@GET
+	@Path("{id}")
+	public Person getPerson(@PathParam("id") Long id) {
+		return entityManager.find(Person.class, id);
+	}
+
+	// Dump all Person objects in the Database
+	@GET
+	public List<Person> getAllPersons() {
+		TypedQuery<Person> query = entityManager.createQuery("SELECT p FROM Person p", Person.class);
+		List<Person> persons = query.getResultList();
+
+		return persons;
+	}
+
+	// delete an object by Person id
+	@DELETE
+    @Path("{id}")
+    public void deletePerson(@PathParam("id") Long id) {
+		try {
+			try {
+				tx.begin();
+				entityManager.remove(getPerson(id));
+			} finally {
+				tx.commit();
+			}
+		} catch (Exception e) {
+			throw new EJBException();
+		}
+    }
+
+	// Save a Person object to Database
+	@POST
+	public Response savePerson(Person person) {
+		try {
+			try {
+			ResponseBuilder builder;
+			if (person.getId() == null) {
+				Person newPerson = new Person();
+				newPerson.setName(person.getName());
+				tx.begin();
+				entityManager.persist(newPerson);
+				builder = Response.ok();
+			} else {
+				Person uPerson;
+				Person updatePerson = getPerson(person.getId());
+				updatePerson.setName(person.getName());
+				uPerson = entityManager.merge(updatePerson);
+				builder = Response.ok(uPerson);
+			}
+
+			return builder.build();
+			}finally {
+				tx.commit();
+			}
+		}catch (Exception e) {
+			throw new EJBException(e);
+		}
+	}
+
+}
diff --git a/solutions/hello-rest/src/main/java/com/redhat/training/rest/Service.java b/solutions/hello-rest/src/main/java/com/redhat/training/rest/Service.java
new file mode 100644
index 0000000..0b01d7e
--- /dev/null
+++ b/solutions/hello-rest/src/main/java/com/redhat/training/rest/Service.java
@@ -0,0 +1,9 @@
+package com.redhat.training.rest;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+@ApplicationPath("/api")
+public class Service extends Application {
+
+}
diff --git a/solutions/hello-rest/src/main/java/com/redhat/training/servlet/PingServlet.java b/solutions/hello-rest/src/main/java/com/redhat/training/servlet/PingServlet.java
new file mode 100644
index 0000000..d413cdf
--- /dev/null
+++ b/solutions/hello-rest/src/main/java/com/redhat/training/servlet/PingServlet.java
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.redhat.training.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * <p>
+ * A simple servlet taking advantage of features added in 3.0.
+ * </p>
+ *
+ * <p>
+ * The servlet is registered and mapped to /HelloServlet using the {@linkplain WebServlet
+ * @HttpServlet}.
+ * </p>
+ *
+ * @author Pete Muir
+ *
+ */
+@SuppressWarnings("serial")
+@WebServlet("/health")
+public class PingServlet extends HttpServlet {
+
+    static String PAGE_HEADER = "<html><head><title>Ping Servlet</title></head><body>";
+
+    static String PAGE_FOOTER = "</body></html>";
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        resp.setContentType("text/html");
+        PrintWriter writer = resp.getWriter();
+        writer.println(PAGE_HEADER);
+        writer.println("<h1>OK.</h1>");
+        writer.println("It is now " + new java.util.Date().toString() + " at the server.");
+        writer.println(PAGE_FOOTER);
+        writer.close();
+    }
+
+}
diff --git a/solutions/hello-rest/src/main/java/com/redhat/training/ui/Hello.java b/solutions/hello-rest/src/main/java/com/redhat/training/ui/Hello.java
new file mode 100755
index 0000000..fd1d43f
--- /dev/null
+++ b/solutions/hello-rest/src/main/java/com/redhat/training/ui/Hello.java
@@ -0,0 +1,51 @@
+package com.redhat.training.ui;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.inject.Inject;
+
+import com.redhat.training.rest.PersonService;
+
+@RequestScoped
+@Named("hello")
+public class Hello {
+	private String name;
+
+	@Inject
+	private PersonService personService;
+
+	public void sayHello() {
+		try {
+			String response = personService.hello(name);
+			FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(response));
+		}catch(Exception e){
+			System.out.println(e.getCause());
+			if(e.getCause() != null && e.getCause() instanceof ConstraintViolationException) {
+				ConstraintViolationException ex = (ConstraintViolationException) e.getCause();
+				String violations = "";
+				for(ConstraintViolation<?> cv: ex.getConstraintViolations()) {
+					
+					violations += cv.getMessage() + "\n";
+					
+					System.out.println("Violations: "+violations);
+				}
+				FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(violations));
+			}
+			
+		}
+		
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+}
diff --git a/solutions/hello-rest/src/main/resources/META-INF/persistence.xml b/solutions/hello-rest/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000..41466e2
--- /dev/null
+++ b/solutions/hello-rest/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence version="2.1"
+             xmlns="http://xmlns.jcp.org/xml/ns/persistence"
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
+    <persistence-unit name="hello" transaction-type="JTA">
+        <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
+        <properties>
+    			<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
+    			<property name="hibernate.hbm2ddl.auto" value="create-drop" />
+    			<property name="hibernate.show_sql" value="true" />
+    			<property name="hibernate.format_sql" value="true" />
+	</properties>
+    </persistence-unit>
+</persistence>

--
Gitblit v1.9.3