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(); } } micro-java/pom.xml
New file @@ -0,0 +1,96 @@ <?xml version="1.0" encoding="UTF-8"?> <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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.redhat.training.openshift</groupId> <artifactId>hello</artifactId> <version>1.0</version> <packaging>war</packaging> <name>Red Hat Training Hello Java app</name> <description>Hello microservice using Thorntail</description> <properties> <!-- Explicitly declaring the source encoding eliminates the following message: --> <!-- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <failOnMissingWebXml>false</failOnMissingWebXml> <!-- Thorntail dependency versions --> <version.thorntail>2.4.0.Final</version.thorntail> <!-- other plugin versions --> <version.compiler.plugin>3.1</version.compiler.plugin> <version.surefire.plugin>2.16</version.surefire.plugin> <version.war.plugin>2.5</version.war.plugin> <version.fabric8.plugin>4.1.0</version.fabric8.plugin> <!-- maven-compiler-plugin --> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.source>1.8</maven.compiler.source> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>io.thorntail</groupId> <artifactId>bom-all</artifactId> <version>${version.thorntail}</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>io.thorntail</groupId> <artifactId>cdi</artifactId> </dependency> <dependency> <groupId>io.thorntail</groupId> <artifactId>jaxrs</artifactId> </dependency> </dependencies> <build> <!-- Maven will append the version to the finalName (which is the name given to the generated war, and hence the context root) --> <finalName>hello</finalName> <plugins> <!-- The Thorntail Maven plugin creates an uber jar --> <!-- To use, run: mvn thorntail:run --> <plugin> <groupId>io.thorntail</groupId> <artifactId>thorntail-maven-plugin</artifactId> <version>${version.thorntail}</version> <executions> <execution> <goals> <goal>package</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>io.fabric8</groupId> <artifactId>fabric8-maven-plugin</artifactId> <version>${version.fabric8.plugin}</version> <executions> <execution> <id>fmp</id> <goals> <goal>resource</goal> <goal>build</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project> micro-java/src/main/fabric8/.gitkeep
micro-java/src/main/java/com/redhat/training/openshift/hello/HelloResource.java
New file @@ -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; } } micro-java/src/main/java/com/redhat/training/openshift/hello/JaxRsActivator.java
New file @@ -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 { } todo-api-micro/pom.xml
New file @@ -0,0 +1,126 @@ <?xml version="1.0" encoding="UTF-8"?> <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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.redhat.training.example</groupId> <artifactId>todo-api</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>war</packaging> <name>ToDo API Thorntail Example</name> <description>ToDo API microservice using Thorntail</description> <properties> <!-- Explicitly declaring the source encoding eliminates the following message: --> <!-- [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <failOnMissingWebXml>false</failOnMissingWebXml> <!-- Thorntail dependency versions --> <version.thorntail>2.4.0.Final</version.thorntail> <!-- MySQL JDBC Connector --> <version.mysql>8.0.16</version.mysql> <!-- other plugin versions --> <version.compiler.plugin>3.1</version.compiler.plugin> <version.surefire.plugin>2.16</version.surefire.plugin> <version.war.plugin>2.5</version.war.plugin> <version.fabric8.plugin>4.1.0</version.fabric8.plugin> <!-- maven-compiler-plugin --> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.source>1.8</maven.compiler.source> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>io.thorntail</groupId> <artifactId>bom-all</artifactId> <version>${version.thorntail}</version> <scope>import</scope> <type>pom</type> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>7.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>io.thorntail</groupId> <artifactId>jaxrs-jsonp</artifactId> </dependency> <dependency> <groupId>io.thorntail</groupId> <artifactId>jpa</artifactId> </dependency> <dependency> <groupId>io.thorntail</groupId> <artifactId>ejb</artifactId> </dependency> <dependency> <groupId>io.thorntail</groupId> <artifactId>datasources</artifactId> </dependency> <dependency> <groupId>io.thorntail</groupId> <artifactId>cdi</artifactId> </dependency> <dependency> <groupId>io.thorntail</groupId> <artifactId>jaxrs</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${version.mysql}</version> </dependency> </dependencies> <build> <!-- Maven will append the version to the finalName (which is the name given to the generated war, and hence the context root) --> <finalName>hello</finalName> <plugins> <!-- The Thorntail Maven plugin creates an uber jar --> <!-- To use, run: mvn thorntail:run --> <plugin> <groupId>io.thorntail</groupId> <artifactId>thorntail-maven-plugin</artifactId> <version>${version.thorntail}</version> <executions> <execution> <goals> <goal>package</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>io.fabric8</groupId> <artifactId>fabric8-maven-plugin</artifactId> <version>${version.fabric8.plugin}</version> <executions> <execution> <id>fmp</id> <goals> <goal>resource</goal> <goal>build</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project> todo-api-micro/src/main/fabric8/deployment.yml
New file @@ -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}' todo-api-micro/src/main/fabric8/route.yml
New file @@ -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} todo-api-micro/src/main/fabric8/svc.yml
New file @@ -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} todo-api-micro/src/main/java/com/redhat/training/example/todoapi/rest/HelloWorldEndpoint.java
New file @@ -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(); } } todo-api-micro/src/main/java/com/redhat/training/example/todoapi/rest/Main.java
New file @@ -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(); } } todo-api-micro/src/main/java/com/redhat/training/model/Host.java
New file @@ -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; } } todo-api-micro/src/main/java/com/redhat/training/model/Item.java
New file @@ -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(); } } todo-api-micro/src/main/java/com/redhat/training/rest/CORSRequestFilter.java
New file @@ -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()); } } } todo-api-micro/src/main/java/com/redhat/training/rest/CORSResponseFilter.java
New file @@ -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<String, Object> 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" ); } } todo-api-micro/src/main/java/com/redhat/training/rest/HostService.java
New file @@ -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; } } todo-api-micro/src/main/java/com/redhat/training/rest/ItemService.java
New file @@ -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<Item> findItems(int startPosition, int maxResults, String sortFields, String sortDirections) { TypedQuery<Item> 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)); } } todo-api-micro/src/main/java/com/redhat/training/rest/RestApplication.java
New file @@ -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 { } todo-api-micro/src/main/java/com/redhat/training/ui/PaginatedListWrapper.java
New file @@ -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<Item> 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<Item> getList() { return list; } public void setList(List<Item> list) { this.list = list; } } todo-api-micro/src/main/resources/META-INF/persistence.xml
New file @@ -0,0 +1,18 @@ <?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="Items" transaction-type="JTA"> <jta-data-source>java:jboss/datasources/MySQLDS</jta-data-source> <properties> <property name="javax.persistence.schema-generation.database.action" value="none"/> <property name="javax.persistence.schema-generation.create-source" value="script"/> <property name="javax.persistence.schema-generation.drop-source" value="script"/> <property name="javax.persistence.schema-generation.create-script-source" value="sql/create.sql"/> <property name="javax.persistence.schema-generation.drop-script-source" value="sql/drop.sql"/> <property name="javax.persistence.sql-load-script-source" value="sql/load.sql"/> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" /> </properties> </persistence-unit> </persistence> todo-api-micro/src/main/resources/modules/com/mysql/main/module.xml
New file @@ -0,0 +1,16 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- ~ Copyright 2015 Red Hat, Inc. and/or its affiliates. ~ ~ Licensed under the Apache License version 2.0, available at http://www.apache.org/licenses/LICENSE-2.0 --> <module xmlns="urn:jboss:module:1.3" name="com.mysql"> <resources> <artifact name="mysql:mysql-connector-java:6.0.6"/> </resources> <dependencies> <module name="javax.api"/> <module name="javax.transaction.api"/> </dependencies> </module> todo-api-micro/src/main/resources/project-defaults.yml
New file @@ -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} todo-api-micro/src/main/resources/sql/create.sql
New file @@ -0,0 +1 @@ CREATE TABLE `Item` (`id` BIGINT not null auto_increment primary key, `description` VARCHAR(100), `done` BIT); todo-api-micro/src/main/resources/sql/drop.sql
New file @@ -0,0 +1 @@ DROP TABLE `Item`; todo-api-micro/src/main/resources/sql/load.sql
New file @@ -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);