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