diff --git a/java-serverhost/src/main/java/com/redhat/training/example/javaserverhost/rest/ServerHostEndPoint.java b/java-serverhost/src/main/java/com/redhat/training/example/javaserverhost/rest/ServerHostEndPoint.java index a5ff9c1..b09770a 100644 --- a/java-serverhost/src/main/java/com/redhat/training/example/javaserverhost/rest/ServerHostEndPoint.java +++ b/java-serverhost/src/main/java/com/redhat/training/example/javaserverhost/rest/ServerHostEndPoint.java @@ -1,26 +1,26 @@ package com.redhat.training.example.javaserverhost.rest; - import javax.ws.rs.Path; import javax.ws.rs.core.Response; import javax.ws.rs.GET; import javax.ws.rs.Produces; import java.net.InetAddress; - @Path("/") public class ServerHostEndPoint { - @GET - @Produces("text/plain") - public Response doGet() { - String host = ""; - try { - host = InetAddress.getLocalHost().getHostName(); - } - catch (Exception e) { - e.printStackTrace(); - } - return Response.ok("I am running on server "+host+" Version 1.0 \n").build(); - } + @GET + @Produces("text/plain") + public Response doGet() { + String host = ""; + try { + host = InetAddress.getLocalHost().getHostName(); + } + catch (Exception e) { + e.printStackTrace(); + } + String msg = "I am running on server "+host+" Version 1.0 \n"; + return Response.ok(msg).build(); + } } + diff --git a/micro-java/pom.xml b/micro-java/pom.xml new file mode 100644 index 0000000..9c8b9cd --- /dev/null +++ b/micro-java/pom.xml @@ -0,0 +1,96 @@ + + + + 4.0.0 + + com.redhat.training.openshift + hello + 1.0 + war + Red Hat Training Hello Java app + Hello microservice using Thorntail + + + + + UTF-8 + false + + + 2.4.0.Final + + + 3.1 + 2.16 + 2.5 + 4.1.0 + + + 1.8 + 1.8 + + + + + + + io.thorntail + bom-all + ${version.thorntail} + import + pom + + + + + + + io.thorntail + cdi + + + io.thorntail + jaxrs + + + + + + hello + + + + + io.thorntail + thorntail-maven-plugin + ${version.thorntail} + + + + package + + + + + + io.fabric8 + fabric8-maven-plugin + ${version.fabric8.plugin} + + + fmp + + resource + build + + + + + + + + diff --git a/micro-java/src/main/fabric8/.gitkeep b/micro-java/src/main/fabric8/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/micro-java/src/main/java/com/redhat/training/openshift/hello/HelloResource.java b/micro-java/src/main/java/com/redhat/training/openshift/hello/HelloResource.java new file mode 100644 index 0000000..41084a4 --- /dev/null +++ b/micro-java/src/main/java/com/redhat/training/openshift/hello/HelloResource.java @@ -0,0 +1,27 @@ +package com.redhat.training.openshift.hello; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +@Path("/") +public class HelloResource { + + @GET + @Path("/hello") + @Produces("text/plain") + public String hello() { + String hostname = System.getenv().getOrDefault("HOSTNAME", "unknown"); + String message = System.getenv().getOrDefault("APP_MSG", null); + String response = ""; + + if (message == null) { + response = "Hello world from host "+hostname+"\n"; + } else { + response = "Hello world from host ["+hostname+"].\n"; + response += "Message received = "+message+"\n"; + } + return response; + } +} diff --git a/micro-java/src/main/java/com/redhat/training/openshift/hello/JaxRsActivator.java b/micro-java/src/main/java/com/redhat/training/openshift/hello/JaxRsActivator.java new file mode 100644 index 0000000..7a6a14a --- /dev/null +++ b/micro-java/src/main/java/com/redhat/training/openshift/hello/JaxRsActivator.java @@ -0,0 +1,8 @@ +package com.redhat.training.openshift.hello; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +@ApplicationPath("/api") +public class JaxRsActivator extends Application { +} diff --git a/todo-api-micro/pom.xml b/todo-api-micro/pom.xml new file mode 100755 index 0000000..9689604 --- /dev/null +++ b/todo-api-micro/pom.xml @@ -0,0 +1,126 @@ + + + + 4.0.0 + + com.redhat.training.example + todo-api + 1.0.0-SNAPSHOT + war + ToDo API Thorntail Example + ToDo API microservice using Thorntail + + + + + UTF-8 + false + + + 2.4.0.Final + + + 8.0.16 + + + 3.1 + 2.16 + 2.5 + 4.1.0 + + + 1.8 + 1.8 + + + + + + + io.thorntail + bom-all + ${version.thorntail} + import + pom + + + + + + + javax + javaee-api + 7.0 + provided + + + io.thorntail + jaxrs-jsonp + + + io.thorntail + jpa + + + io.thorntail + ejb + + + io.thorntail + datasources + + + io.thorntail + cdi + + + io.thorntail + jaxrs + + + mysql + mysql-connector-java + ${version.mysql} + + + + + + hello + + + + + io.thorntail + thorntail-maven-plugin + ${version.thorntail} + + + + package + + + + + + io.fabric8 + fabric8-maven-plugin + ${version.fabric8.plugin} + + + fmp + + resource + build + + + + + + + + diff --git a/todo-api-micro/src/main/fabric8/deployment.yml b/todo-api-micro/src/main/fabric8/deployment.yml new file mode 100644 index 0000000..f9fa89d --- /dev/null +++ b/todo-api-micro/src/main/fabric8/deployment.yml @@ -0,0 +1,21 @@ +spec: + template: + spec: + containers: + - + resources: + requests: + cpu: "0.2" +# memory: 256Mi + limits: + cpu: "1.0" +# memory: 256Mi + env: + - name: DATABASE_USER + value: '${database.user}' + - name: DATABASE_PASSWORD + value: '${database.password}' + - name: DATABASE_SVC_HOSTNAME + value: '${database.svc.hostname}' + - name: DATABASE_NAME + value: '${database.name}' diff --git a/todo-api-micro/src/main/fabric8/route.yml b/todo-api-micro/src/main/fabric8/route.yml new file mode 100644 index 0000000..d7f59ab --- /dev/null +++ b/todo-api-micro/src/main/fabric8/route.yml @@ -0,0 +1,18 @@ +--- +apiVersion: v1 +kind: Route +metadata: + labels: + expose: "true" + app: ${project.artifactId} + provider: fabric8 + version: "1.0" + group: com.redhat.training + name: ${project.artifactId} +spec: + host: ${hostname} + port: + targetPort: ${service-port} + to: + kind: Service + name: ${project.artifactId} diff --git a/todo-api-micro/src/main/fabric8/svc.yml b/todo-api-micro/src/main/fabric8/svc.yml new file mode 100644 index 0000000..b812eb9 --- /dev/null +++ b/todo-api-micro/src/main/fabric8/svc.yml @@ -0,0 +1,21 @@ +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + fabric8.io/iconUrl: img/icons/camel.svg + labels: + expose: "true" + app: ${project.artifactId} + provider: fabric8 + version: "1.0" + group: com.redhat.training + name: ${project.artifactId} +spec: + ports: + - name: http + port: ${service-port} + protocol: TCP + targetPort: ${service-port} + selector: + deploymentconfig: ${project.artifactId} diff --git a/todo-api-micro/src/main/java/com/redhat/training/example/todoapi/rest/HelloWorldEndpoint.java b/todo-api-micro/src/main/java/com/redhat/training/example/todoapi/rest/HelloWorldEndpoint.java new file mode 100755 index 0000000..ec8817b --- /dev/null +++ b/todo-api-micro/src/main/java/com/redhat/training/example/todoapi/rest/HelloWorldEndpoint.java @@ -0,0 +1,19 @@ +package com.redhat.training.example.todoapi.rest; + + +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; +import javax.ws.rs.GET; +import javax.ws.rs.Produces; + + +@Path("/hello") +public class HelloWorldEndpoint { + + @GET + @Produces("text/plain") + public Response doGet() { + return Response.ok("Hello World!").build(); + + } +} diff --git a/todo-api-micro/src/main/java/com/redhat/training/example/todoapi/rest/Main.java b/todo-api-micro/src/main/java/com/redhat/training/example/todoapi/rest/Main.java new file mode 100644 index 0000000..2dbeece --- /dev/null +++ b/todo-api-micro/src/main/java/com/redhat/training/example/todoapi/rest/Main.java @@ -0,0 +1,25 @@ +package com.redhat.training.example.todoapi.rest; + +import org.wildfly.swarm.Swarm; +import org.wildfly.swarm.datasources.DatasourcesFraction; + +public class Main { + public static void main(String[] args) throws Exception { + String host = System.getenv("HOST"); + new Swarm() + .fraction(new DatasourcesFraction() + .jdbcDriver("mysql", (d) -> { + d.driverClassName("com.mysql.cj.jdbc.Driver"); + d.xaDatasourceClass("com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"); + d.driverModuleName("com.mysql"); + }) + .dataSource("MySQLDS", (ds) -> { + ds.driverName("mysql"); + ds.connectionUrl("jdbc:mysql://"+host+":8889/todo"); + ds.userName("root"); + ds.password("root"); + })) + .start() + .deploy(); + } +} diff --git a/todo-api-micro/src/main/java/com/redhat/training/model/Host.java b/todo-api-micro/src/main/java/com/redhat/training/model/Host.java new file mode 100644 index 0000000..30dbcf2 --- /dev/null +++ b/todo-api-micro/src/main/java/com/redhat/training/model/Host.java @@ -0,0 +1,24 @@ +package com.redhat.training.model; + +import java.net.InetAddress; + +public class Host { + + private String ip; + private String hostname; + + public Host(String ip, String hostname) { + this.ip = ip; + this.hostname = hostname; + } + + public String getIp() { + return ip; + } + + public String getHostname() { + return hostname; + } + +} + diff --git a/todo-api-micro/src/main/java/com/redhat/training/model/Item.java b/todo-api-micro/src/main/java/com/redhat/training/model/Item.java new file mode 100644 index 0000000..5067fe5 --- /dev/null +++ b/todo-api-micro/src/main/java/com/redhat/training/model/Item.java @@ -0,0 +1,53 @@ +package com.redhat.training.model; + +import javax.persistence.*; + +@Entity +public class Item { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String description; + + private Boolean done = false; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Boolean isDone() { + return done; + } + + public void setDone(Boolean done) { + this.done = done; + } + + @Override + public boolean equals(Object o) { + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } + + Item item = (Item) o; + + return id.equals(item.id); + } + + @Override + public int hashCode() { + return id.hashCode(); + } +} diff --git a/todo-api-micro/src/main/java/com/redhat/training/rest/CORSRequestFilter.java b/todo-api-micro/src/main/java/com/redhat/training/rest/CORSRequestFilter.java new file mode 100644 index 0000000..d8b03ce --- /dev/null +++ b/todo-api-micro/src/main/java/com/redhat/training/rest/CORSRequestFilter.java @@ -0,0 +1,30 @@ +package com.redhat.training.rest; + +import java.io.IOException; +import java.util.logging.Logger; + +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.Provider; + +@Provider +@PreMatching +public class CORSRequestFilter implements ContainerRequestFilter { + + private final static Logger log = Logger.getLogger(CORSRequestFilter.class.getName()); + + @Override + public void filter(ContainerRequestContext requestCtx) throws IOException { + log.fine("Executing REST request filter"); + + // When HttpMethod comes as OPTIONS, just acknowledge that it accepts... + if (requestCtx.getRequest().getMethod().equals( "OPTIONS" )) { + log.fine("HTTP Method (OPTIONS) - Detected!"); + + // Just send a OK signal back to the browser + requestCtx.abortWith(Response.status(Response.Status.OK).build()); + } + } +} diff --git a/todo-api-micro/src/main/java/com/redhat/training/rest/CORSResponseFilter.java b/todo-api-micro/src/main/java/com/redhat/training/rest/CORSResponseFilter.java new file mode 100644 index 0000000..6421190 --- /dev/null +++ b/todo-api-micro/src/main/java/com/redhat/training/rest/CORSResponseFilter.java @@ -0,0 +1,32 @@ +package com.redhat.training.rest; + +import java.io.IOException; +import java.util.logging.Logger; + +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.container.ContainerResponseFilter; +import javax.ws.rs.container.PreMatching; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.Provider; + +@Provider +@PreMatching +public class CORSResponseFilter implements ContainerResponseFilter { + + private final static Logger log = Logger.getLogger(CORSResponseFilter.class.getName()); + + @Override + public void filter(ContainerRequestContext requestCtx, ContainerResponseContext responseCtx) throws IOException { + log.fine("Executing REST response filter"); + + MultivaluedMap headers = responseCtx.getHeaders(); + + headers.add("Access-Control-Allow-Origin", "*"); + headers.add("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS"); + headers.add("Access-Control-Allow-Headers", "X-Requested-With, Content-Type"); + //responseCtx.getHeaders().add( "Access-Control-Allow-Credentials", "true" ); + } + +} diff --git a/todo-api-micro/src/main/java/com/redhat/training/rest/HostService.java b/todo-api-micro/src/main/java/com/redhat/training/rest/HostService.java new file mode 100644 index 0000000..f62aac1 --- /dev/null +++ b/todo-api-micro/src/main/java/com/redhat/training/rest/HostService.java @@ -0,0 +1,28 @@ +package com.redhat.training.rest; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import javax.ejb.Stateless; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import com.redhat.training.model.Host; + +@Stateless +@Path("host") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public class HostService { + + @GET + public Host getHostInfo() throws UnknownHostException { + InetAddress address = InetAddress.getLocalHost(); + Host host = new Host(address.getHostAddress(), address.getHostName()); + return host; + } +} + diff --git a/todo-api-micro/src/main/java/com/redhat/training/rest/ItemService.java b/todo-api-micro/src/main/java/com/redhat/training/rest/ItemService.java new file mode 100644 index 0000000..bf0b030 --- /dev/null +++ b/todo-api-micro/src/main/java/com/redhat/training/rest/ItemService.java @@ -0,0 +1,97 @@ +package com.redhat.training.rest; + +import com.redhat.training.model.Item; +import com.redhat.training.ui.PaginatedListWrapper; + +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.persistence.TypedQuery; +import javax.ws.rs.*; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.MediaType; + +import java.util.List; + +@Stateless +@Path("items") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public class ItemService extends Application { + + @PersistenceContext + private EntityManager entityManager; + + private Integer countItems() { + Query query = entityManager.createQuery("SELECT COUNT(i.id) FROM Item i"); + return ((Long) query.getSingleResult()).intValue(); + } + + private List findItems(int startPosition, int maxResults, String sortFields, String sortDirections) { + TypedQuery query = + entityManager.createQuery("SELECT i FROM Item i ORDER BY i." + sortFields + " " + sortDirections, + Item.class); + query.setFirstResult(startPosition); + query.setMaxResults(maxResults); + return query.getResultList(); + } + + private PaginatedListWrapper findItems(PaginatedListWrapper wrapper) { + wrapper.setTotalResults(countItems()); + int start = (wrapper.getCurrentPage() - 1) * wrapper.getPageSize(); + wrapper.setList(findItems(start, + wrapper.getPageSize(), + wrapper.getSortFields(), + wrapper.getSortDirections())); + return wrapper; + } + + @GET + @Produces(MediaType.APPLICATION_JSON) + public PaginatedListWrapper listItems(@DefaultValue("1") + @QueryParam("page") + Integer page, + @DefaultValue("id") + @QueryParam("sortFields") + String sortFields, + @DefaultValue("asc") + @QueryParam("sortDirections") + String sortDirections) { + PaginatedListWrapper paginatedListWrapper = new PaginatedListWrapper(); + paginatedListWrapper.setCurrentPage(page); + paginatedListWrapper.setSortFields(sortFields); + paginatedListWrapper.setSortDirections(sortDirections); + paginatedListWrapper.setPageSize(10); + return findItems(paginatedListWrapper); + } + + @GET + @Path("{id}") + public Item getitem(@PathParam("id") Long id) { + return entityManager.find(Item.class, id); + } + + @POST + public Item saveItem(Item item) { + if (item.getId() == null) { + Item itemToSave = new Item(); + itemToSave.setDescription(item.getDescription()); + itemToSave.setDone(item.isDone()); + entityManager.persist(item); + } else { + Item itemToUpdate = getitem(item.getId()); + itemToUpdate.setDescription(item.getDescription()); + itemToUpdate.setDone(item.isDone()); + item = entityManager.merge(itemToUpdate); + } + + return item; + } + + @DELETE + @Path("{id}") + public void deleteItem(@PathParam("id") Long id) { + entityManager.remove(getitem(id)); + } +} diff --git a/todo-api-micro/src/main/java/com/redhat/training/rest/RestApplication.java b/todo-api-micro/src/main/java/com/redhat/training/rest/RestApplication.java new file mode 100644 index 0000000..d6aa93a --- /dev/null +++ b/todo-api-micro/src/main/java/com/redhat/training/rest/RestApplication.java @@ -0,0 +1,8 @@ +package com.redhat.training.rest; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +@ApplicationPath("/todo/api") +public class RestApplication extends Application { +} diff --git a/todo-api-micro/src/main/java/com/redhat/training/ui/PaginatedListWrapper.java b/todo-api-micro/src/main/java/com/redhat/training/ui/PaginatedListWrapper.java new file mode 100644 index 0000000..7eaeb51 --- /dev/null +++ b/todo-api-micro/src/main/java/com/redhat/training/ui/PaginatedListWrapper.java @@ -0,0 +1,72 @@ +package com.redhat.training.ui; + +import com.redhat.training.model.Item; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import java.io.Serializable; +import java.util.List; + +@XmlRootElement +public class PaginatedListWrapper implements Serializable { + + private static final long serialVersionUID = 1L; + + private Integer currentPage; + private Integer pageSize; + private Integer totalResults; + + private String sortFields; + private String sortDirections; + @XmlElement + private List list; + + public Integer getCurrentPage() { + return currentPage; + } + + public void setCurrentPage(Integer currentPage) { + this.currentPage = currentPage; + } + + public Integer getPageSize() { + return pageSize; + } + + public void setPageSize(Integer pageSize) { + this.pageSize = pageSize; + } + + public Integer getTotalResults() { + return totalResults; + } + + public void setTotalResults(Integer totalResults) { + this.totalResults = totalResults; + } + + public String getSortFields() { + return sortFields; + } + + public void setSortFields(String sortFields) { + this.sortFields = sortFields; + } + + public String getSortDirections() { + return sortDirections; + } + + public void setSortDirections(String sortDirections) { + this.sortDirections = sortDirections; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } +} diff --git a/todo-api-micro/src/main/resources/META-INF/persistence.xml b/todo-api-micro/src/main/resources/META-INF/persistence.xml new file mode 100644 index 0000000..acf40ff --- /dev/null +++ b/todo-api-micro/src/main/resources/META-INF/persistence.xml @@ -0,0 +1,18 @@ + + + + java:jboss/datasources/MySQLDS + + + + + + + + + + + diff --git a/todo-api-micro/src/main/resources/modules/com/mysql/main/module.xml b/todo-api-micro/src/main/resources/modules/com/mysql/main/module.xml new file mode 100644 index 0000000..6d88728 --- /dev/null +++ b/todo-api-micro/src/main/resources/modules/com/mysql/main/module.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/todo-api-micro/src/main/resources/project-defaults.yml b/todo-api-micro/src/main/resources/project-defaults.yml new file mode 100644 index 0000000..16a4f1e --- /dev/null +++ b/todo-api-micro/src/main/resources/project-defaults.yml @@ -0,0 +1,13 @@ +swarm: + datasources: + jdbc-drivers: + com.mysql: + driver-class-name: com.mysql.cj.jdbc.Driver + xa-datasource-class-name: com.mysql.jdbc.jdbc2.optional.MysqlXADataSource + driver-module-name: com.mysql + data-sources: + MySQLDS: + driver-name: com.mysql + connection-url: jdbc:mysql://${env.DATABASE_SVC_HOSTNAME}:3306/${env.DATABASE_NAME} + user-name: ${env.DATABASE_USER} + password: ${env.DATABASE_PASSWORD} diff --git a/todo-api-micro/src/main/resources/sql/create.sql b/todo-api-micro/src/main/resources/sql/create.sql new file mode 100644 index 0000000..6289f7c --- /dev/null +++ b/todo-api-micro/src/main/resources/sql/create.sql @@ -0,0 +1 @@ +CREATE TABLE `Item` (`id` BIGINT not null auto_increment primary key, `description` VARCHAR(100), `done` BIT); diff --git a/todo-api-micro/src/main/resources/sql/drop.sql b/todo-api-micro/src/main/resources/sql/drop.sql new file mode 100644 index 0000000..35ef5b3 --- /dev/null +++ b/todo-api-micro/src/main/resources/sql/drop.sql @@ -0,0 +1 @@ +DROP TABLE `Item`; diff --git a/todo-api-micro/src/main/resources/sql/load.sql b/todo-api-micro/src/main/resources/sql/load.sql new file mode 100644 index 0000000..6dec667 --- /dev/null +++ b/todo-api-micro/src/main/resources/sql/load.sql @@ -0,0 +1,2 @@ +INSERT INTO `Item` (`id`,`description`,`done`) VALUES (1,'Pick up newspaper', 0); +INSERT INTO `Item` (`id`,`description`,`done`) VALUES (2,'Buy groceries', 1);