From b4217ce56ce4a451e0c89474d1fa5c3bfb4740ab Mon Sep 17 00:00:00 2001 From: Scott Marlow Date: Thu, 23 Aug 2018 11:26:18 -0400 Subject: [PATCH] Add MongoDB example that works with prestarted MongoDB --- microprofile-nosql/README.md | 81 +++++++++ microprofile-nosql/pom.xml | 172 ++++++++++++++++++ .../swarm/it/jaxrs/JAXRSApplicationIT.java | 39 ++++ .../example-microprofile-deployment.yml | 45 +++++ .../fabric8/example-microprofile-route.yml | 10 + .../main/fabric8/example-microprofile-svc.yml | 14 ++ .../examples/swarm/jaxrs/MyApplication.java | 14 ++ .../examples/swarm/jaxrs/MyResource.java | 57 ++++++ .../swarm/jaxrs/NotFoundExceptionMapper.java | 22 +++ .../src/main/resources/project-defaults.yml | 34 ++++ .../src/main/webapp/WEB-INF/beans.xml | 5 + pom.xml | 1 + 12 files changed, 494 insertions(+) create mode 100644 microprofile-nosql/README.md create mode 100644 microprofile-nosql/pom.xml create mode 100644 microprofile-nosql/src/it/java/org/wildfly/swarm/it/jaxrs/JAXRSApplicationIT.java create mode 100644 microprofile-nosql/src/main/fabric8/example-microprofile-deployment.yml create mode 100644 microprofile-nosql/src/main/fabric8/example-microprofile-route.yml create mode 100644 microprofile-nosql/src/main/fabric8/example-microprofile-svc.yml create mode 100644 microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/MyApplication.java create mode 100644 microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/MyResource.java create mode 100644 microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/NotFoundExceptionMapper.java create mode 100644 microprofile-nosql/src/main/resources/project-defaults.yml create mode 100644 microprofile-nosql/src/main/webapp/WEB-INF/beans.xml diff --git a/microprofile-nosql/README.md b/microprofile-nosql/README.md new file mode 100644 index 000000000..709bb03d8 --- /dev/null +++ b/microprofile-nosql/README.md @@ -0,0 +1,81 @@ +# MicroProfile plus MongoDB in a .war Example + +This example takes a normal [MicroProfile](http://microprofile.io) WAR, and wraps it into +a `-thorntail` runnable jar, with a little added MongoDB access for more fun! + +> Please raise any issues found with this example in our JIRA: +> https://issues.jboss.org/browse/THORN + +## Project `pom.xml` + +This project is a traditional WAR project, with maven packaging +of `war` in the `pom.xml` + + war + +The project adds a `` to configure `thorntail-maven-plugin` to +create the runnable `.jar`. + + + io.thorntail + thorntail-maven-plugin + ${version.thorntail} + + + + package + + + + + +To define the needed parts of Thorntail, a dependency is added + + + io.thorntail + microprofile + ${version.thorntail} + + +This dependency provides the APIs that are part of the MicroProfile +to your application, so the project does *not* need to specify those. + +Additional application dependencies (in this case `joda-time`) can be +specified and will be included in the normal `.war` construction and available +within the Thorntail application `.jar`. + +## Start MongoDB + +First start the MondoDB server, which may take some time to launch in the background (which is why we hacked a sleep of 5 seconds below). +Then, create 'devuser' account and set the password to 'tTeX%4#MpN0~sQl': + +* docker run -d --name some-mongo -p 27017:27017 -e MONGO_INITDB_DATABASE=mongotestdb mongo +* sleep 5 +* docker exec some-mongo /bin/sh -c "mongo mongotestdb --eval \"db.createUser({ user: 'devuser', pwd: 'tTeX%4#MpN0~sQl', roles: ['dbAdmin'] }); db.auth('devuser', 'tTeX%4#MpN0~sQl'); \" " + +## Stop MongoDB + +After you done playing with this example, you can stop the MongoDB database via: +* docker stop some-mongo +* docker rm some-mongo + +## Run + +* mvn thorntail:run + +For build and deployment to OpenShift, will deploy to active OpenShift project. +* oc project +* mvn clean package fabric8:build fabric8:deploy + +Read about the maven fabric8 plugin at https://maven.fabric8.io/ + +## Use + +Since Thorntail apps tend to support one deployment per executable, it +automatically adds a `jboss-web.xml` to the deployment if it doesn't already +exist. This is used to bind the deployment to the root of the web-server, +instead of using the `.war`'s own name as the application context. + + http://localhost:8080/Hello to show that the application prints a 'Howdy' message, then + http://localhost:8080/Hello/createDiaryEntry to show that the application can write and read the MongoDB database. + diff --git a/microprofile-nosql/pom.xml b/microprofile-nosql/pom.xml new file mode 100644 index 000000000..b633849ed --- /dev/null +++ b/microprofile-nosql/pom.xml @@ -0,0 +1,172 @@ + + + + 4.0.0 + + + io.thorntail.examples + examples-parent + 2.2.0.Final-SNAPSHOT + ../ + + + example-microprofile-nosql + + Thorntail Examples: Microprofile NoSQL + Thorntail Examples: Microprofile NoSQL + + war + + + + + org.apache.maven.plugins + maven-war-plugin + + false + + + + io.thorntail + thorntail-maven-plugin + + + package + + + start + + + stop + + + + + io.fabric8 + fabric8-maven-plugin + 3.5.41 + + + + resource + + + + execution1 + + + + + mongo + + mymongo + + + + + + + + quickstarts + + + + + ${project.artifactId} + + 1 + + + + + camel-service + + + 8778 + + + /var/scratch + + + + + + + scratch + emptyDir + + + + + + + ${project.artifactId} + true + + + + + + + + + + thorntail-v2 + + + + registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift + + + + + + + + + + + io.thorntail.examples + examples-base + + + io.thorntail + microprofile + + + joda-time + joda-time + 2.7 + + + io.thorntail + mongodb + + + org.mongodb + mongo-java-driver + 3.2.2 + + + + diff --git a/microprofile-nosql/src/it/java/org/wildfly/swarm/it/jaxrs/JAXRSApplicationIT.java b/microprofile-nosql/src/it/java/org/wildfly/swarm/it/jaxrs/JAXRSApplicationIT.java new file mode 100644 index 000000000..6a33dbffa --- /dev/null +++ b/microprofile-nosql/src/it/java/org/wildfly/swarm/it/jaxrs/JAXRSApplicationIT.java @@ -0,0 +1,39 @@ +package org.wildfly.swarm.it.jaxrs; + +import org.jboss.arquillian.drone.api.annotation.Drone; +import org.jboss.arquillian.junit.Arquillian; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.openqa.selenium.WebDriver; +import org.wildfly.swarm.it.AbstractIntegrationTest; + +import static org.fest.assertions.Assertions.assertThat; + +/** + * @author Bob McWhirter + * @author Ken Finnigan + */ +@RunWith(Arquillian.class) +public class JAXRSApplicationIT extends AbstractIntegrationTest { + + @Drone + WebDriver browser; + + @Test + public void testIt() { + browser.navigate().to("http://localhost:8080/"); + assertThat(browser.getPageSource()).contains("Howdy at "); + } + + @Test + public void testExceptionMapping() { + browser.navigate().to("http://localhost:8080/bad"); + assertThat(browser.getPageSource()).contains("This is our exception page!"); + } + + @Test + public void testCreateMongoDBDocument() { + browser.navigate().to("http://localhost:8080/createDiaryEntry"); + assertThat(browser.getPageSource()).contains("MongoDB example"); + } +} diff --git a/microprofile-nosql/src/main/fabric8/example-microprofile-deployment.yml b/microprofile-nosql/src/main/fabric8/example-microprofile-deployment.yml new file mode 100644 index 000000000..78247fd33 --- /dev/null +++ b/microprofile-nosql/src/main/fabric8/example-microprofile-deployment.yml @@ -0,0 +1,45 @@ +apiVersion: v1 +kind: DeploymentConfig +metadata: + name: example-microprofile +spec: + replicas: 1 + strategy: + rollingParams: + timeoutSeconds: 10800 + type: Rolling + template: + metadata: + labels: + app: example-microprofile + deploymentconfig: example-microprofile + spec: + containers: + - env: + - name: KUBERNETES_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: JAVA_APP_DIR + value: /deployments + - name: JAVA_OPTIONS + value: -Dswarm.project.stage=production -Djava.net.preferIPv4Stack=true + name: example-microprofile + image: example-microprofile:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8080 + name: http + protocol: TCP + securityContext: + privileged: false + triggers: + - type: ConfigChange + - imageChangeParams: + automatic: true + containerNames: + - example-microprofile + from: + kind: ImageStreamTag + name: example-microprofile:latest + type: ImageChange diff --git a/microprofile-nosql/src/main/fabric8/example-microprofile-route.yml b/microprofile-nosql/src/main/fabric8/example-microprofile-route.yml new file mode 100644 index 000000000..7458dd74d --- /dev/null +++ b/microprofile-nosql/src/main/fabric8/example-microprofile-route.yml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Route +metadata: + name: example-microprofile +spec: + port: + targetPort: 8080 + to: + kind: Service + name: example-microprofile diff --git a/microprofile-nosql/src/main/fabric8/example-microprofile-svc.yml b/microprofile-nosql/src/main/fabric8/example-microprofile-svc.yml new file mode 100644 index 000000000..e6b64fed1 --- /dev/null +++ b/microprofile-nosql/src/main/fabric8/example-microprofile-svc.yml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: example-microprofile + annotations: + description: Inventory Service based on WF Swarm +spec: + ports: + - protocol: TCP + port: 8080 + targetPort: 8080 + selector: + deploymentconfig: example-microprofile + type: LoadBalancer diff --git a/microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/MyApplication.java b/microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/MyApplication.java new file mode 100644 index 000000000..cc516620b --- /dev/null +++ b/microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/MyApplication.java @@ -0,0 +1,14 @@ +package org.wildfly.examples.swarm.jaxrs; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +/** + * @author Bob McWhirter + */ +@ApplicationPath("/") +public class MyApplication extends Application { + + public MyApplication() { + } +} diff --git a/microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/MyResource.java b/microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/MyResource.java new file mode 100644 index 000000000..f303a7318 --- /dev/null +++ b/microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/MyResource.java @@ -0,0 +1,57 @@ +package org.wildfly.examples.swarm.jaxrs; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +import org.joda.time.DateTime; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import org.bson.Document; + + +/** + * @author Scott Marlow + */ +@Path("/Hello") +public class MyResource { + + @Inject @Named("mongodbtestprofile") + MongoDatabase database; + + @GET + @Produces("text/plain") + public String get() { + return "Howdy at " + new DateTime(); + } + + @GET + @Path("/createDiaryEntry") + @Produces("text/plain") + public String createDiaryEntry() { + MongoCollection collection = null; + Document query = null; + try { + String who = "Felix"; + Document entry = new Document("_id", who) + .append("name", who) + + .append("entry", "Friday, August 24, added MongoDB example."); + // save the comment + collection = database.getCollection("diary"); + collection.insertOne(entry); + + query = new Document("_id", who); + FindIterable cursor = collection.find(query); + Object diaryEntry = cursor.first(); + return diaryEntry.toString(); + } finally { + collection.drop(); + } + } + +} diff --git a/microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/NotFoundExceptionMapper.java b/microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/NotFoundExceptionMapper.java new file mode 100644 index 000000000..3a9018616 --- /dev/null +++ b/microprofile-nosql/src/main/java/org/wildfly/examples/swarm/jaxrs/NotFoundExceptionMapper.java @@ -0,0 +1,22 @@ +package org.wildfly.examples.swarm.jaxrs; + +import javax.ws.rs.NotFoundException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +/** + * @author Ken Finnigan + */ +@Provider +public class NotFoundExceptionMapper implements ExceptionMapper { + @Override + public Response toResponse(NotFoundException e) { + return Response + .status(Response.Status.OK) + .entity("This is our exception page!") + .type(MediaType.TEXT_PLAIN_TYPE) + .build(); + } +} diff --git a/microprofile-nosql/src/main/resources/project-defaults.yml b/microprofile-nosql/src/main/resources/project-defaults.yml new file mode 100644 index 000000000..32c64555e --- /dev/null +++ b/microprofile-nosql/src/main/resources/project-defaults.yml @@ -0,0 +1,34 @@ +swarm: + mongodb: + mongos: + mongodbtestprofile: + database: mongotestdb + jndi-name: java:jboss/mongodb/test + id: mongodbtestprofile + module: org.mongodb.driver.custom + security-domain: mongoRealm + hosts: + mongotesthost: + outbound-socket-binding-ref: mongotesthost + security: + security-domains: + mongoRealm: + cache-type: + classic-authentication: + login-modules: + ConfiguredIdentity: + code: ConfiguredIdentity + flag: required + ConfiguredIdentity: + module-options: + principal: devuser + password: tTeX%4#MpN0~sQl + username: devuser + network: + socket-binding-groups: + standard-sockets: + outbound-socket-bindings: + mongotesthost: + remote-host: localhost + remote-port: 27017 + diff --git a/microprofile-nosql/src/main/webapp/WEB-INF/beans.xml b/microprofile-nosql/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 000000000..4d654f805 --- /dev/null +++ b/microprofile-nosql/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,5 @@ + + diff --git a/pom.xml b/pom.xml index 3f1e7ba24..5d9a6835f 100644 --- a/pom.xml +++ b/pom.xml @@ -276,6 +276,7 @@ microprofile logstash microprofile-opentracing + microprofile-nosql opentracing jaeger ribbon