diff --git a/.gitignore b/.gitignore index 9f00933484..d423ec626f 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ atlassian-ide-plugin.xml *.log build.metadata +/**/nbproject/ diff --git a/cmt/README.adoc b/cmt/README.adoc index 24befe665b..bf7957d666 100644 --- a/cmt/README.adoc +++ b/cmt/README.adoc @@ -47,20 +47,22 @@ NotSupported:: If there is a transaction running, it will be suspended and no tr Supports:: This will run the method within a transaction if a transaction exists, alternatively, if there is no transaction running, the method will not be executed within the scope of a transaction. Never:: If the client has a transaction running and does not suspend it but calls a method annotated with Never then an EJB exception will be raised. -ifndef::EAPCDRelease[] - // Considerations for Use in a Production Environment include::../shared-doc/development-shortcuts.adoc[leveloffset=+1] // System Requirements include::../shared-doc/system-requirements.adoc[leveloffset=+1] // Use of {jbossHomeName} include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] -// Start the {productName} Standalone Server (with the full profile) -include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+1] + +// build and run with standard server distribution +[[build_and_run_the_quickstart_with_server_dist]] +== Building and running the quickstart application with a {productName} server distribution +// Start the {productName} Standalone Server +include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+2] // Build and Deploy the Quickstart -include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1] +include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+2] -== Access the Application +=== Access the Application The application will be running at the following URL: http://localhost:8080/{artifactId}/ @@ -77,7 +79,7 @@ If an existing customer name is provided, no JMS message is sent. Instead of the The customer name should match: letter & '-', otherwise an error is given. This is to show that a `LogMessage` entity is still stored in the database. That is because the `logCreateCustomer` method in the `LogMessageManagerEJB` EJB is decorated with the `@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)` annotation. -== Server Log: Expected Warnings and Errors +=== Server Log: Expected Warnings and Errors You will see the following warnings in the server log. You can ignore these warnings. @@ -86,34 +88,13 @@ You will see the following warnings in the server log. You can ignore these warn HHH000431: Unable to determine H2 database version, certain features may not work ---- +// Testing with Arquillian +include::../shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc[leveloffset=+2] // Undeploy the Quickstart -include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] -// Run the Quickstart in Red Hat CodeReady Studio or Eclipse -include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1] - -// Additional Red Hat CodeReady Studio instructions -NOTE: Within {JBDSProductName}, make sure you define a server runtime environment that uses the `standalone-full.xml` configuration file. - -// Debug the Application -include::../shared-doc/debug-the-application.adoc[leveloffset=+1] +include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+2] +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] +include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1] endif::[] - -//************************************************* -// Product Release content only -//************************************************* -ifdef::ProductRelease[] - -// Getting Started with OpenShift -include::../shared-doc/openshift-getting-started.adoc[leveloffset=+1] -//Prepare OpenShift for Quickstart Deployment -include::../shared-doc/openshift-create-project.adoc[leveloffset=+1] -// Import the Latest {xpaasproduct-shortname} Image Streams and Templates -include::../shared-doc/openshift-import-imagestreams-templates.adoc[leveloffset=+1] -// Deploy the {ProductShortName} Source-to-Image (S2I) Quickstart to OpenShift -include::../shared-doc/openshift-deploy-project.adoc[leveloffset=+1] -// Openshift post deployment tasks -include::../shared-doc/openshift-post-deployment-tasks.adoc[leveloffset=+1] - - -endif::[] \ No newline at end of file +include::../shared-doc/build-and-run-the-quickstart-with-openshift.adoc[leveloffset=+1] \ No newline at end of file diff --git a/cmt/charts/helm.yaml b/cmt/charts/helm.yaml new file mode 100644 index 0000000000..672ba19145 --- /dev/null +++ b/cmt/charts/helm.yaml @@ -0,0 +1,6 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: cmt +deploy: + replicas: 1 \ No newline at end of file diff --git a/cmt/pom.xml b/cmt/pom.xml index 27888a9eca..b69a794973 100644 --- a/cmt/pom.xml +++ b/cmt/pom.xml @@ -45,6 +45,9 @@ 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final @@ -123,12 +126,6 @@ provided - - - junit - junit - test - jakarta.persistence @@ -170,6 +167,169 @@ provided + + + + junit + junit + test + + + org.jboss.arquillian.container + arquillian-container-test-api + test + jar + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet + test + + + org.wildfly.arquillian + wildfly-arquillian-common + test + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + provisioned-server + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + cloud-server + ejb + jsf + embedded-activemq + h2-default-datasource + + ROOT.war + + + + + package + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + ${project.build.directory}/server + + + **/ProvisionedManagedCustomerIT + + + **/RemoteCustomerIT + + + + + + integration-test + verify + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + + cloud-server + ejb + jsf + embedded-activemq + h2-default-datasource + + ROOT.war + + + + + package + + + + + + + + + arq-remote + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + **/RemoteCustomerIT + + + **/ProvisionedManagedCustomerIT + + + + + + integration-test + verify + + + + + + + + diff --git a/cmt/scripts/embedded-broker.cli b/cmt/scripts/embedded-broker.cli new file mode 100644 index 0000000000..265c11be65 --- /dev/null +++ b/cmt/scripts/embedded-broker.cli @@ -0,0 +1,14 @@ +if (outcome == success) of /subsystem=messaging-activemq:read-resource + /subsystem=messaging-activemq/server=default:add(elytron-domain=ApplicationDomain) +end-if +if (outcome == success) of /subsystem=messaging-activemq/server=default:read-resource + /subsystem=messaging-activemq/server=default/in-vm-acceptor=in-vm:add(server-id=0, params=[buffer-pooling=false]) + /subsystem=messaging-activemq/server=default/in-vm-connector=in-vm:add(server-id=0, params=[buffer-pooling=false]) + /subsystem=messaging-activemq/server=default/pooled-connection-factory=activemq-ra:add(connectors=[in-vm], transaction=xa, entries=[java:/JmsXA,java:jboss/DefaultJMSConnectionFactory]) + /subsystem=messaging-activemq/server=default/jms-queue=DLQ:add(entries=[java:/jms/queue/DLQ]) + /subsystem=messaging-activemq/server=default/jms-queue=ExpiryQueue:add(entries=[java:/jms/queue/ExpiryQueue]) + /subsystem=messaging-activemq/server=default/address-setting=#:add(dead-letter-address=jms.queue.DLQ, expiry-address=jms.queue.ExpiryQueue) +end-if +if (outcome == success) of /subsystem=ee/service=default-bindings:read-resource + /subsystem=ee/service=default-bindings:write-attribute(name="jms-connection-factory", value="java:jboss/DefaultJMSConnectionFactory") +end-if \ No newline at end of file diff --git a/cmt/src/main/webapp/WEB-INF/faces-config.xml b/cmt/src/main/webapp/WEB-INF/faces-config.xml index c61daf9c69..84488dc5e5 100644 --- a/cmt/src/main/webapp/WEB-INF/faces-config.xml +++ b/cmt/src/main/webapp/WEB-INF/faces-config.xml @@ -16,7 +16,7 @@ limitations under the License. --> - + xmlns:ui="jakarta.faces.facelets" + xmlns:h="jakarta.faces.html" + xmlns:f="jakarta.faces.core"> - - - - - - Name: - - - - - -
    -
  • List customers
  • -
  • List log messages
  • -
-
-
+ + + + + + Name: + + + + + +
    +
  • List customers
  • +
  • List log messages
  • +
+
+
diff --git a/cmt/src/main/webapp/customers.xhtml b/cmt/src/main/webapp/customers.xhtml index 6795085960..19334251c2 100644 --- a/cmt/src/main/webapp/customers.xhtml +++ b/cmt/src/main/webapp/customers.xhtml @@ -16,29 +16,29 @@ --> + xmlns:ui="jakarta.faces.facelets" + xmlns:h="jakarta.faces.html" + xmlns:f="jakarta.faces.core"> - - - -

List of customers

- - - - Name - - - - - - Id - - - - - Go Back -
-
+ + + +

List of customers

+ + + + Name + + + + + + Id + + + + + Go Back +
+
diff --git a/cmt/src/main/webapp/duplicate.xhtml b/cmt/src/main/webapp/duplicate.xhtml index 23e75a9443..76e0000949 100644 --- a/cmt/src/main/webapp/duplicate.xhtml +++ b/cmt/src/main/webapp/duplicate.xhtml @@ -16,15 +16,15 @@ --> + xmlns:ui="jakarta.faces.facelets" + xmlns:h="jakarta.faces.html" + xmlns:f="jakarta.faces.core"> - - -

Customer Already Existed

- - Go back -
-
+ + +

Customer Already Existed

+ + Go back +
+
diff --git a/cmt/src/main/webapp/invalidName.xhtml b/cmt/src/main/webapp/invalidName.xhtml index d067d5d3e9..f92e323265 100644 --- a/cmt/src/main/webapp/invalidName.xhtml +++ b/cmt/src/main/webapp/invalidName.xhtml @@ -16,15 +16,15 @@ --> + xmlns:ui="jakarta.faces.facelets" + xmlns:h="jakarta.faces.html" + xmlns:f="jakarta.faces.core"> - - -

Name of the customer is invalid

- - Go back -
-
+ + +

Name of the customer is invalid

+ + Go back +
+
diff --git a/cmt/src/main/webapp/logMessages.xhtml b/cmt/src/main/webapp/logMessages.xhtml index f65bbbdf66..1601d2b6cc 100644 --- a/cmt/src/main/webapp/logMessages.xhtml +++ b/cmt/src/main/webapp/logMessages.xhtml @@ -16,29 +16,29 @@ --> + xmlns:ui="jakarta.faces.facelets" + xmlns:h="jakarta.faces.html" + xmlns:f="jakarta.faces.core"> - - - -

List of log-messages

- - - - Message - - - - - - Id - - - - - Go Back -
-
+ + + +

List of log-messages

+ + + + Message + + + + + + Id + + + + + Go Back +
+
diff --git a/cmt/src/main/webapp/template.xhtml b/cmt/src/main/webapp/template.xhtml index 7bfa052a8b..edebe920c9 100644 --- a/cmt/src/main/webapp/template.xhtml +++ b/cmt/src/main/webapp/template.xhtml @@ -16,33 +16,32 @@ --> + xmlns:ui="jakarta.faces.facelets" + xmlns:h="jakarta.faces.html" + xmlns:f="jakarta.faces.core"> - + - - -cmt - - + + + cmt + + - + -

Customer Database

-
- +

Customer Database

+
+ - + -
- -
+
+ +
-
-
+
+
- + - diff --git a/cmt/src/test/java/org/jboss/as/quickstarts/cmt/ProvisionedManagedCustomerIT.java b/cmt/src/test/java/org/jboss/as/quickstarts/cmt/ProvisionedManagedCustomerIT.java new file mode 100644 index 0000000000..24bbcc1859 --- /dev/null +++ b/cmt/src/test/java/org/jboss/as/quickstarts/cmt/ProvisionedManagedCustomerIT.java @@ -0,0 +1,51 @@ +/* + * 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 org.jboss.as.quickstarts.cmt; + + +import java.net.URI; +import java.net.URISyntaxException; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.junit.Test; + +import org.junit.runner.RunWith; + +@RunWith(Arquillian.class) +@RunAsClient +public class ProvisionedManagedCustomerIT extends RemoteCustomerIT { + + @Override + protected URI getHTTPEndpoint(String path) { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080/"; + } + try { + return new URI(host + path); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + @Test + @Override + public void testAddCustomer() throws Exception { + addCustomer("LisaS"); + } + +} diff --git a/cmt/src/test/java/org/jboss/as/quickstarts/cmt/RemoteCustomerIT.java b/cmt/src/test/java/org/jboss/as/quickstarts/cmt/RemoteCustomerIT.java new file mode 100644 index 0000000000..f8688e20f8 --- /dev/null +++ b/cmt/src/test/java/org/jboss/as/quickstarts/cmt/RemoteCustomerIT.java @@ -0,0 +1,111 @@ +/* + * 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 org.jboss.as.quickstarts.cmt; + +import java.io.IOException; +import java.net.CookieManager; +import java.net.CookiePolicy; +import java.util.logging.Logger; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublisher; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import org.junit.Assert; +import org.junit.Test; + + +public class RemoteCustomerIT { + + private static final Logger log = Logger.getLogger(RemoteCustomerIT.class.getName()); + + protected URI getHTTPEndpoint(String path) { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080/cmt"; + } + try { + return new URI(host + path); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + protected String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } + + @Test + public void testAddCustomer() throws Exception { + addCustomer("BartS"); + } + + public void addCustomer(String name) throws IOException, InterruptedException { + CookieManager manager = new CookieManager(null, CookiePolicy.ACCEPT_ALL); + HttpClient client = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.ALWAYS) + .cookieHandler(manager) + .version(HttpClient.Version.HTTP_1_1) + .build(); + HttpResponse response = client.send(HttpRequest.newBuilder(getHTTPEndpoint("/addCustomer.jsf")).GET().build(), HttpResponse.BodyHandlers.ofString()); + String body = response.body().toString(); + Assert.assertEquals(200, response.statusCode()); + Assert.assertTrue(body, body.contains(" data) { + StringBuilder builder = new StringBuilder(); + for (Map.Entry entry : data.entrySet()) { + if (builder.length() > 0) { + builder.append("&"); + } + builder.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8)); + builder.append("="); + builder.append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8)); + } + return BodyPublishers.ofString(builder.toString()); + } + +} diff --git a/ee-security/README.adoc b/ee-security/README.adoc index 8d9fe228b9..cabe47c770 100644 --- a/ee-security/README.adoc +++ b/ee-security/README.adoc @@ -4,6 +4,7 @@ include::../shared-doc/attributes.adoc[] :author: Darran Lofthouse :level: Intermediate :technologies: EE Security, Servlet, CDI +:openshift: true [abstract] The `ee-security` quickstart demonstrates Jakarta EE security. @@ -24,13 +25,17 @@ This quickstart is hard coded to work with a user `quickstartUser` with password include::../shared-doc/system-requirements.adoc[leveloffset=+1] // Use of {jbossHomeName} include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] + +// build and run with standard server distribution +[[build_and_run_the_quickstart_with_server_dist]] +== Building and running the quickstart application with a {productName} server distribution // Back Up the {productName} Standalone Server Configuration -include::../shared-doc/back-up-server-standalone-configuration.adoc[leveloffset=+1] +include::../shared-doc/back-up-server-standalone-configuration.adoc[leveloffset=+2] // Start the {productName} Standalone Server -include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+1] +include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+2] [[configure_the_server]] -== Configure the Server +=== Configure the Server You configure the security domain by running JBoss CLI commands. For your convenience, this quickstart batches the commands into a `configure-elytron.cli` script provided in the root directory of this quickstart. @@ -58,10 +63,17 @@ The batch executed successfully process-state: reload-required ---- +. You'll need to reload the configuration after that: ++ +[source,subs="+quotes,attributes+",options="nowrap"] +---- +$ __{jbossHomeName}__/bin/jboss-cli.sh --connect --commands=reload +---- + // Build and Deploy the Quickstart -include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1] +include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+2] -== Access the Application +=== Access the Application The application will be running at the following URL: http://localhost:8080/{artifactId}/secured @@ -102,23 +114,18 @@ Identity as available from injection 'quickstartUser' The resulting output shows authentication was successful and the correct identity has been established. +// Testing with Arquillian +include::../shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc[leveloffset=+2] // Undeploy the Quickstart -include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] - -// Restore the {productName} Standalone Server Configuration -include::../shared-doc/restore-standalone-server-configuration.adoc[leveloffset=+1] - +include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+2] +// Restore the {productName} Standalone Server Configuration +include::../shared-doc/restore-standalone-server-configuration.adoc[leveloffset=+2] // Restore the {productName} Standalone Server Configuration Manually -include::../shared-doc/restore-standalone-server-configuration-manual.adoc[leveloffset=+2] - -//************************************************* -// Product Release content only -//************************************************* -ifdef::ProductRelease[] - -// Quickstart not compatible with OpenShift -include::../shared-doc/openshift-incompatibility.adoc[leveloffset=+1] +include::../shared-doc/restore-standalone-server-configuration-manual.adoc[leveloffset=+3] +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] +include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1] endif::[] - +include::../shared-doc/build-and-run-the-quickstart-with-openshift.adoc[leveloffset=+1] diff --git a/ee-security/charts/helm.yaml b/ee-security/charts/helm.yaml new file mode 100644 index 0000000000..4c393c54d9 --- /dev/null +++ b/ee-security/charts/helm.yaml @@ -0,0 +1,6 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: ee-security +deploy: + replicas: 1 \ No newline at end of file diff --git a/ee-security/configure-elytron.cli b/ee-security/configure-elytron.cli index 6fd9e666ae..f929bcff2e 100644 --- a/ee-security/configure-elytron.cli +++ b/ee-security/configure-elytron.cli @@ -7,4 +7,4 @@ /subsystem=undertow/application-security-domain=other:write-attribute(name=integrated-jaspi, value=false) # Reload the server configuration -reload +#reload diff --git a/ee-security/pom.xml b/ee-security/pom.xml index aabb9393a7..ae6344935a 100644 --- a/ee-security/pom.xml +++ b/ee-security/pom.xml @@ -44,9 +44,11 @@ - 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final @@ -120,7 +122,7 @@ + are all available within the application server. --> jakarta.enterprise @@ -145,5 +147,169 @@ wildfly-elytron provided + + + + + junit + junit + test + + + + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet + test + + + + + provisioned-server + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + cloud-server + + ROOT.war + + + + + + + false + + + + + + + package + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + ${project.build.directory}/server + + + **/ProvisionedManagedSecureIT + + + **/RemoteSecureIT + + + + + + integration-test + verify + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + + cloud-server + + ROOT.war + + + + + + + false + + + + + + + package + + + + + + + + + arq-remote + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + **/RemoteSecureIT + + + **/ProvisionedManagedSecureIT + + + + + + integration-test + verify + + + + + + + + diff --git a/ee-security/src/test/java/org/jboss/as/quickstarts/ee_security/ProvisionedManagedSecureIT.java b/ee-security/src/test/java/org/jboss/as/quickstarts/ee_security/ProvisionedManagedSecureIT.java new file mode 100644 index 0000000000..3de8e8477b --- /dev/null +++ b/ee-security/src/test/java/org/jboss/as/quickstarts/ee_security/ProvisionedManagedSecureIT.java @@ -0,0 +1,49 @@ +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.jboss.as.quickstarts.ee_security; + +import java.net.URI; +import java.net.URISyntaxException; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.junit.runner.RunWith; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +@RunWith(Arquillian.class) +@RunAsClient +public class ProvisionedManagedSecureIT extends RemoteSecureIT { + + @Override + protected URI getHTTPEndpoint() { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080"; + } + try { + return new URI(host + "/secured"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/ee-security/src/test/java/org/jboss/as/quickstarts/ee_security/RemoteSecureIT.java b/ee-security/src/test/java/org/jboss/as/quickstarts/ee_security/RemoteSecureIT.java new file mode 100644 index 0000000000..c4708744d8 --- /dev/null +++ b/ee-security/src/test/java/org/jboss/as/quickstarts/ee_security/RemoteSecureIT.java @@ -0,0 +1,78 @@ +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.jboss.as.quickstarts.ee_security; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +public class RemoteSecureIT { + + protected URI getHTTPEndpoint() { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080/ee-security"; + } + try { + return new URI(host + "/secured"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + protected static String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } + + @Test + public void testConnectOk() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder(getHTTPEndpoint()) + .GET() + .build(); + HttpResponse response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); + Assert.assertEquals(401, response.statusCode()); + request = HttpRequest.newBuilder(getHTTPEndpoint()) + .header("X-Username", "quickstartUser") + .header("X-Password", "quickstartPwd1!") + .GET() + .build(); + response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); + Assert.assertEquals(200, response.statusCode()); + String[] lines = response.body().toString().split(System.lineSeparator()); + Assert.assertEquals("SecuredServlet - doGet()", lines[0].trim()); + Assert.assertEquals("Identity as available from SecurityContext 'quickstartUser'", lines[1].trim()); + Assert.assertEquals("Identity as available from injection 'quickstartUser'", lines[2].trim()); + } + +} diff --git a/helloworld-mdb/charts/helm.yaml b/helloworld-mdb/charts/helm.yaml new file mode 100644 index 0000000000..ac3cf2bd19 --- /dev/null +++ b/helloworld-mdb/charts/helm.yaml @@ -0,0 +1,6 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: helloworld-mdb +deploy: + replicas: 2 \ No newline at end of file diff --git a/helloworld-mdb/pom.xml b/helloworld-mdb/pom.xml index da79f0bed4..f5402589db 100644 --- a/helloworld-mdb/pom.xml +++ b/helloworld-mdb/pom.xml @@ -46,6 +46,9 @@ 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final @@ -147,4 +150,71 @@ + + + provisioned-server + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + cloud-server + ejb + embedded-activemq + + ROOT.war + + + + + package + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + + cloud-server + ejb + embedded-activemq + + ROOT.war + + + + + package + + + + + + + + diff --git a/helloworld-mdb/scripts/embedded-broker.cli b/helloworld-mdb/scripts/embedded-broker.cli new file mode 100644 index 0000000000..caca0381cf --- /dev/null +++ b/helloworld-mdb/scripts/embedded-broker.cli @@ -0,0 +1,11 @@ +if (outcome == success) of /subsystem=messaging-activemq:read-resource + /subsystem=messaging-activemq/server=default:add(elytron-domain=ApplicationDomain) +end-if +if (outcome == success) of /subsystem=messaging-activemq/server=default:read-resource + /subsystem=messaging-activemq/server=default/in-vm-acceptor=in-vm:add(server-id=0, params=[buffer-pooling=false]) + /subsystem=messaging-activemq/server=default/in-vm-connector=in-vm:add(server-id=0, params=[buffer-pooling=false]) + /subsystem=messaging-activemq/server=default/pooled-connection-factory=activemq-ra:add(connectors=[in-vm], transaction=xa, entries=[java:/JmsXA,java:jboss/DefaultJMSConnectionFactory]) +end-if +if (outcome == success) of /subsystem=ee/service=default-bindings:read-resource + /subsystem=ee/service=default-bindings:write-attribute(name="jms-connection-factory", value="java:jboss/DefaultJMSConnectionFactory") +end-if \ No newline at end of file diff --git a/helloworld-ws/README.adoc b/helloworld-ws/README.adoc index a185f107d5..61e6a241d1 100644 --- a/helloworld-ws/README.adoc +++ b/helloworld-ws/README.adoc @@ -4,6 +4,7 @@ include::../shared-doc/attributes.adoc[] :author: Lee Newson :level: Beginner :technologies: JAX-WS +:openshift: true [abstract] The `helloworld-ws` quickstart demonstrates a simple Hello World application, bundled and deployed as a WAR, that uses JAX-WS to say Hello. @@ -19,10 +20,14 @@ The `helloworld-ws` quickstart demonstrates the use of JAX-WS in {productNameFul include::../shared-doc/system-requirements.adoc[leveloffset=+1] // Use of {jbossHomeName} include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] + +// build and run with standard server distribution +[[build_and_run_the_quickstart_with_server_dist]] +== Building and running the quickstart application with a {productName} server distribution // Start the {productName} Standalone Server -include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+1] +include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+2] // Build and Deploy the Quickstart -include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1] +include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+2] Review the server log to see useful information about the deployed web service endpoint. @@ -38,16 +43,14 @@ JBWS024061: Adding service endpoint metadata: id=org.jboss.as.quickstarts.wshell mtomEnabled=false ---- -== Access the Application +=== Access the Application You can verify that the Web Service is running and deployed correctly by accessing the following URL: http://localhost:8080/{artifactId}/HelloWorldService?wsdl. This URL will display the deployed WSDL endpoint for the Web Service. -// Undeploy the Quickstart -include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] -// Run the Arquillian Tests -include::../shared-doc/run-arquillian-tests.adoc[leveloffset=+1] +// Testing with Arquillian +include::../shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc[leveloffset=+2] -== Investigate the Console Output +=== Investigate the Console Output When you run the Arquillian tests, Maven prints summary of the performed tests to the console. You should see the following results. @@ -66,21 +69,11 @@ Running org.jboss.as.quickstarts.wshelloworld.ClientArqTest Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.988 sec ---- -// Run the Quickstart in Red Hat CodeReady Studio or Eclipse -include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1] - -// Additional Red Hat CodeReady Studio instructions -When you deploy this quickstart, you are presented with a window that explains there is no user interface for this quickstart and directs you to click on a link to view the WSDL definition. However, the Eclipse browser does not support the display of WSDL definitions. Instead, open an external browser and access the following URL: http://localhost:8080/{artifactId}/HelloWorldService?wsdl. This URL will display the deployed WSDL endpoint for the Web Service. - -// Debug the Application -include::../shared-doc/debug-the-application.adoc[leveloffset=+1] - -//************************************************* -// Product Release content only -//************************************************* -ifdef::ProductRelease[] - -// Quickstart not compatible with OpenShift -include::../shared-doc/openshift-incompatibility.adoc[leveloffset=+1] +// Undeploy the Quickstart +include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+2] -endif::[] \ No newline at end of file +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] +include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1] +endif::[] +include::../shared-doc/build-and-run-the-quickstart-with-openshift.adoc[leveloffset=+1] \ No newline at end of file diff --git a/helloworld-ws/charts/helm.yaml b/helloworld-ws/charts/helm.yaml new file mode 100644 index 0000000000..86e1ccf577 --- /dev/null +++ b/helloworld-ws/charts/helm.yaml @@ -0,0 +1,6 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: helloworld-ws +deploy: + replicas: 1 \ No newline at end of file diff --git a/helloworld-ws/pom.xml b/helloworld-ws/pom.xml index c22780731e..02cc5fbde6 100644 --- a/helloworld-ws/pom.xml +++ b/helloworld-ws/pom.xml @@ -43,10 +43,11 @@ - - http://localhost:8080/ 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final @@ -106,7 +107,7 @@ - + org.wildfly.bom wildfly-ee-with-tools @@ -119,27 +120,50 @@ + in JBoss EAP --> jakarta.enterprise jakarta.enterprise.cdi-api provided - + junit junit test + jar + + + org.jboss.arquillian.container + arquillian-container-test-api + test + jar org.jboss.arquillian.junit arquillian-junit-container test + + org.jboss.arquillian.protocol + arquillian-protocol-servlet + test + + + org.wildfly.arquillian + wildfly-arquillian-common + test + + + org.wildfly + wildfly-jaxws-client-bom + pom + test + + scope as the API is included in JBoss EAP --> jakarta.annotation jakarta.annotation-api @@ -147,7 +171,7 @@ + included in JBoss EAP --> jakarta.servlet jakarta.servlet-api @@ -160,11 +184,12 @@ + + This profile will start a new JBoss EAP instance, and execute the test, shutting it down when done. + Run with: mvn clean verify -Parq-managed --> arq-managed @@ -175,15 +200,85 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + + **/ClientArqIT + + + **/RemoteClientIT + **/ClientIT + + + + + + + + + provisioned-server + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + cloud-server + webservices + + + + + + package + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + org.apache.maven.plugins maven-failsafe-plugin ${version.failsafe.plugin} + + + ${project.build.directory}/server + + + **/RemoteClientIT + + + **/ClientArqIT + **/ClientIT + + integration-test - verify @@ -193,7 +288,7 @@ + Run with: mvn clean verify -Parq-remote --> arq-remote @@ -204,14 +299,35 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + + **/RemoteClientIT + + + **/ClientArqIT + **/ClientIT + + + org.apache.maven.plugins maven-failsafe-plugin ${version.failsafe.plugin} + + + **/ClientIT + + + **/ClientArqIT + **/RemoteClientIT + + - integration-test verify @@ -220,6 +336,46 @@ + + openshift + + + + org.apache.maven.plugins + maven-war-plugin + + ${project.artifactId} + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + + cloud-server + webservices + + ${project.artifactId}.war + + + + + package + + + + + + + diff --git a/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/Client.java b/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/Client.java index f0cf088fba..7eba80e145 100644 --- a/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/Client.java +++ b/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/Client.java @@ -33,7 +33,7 @@ public class Client implements HelloWorldService { /** * Default constructor * - * @param url The URL to the Hello World WSDL endpoint. + * @param wsdlUrl The URL to the Hello World WSDL endpoint. */ public Client(final URL wsdlUrl) { QName serviceName = new QName("http://www.jboss.org/eap/quickstarts/wshelloworld/HelloWorld", "HelloWorldService"); diff --git a/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/ClientArqIT.java b/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/ClientArqIT.java index 849d8c912b..5ad885a81c 100644 --- a/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/ClientArqIT.java +++ b/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/ClientArqIT.java @@ -24,6 +24,7 @@ import java.util.List; import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; import org.jboss.arquillian.junit.Arquillian; import org.jboss.arquillian.test.api.ArquillianResource; import org.jboss.shrinkwrap.api.ShrinkWrap; @@ -38,6 +39,7 @@ * @author lnewson@redhat.com */ @RunWith(Arquillian.class) +@RunAsClient public class ClientArqIT { /** * The name of the WAR Archive that will be used by Arquillian to deploy the application. diff --git a/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/ClientTest.java b/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/ClientIT.java similarity index 70% rename from helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/ClientTest.java rename to helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/ClientIT.java index 36149083df..8e7ef788ca 100644 --- a/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/ClientTest.java +++ b/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/ClientIT.java @@ -19,11 +19,12 @@ import static org.junit.Assert.assertEquals; import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.List; -import org.junit.Assume; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -33,62 +34,47 @@ * * @author lnewson@redhat.com */ -public class ClientTest { - /** - * The name of the WAR Archive that will be used by Arquillian to deploy the application. - */ - private static final String APP_NAME = "helloworld-ws"; +public class ClientIT { /** * The path of the WSDL endpoint in relation to the deployed web application. */ private static final String WSDL_PATH = "HelloWorldService?wsdl"; - /** - * The name for the Server URL System Property. - */ - private static final String SERVER_URL_PROPERTY = "serverUrl"; - /** - * The Default Server URL if one isn't specified as a System Property - */ - private static final String DEFAULT_SERVER_URL = "http://localhost:8080/"; + protected static URL getHTTPEndpoint() { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080"; + } + try { + return new URI(host + "/helloworld-ws/" + WSDL_PATH).toURL(); + } catch (URISyntaxException | MalformedURLException ex) { + throw new RuntimeException(ex); + } + } + private static String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } private static URL deploymentUrl; private HelloWorldService client; @BeforeClass public static void beforeClass() throws MalformedURLException { - String deploymentUrl = System.getProperty(SERVER_URL_PROPERTY); - - // Check that the server URL property was set. If it wasn't then use the default. - if (deploymentUrl == null || deploymentUrl.isEmpty()) { - deploymentUrl = DEFAULT_SERVER_URL; - } - - // Ensure that the URL ends with a forward slash - if (!deploymentUrl.endsWith("/")) { - deploymentUrl += "/"; - } - - // Ensure the App Name is specified in the URL - if (!deploymentUrl.matches(".*" + APP_NAME + ".*")) { - deploymentUrl += APP_NAME + "/"; - } - - // Add the WDSL Document location to the URL - deploymentUrl += WSDL_PATH; + URL deploymentUrl = getHTTPEndpoint(); System.out.println("WSDL Deployment URL: " + deploymentUrl); // Set the deployment url - ClientTest.deploymentUrl = new URL(deploymentUrl); + ClientIT.deploymentUrl = deploymentUrl; } @Before public void setup() { - if (true){ - Assume.assumeFalse(true); - } try { client = new Client(new URL(deploymentUrl, WSDL_PATH)); } catch (MalformedURLException e) { diff --git a/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/RemoteClientIT.java b/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/RemoteClientIT.java new file mode 100644 index 0000000000..2bdf897fb9 --- /dev/null +++ b/helloworld-ws/src/test/java/org/jboss/as/quickstarts/wshelloworld/RemoteClientIT.java @@ -0,0 +1,35 @@ +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.jboss.as.quickstarts.wshelloworld; + +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.junit.runner.RunWith; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +@RunWith(Arquillian.class) +@RunAsClient +public class RemoteClientIT extends ClientIT { + +} diff --git a/helloworld/README.adoc b/helloworld/README.adoc index 841dfc62a9..dff36ed8e8 100644 --- a/helloworld/README.adoc +++ b/helloworld/README.adoc @@ -7,59 +7,38 @@ include::../shared-doc/attributes.adoc[] :openshift: true [abstract] -The `helloworld` quickstart demonstrates the use of CDI and Servlet 3 and is a good starting point to verify {productName} is configured correctly. +The `helloworld` quickstart demonstrates the use of CDI and Servlet 6 and is a good starting point to verify {productName} is configured correctly. :standalone-server-type: default :archiveType: war == What is it? -The `helloworld` quickstart demonstrates the use of _CDI_ and _Servlet 3_ in {productNameFull} {productVersion}. - - -//************************************************* -// Product Release content only -//************************************************* - -ifndef::EAPCDRelease[] +The `helloworld` quickstart demonstrates the use of _CDI_ and _Servlet 6_ in {productNameFull} {productVersion}. // System Requirements include::../shared-doc/system-requirements.adoc[leveloffset=+1] // Use of {jbossHomeName} include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] + +// build and run with standard server distribution +[[build_and_run_the_quickstart_with_server_dist]] +== Building and running the quickstart application with a {productName} server distribution // Start the {productName} Standalone Server -include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+1] +include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+2] // Build and Deploy the Quickstart -include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1] - -== Access the Application +include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+2] +=== Access the Application The application will be running at the following URL: http://localhost:8080/{artifactId}/. +// Testing with Arquillian +include::../shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc[leveloffset=+2] // Undeploy the Quickstart -include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] -// Run the Quickstart in Red Hat CodeReady Studio or Eclipse -include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1] -// Debug the Application -include::../shared-doc/debug-the-application.adoc[leveloffset=+1] +include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+2] +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] +include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1] endif::[] - -//************************************************* -// Product Release content only -//************************************************* -ifdef::ProductRelease[] - -// Getting Started with OpenShift -include::../shared-doc/openshift-getting-started.adoc[leveloffset=+1] -//Prepare OpenShift for Quickstart Deployment -include::../shared-doc/openshift-create-project.adoc[leveloffset=+1] -// Import the Latest {xpaasproduct-shortname} Image Streams and Templates -include::../shared-doc/openshift-import-imagestreams-templates.adoc[leveloffset=+1] -// Deploy the {ProductShortName} Source-to-Image (S2I) Quickstart to OpenShift -include::../shared-doc/openshift-deploy-project.adoc[leveloffset=+1] -// Openshift post deployment tasks -include::../shared-doc/openshift-post-deployment-tasks.adoc[leveloffset=+1] - - -endif::[] \ No newline at end of file +include::../shared-doc/build-and-run-the-quickstart-with-openshift.adoc[leveloffset=+1] \ No newline at end of file diff --git a/helloworld/charts/helm.yaml b/helloworld/charts/helm.yaml new file mode 100644 index 0000000000..cf70083673 --- /dev/null +++ b/helloworld/charts/helm.yaml @@ -0,0 +1,6 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: helloworld +deploy: + replicas: 1 \ No newline at end of file diff --git a/helloworld/pom.xml b/helloworld/pom.xml index 9dbea4ccd9..5c8145ace1 100644 --- a/helloworld/pom.xml +++ b/helloworld/pom.xml @@ -45,6 +45,9 @@ 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final @@ -125,7 +128,7 @@ + as the API is included in WildFly --> jakarta.annotation jakarta.annotation-api @@ -139,6 +142,152 @@ provided + + + junit + junit + test + jar + + + org.jboss.arquillian.container + arquillian-container-test-api + test + jar + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet + test + + + org.wildfly.arquillian + wildfly-arquillian-common + test + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + provisioned-server + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + + cloud-server + + + ROOT.war + + + + + package + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + ${project.build.directory}/server + + + **/managed/* + + + + + + integration-test + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + + cloud-server + + ROOT.war + + + + + package + + + + + + + + + arq-remote + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + **/HelloWorldServletIT + + + **/managed/* + + + + + + integration-test + + + + + + + + + diff --git a/helloworld/src/main/webapp/index.html b/helloworld/src/main/webapp/index.html index 8e59c00ac4..eb15de324c 100644 --- a/helloworld/src/main/webapp/index.html +++ b/helloworld/src/main/webapp/index.html @@ -17,7 +17,7 @@ - - - + + + diff --git a/helloworld/src/test/java/org/jboss/as/quickstarts/helloworld/HelloWorldServletIT.java b/helloworld/src/test/java/org/jboss/as/quickstarts/helloworld/HelloWorldServletIT.java new file mode 100644 index 0000000000..39507d19da --- /dev/null +++ b/helloworld/src/test/java/org/jboss/as/quickstarts/helloworld/HelloWorldServletIT.java @@ -0,0 +1,84 @@ +/* + * Copyright 2022 JBoss by Red Hat. + * + * 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 org.jboss.as.quickstarts.helloworld; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpClient.Redirect; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.time.Duration; +import java.util.Optional; +import org.junit.Test; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +public class HelloWorldServletIT { + + protected URI getHTTPEndpoint() { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080/helloworld"; + } + try { + return new URI(host + "/HelloWorld"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + private String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } + + @Test + public void testHelloWorld() throws IOException, InterruptedException { + HttpClient client = HttpClient.newBuilder() + .followRedirects(Redirect.ALWAYS) + .connectTimeout(Duration.ofMinutes(1)) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .uri(getHTTPEndpoint()) + .GET() + .build(); + HttpResponse response = client.send(request, BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + Optional contentType = response.headers().firstValue("Content-Type"); + assertTrue(contentType.isPresent()); + assertEquals("text/html;charset=ISO-8859-1", contentType.get()); + String[] content = response.body().split(getLineSeparator()); + assertEquals(3, content.length); + assertEquals("helloworld", content[0].trim()); + assertEquals("

Hello World!

", content[1].trim()); + assertEquals("", content[2].trim()); + } + + protected String getLineSeparator() { + return"\n"; + } +} diff --git a/helloworld/src/test/java/org/jboss/as/quickstarts/helloworld/managed/ManagedHelloWorldServletIT.java b/helloworld/src/test/java/org/jboss/as/quickstarts/helloworld/managed/ManagedHelloWorldServletIT.java new file mode 100644 index 0000000000..d03fef8c31 --- /dev/null +++ b/helloworld/src/test/java/org/jboss/as/quickstarts/helloworld/managed/ManagedHelloWorldServletIT.java @@ -0,0 +1,46 @@ +/* + * Copyright 2022 JBoss by Red Hat. + * + * 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 org.jboss.as.quickstarts.helloworld.managed; + +import java.net.URI; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.as.arquillian.api.ContainerResource; +import org.jboss.as.arquillian.container.ManagementClient; +import org.jboss.as.quickstarts.helloworld.HelloWorldServletIT; +import org.junit.runner.RunWith; + + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +@RunWith(Arquillian.class) +@RunAsClient +public class ManagedHelloWorldServletIT extends HelloWorldServletIT { + @ContainerResource + private ManagementClient managementClient; + + @Override + protected URI getHTTPEndpoint() { + return managementClient.getWebUri().resolve("/HelloWorld"); + } + + @Override + protected String getLineSeparator() { + return System.lineSeparator(); + } +} diff --git a/helloworld/src/test/resources/arquillian.xml b/helloworld/src/test/resources/arquillian.xml new file mode 100644 index 0000000000..31d4c3cc43 --- /dev/null +++ b/helloworld/src/test/resources/arquillian.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/jaxrs-client/README.adoc b/jaxrs-client/README.adoc index 46f85fb741..059b09ff80 100644 --- a/jaxrs-client/README.adoc +++ b/jaxrs-client/README.adoc @@ -18,25 +18,22 @@ The `jaxrs-client` quickstart demonstrates the JAX-RS Client API which interacts This client "calls" many `POST`, `GET`, and `DELETE` operations using different ways: synchronized, asynchronous, delayed and filtered invocations. -//************************************************* -// Product Release content only -//************************************************* - -ifndef::EAPCDRelease[] - // System Requirements include::../shared-doc/system-requirements.adoc[leveloffset=+1] // Use of {jbossHomeName} include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] + +// build and run with standard server distribution +[[build_and_run_the_quickstart_with_server_dist]] +== Building and running the quickstart application with a {productName} server distribution // Start the {productName} Standalone Server -include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+1] +include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+2] // Build and Deploy the Quickstart -include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1] -// Run the Arquillian Tests -include::../shared-doc/run-arquillian-tests.adoc[leveloffset=+1] +include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+2] +// Testing with Arquillian +include::../shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc[leveloffset=+2] - -== Investigate the Console Output +=== Investigate the Console Output When you run the Arquillian tests, Maven prints summary of the performed tests to the console. You should see the following results. @@ -106,35 +103,10 @@ Tests run: 5, Failures: 0, Errors: 0, Skipped: 0 ---- // Undeploy the Quickstart -include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] -// Run the Quickstart in Red Hat CodeReady Studio or Eclipse -include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1] - -// Additional Red Hat CodeReady Studio instructions -To run the tests in {JBDSProductName}: - -. You must first set the active Maven profile in project properties to be either `arq-managed` for running on managed server or `arq-remote` for running on remote server. -. Then, to run the tests, right click on the project or individual classes and select Run As –> JUnit Test in the context menu. - -// Debug the Application -include::../shared-doc/debug-the-application.adoc[leveloffset=+1] - -endif::[] - -//************************************************* -// Product Release content only -//************************************************* -ifdef::ProductRelease[] - -// Getting Started with OpenShift -include::../shared-doc/openshift-getting-started.adoc[leveloffset=+1] -//Prepare OpenShift for Quickstart Deployment -include::../shared-doc/openshift-create-project.adoc[leveloffset=+1] -// Import the Latest {xpaasproduct-shortname} Image Streams and Templates -include::../shared-doc/openshift-import-imagestreams-templates.adoc[leveloffset=+1] -// Deploy the {ProductShortName} Source-to-Image (S2I) Quickstart to OpenShift -include::../shared-doc/openshift-deploy-project.adoc[leveloffset=+1] -// Openshift post deployment tasks -include::../shared-doc/openshift-post-deployment-tasks.adoc[leveloffset=+1] +include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+2] +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] +include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1] endif::[] +include::../shared-doc/build-and-run-the-quickstart-with-openshift.adoc[leveloffset=+1] \ No newline at end of file diff --git a/jaxrs-client/charts/helm.yaml b/jaxrs-client/charts/helm.yaml new file mode 100644 index 0000000000..3e17b4ab5f --- /dev/null +++ b/jaxrs-client/charts/helm.yaml @@ -0,0 +1,6 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: jaxrs-client +deploy: + replicas: 1 \ No newline at end of file diff --git a/jaxrs-client/pom.xml b/jaxrs-client/pom.xml index 1a7c8cf786..910ada89e9 100644 --- a/jaxrs-client/pom.xml +++ b/jaxrs-client/pom.xml @@ -46,6 +46,9 @@ 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final @@ -119,10 +122,10 @@ + of them are provided by JBoss EAP --> + JBoss EAP --> jakarta.enterprise jakarta.enterprise.cdi-api @@ -157,7 +160,7 @@ + as the API is included in JBoss EAP --> jakarta.annotation jakarta.annotation-api @@ -165,7 +168,7 @@ + in JBoss EAP --> jakarta.ws.rs jakarta.ws.rs-api @@ -173,7 +176,7 @@ + such as EJBs and Transactional(JTA) JPA from JUnit/TestNG --> org.jboss.arquillian.junit arquillian-junit-container @@ -200,11 +203,105 @@ + + + provisioned-server + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + cloud-server + + ROOT.war + + + + + package + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + ${project.build.directory}/server + + + **/ProvisionedManagedContactRestClientIT + + + **/ManagedContactsRestClientIT + **/RemoteContactsRestClientIT + + + + + + integration-test + verify + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + + cloud-server + + ROOT.war + + + + + package + + + + + + + + This profile will start a new JBoss EAP instance, and execute the test, shutting it down when done. + Run with: mvn clean verify -Parq-managed --> arq-managed @@ -219,6 +316,15 @@ org.apache.maven.plugins maven-failsafe-plugin ${version.failsafe.plugin} + + + **/ManagedContactsRestClientIT + + + **/RemoteContactsRestClientIT + **/ProvisionedManagedContactRestClientIT + + @@ -233,7 +339,7 @@ + Run with: mvn clean verify -Parq-remote --> arq-remote @@ -248,6 +354,15 @@ org.apache.maven.plugins maven-failsafe-plugin ${version.failsafe.plugin} + + + **/RemoteContactsRestClientIT + + + **/ManagedContactsRestClientIT + **/ProvisionedManagedContactRestClientIT + + diff --git a/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ContactsRestClientIT.java b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/AbstractContactsRestClient.java similarity index 82% rename from jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ContactsRestClientIT.java rename to jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/AbstractContactsRestClient.java index cba623f6f2..42d13ee13a 100644 --- a/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ContactsRestClientIT.java +++ b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/AbstractContactsRestClient.java @@ -1,6 +1,6 @@ /* * JBoss, Home of Professional Open Source - * Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual + * Copyright 2022, 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. * @@ -16,10 +16,6 @@ */ package org.jboss.as.quickstarts.jaxrsclient.test; -import java.net.URL; -import java.util.List; -import java.util.concurrent.Future; -import java.util.logging.Logger; import jakarta.ws.rs.client.ClientBuilder; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.client.Invocation; @@ -27,53 +23,29 @@ import jakarta.ws.rs.core.GenericType; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; - -import org.jboss.arquillian.container.test.api.Deployment; -import org.jboss.arquillian.container.test.api.RunAsClient; -import org.jboss.arquillian.junit.Arquillian; -import org.jboss.arquillian.test.api.ArquillianResource; +import java.util.List; +import java.util.concurrent.Future; +import java.util.logging.Logger; import org.jboss.as.quickstarts.jaxrsclient.model.Contact; -import org.jboss.as.quickstarts.jaxrsclient.rest.JaxRsActivator; -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.asset.EmptyAsset; -import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Assert; import org.junit.Test; -import org.junit.runner.RunWith; -@RunWith(Arquillian.class) -@RunAsClient -public class ContactsRestClientIT { +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +public abstract class AbstractContactsRestClient { + + private static final Logger log = Logger.getLogger(AbstractContactsRestClient.class.getName()); - //private static final String getRequestUrl() = "http://localhost:8080/jaxrs-client/rest/contacts"; private static final String CONTACT_NAME = "New Contact"; private static final String CONTACT_PHONE = "+55-61-5555-1234"; - private Logger log = Logger.getLogger(ContactsRestClientIT.class.getName()); - - @ArquillianResource - private URL deploymentUrl; - - @Deployment(testable = false) - public static WebArchive createDeployment() { - WebArchive war = ShrinkWrap.create(WebArchive.class, "managed-executor-service.war") - .addPackage(JaxRsActivator.class.getPackage()) - .addPackage(Contact.class.getPackage()) - .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); - return war; - } - - private String getRequestUrl() { - return new StringBuilder(deploymentUrl.toString()) - .append("rest/contacts") - .toString(); - } - + abstract String getRequestUrl(); // This test shows basic operations - @Test public void cruedTest() { - log.info("### CRUD tests ###"); + log.info("### CRUD tests " + getRequestUrl() + " ###"); // 1 - drop all contacts log.info("dropping all contacts"); Response response = ClientBuilder.newClient().target(getRequestUrl()).request().delete(); @@ -85,13 +57,13 @@ public void cruedTest() { c.setName(CONTACT_NAME); c.setPhoneNumber(CONTACT_PHONE); Contact persistedContact = ClientBuilder.newClient().target(getRequestUrl()).request().post(Entity.entity(c, MediaType.APPLICATION_JSON), Contact.class); - Assert.assertEquals("A book should be persisted with Id=1!", (Long) 1L, (Long) persistedContact.getId()); + Assert.assertEquals("A book should be persisted with Id=1!", (Long) 1L, persistedContact.getId()); // 3 - Fetch Contact by Id log.info("fetching a contact by id"); - Contact fetchContctById = - ClientBuilder.newClient().target(getRequestUrl()).path("/{contactId}").resolveTemplate("contactId", persistedContact.getId()).request().get(Contact.class); - Assert.assertEquals("Fetched book with Id=1!", (Long) 1L, (Long) fetchContctById.getId()); + Contact fetchContctById + = ClientBuilder.newClient().target(getRequestUrl()).path("/{contactId}").resolveTemplate("contactId", persistedContact.getId()).request().get(Contact.class); + Assert.assertEquals("Fetched book with Id=1!", (Long) 1L, fetchContctById.getId()); Assert.assertEquals("Fetched book with equal name", CONTACT_NAME, fetchContctById.getName()); Assert.assertEquals("Fetched book with equal phone", CONTACT_PHONE, fetchContctById.getPhoneNumber()); @@ -109,7 +81,6 @@ public void cruedTest() { } // This test shows some basic operations using ASYNC invocations and java.util.concurrent.Future - @Test public void asyncCrudTest() throws Exception { log.info("### CRUD tests ASYNC ###"); @@ -127,7 +98,7 @@ public void asyncCrudTest() throws Exception { Future futureContact = ClientBuilder.newClient().target(getRequestUrl()).request().async().post(Entity.entity(c, MediaType.APPLICATION_JSON), Contact.class); Contact persistedContact = futureContact.get(); - Assert.assertEquals("A contact should be persisted with Id=1!", (Long) 1L, (Long) persistedContact.getId()); + Assert.assertEquals("A contact should be persisted with Id=1!", (Long) 1L, persistedContact.getId()); // 3 - Delete a contact ASYNC log.info("delete a contact by id ASYNC"); @@ -174,7 +145,6 @@ public void failed(Throwable throwable) { } // Shows how to use a delayed REST invocation - @Test public void delayedInvocationTest() throws Exception { log.info("### Testing Delayed invocaton ###"); @@ -209,7 +179,6 @@ public void delayedInvocationTest() throws Exception { } // Shows how to use Request and Response filters - @Test public void requestResponseFiltersTest() { log.info("### Testing Request and Response Filters ###"); @@ -223,8 +192,8 @@ public void requestResponseFiltersTest() { Contact c = new Contact(); c.setName(CONTACT_NAME); c.setPhoneNumber(CONTACT_PHONE); - Contact persistedContact = - ClientBuilder.newClient().register(SavedByClientRequestFilter.class).target(getRequestUrl()).request() + Contact persistedContact + = ClientBuilder.newClient().register(SavedByClientRequestFilter.class).target(getRequestUrl()).request() .post(Entity.entity(c, MediaType.APPLICATION_JSON), Contact.class); Assert.assertEquals("A contact should be persisted with savedBy", SavedByClientRequestFilter.USERNAME, persistedContact.getSavedBy()); diff --git a/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ContactsRestClient.java b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ContactsRestClient.java index b0d2a89bcc..5554ab314c 100644 --- a/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ContactsRestClient.java +++ b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ContactsRestClient.java @@ -16,27 +16,9 @@ */ package org.jboss.as.quickstarts.jaxrsclient.test; -import java.util.List; -import java.util.concurrent.Future; -import java.util.logging.Logger; -import jakarta.ws.rs.client.ClientBuilder; -import jakarta.ws.rs.client.Entity; -import jakarta.ws.rs.client.Invocation; -import jakarta.ws.rs.client.InvocationCallback; -import jakarta.ws.rs.core.GenericType; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; - -import org.jboss.as.quickstarts.jaxrsclient.model.Contact; -import org.junit.Assert; - -public class ContactsRestClient { +public class ContactsRestClient extends AbstractContactsRestClient { private static final String REST_TARGET_URL = "http://localhost:8080/jaxrs-client/rest/contacts"; - private static final String CONTACT_NAME = "New Contact"; - private static final String CONTACT_PHONE = "+55-61-5555-1234"; - - private Logger log = Logger.getLogger(ContactsRestClient.class.getName()); public static void main(String[] args) throws Exception { ContactsRestClient client = new ContactsRestClient(); @@ -48,165 +30,22 @@ public static void main(String[] args) throws Exception { } - // This test shows basic operations - - public void cruedTest() { - log.info("### CRUD tests ###"); - // 1 - drop all contacts - log.info("dropping all contacts"); - Response response = ClientBuilder.newClient().target(REST_TARGET_URL).request().delete(); - Assert.assertEquals("All contacts should be dropped", Response.ok().build().getStatus(), response.getStatus()); - - // 2 - Create a new contact - log.info("creating a new contact"); - Contact c = new Contact(); - c.setName(CONTACT_NAME); - c.setPhoneNumber(CONTACT_PHONE); - Contact persistedContact = ClientBuilder.newClient().target(REST_TARGET_URL).request().post(Entity.entity(c, MediaType.APPLICATION_JSON), Contact.class); - Assert.assertEquals("A book should be persisted with Id=1!", (Long) 1L, (Long) persistedContact.getId()); - - // 3 - Fetch Contact by Id - log.info("fetching a contact by id"); - Contact fetchContctById = - ClientBuilder.newClient().target(REST_TARGET_URL).path("/{contactId}").resolveTemplate("contactId", persistedContact.getId()).request().get(Contact.class); - Assert.assertEquals("Fetched book with Id=1!", (Long) 1L, (Long) fetchContctById.getId()); - Assert.assertEquals("Fetched book with equal name", CONTACT_NAME, fetchContctById.getName()); - Assert.assertEquals("Fetched book with equal phone", CONTACT_PHONE, fetchContctById.getPhoneNumber()); - - // 4 - Fetch all Contacts - log.info("fetching all contacts"); - GenericType> contactsListType = new GenericType>() { - }; - List allContacts = ClientBuilder.newClient().target(REST_TARGET_URL).request().get(contactsListType); - Assert.assertEquals("Should have a single contact", 1, allContacts.size()); - - // 5 - Delete a Contact - log.info("delete a contact by id"); - response = ClientBuilder.newClient().target(REST_TARGET_URL).path("/{contactId}").resolveTemplate("contactId", persistedContact.getId()).request().delete(); - Assert.assertEquals("Contact 1 should be dropped", Response.ok().build().getStatus(), response.getStatus()); - } - - // This test shows some basic operations using ASYNC invocations and java.util.concurrent.Future - public void asyncCrudTest() throws Exception { - log.info("### CRUD tests ASYNC ###"); - - // 1 - drop all contacts ASYNC - log.info("dropping all contacts ASYNC"); - Response response = ClientBuilder.newClient().target(REST_TARGET_URL).request().async().delete().get(); - Assert.assertEquals("All contacts should be dropped", Response.ok().build().getStatus(), response.getStatus()); - - // 2 - Create a new Contact ASYNC - log.info("creating a new contact ASYNC"); - Contact c = new Contact(); - c.setName(CONTACT_NAME); - c.setPhoneNumber(CONTACT_PHONE); - - Future futureContact = ClientBuilder.newClient().target(REST_TARGET_URL).request().async().post(Entity.entity(c, MediaType.APPLICATION_JSON), Contact.class); - - Contact persistedContact = futureContact.get(); - Assert.assertEquals("A contact should be persisted with Id=1!", (Long) 1L, (Long) persistedContact.getId()); - - // 3 - Delete a contact ASYNC - log.info("delete a contact by id ASYNC"); - ClientBuilder.newClient().target(REST_TARGET_URL).path("{contactId}").resolveTemplate("contactId", persistedContact.getId()).request().async().delete().get(); - - // 4 - Fetch All Contacts ASYNC - log.info("fetching all contacts ASYNC"); - Future> futureContacts = ClientBuilder.newClient().target(REST_TARGET_URL).request().async().get(new GenericType>() { - }); - List allContacts = futureContacts.get(); - Assert.assertEquals("Should have no contacts", 0, allContacts.size()); - } - - // This test shows how to use jakarta.ws.rs.client.InvocationCallback - public void invocationCallBackTest() throws Exception { - log.info("### Testing invocation callback ###"); - - // 1 - drop all contacts - log.info("dropping all contacts"); - Response response = ClientBuilder.newClient().target(REST_TARGET_URL).request().delete(); - Assert.assertEquals("All contacts should be dropped", Response.ok().build().getStatus(), response.getStatus()); - - // 2 - Create a InvocationCallback - log.info("Creating a InvocationCallback"); - InvocationCallback> invocationCallback = new InvocationCallback>() { - - @Override - public void completed(List allContacts) { - // Completed the invocation with no contact - Assert.assertEquals("Should have no contacts", 0, allContacts.size()); - } - - @Override - public void failed(Throwable throwable) { - // It should fail - Assert.fail(throwable.getMessage()); - - } - }; - // 3 - Invoke the service - log.info("Invoking a service using the InvocationCallback"); - ClientBuilder.newClient().target(REST_TARGET_URL).request().async().get(invocationCallback).get(); - } - - // Shows how to use a delayed REST invocation - public void delayedInvocationTest() throws Exception { - log.info("### Testing Delayed invocaton ###"); - - // 1 - Drop all contacts - log.info("dropping all contacts"); - Response response = ClientBuilder.newClient().target(REST_TARGET_URL).request().delete(); - Assert.assertEquals("All contacts should be dropped", Response.ok().build().getStatus(), response.getStatus()); - - // 2 - Create a new Contact Invocation - log.info("Creating a new contact invocation"); - Contact c = new Contact(); - c.setName(CONTACT_NAME); - c.setPhoneNumber(CONTACT_PHONE); - Invocation saveContactInvocation = ClientBuilder.newClient().target(REST_TARGET_URL).request().buildPost(Entity.entity(c, MediaType.APPLICATION_JSON)); - - // 3 - Create a new list Contacts Invocation - log.info("Creating list all contacts invocation"); - Invocation listContactsInvocation = ClientBuilder.newClient().target(REST_TARGET_URL).request().buildGet(); - - // 4 - Synch Save contact - log.info("invoking the new contact"); - Contact persistedContact = saveContactInvocation.invoke(Contact.class); - Assert.assertEquals("A contacts should be persisted with Id=1!", (Long) 1L, (Long) persistedContact.getId()); - - // 5 - Async List contacts - log.info("invoking list all contacts ASYNC"); - GenericType> contactsListType = new GenericType>() { - }; - Future> futureAllContacts = listContactsInvocation.submit(contactsListType); - List allContacts = futureAllContacts.get(); - Assert.assertEquals("Should have a single contact", 1, allContacts.size()); + private String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; } - // Shows how to use Request and Response filters - public void requestResponseFiltersTest() { - log.info("### Testing Request and Response Filters ###"); - - // 1 - Drop all contacts - log.info("dropping all contacts"); - Response response = ClientBuilder.newClient().target(REST_TARGET_URL).request().delete(); - Assert.assertEquals("All contacts should be dropped", Response.ok().build().getStatus(), response.getStatus()); - - // 2 - Create a new Contact Invocation - log.info("Invoking create new contact using a ClientRequestFilter"); - Contact c = new Contact(); - c.setName(CONTACT_NAME); - c.setPhoneNumber(CONTACT_PHONE); - Contact persistedContact = - ClientBuilder.newClient().register(SavedByClientRequestFilter.class).target(REST_TARGET_URL).request() - .post(Entity.entity(c, MediaType.APPLICATION_JSON), Contact.class); - Assert.assertEquals("A contact should be persisted with savedBy", SavedByClientRequestFilter.USERNAME, persistedContact.getSavedBy()); + ; - // 3 - Fetch all Contacts - log.info("Invoking list all contacts using a ClientResponseFilter"); - GenericType> contactsListType = new GenericType>() { - }; - List allContacts = ClientBuilder.newClient().register(LogResponseFilter.class).target(REST_TARGET_URL).request().get(contactsListType); - Assert.assertEquals("Should have a single contact", 1, allContacts.size()); + @Override + String getRequestUrl() { + String host = getServerHost(); + if (host == null) { + host = REST_TARGET_URL; + } + return "http://" + host + "/jaxrs-client/rest/contacts"; } } diff --git a/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/LogResponseFilter.java b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/LogResponseFilter.java index a4a5840f39..7707f4eac2 100644 --- a/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/LogResponseFilter.java +++ b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/LogResponseFilter.java @@ -22,14 +22,15 @@ import jakarta.ws.rs.client.ClientRequestContext; import jakarta.ws.rs.client.ClientResponseContext; import jakarta.ws.rs.client.ClientResponseFilter; +import java.util.logging.Level; //This filter will log response date and status public class LogResponseFilter implements ClientResponseFilter { - private Logger log = Logger.getLogger(LogResponseFilter.class.getName()); + private static final Logger log = Logger.getLogger(LogResponseFilter.class.getName()); @Override public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext) throws IOException { - log.info("Date: " + responseContext.getDate() + "- Status: " + responseContext.getStatus()); + log.log(Level.INFO, "Date: {0}- Status: {1}", new Object[]{responseContext.getDate(), responseContext.getStatus()}); } } diff --git a/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ManagedContactsRestClientIT.java b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ManagedContactsRestClientIT.java new file mode 100644 index 0000000000..9266684937 --- /dev/null +++ b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ManagedContactsRestClientIT.java @@ -0,0 +1,95 @@ +/* + * 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 org.jboss.as.quickstarts.jaxrsclient.test; + +import java.net.URL; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.as.quickstarts.jaxrsclient.model.Contact; +import org.jboss.as.quickstarts.jaxrsclient.rest.JaxRsActivator; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(Arquillian.class) +@RunAsClient +public class ManagedContactsRestClientIT extends AbstractContactsRestClient { + + @ArquillianResource + private URL deploymentUrl; + + @Deployment + public static WebArchive createDeployment() { + WebArchive war = ShrinkWrap.create(WebArchive.class, "managed-executor-service.war") + .addPackage(JaxRsActivator.class.getPackage()) + .addPackage(Contact.class.getPackage()) + .addClass(AbstractContactsRestClient.class) + .addAsWebInfResource(new StringAsset("\n" + + ""), "beans.xml"); + return war; + } + + @Override + protected String getRequestUrl() { + return new StringBuilder(deploymentUrl.toString()) + .append("rest/contacts") + .toString(); + } + + + // This test shows basic operations + @Test + @Override + public void cruedTest() { + super.cruedTest(); + } + + // This test shows some basic operations using ASYNC invocations and java.util.concurrent.Future + @Test + @Override + public void asyncCrudTest() throws Exception { + super.asyncCrudTest(); + } + + // This test shows how to use jakarta.ws.rs.client.InvocationCallback + @Test + @Override + public void invocationCallBackTest() throws Exception { + super.invocationCallBackTest(); + } + + // Shows how to use a delayed REST invocation + @Test + @Override + public void delayedInvocationTest() throws Exception { + super.delayedInvocationTest(); + } + + // Shows how to use Request and Response filters + @Test + @Override + public void requestResponseFiltersTest() { + super.requestResponseFiltersTest(); + } +} diff --git a/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ProvisionedManagedContactRestClientIT.java b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ProvisionedManagedContactRestClientIT.java new file mode 100644 index 0000000000..f25148662c --- /dev/null +++ b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/ProvisionedManagedContactRestClientIT.java @@ -0,0 +1,96 @@ +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.jboss.as.quickstarts.jaxrsclient.test; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +@RunWith(Arquillian.class) +@RunAsClient +public class ProvisionedManagedContactRestClientIT extends AbstractContactsRestClient { + private static final String REST_TARGET_URL = "http://localhost:8080"; + + private String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } + + @Override + String getRequestUrl() { + String host = getServerHost(); + if (host == null) { + host = REST_TARGET_URL; + } + try { + return new URI(host + "/rest/contacts").toURL().toString(); + } catch (URISyntaxException | MalformedURLException ex) { + throw new RuntimeException(ex); + } + } + + + // This test shows basic operations + @Test + @Override + public void cruedTest() { + super.cruedTest(); + } + + // This test shows some basic operations using ASYNC invocations and java.util.concurrent.Future + @Test + @Override + public void asyncCrudTest() throws Exception { + super.asyncCrudTest(); + } + + // This test shows how to use jakarta.ws.rs.client.InvocationCallback + @Test + @Override + public void invocationCallBackTest() throws Exception { + super.invocationCallBackTest(); + } + + // Shows how to use a delayed REST invocation + @Test + @Override + public void delayedInvocationTest() throws Exception { + super.delayedInvocationTest(); + } + + // Shows how to use Request and Response filters + @Test + @Override + public void requestResponseFiltersTest() { + super.requestResponseFiltersTest(); + } +} diff --git a/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/RemoteContactsRestClientIT.java b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/RemoteContactsRestClientIT.java new file mode 100644 index 0000000000..655c241ce4 --- /dev/null +++ b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/RemoteContactsRestClientIT.java @@ -0,0 +1,84 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2022, 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 org.jboss.as.quickstarts.jaxrsclient.test; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import org.junit.Test; + +public class RemoteContactsRestClientIT extends AbstractContactsRestClient { + + private static final String REST_TARGET_URL = "http://localhost:8080/jaxrs-client"; + + private String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } + + @Override + String getRequestUrl() { + String host = getServerHost(); + if (host == null) { + host = REST_TARGET_URL; + } + try { + return new URI(host + "/rest/contacts").toURL().toString(); + } catch (URISyntaxException | MalformedURLException ex) { + throw new RuntimeException(ex); + } + } + + + // This test shows basic operations + @Test + @Override + public void cruedTest() { + super.cruedTest(); + } + + // This test shows some basic operations using ASYNC invocations and java.util.concurrent.Future + @Test + @Override + public void asyncCrudTest() throws Exception { + super.asyncCrudTest(); + } + + // This test shows how to use jakarta.ws.rs.client.InvocationCallback + @Test + @Override + public void invocationCallBackTest() throws Exception { + super.invocationCallBackTest(); + } + + // Shows how to use a delayed REST invocation + @Test + @Override + public void delayedInvocationTest() throws Exception { + super.delayedInvocationTest(); + } + + // Shows how to use Request and Response filters + @Test + @Override + public void requestResponseFiltersTest() { + super.requestResponseFiltersTest(); + } +} diff --git a/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/SavedByClientRequestFilter.java b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/SavedByClientRequestFilter.java index 46b57a7fae..df80be4844 100644 --- a/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/SavedByClientRequestFilter.java +++ b/jaxrs-client/src/test/java/org/jboss/as/quickstarts/jaxrsclient/test/SavedByClientRequestFilter.java @@ -16,6 +16,7 @@ */ package org.jboss.as.quickstarts.jaxrsclient.test; +import static jakarta.ws.rs.HttpMethod.POST; import java.io.IOException; import jakarta.ws.rs.client.ClientRequestContext; @@ -31,7 +32,7 @@ public class SavedByClientRequestFilter implements ClientRequestFilter { @Override public void filter(ClientRequestContext requestContext) throws IOException { String method = requestContext.getMethod(); - if ("POST".equals(method) && requestContext.hasEntity()) { + if (POST.equals(method) && requestContext.hasEntity()) { Contact contact = (Contact) requestContext.getEntity(); contact.setSavedBy(USERNAME); requestContext.setEntity(contact); diff --git a/jaxrs-client/src/test/resources/arquillian.xml b/jaxrs-client/src/test/resources/arquillian.xml new file mode 100644 index 0000000000..31d4c3cc43 --- /dev/null +++ b/jaxrs-client/src/test/resources/arquillian.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/kitchensink/README.adoc b/kitchensink/README.adoc index 8f23353512..babe244c1b 100644 --- a/kitchensink/README.adoc +++ b/kitchensink/README.adoc @@ -20,28 +20,26 @@ The `kitchensink` quickstart is a deployable Maven 3 project designed to help yo It demonstrates how to create a compliant {javaVersion} application using JSF, CDI, JAX-RS, EJB, JPA, and Bean Validation. It also includes a persistence unit and some sample persistence and transaction code to introduce you to database access in enterprise Java. -//************************************************* -// Product Release content only -//************************************************* - -ifndef::EAPCDRelease[] - // Considerations for Use in a Production Environment include::../shared-doc/development-shortcuts.adoc[leveloffset=+1] // System Requirements include::../shared-doc/system-requirements.adoc[leveloffset=+1] // Use of {jbossHomeName} include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] -// Start the {productName} Standalone Server -include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+1] -// Build and Deploy the Quickstart -include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1] -== Access the Application +// build and run with standard server distribution +[[build_and_run_the_quickstart_with_server_dist]] +== Building and running the quickstart application with a {productName} server distribution +// Start the {productName} Standalone Server +include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+2] +// Build and Deploy the Quickstart +include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+2] + +=== Access the Application The application will be running at the following URL: http://localhost:8080/{artifactId}/. -== Server Log: Expected Warnings and Errors +=== Server Log: Expected Warnings and Errors You will see the following warnings in the server log. You can ignore these warnings. @@ -52,32 +50,13 @@ WFLYJCA0091: -ds.xml file deployments are deprecated. Support may be removed in HHH000431: Unable to determine H2 database version, certain features may not work ---- +// Testing with Arquillian +include::../shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc[leveloffset=+2] // Undeploy the Quickstart -include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] -// Run the Arquillian Tests -include::../shared-doc/run-arquillian-tests.adoc[leveloffset=+1] -// Run the Quickstart in Red Hat CodeReady Studio or Eclipse -include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1] -// Debug the Application -include::../shared-doc/debug-the-application.adoc[leveloffset=+1] +include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+2] +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] +include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1] endif::[] - -//************************************************* -// Product Release content only -//************************************************* -ifdef::ProductRelease[] - -// Getting Started with OpenShift -include::../shared-doc/openshift-getting-started.adoc[leveloffset=+1] -//Prepare OpenShift for Quickstart Deployment -include::../shared-doc/openshift-create-project.adoc[leveloffset=+1] -// Import the Latest {xpaasproduct-shortname} Image Streams and Templates -include::../shared-doc/openshift-import-imagestreams-templates.adoc[leveloffset=+1] -// Deploy the {ProductShortName} Source-to-Image (S2I) Quickstart to OpenShift -include::../shared-doc/openshift-deploy-project.adoc[leveloffset=+1] -// Openshift post deployment tasks -include::../shared-doc/openshift-post-deployment-tasks.adoc[leveloffset=+1] - - -endif::[] \ No newline at end of file +include::../shared-doc/build-and-run-the-quickstart-with-openshift.adoc[leveloffset=+1] diff --git a/kitchensink/charts/helm.yaml b/kitchensink/charts/helm.yaml new file mode 100644 index 0000000000..07593d4f85 --- /dev/null +++ b/kitchensink/charts/helm.yaml @@ -0,0 +1,6 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: kitchensink +deploy: + replicas: 1 \ No newline at end of file diff --git a/kitchensink/pom.xml b/kitchensink/pom.xml index e9e2efb771..1dbbcf5b01 100644 --- a/kitchensink/pom.xml +++ b/kitchensink/pom.xml @@ -45,6 +45,9 @@ 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final @@ -118,10 +121,10 @@ + of them are provided by JBoss EAP --> + JBoss EAP --> jakarta.enterprise jakarta.enterprise.cdi-api @@ -138,7 +141,7 @@ + typesafe criteria queries --> org.hibernate.orm hibernate-jpamodelgen @@ -152,8 +155,8 @@ + Provides portable constraints such as @Email + Hibernate Validator is shipped in JBoss EAP --> org.hibernate.validator hibernate-validator @@ -167,7 +170,7 @@ + annotations are incorrectly used. --> org.hibernate.validator hibernate-validator-annotation-processor @@ -175,7 +178,7 @@ + JBoss EAP --> jakarta.persistence jakarta.persistence-api @@ -184,7 +187,7 @@ + JPA from JUnit/TestNG --> org.jboss.arquillian.junit arquillian-junit-container @@ -198,7 +201,7 @@ + as the API is included in JBoss EAP --> jakarta.annotation jakarta.annotation-api @@ -206,7 +209,7 @@ + JBoss EAP --> jakarta.ejb jakarta.ejb-api @@ -214,7 +217,7 @@ + JBoss EAP --> jakarta.faces jakarta.faces-api @@ -222,7 +225,7 @@ + in JBoss EAP --> jakarta.ws.rs jakarta.ws.rs-api @@ -234,19 +237,88 @@ jakarta.xml.bind-api provided + + + jakarta.json + jakarta.json-api + test + + + org.eclipse.parsson + parsson + test + - - - ${project.artifactId} - - + + provisioned-server + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + cloud-server + h2-driver + ejb + jsf + + ROOT.war + + + + + package + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + ${project.build.directory}/server + + + **/MemberRegistrationIT + + + **/RemoteMemberRegistrationIT + + + + + + integration-test + verify + + + + + + + + This profile will start a new JBoss EAP instance, and execute the test, shutting it down when done. + Run with: mvn clean verify -Parq-managed --> arq-managed @@ -261,6 +333,14 @@ org.apache.maven.plugins maven-failsafe-plugin ${version.failsafe.plugin} + + + **/MemberRegistrationIT + + + **/RemoteMemberRegistrationIT + + @@ -275,7 +355,7 @@ + Run with: mvn clean verify -Parq-remote --> arq-remote @@ -290,6 +370,14 @@ org.apache.maven.plugins maven-failsafe-plugin ${version.failsafe.plugin} + + + **/RemoteMemberRegistrationIT + + + **/MemberRegistrationIT + + @@ -302,6 +390,41 @@ + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + + cloud-server + h2-driver + ejb + jsf + + ROOT.war + + + + + package + + + + + + + diff --git a/kitchensink/src/main/webapp/index.html b/kitchensink/src/main/webapp/index.html index 5d4d3cbb4d..aa3c7c294e 100644 --- a/kitchensink/src/main/webapp/index.html +++ b/kitchensink/src/main/webapp/index.html @@ -17,7 +17,7 @@ - - - + + + diff --git a/kitchensink/src/main/webapp/index.xhtml b/kitchensink/src/main/webapp/index.xhtml index fd25bef908..eee432fe17 100644 --- a/kitchensink/src/main/webapp/index.xhtml +++ b/kitchensink/src/main/webapp/index.xhtml @@ -16,10 +16,10 @@ limitations under the License. --> + xmlns:ui="jakarta.faces.facelets" + xmlns:f="jakarta.faces.core" + xmlns:h="jakarta.faces.html" + template="/WEB-INF/templates/default.xhtml">

Welcome to JBoss!

@@ -43,18 +43,18 @@ + value="#{newMember.phoneNumber}" />

+ action="#{memberController.register}" + value="Register" styleClass="register" /> + errorClass="invalid" infoClass="valid" + warnClass="warning" globalOnly="true" />

@@ -63,23 +63,23 @@ No registered members. + rendered="#{not empty members}" + styleClass="simpletablestyle"> Id - #{_member.id} + #{_member.id} Name - #{_member.name} + #{_member.name} Email - #{_member.email} + #{_member.email} Phone # - #{_member.phoneNumber} + #{_member.phoneNumber} REST URL @@ -87,7 +87,7 @@ href="#{request.contextPath}/rest/members/#{_member.id}">/rest/members/#{_member.id} - REST URL for all members: /rest/members diff --git a/kitchensink/src/test/java/org/jboss/as/quickstarts/kitchensink/test/MemberRegistrationIT.java b/kitchensink/src/test/java/org/jboss/as/quickstarts/kitchensink/test/MemberRegistrationIT.java index af9aaf8708..b7522976e4 100644 --- a/kitchensink/src/test/java/org/jboss/as/quickstarts/kitchensink/test/MemberRegistrationIT.java +++ b/kitchensink/src/test/java/org/jboss/as/quickstarts/kitchensink/test/MemberRegistrationIT.java @@ -29,7 +29,7 @@ import org.jboss.as.quickstarts.kitchensink.util.Resources; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.asset.StringAsset; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Test; import org.junit.runner.RunWith; @@ -41,7 +41,10 @@ public static Archive createTestArchive() { return ShrinkWrap.create(WebArchive.class, "test.war") .addClasses(Member.class, MemberRegistration.class, Resources.class) .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml") - .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") + .addAsWebInfResource(new StringAsset("\n" + + ""), "beans.xml") // Deploy our test datasource .addAsWebInfResource("test-ds.xml"); } diff --git a/kitchensink/src/test/java/org/jboss/as/quickstarts/kitchensink/test/RemoteMemberRegistrationIT.java b/kitchensink/src/test/java/org/jboss/as/quickstarts/kitchensink/test/RemoteMemberRegistrationIT.java new file mode 100644 index 0000000000..6dde3a7654 --- /dev/null +++ b/kitchensink/src/test/java/org/jboss/as/quickstarts/kitchensink/test/RemoteMemberRegistrationIT.java @@ -0,0 +1,77 @@ +/* + * 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 org.jboss.as.quickstarts.kitchensink.test; + +import jakarta.json.Json; +import jakarta.json.JsonObject; + +import java.util.logging.Logger; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +import org.jboss.as.quickstarts.kitchensink.model.Member; +import org.junit.Assert; +import org.junit.Test; + +public class RemoteMemberRegistrationIT { + + private static final Logger log = Logger.getLogger(RemoteMemberRegistrationIT.class.getName()); + + protected URI getHTTPEndpoint() { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080/kitchensink"; + } + try { + return new URI(host + "/rest/members"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + private String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } + + @Test + public void testRegister() throws Exception { + Member newMember = new Member(); + newMember.setName("Jane Doe"); + newMember.setEmail("jane@mailinator.com"); + newMember.setPhoneNumber("2125551234"); + JsonObject json = Json.createObjectBuilder() + .add("name", "Jane Doe") + .add("email", "jane@mailinator.com") + .add("phoneNumber", "2125551234").build(); + HttpRequest request = HttpRequest.newBuilder(getHTTPEndpoint()) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(json.toString())) + .build(); + HttpResponse response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString()); + Assert.assertEquals(200, response.statusCode()); + Assert.assertEquals("", response.body().toString() ); + } + +} diff --git a/microprofile-jwt/pom.xml b/microprofile-jwt/pom.xml index 1d09937299..fe27c3a1a3 100644 --- a/microprofile-jwt/pom.xml +++ b/microprofile-jwt/pom.xml @@ -369,4 +369,3 @@
- diff --git a/numberguess/README.adoc b/numberguess/README.adoc index e4e017b592..d6d0743424 100644 --- a/numberguess/README.adoc +++ b/numberguess/README.adoc @@ -16,51 +16,30 @@ The `numberguess` quickstart demonstrates the use of CDI (Contexts and Dependen The `numberguess` quickstart demonstrates the use of CDI (Contexts and Dependency Injection) and JSF (JavaServer Faces) in {productNameFull}. - -//************************************************* -// Product Release content only -//************************************************* - -ifndef::EAPCDRelease[] - - // System Requirements include::../shared-doc/system-requirements.adoc[leveloffset=+1] // Use of {jbossHomeName} include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] + +// build and run with standard server distribution +[[build_and_run_the_quickstart_with_server_dist]] +== Building and running the quickstart application with a {productName} server distribution // Start the {productName} Standalone Server -include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+1] +include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+2] // Build and Deploy the Quickstart -include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1] +include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+2] -== Access the Application +=== Access the Application The application will be running at the following URL: http://localhost:8080/{artifactId}/. +// Testing with Arquillian +include::../shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc[leveloffset=+2] // Undeploy the Quickstart -include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] -// Run the Quickstart in Red Hat CodeReady Studio or Eclipse -include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1] -// Debug the Application -include::../shared-doc/debug-the-application.adoc[leveloffset=+1] +include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+2] +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] +include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1] endif::[] - -//************************************************* -// Product Release content only -//************************************************* -ifdef::ProductRelease[] - -// Getting Started with OpenShift -include::../shared-doc/openshift-getting-started.adoc[leveloffset=+1] -//Prepare OpenShift for Quickstart Deployment -include::../shared-doc/openshift-create-project.adoc[leveloffset=+1] -// Import the Latest {xpaasproduct-shortname} Image Streams and Templates -include::../shared-doc/openshift-import-imagestreams-templates.adoc[leveloffset=+1] -// Deploy the {ProductShortName} Source-to-Image (S2I) Quickstart to OpenShift -include::../shared-doc/openshift-deploy-project.adoc[leveloffset=+1] -// Openshift post deployment tasks -include::../shared-doc/openshift-post-deployment-tasks.adoc[leveloffset=+1] - - -endif::[] \ No newline at end of file +include::../shared-doc/build-and-run-the-quickstart-with-openshift.adoc[leveloffset=+1] \ No newline at end of file diff --git a/numberguess/charts/helm.yaml b/numberguess/charts/helm.yaml new file mode 100644 index 0000000000..716217e700 --- /dev/null +++ b/numberguess/charts/helm.yaml @@ -0,0 +1,6 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: numberguess +deploy: + replicas: 1 \ No newline at end of file diff --git a/numberguess/pom.xml b/numberguess/pom.xml index ce867d5b17..13f718555e 100644 --- a/numberguess/pom.xml +++ b/numberguess/pom.xml @@ -45,6 +45,9 @@ 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final @@ -125,7 +128,7 @@ + as the API is included in JBoss EAP --> jakarta.annotation jakarta.annotation-api @@ -139,6 +142,164 @@ provided + + + org.junit.jupiter + junit-jupiter-api + 5.9.1 + test + + + + org.junit.jupiter + junit-jupiter-params + 5.9.1 + test + + + + org.junit.jupiter + junit-jupiter-engine + 5.9.1 + test + + + + org.jboss.arquillian.junit5 + arquillian-junit5-container + test + + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet-jakarta + test + + + + + provisioned-server + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + cloud-server + jsf + + ROOT.war + + + + + package + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + ${project.build.directory}/server + + + **/ProvisionedManagedNumberGuessIT + + + **/RemoteNumberGuessIT + + + + + + integration-test + verify + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + + cloud-server + jsf + + ROOT.war + + + + + package + + + + + + + + + arq-remote + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + **/RemoteNumberGuessIT + + + **/ProvisionedManagedNumberGuessIT + + + + + + integration-test + verify + + + + + + + + diff --git a/numberguess/src/main/webapp/home.xhtml b/numberguess/src/main/webapp/home.xhtml index 103d4105a3..3c2fe83fe4 100644 --- a/numberguess/src/main/webapp/home.xhtml +++ b/numberguess/src/main/webapp/home.xhtml @@ -15,60 +15,60 @@ limitations under the License. --> + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + xmlns:ui="jakarta.faces.facelets" + xmlns:h="jakarta.faces.html" + xmlns:f="jakarta.faces.core"> - - -numberguess - + + + numberguess + - -
-

Guess a number...

- + +
+

Guess a number...

+ - -
- - - -
+ +
+ + + +
- -
- I'm thinking of a number between #{game.smallest} and #{game.biggest}. You have - #{game.remainingGuesses} guesses remaining. -
+ +
+ I'm thinking of a number between #{game.smallest} and #{game.biggest}. You have + #{game.remainingGuesses} guesses remaining. +
- - -
- Your guess: - - -
-
- -
-
+ + +
+ Your guess: + + +
+
+ +
+ -
+
-
+
- + diff --git a/numberguess/src/test/java/org/jboss/as/quickstarts/numberguess/ProvisionedManagedNumberGuessIT.java b/numberguess/src/test/java/org/jboss/as/quickstarts/numberguess/ProvisionedManagedNumberGuessIT.java new file mode 100644 index 0000000000..84a0019897 --- /dev/null +++ b/numberguess/src/test/java/org/jboss/as/quickstarts/numberguess/ProvisionedManagedNumberGuessIT.java @@ -0,0 +1,51 @@ +/* + * 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 org.jboss.as.quickstarts.numberguess; + + +import java.net.URI; +import java.net.URISyntaxException; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit5.ArquillianExtension; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(ArquillianExtension.class) +@RunAsClient +public class ProvisionedManagedNumberGuessIT extends RemoteNumberGuessIT { + + @Override + protected URI getHTTPEndpoint(String path) { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080/"; + } + try { + return new URI(host + path); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + @Test + @Override + public void testGuessNumber() throws Exception { + guessNumber(); + } + +} diff --git a/numberguess/src/test/java/org/jboss/as/quickstarts/numberguess/RemoteNumberGuessIT.java b/numberguess/src/test/java/org/jboss/as/quickstarts/numberguess/RemoteNumberGuessIT.java new file mode 100644 index 0000000000..f813572724 --- /dev/null +++ b/numberguess/src/test/java/org/jboss/as/quickstarts/numberguess/RemoteNumberGuessIT.java @@ -0,0 +1,100 @@ +/* + * 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 org.jboss.as.quickstarts.numberguess; + +import java.io.IOException; +import java.net.CookieManager; +import java.net.CookiePolicy; +import java.util.logging.Logger; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublisher; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class RemoteNumberGuessIT { + + private java.util.Random random = new java.util.Random(System.currentTimeMillis()); + private static final Logger log = Logger.getLogger(RemoteNumberGuessIT.class.getName()); + + protected URI getHTTPEndpoint(String path) { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080/numberguess"; + } + try { + return new URI(host + path); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + protected String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } + + @Test + public void testGuessNumber() throws Exception { + guessNumber(); + } + + public void guessNumber() throws IOException, InterruptedException { + HttpClient client = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.ALWAYS) + .cookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ALL)) + .build(); + HttpRequest request = HttpRequest.newBuilder(getHTTPEndpoint("/home.jsf")) + .POST(ofFormData(Map.of("numberGuess:inputGuess", (Object) getNumber()))) + .build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + Assertions.assertEquals(200, response.statusCode()); + Assertions.assertTrue(response.body().toString().contains("
data) { + StringBuilder builder = new StringBuilder(); + for (Map.Entry entry : data.entrySet()) { + if (builder.length() > 0) { + builder.append("&"); + } + builder + .append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8)); + builder.append("="); + builder + .append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8)); + } + return BodyPublishers.ofString(builder.toString()); + } + +} diff --git a/pom.xml b/pom.xml index 3276835b7f..973dfc0105 100644 --- a/pom.xml +++ b/pom.xml @@ -52,7 +52,7 @@ WildFly 2.1.0 - 2.0.2.Final + 4.0.0.Beta3 1.0.7.Final 2.3.0.Final diff --git a/servlet-security/README.adoc b/servlet-security/README.adoc index 91884753eb..b58482eec8 100644 --- a/servlet-security/README.adoc +++ b/servlet-security/README.adoc @@ -4,6 +4,7 @@ include::../shared-doc/attributes.adoc[] :author: Sherif F. Makary, Pedro Igor, Stefan Guilhen :level: Intermediate :technologies: Servlet, Security +:openshift: true [abstract] The `servlet-security` quickstart demonstrates the use of Jakarta EE declarative security to control access to Servlets and Security in {productName}. @@ -53,14 +54,17 @@ include::../shared-doc/development-shortcuts.adoc[leveloffset=+1] include::../shared-doc/system-requirements.adoc[leveloffset=+1] // Use of {jbossHomeName} include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] + +// build and run with standard server distribution +[[build_and_run_the_quickstart_with_server_dist]] +== Building and running the quickstart application with a {productName} server distribution // Back Up the {productName} Standalone Server Configuration -include::../shared-doc/back-up-server-standalone-configuration.adoc[leveloffset=+1] +include::../shared-doc/back-up-server-standalone-configuration.adoc[leveloffset=+2] // Start the {productName} Standalone Server -include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+1] - +include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+2] [[configure_the_server]] -== Configure the Server +=== Configure the Server You can configure the server by running JBoss CLI commands. For your convenience, this quickstart batches the commands into a `configure-server.cli` script provided in the root directory of this quickstart. @@ -89,7 +93,7 @@ The batch executed successfully . Stop the {productName} server. -== Review the Modified Server Configuration +=== Review the Modified Server Configuration After stopping the server, open the `__{jbossHomeName}__/standalone/configuration/standalone.xml` file and review the changes. @@ -164,9 +168,9 @@ The purpose of a `role-decoder` is to instruct the security domain how roles are This configuration tells `Undertow` that applications with the `servlet-security-quickstart` security domain, as defined in the `jboss-web.xml` or by using the `@SecurityDomain` annotation in the Servlet class, should use the `security-domain` named `servlet-security-quickstart-sd`. // Build and Deploy the Quickstart -include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1] +include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+2] -== Access the Application +=== Access the Application The application will be running at the following URL http://localhost:8080/{artifactId}/. @@ -190,11 +194,13 @@ Now close the browser. Open a new browser and log in with username `guest` and p Forbidden ---- +// Testing with Arquillian +include::../shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc[leveloffset=+2] // Undeploy the Quickstart -include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] +include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+2] // Restore the {productName} Standalone Server Configuration -include::../shared-doc/restore-standalone-server-configuration.adoc[leveloffset=+1] +include::../shared-doc/restore-standalone-server-configuration.adoc[leveloffset=+2] // Additional information about this script This script removes the `application-security-domain` configuration from the `undertow` subsystem, the `http-authentication-factory`, `security-domain`, `security-realm` and `role-decoder` configuration from the `elytron` subsystem and it also removes the datasource used for this quickstart. You should see the following result when you run the script: @@ -206,23 +212,10 @@ process-state: reload-required ---- // Restore the {productName} Standalone Server Configuration Manually -include::../shared-doc/restore-standalone-server-configuration-manual.adoc[leveloffset=+2] -// Run the Quickstart in Red Hat CodeReady Studio or Eclipse -include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1] - -// Additional Red Hat CodeReady Studio instructions -* Make sure you configure the server by running the JBoss CLI commands as described above under xref:configure_the_server{Configure the Server]. Stop the server at the end of that step. -* Make sure you xref:restore_the_server_configuration[restore the {productName} server configuration] when you have completed testing this quickstart. - -// Debug the Application -include::../shared-doc/debug-the-application.adoc[leveloffset=+1] - -//************************************************* -// Product Release content only -//************************************************* -ifdef::ProductRelease[] - -// Quickstart not compatible with OpenShift -include::../shared-doc/openshift-incompatibility.adoc[leveloffset=+1] +include::../shared-doc/restore-standalone-server-configuration-manual.adoc[leveloffset=+3] -endif::[] \ No newline at end of file +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] +include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1] +endif::[] +include::../shared-doc/build-and-run-the-quickstart-with-openshift.adoc[leveloffset=+1] diff --git a/servlet-security/charts/helm.yaml b/servlet-security/charts/helm.yaml new file mode 100644 index 0000000000..6d710d083a --- /dev/null +++ b/servlet-security/charts/helm.yaml @@ -0,0 +1,6 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: servlet-security +deploy: + replicas: 1 diff --git a/servlet-security/configure-server.cli b/servlet-security/configure-server.cli index 2791666240..95ceea1bf3 100644 --- a/servlet-security/configure-server.cli +++ b/servlet-security/configure-server.cli @@ -18,6 +18,6 @@ batch run-batch # Reload the server configuration -reload +#reload diff --git a/servlet-security/pom.xml b/servlet-security/pom.xml index c315072bfe..7abb68385b 100644 --- a/servlet-security/pom.xml +++ b/servlet-security/pom.xml @@ -46,6 +46,10 @@ 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final + 3.0.0.Final @@ -126,7 +130,7 @@ + as the API is included in JBoss EAP --> jakarta.annotation jakarta.annotation-api @@ -146,15 +150,179 @@ provided + + + junit + junit + test + + + + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet + test + - - - - - org.wildfly.plugins - wildfly-maven-plugin - - - + + + provisioned-server + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly + wildfly-datasources-galleon-pack + ${version.wildfly-datasources-galleon-pack} + + + + cloud-server + h2-datasource + + ROOT.war + + + + + + + false + + + + + + + package + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + ${project.build.directory}/server + + + **/ProvisionedManagedSecureIT + + + **/RemoteSecureIT + + + + + + integration-test + verify + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + org.wildfly + wildfly-datasources-galleon-pack + ${version.wildfly-datasources-galleon-pack} + + + + cloud-server + h2-datasource + + ROOT.war + + + + + + + false + + + + + + + package + + + + + + + + + arq-remote + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + **/RemoteSecureIT + + + **/ProvisionedManagedSecureIT + + + + + + integration-test + verify + + + + + + + + diff --git a/servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/SecuredServlet.java b/servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/SecuredServlet.java index 25ad4562d2..9ca07b46ba 100644 --- a/servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/SecuredServlet.java +++ b/servlet-security/src/main/java/org/jboss/as/quickstarts/servlet_security/SecuredServlet.java @@ -47,16 +47,12 @@ public class SecuredServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); - Principal principal = null; - String authType = null; - String remoteUser = null; - // Get security principal - principal = req.getUserPrincipal(); + Principal principal = req.getUserPrincipal(); // Get user name from login principal - remoteUser = req.getRemoteUser(); + String remoteUser = req.getRemoteUser(); // Get authentication type - authType = req.getAuthType(); + String authType = req.getAuthType(); writer.println(PAGE_HEADER); writer.println("

" + "Successfully called Secured Servlet " + "

"); diff --git a/servlet-security/src/main/webapp/index.html b/servlet-security/src/main/webapp/index.html index db8a28efc5..4206889a5d 100644 --- a/servlet-security/src/main/webapp/index.html +++ b/servlet-security/src/main/webapp/index.html @@ -17,7 +17,7 @@ - - - + + + diff --git a/servlet-security/src/test/java/org/jboss/as/quickstarts/servlet_security/ProvisionedManagedSecureIT.java b/servlet-security/src/test/java/org/jboss/as/quickstarts/servlet_security/ProvisionedManagedSecureIT.java new file mode 100644 index 0000000000..ba24ab246c --- /dev/null +++ b/servlet-security/src/test/java/org/jboss/as/quickstarts/servlet_security/ProvisionedManagedSecureIT.java @@ -0,0 +1,49 @@ +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.jboss.as.quickstarts.servlet_security; + +import java.net.URI; +import java.net.URISyntaxException; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.junit.runner.RunWith; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +@RunWith(Arquillian.class) +@RunAsClient +public class ProvisionedManagedSecureIT extends RemoteSecureIT { + + @Override + protected URI getHTTPEndpoint() { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080"; + } + try { + return new URI(host + "/SecuredServlet"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/servlet-security/src/test/java/org/jboss/as/quickstarts/servlet_security/RemoteSecureIT.java b/servlet-security/src/test/java/org/jboss/as/quickstarts/servlet_security/RemoteSecureIT.java new file mode 100644 index 0000000000..ddd7426592 --- /dev/null +++ b/servlet-security/src/test/java/org/jboss/as/quickstarts/servlet_security/RemoteSecureIT.java @@ -0,0 +1,95 @@ +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.jboss.as.quickstarts.servlet_security; + +import java.io.IOException; +import java.net.Authenticator; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import org.junit.Assert; +import org.junit.Test; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ + +public class RemoteSecureIT { + + protected URI getHTTPEndpoint() { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080/servlet-security"; + } + try { + return new URI(host + "/SecuredServlet"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + protected static String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } + + @Test + public void testConnectOk() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder(getHTTPEndpoint()) + .GET() + .build(); + HttpClient client = HttpClient.newBuilder().authenticator(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication("quickstartUser", "quickstartPwd1!".toCharArray()); + } + }).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + Assert.assertEquals(200, response.statusCode()); + String[] lines = response.body().toString().split(System.lineSeparator()); + Assert.assertEquals("

Successfully called Secured Servlet

", lines[1].trim()); + Assert.assertEquals("

Principal : quickstartUser

", lines[2].trim()); + Assert.assertEquals("

Remote User : quickstartUser

", lines[3].trim()); + Assert.assertEquals("

Authentication Type : BASIC

", lines[4].trim()); + } + + @Test + public void testConnectNotOk() throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder(getHTTPEndpoint()) + .GET() + .build(); + HttpClient client = HttpClient.newBuilder().authenticator(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication("guest", "guestPwd1!".toCharArray()); + } + }).build(); + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + Assert.assertEquals(403, response.statusCode()); + } +} diff --git a/shared-doc/attributes.adoc b/shared-doc/attributes.adoc index fc77313213..2a36779fc4 100644 --- a/shared-doc/attributes.adoc +++ b/shared-doc/attributes.adoc @@ -30,6 +30,7 @@ ifdef::ProductRelease[] :DocInfoProductNumber: {productVersion} :WildFlyQuickStartRepoTag: EAP_7.4.0.GA :productImageVersion: 7.4.0 +:helmChartName: jboss-eap/eap-xp3 endif::[] ifdef::EAPXPRelease[] @@ -57,10 +58,11 @@ ifdef::ProductRelease,EAPXPRelease[] // END ifdef::ProductRelease,EAPXPRelease[] endif::[] -ifndef::ProductRelease,EAPCDRelease,EAPXPRelease[] +ifndef::ProductRelease,EAPXPRelease[] // WildFly project :productName: WildFly :productNameFull: WildFly Application Server +:ProductShortName: WildFly :jbossHomeName: WILDFLY_HOME :productVersion: 27 :productImageVersion: 27.0 @@ -163,7 +165,7 @@ endif::[] //************************* // Other values //************************* -:buildRequirements: Java 8.0 (Java SDK 1.8) or later and Maven 3.3.1 or later +:buildRequirements: Java 11.0 (Java SDK 11) or later and Maven 3.6.0 or later :jbdsEapServerName: Red Hat JBoss Enterprise Application Platform 7.3 :javaVersion: Jakarta EE 10 ifdef::EAPXPRelease[] diff --git a/shared-doc/build-and-deploy-the-quickstart.adoc b/shared-doc/build-and-deploy-the-quickstart.adoc index d062c1aebb..79cbb257f2 100644 --- a/shared-doc/build-and-deploy-the-quickstart.adoc +++ b/shared-doc/build-and-deploy-the-quickstart.adoc @@ -54,15 +54,15 @@ endif::archiveDir[] ifndef::mavenCommand[] ifeval::["{archiveType}"=="ear"] -:mavenCommand: clean install wildfly:deploy +:mavenCommand: clean install endif::[] ifeval::["{archiveType}"=="war"] -:mavenCommand: clean package wildfly:deploy +:mavenCommand: clean package endif::[] ifeval::["{archiveType}"=="jar"] -:mavenCommand: clean install wildfly:deploy +:mavenCommand: clean install endif::[] endif::mavenCommand[] @@ -77,15 +77,22 @@ ifdef::reactive-messaging[] $ __{jbossHomeName}__/bin/jboss-cli.sh --connect --file=enable-reactive-messaging.cli ---- endif::reactive-messaging[] -. Type the following command to build the artifacts. +. Type the following command to build the quickstart. + [source,subs="attributes+",options="nowrap"] ---- $ mvn {mavenCommand} ---- +. Type the following command to deploy the quickstart. ++ +[source,subs="attributes+",options="nowrap"] +---- +$ mvn wildfly:deploy +---- + ifdef::rest-client-qs[] -This deploys the `country-server` and `country-client` to the running instance of the server. +This builds and deploys the `country-server` and `country-client` to the running instance of the server. You should see a message in the server log indicating that the archives deployed successfully. endif::[] diff --git a/shared-doc/build-and-run-the-quickstart-with-openshift.adoc b/shared-doc/build-and-run-the-quickstart-with-openshift.adoc new file mode 100644 index 0000000000..15b3cf6405 --- /dev/null +++ b/shared-doc/build-and-run-the-quickstart-with-openshift.adoc @@ -0,0 +1,8 @@ +[[build_and_run_the_quickstart_on_openshift]] += Building and running the quickstart application with OpenShift +// Getting Started with Helm +include::../shared-doc/helm-getting-started-overview.adoc[leveloffset=+1] +//Prepare Helm for Quickstart Deployment +include::../shared-doc/helm-deploy-project.adoc[leveloffset=+1] +// Testing on Openshift +include::../shared-doc/run-arquillian-integration-tests-with-openshift.adoc[leveloffset=+1] diff --git a/shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc b/shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc new file mode 100644 index 0000000000..e5fffa6023 --- /dev/null +++ b/shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc @@ -0,0 +1,70 @@ +[[build_and_run_the_quickstart_with_provisioned_server]] += Building and running the quickstart application with provisioned {productName} server + +Instead of using a standard {productName} server distribution, you can alternatively provision a {productName} server to deploy and run the quickstart, by activating the Maven profile named `provisioned-server` when building the quickstart: + +ifndef::mavenServerProvisioningCommand[] +ifeval::["{archiveType}"=="ear"] +:mavenServerProvisioningCommand: clean install +endif::[] + +ifeval::["{archiveType}"=="war"] +:mavenServerProvisioningCommand: clean package +endif::[] + +ifeval::["{archiveType}"=="jar"] +:mavenServerProvisioningCommand: clean install +endif::[] + +[source,subs="attributes+",options="nowrap"] +---- +$ mvn {mavenServerProvisioningCommand} -Pprovisioned-server +---- + +The provisioned {productName} server, with the quickstart deployed, can then be found in the `target/server` directory, and its usage is similar to a standard server distribution. + +The server provisioning functionality is provided by the WildFly Maven Plugin, and you may find its configuration in the quickstart `pom.xml`: + +[source,xml,subs="attributes+"] +---- + + provisioned-server + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + + cloud-server + + + ROOT.war + + + + + package + + + + + + + + +---- + +[NOTE] +==== +Since the plugin configuration above deploys quickstart on root web context of the provisioned server, the URL to access the application should not have the `/{artifactId}` path segment after `HOST:PORT`. +==== + +// Testing with Arquillian +include::../shared-doc/run-arquillian-integration-tests-with-provisioned-server.adoc[leveloffset=+1] diff --git a/shared-doc/helm-deploy-project.adoc b/shared-doc/helm-deploy-project.adoc new file mode 100644 index 0000000000..1ab7f963e0 --- /dev/null +++ b/shared-doc/helm-deploy-project.adoc @@ -0,0 +1,66 @@ +[[deploy_helm]] +== Deploy the {ProductShortName} Source-to-Image (S2I) Quickstart to OpenShift with Helm Charts + +Log in to your OpenShift instance using the `oc login` command. +The backend will be built and deployed on OpenShift with a Helm Chart for {productName}. + +Navigate to the root directory of this quickstart and run the following command: +[source,options="nowrap",subs="+attributes"] +---- +$ helm install {artifactId} -f charts/helm.yaml {helmChartName} +NAME: {artifactId} +... +STATUS: deployed +REVISION: 1 +---- + +The Helm Chart for this quickstart contains all the information to build an image from the source code using S2I on Java 17: + +[source,options="nowrap",subs="+attributes"] +---- +build: + uri: {githubRepoCodeUrl} + contextDir: {artifactId} +deploy: + replicas: 1 +---- + +This will create a new deployment on OpenShift and deploy the application. + +If you want to see all the configuration elements to customize your deployment you can use the following command: +[source,options="nowrap",subs="+attributes"] +---- +$ helm show readme {helmChartName} +---- + +Let’s wait for the application to be built and deployed: +[source,options="nowrap",subs="+attributes"] +---- +$ oc get deployment {artifactId} -w +NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE +{artifactId} 1 1 1 0 12s +... +{artifactId} 1 1 1 1 2m +---- + +Get the URL of the route to the deployment. + +[source,options="nowrap",subs="+attributes"] +---- +$ oc get route {artifactId} -o jsonpath="{.spec.host}" +---- +Access the application in your web browser using the displayed URL. + +[NOTE] +==== +The Maven profile named `openshift` is used by the Helm chart to provision the server with the quickstart deployed on the root web context, and thus the application should be accessed with the URL without the `/{artifactId}` path segment after `HOST:PORT`. +==== + +[[undeploy_helm]] +== Undeploy the {ProductShortName} Source-to-Image (S2I) Quickstart from OpenShift with Helm Charts + + +[source,options="nowrap",subs="+attributes"] +---- +$ helm uninstall {artifactId} +---- \ No newline at end of file diff --git a/shared-doc/helm-getting-started-overview.adoc b/shared-doc/helm-getting-started-overview.adoc new file mode 100644 index 0000000000..2f876b2bd3 --- /dev/null +++ b/shared-doc/helm-getting-started-overview.adoc @@ -0,0 +1,6 @@ +[[getting_started_with_helm]] += Getting Started with {xpaasproduct-shortname} and Helm Charts + +This section contains the basic instructions to build and deploy this quickstart to {xpaasproduct-shortname} or {xpaasproductOpenShiftOnline-shortname} using Helm Charts. + +include::../shared-doc/helm-pre-requisites.adoc[] \ No newline at end of file diff --git a/shared-doc/helm-pre-requisites.adoc b/shared-doc/helm-pre-requisites.adoc new file mode 100644 index 0000000000..cef861a32e --- /dev/null +++ b/shared-doc/helm-pre-requisites.adoc @@ -0,0 +1,39 @@ +[[prerequisites_helm_openshift]] +== Prerequisites + +* You must be logged in OpenShift and have an `oc` client to connect to OpenShift +* https://helm.sh[Helm] must be installed to deploy the backend on OpenShift. + +Once you have installed Helm, you need to add the repository that provides Helm Charts for {productName}. + +ifndef::ProductRelease,EAPXPRelease[] +[source,options="nowrap"] +---- +$ helm repo add wildfly https://docs.wildfly.org/wildfly-charts/ +"wildfly" has been added to your repositories +$ helm search repo wildfly +NAME CHART VERSION APP VERSION DESCRIPTION +wildfly/wildfly ... ... Build and Deploy WildFly applications on OpenShift +wildfly/wildfly-common ... ... A library chart for WildFly-based applications +---- +endif::[] +ifdef::ProductRelease[] +[source,options="nowrap"] +---- +$ helm repo add jboss-eap https://jbossas.github.io/eap-charts/ +"jboss-eap" has been added to your repositories +$ helm search repo jboss-eap +NAME CHART VERSION APP VERSION DESCRIPTION +jboss-eap/eap74 ... ... A Helm chart to build and deploy EAP 7.4 applications +---- +endif::[] +ifdef::EAPXPRelease[] +[source,options="nowrap"] +---- +$ helm repo add jboss-eap https://jbossas.github.io/eap-charts/ +"jboss-eap" has been added to your repositories +$ helm search repo jboss-eap +NAME CHART VERSION APP VERSION DESCRIPTION +jboss-eap/eap-xp3 ... ... A Helm chart to build and deploy EAP XP 3 applications +---- +endif::[] diff --git a/shared-doc/run-arquillian-functional-tests-remote.adoc b/shared-doc/run-arquillian-functional-tests-remote.adoc new file mode 100644 index 0000000000..c9bfbba246 --- /dev/null +++ b/shared-doc/run-arquillian-functional-tests-remote.adoc @@ -0,0 +1,37 @@ +[[run_the_arquillian_functional_tests-remote]] += Run the Arquillian Functional Tests +//****************************************************************************** +// Include this template if your quickstart provides standard Arquillian +// functional tests. +//****************************************************************************** + +This quickstart provides Arquillian functional tests. They are located under the `src/tests/` directory. Functional tests verify that your application behaves correctly from the user's point of view and simulate clicking around the web page as a normal user would do. + +Follow these steps to run the functional tests. + +ifdef::standalone-server-type[] +. xref:start_the_eap_standalone_server[Start the {productName} server] as described above. + +endif::[] + +ifdef::managed-domain-type[] +. xref:start_the_eap_managed_domain[Start the {productName} server] as described above. +endif::[] + +ifdef::standalone-server-type,managed-domain-type[] +. Type the following command to run the `verify` goal with the `arq-remote` profile activated. +endif::[] +ifndef::standalone-server-type,managed-domain-type[] +. You need to start the provisioned server or the bootable jar server, as previously described. +. Type the following command to run the `verify` goal with the `arq-remote` profile activated. +endif::[] + +[source,options="nowrap"] +---- +$ mvn verify -Parq-remote +---- + +[NOTE] +==== +You may also use the environment variable `SERVER_HOST` or the system property `server.host` to define the target host of the tests. +==== diff --git a/shared-doc/run-arquillian-integration-tests-with-openshift.adoc b/shared-doc/run-arquillian-integration-tests-with-openshift.adoc new file mode 100644 index 0000000000..27c6f39d52 --- /dev/null +++ b/shared-doc/run-arquillian-integration-tests-with-openshift.adoc @@ -0,0 +1,24 @@ +[[run_the_arquillian_integration_tests_with_openshift]] += Run the Arquillian Integration Tests with OpenShift +//****************************************************************************** +// Include this template if your quickstart provides Openshift Arquillian +// integration tests. +//****************************************************************************** + +This quickstart includes Arquillian integration tests. They are located under the `src/test/` directory. The integration tests verify that the quickstart runs correctly when deployed on the server. + +[NOTE] +==== +The Arquillian integration tests expect a deployed application, so make sure you have deployed the quickstart on OpenShift before you begin. +==== + +Run the integration tests using the following command to run the `verify` goal with the `arq-remote` profile activated and the proper URL: +[source,options="nowrap",subs="+attributes"] +---- +$ mvn clean verify -Parq-remote -Dserver.host=https://$(oc get route {artifactId} --template='{{ .spec.host }}') +---- + +[NOTE] +==== +The tests are using SSL to connect to the quickstart running on OpenShift. So you need the certificates to be trusted by the machine the tests are run from. +==== \ No newline at end of file diff --git a/shared-doc/run-arquillian-integration-tests-with-provisioned-server.adoc b/shared-doc/run-arquillian-integration-tests-with-provisioned-server.adoc new file mode 100644 index 0000000000..b6315ca41d --- /dev/null +++ b/shared-doc/run-arquillian-integration-tests-with-provisioned-server.adoc @@ -0,0 +1,17 @@ +[[run_the_arquillian_integration_tests_with_provisioned_server_]] += Run the Arquillian Integration Tests with a provisioned server +//****************************************************************************** +// Include this template if your quickstart provides standard Arquillian +// integration tests. +//****************************************************************************** + +This quickstart includes Arquillian integration tests. They are located under the `src/test/` directory. The integration tests verify that the quickstart runs correctly when deployed on the server. + +. Type the following command to run the `verify` goal with the `provisioned-server` profile activated. ++ +[source,options="nowrap"] +---- +$ mvn clean verify -Pprovisioned-server +---- + +This will build the provisioned server with the quickstart application, start it, run the integration tests and stop the server. \ No newline at end of file diff --git a/shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc b/shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc new file mode 100644 index 0000000000..d446e08e44 --- /dev/null +++ b/shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc @@ -0,0 +1,26 @@ +[[run_the_arquillian_integration_tests_with_server_distribution]] += Run the Arquillian Integration Tests +//****************************************************************************** +// Include this template if your quickstart provides standard Arquillian +// integration tests. +//****************************************************************************** + +This quickstart includes Arquillian integration tests. They are located under the `src/test/` directory. The integration tests verify that the quickstart runs correctly when deployed on the server. + +Follow these steps to run the integration tests. + +. Make sure you start the {productName} server, as previously described. + +. Make sure you build and deploy the quickstart, as previously described. + +. Type the following command to run the `verify` goal with the `arq-remote` profile activated. ++ +[source,options="nowrap"] +---- +$ mvn verify -Parq-remote +---- + +[NOTE] +==== +You may also use the environment variable `SERVER_HOST` or the system property `server.host` to define the target host of the tests. +==== \ No newline at end of file diff --git a/temperature-converter/README.adoc b/temperature-converter/README.adoc index 63fd2f7f5b..096f13d1f6 100644 --- a/temperature-converter/README.adoc +++ b/temperature-converter/README.adoc @@ -24,23 +24,20 @@ The application does the following: . The response from TemperatureConvertEJB is stored in the `temperature` field of the managed bean. . The managed bean is annotated as @SessionScoped, so the same managed bean instance is used for the entire session. - -//************************************************* -// Product Release content only -//************************************************* - -ifndef::EAPCDRelease[] - // System Requirements include::../shared-doc/system-requirements.adoc[leveloffset=+1] // Use of {jbossHomeName} include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] + +// build and run with standard server distribution +[[build_and_run_the_quickstart_with_server_dist]] +== Building and running the quickstart application with a {productName} server distribution // Start the {productName} Standalone Server -include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+1] +include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+2] // Build and Deploy the Quickstart -include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1] +include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+2] -== Access the Application +=== Access the Application The application will be running at the following URL: http://localhost:8080/{artifactId}/. @@ -50,30 +47,13 @@ You will be presented with a simple form for temperature conversion. . Enter a temperature. . Press the `Convert` button to see the results. +// Testing with Arquillian +include::../shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc[leveloffset=+2] // Undeploy the Quickstart -include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] -// Run the Quickstart in Red Hat CodeReady Studio or Eclipse -include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1] -// Debug the Application -include::../shared-doc/debug-the-application.adoc[leveloffset=+1] - -endif::[] - -//************************************************* -// Product Release content only -//************************************************* -ifdef::ProductRelease[] - -// Getting Started with OpenShift -include::../shared-doc/openshift-getting-started.adoc[leveloffset=+1] -//Prepare OpenShift for Quickstart Deployment -include::../shared-doc/openshift-create-project.adoc[leveloffset=+1] -// Import the Latest {xpaasproduct-shortname} Image Streams and Templates -include::../shared-doc/openshift-import-imagestreams-templates.adoc[leveloffset=+1] -// Deploy the {ProductShortName} Source-to-Image (S2I) Quickstart to OpenShift -include::../shared-doc/openshift-deploy-project.adoc[leveloffset=+1] -// Openshift post deployment tasks -include::../shared-doc/openshift-post-deployment-tasks.adoc[leveloffset=+1] - +include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+2] +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] +include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1] endif::[] +include::../shared-doc/build-and-run-the-quickstart-with-openshift.adoc[leveloffset=+1] \ No newline at end of file diff --git a/temperature-converter/charts/helm.yaml b/temperature-converter/charts/helm.yaml new file mode 100644 index 0000000000..629e4ca523 --- /dev/null +++ b/temperature-converter/charts/helm.yaml @@ -0,0 +1,6 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: temperature-converter +deploy: + replicas: 1 \ No newline at end of file diff --git a/temperature-converter/pom.xml b/temperature-converter/pom.xml index f2373edbe3..5c0c8ec57a 100644 --- a/temperature-converter/pom.xml +++ b/temperature-converter/pom.xml @@ -45,6 +45,9 @@ 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final @@ -125,7 +128,7 @@ + as the API is included in JBoss EAP --> jakarta.annotation jakarta.annotation-api @@ -145,5 +148,165 @@ provided + + + org.junit.jupiter + junit-jupiter-api + 5.9.1 + test + + + + org.junit.jupiter + junit-jupiter-params + 5.9.1 + test + + + + org.junit.jupiter + junit-jupiter-engine + 5.9.1 + test + + + + org.jboss.arquillian.junit5 + arquillian-junit5-container + test + + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet-jakarta + test + + + + + provisioned-server + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + cloud-server + ejb + jsf + + ROOT.war + + + + + package + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + ${project.build.directory}/server + + + **/ProvisionedManagedTemperatureConverterIT + + + **/RemoteTemperatureConverterIT + + + + + + integration-test + verify + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + + cloud-server + ejb + jsf + + ROOT.war + + + + + package + + + + + + + + + arq-remote + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + **/RemoteTemperatureConverterIT + + + **/ProvisionedManagedTemperatureConverterIT + + + + + + integration-test + verify + + + + + + + + diff --git a/temperature-converter/src/main/webapp/temperatureconvert.xhtml b/temperature-converter/src/main/webapp/temperatureconvert.xhtml index 4b6fa4ae32..c85a0c1bba 100644 --- a/temperature-converter/src/main/webapp/temperatureconvert.xhtml +++ b/temperature-converter/src/main/webapp/temperatureconvert.xhtml @@ -15,8 +15,8 @@ limitations under the License. --> - + diff --git a/temperature-converter/src/test/java/org/jboss/as/quickstarts/temperatureconverter/ProvisionedManagedTemperatureConverterIT.java b/temperature-converter/src/test/java/org/jboss/as/quickstarts/temperatureconverter/ProvisionedManagedTemperatureConverterIT.java new file mode 100644 index 0000000000..027257ebf6 --- /dev/null +++ b/temperature-converter/src/test/java/org/jboss/as/quickstarts/temperatureconverter/ProvisionedManagedTemperatureConverterIT.java @@ -0,0 +1,51 @@ +/* + * 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 org.jboss.as.quickstarts.temperatureconverter; + + +import java.net.URI; +import java.net.URISyntaxException; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit5.ArquillianExtension; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@ExtendWith(ArquillianExtension.class) +@RunAsClient +public class ProvisionedManagedTemperatureConverterIT extends RemoteTemperatureConverterIT { + + @Override + protected URI getHTTPEndpoint(String path) { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080/"; + } + try { + return new URI(host + path); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + @Test + @Override + public void testConvertTemperature() throws Exception { + convertTemperature(); + } + +} diff --git a/temperature-converter/src/test/java/org/jboss/as/quickstarts/temperatureconverter/RemoteTemperatureConverterIT.java b/temperature-converter/src/test/java/org/jboss/as/quickstarts/temperatureconverter/RemoteTemperatureConverterIT.java new file mode 100644 index 0000000000..5392b4a558 --- /dev/null +++ b/temperature-converter/src/test/java/org/jboss/as/quickstarts/temperatureconverter/RemoteTemperatureConverterIT.java @@ -0,0 +1,112 @@ +/* + * 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 org.jboss.as.quickstarts.temperatureconverter; + +import java.io.IOException; +import java.net.CookieManager; +import java.net.CookiePolicy; +import java.util.logging.Logger; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLEncoder; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpRequest.BodyPublisher; +import java.net.http.HttpRequest.BodyPublishers; +import java.net.http.HttpResponse; +import java.nio.charset.StandardCharsets; +import java.util.Map; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class RemoteTemperatureConverterIT { + + private static final Logger log = Logger.getLogger(RemoteTemperatureConverterIT.class.getName()); + + protected URI getHTTPEndpoint(String path) { + String host = getServerHost(); + if (host == null) { + host = "http://localhost:8080/temperature-converter"; + } + try { + return new URI(host + path); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + protected String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } + + @Test + public void testConvertTemperature() throws Exception { + convertTemperature(); + } + + public void convertTemperature() throws IOException, InterruptedException { + CookieManager manager = new CookieManager(null, CookiePolicy.ACCEPT_ALL); + HttpClient client = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.ALWAYS) + .cookieHandler(manager) + .version(HttpClient.Version.HTTP_1_1) + .build(); + HttpResponse response = client.send(HttpRequest.newBuilder(getHTTPEndpoint("/temperatureconvert.jsf")).GET().build(), HttpResponse.BodyHandlers.ofString()); + String body = response.body().toString(); + Assertions.assertEquals(200, response.statusCode()); + Assertions.assertTrue(body.contains(" data) { + StringBuilder builder = new StringBuilder(); + for (Map.Entry entry : data.entrySet()) { + if (builder.length() > 0) { + builder.append("&"); + } + builder.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8)); + builder.append("="); + builder.append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8)); + } + return BodyPublishers.ofString(builder.toString()); + } + +} diff --git a/thread-racing/README.adoc b/thread-racing/README.adoc index a11cdc3db8..5e3aca05da 100644 --- a/thread-racing/README.adoc +++ b/thread-racing/README.adoc @@ -45,19 +45,22 @@ include::../shared-doc/development-shortcuts.adoc[leveloffset=+1] include::../shared-doc/system-requirements.adoc[leveloffset=+1] // Use of {jbossHomeName} include::../shared-doc/use-of-jboss-home-name.adoc[leveloffset=+1] + +// build and run with standard server distribution +[[build_and_run_the_quickstart_with_server_dist]] +== Building and running the quickstart application with a {productName} server distribution // Start the {productName} Standalone Server -include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+1] +include::../shared-doc/start-the-standalone-server.adoc[leveloffset=+2] // Build and Deploy the Quickstart -include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+1] - +include::../shared-doc/build-and-deploy-the-quickstart.adoc[leveloffset=+2] -== Access the application +=== Access the application The application will be running at the following URL http://localhost:8080/{artifactId}/. To start a race press the `Insert Coin` button. The page displays the names of the threads as they join the race. It then tracks the progress of each thread through the Batch, EE Concurrency, JAX-RS, JMS, and JSON stages of the race. Finally, it displays the official race results and championship standings. -== Server Log: Expected Warnings and Errors +=== Server Log: Expected Warnings and Errors NOTE: You will see the following warning in the server log. You can ignore this warning. @@ -66,35 +69,13 @@ NOTE: You will see the following warning in the server log. You can ignore this HHH000431: Unable to determine H2 database version, certain features may not work ---- +// Testing with Arquillian +include::../shared-doc/run-arquillian-integration-tests-with-server-distribution.adoc[leveloffset=+2] // Undeploy the Quickstart -include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+1] -// Run the Quickstart in Red Hat CodeReady Studio or Eclipse -include::../shared-doc/run-the-quickstart-in-jboss-developer-studio.adoc[leveloffset=+1] - -// Additional Red Hat CodeReady Studio instructions -NOTE: Within {JBDSProductName}, make sure you define a server runtime environment that uses the `standalone-full.xml` configuration file. - -// Debug the Application -include::../shared-doc/debug-the-application.adoc[leveloffset=+1] +include::../shared-doc/undeploy-the-quickstart.adoc[leveloffset=+2] +// Build and run sections for other environments/builds +ifndef::ProductRelease,EAPXPRelease[] +include::../shared-doc/build-and-run-the-quickstart-with-provisioned-server.adoc[leveloffset=+1] endif::[] - -//************************************************* -// Product Release content only -//************************************************* -ifdef::ProductRelease[] - -// Getting Started with OpenShift -include::../shared-doc/openshift-getting-started.adoc[leveloffset=+1] -//Prepare OpenShift for Quickstart Deployment -include::../shared-doc/openshift-create-project.adoc[leveloffset=+1] -// Import the Latest {xpaasproduct-shortname} Image Streams and Templates -include::../shared-doc/openshift-import-imagestreams-templates.adoc[leveloffset=+1] -// Deploy the {ProductShortName} Source-to-Image (S2I) Quickstart to OpenShift -include::../shared-doc/openshift-deploy-project.adoc[leveloffset=+1] -// Openshift post deployment tasks -include::../shared-doc/openshift-post-deployment-tasks.adoc[leveloffset=+1] - - -endif::[] - +include::../shared-doc/build-and-run-the-quickstart-with-openshift.adoc[leveloffset=+1] diff --git a/thread-racing/charts/helm.yaml b/thread-racing/charts/helm.yaml new file mode 100644 index 0000000000..4ed9f36167 --- /dev/null +++ b/thread-racing/charts/helm.yaml @@ -0,0 +1,6 @@ +build: + uri: https://github.com/wildfly/quickstart.git + ref: main + contextDir: thread-racing +deploy: + replicas: 1 \ No newline at end of file diff --git a/thread-racing/pom.xml b/thread-racing/pom.xml index d552022418..6ee919d77b 100644 --- a/thread-racing/pom.xml +++ b/thread-racing/pom.xml @@ -45,6 +45,9 @@ 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final @@ -131,7 +134,7 @@ + as the API is included in JBoss EAP --> jakarta.annotation jakarta.annotation-api @@ -157,6 +160,12 @@ jakarta.enterprise.concurrent jakarta.enterprise.concurrent-api provided + + + org.testng + testng + + @@ -191,5 +200,181 @@ jakarta.ws.rs-api provided + + org.jboss.resteasy + resteasy-client-api + jar + provided + + + + + org.junit.jupiter + junit-jupiter-api + 5.9.1 + test + + + org.junit.jupiter + junit-jupiter-params + 5.9.1 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.9.1 + test + + + + org.jboss.arquillian.junit5 + arquillian-junit5-container + test + + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet-jakarta + test + + + + + provisioned-server + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + cloud-server + ejb + batch-jberet + embedded-activemq + h2-default-datasource + + ROOT.war + + + + + package + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + ${project.build.directory}/server + + + **/ProvisionedManagedThreadRacingIT + + + **/RemoteThreadRacingIT + + + + + + integration-test + verify + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + + cloud-server + ejb + batch-jberet + embedded-activemq + h2-default-datasource + + ROOT.war + + + + + package + + + + + + + + + arq-remote + + + org.wildfly.arquillian + wildfly-arquillian-container-remote + test + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + **/RemoteThreadRacingIT + + + **/ProvisionedManagedThreadRacingIT + + + + + + integration-test + verify + + + + + + + + diff --git a/thread-racing/scripts/embedded-broker.cli b/thread-racing/scripts/embedded-broker.cli new file mode 100644 index 0000000000..265c11be65 --- /dev/null +++ b/thread-racing/scripts/embedded-broker.cli @@ -0,0 +1,14 @@ +if (outcome == success) of /subsystem=messaging-activemq:read-resource + /subsystem=messaging-activemq/server=default:add(elytron-domain=ApplicationDomain) +end-if +if (outcome == success) of /subsystem=messaging-activemq/server=default:read-resource + /subsystem=messaging-activemq/server=default/in-vm-acceptor=in-vm:add(server-id=0, params=[buffer-pooling=false]) + /subsystem=messaging-activemq/server=default/in-vm-connector=in-vm:add(server-id=0, params=[buffer-pooling=false]) + /subsystem=messaging-activemq/server=default/pooled-connection-factory=activemq-ra:add(connectors=[in-vm], transaction=xa, entries=[java:/JmsXA,java:jboss/DefaultJMSConnectionFactory]) + /subsystem=messaging-activemq/server=default/jms-queue=DLQ:add(entries=[java:/jms/queue/DLQ]) + /subsystem=messaging-activemq/server=default/jms-queue=ExpiryQueue:add(entries=[java:/jms/queue/ExpiryQueue]) + /subsystem=messaging-activemq/server=default/address-setting=#:add(dead-letter-address=jms.queue.DLQ, expiry-address=jms.queue.ExpiryQueue) +end-if +if (outcome == success) of /subsystem=ee/service=default-bindings:read-resource + /subsystem=ee/service=default-bindings:write-attribute(name="jms-connection-factory", value="java:jboss/DefaultJMSConnectionFactory") +end-if \ No newline at end of file diff --git a/thread-racing/src/main/java/org/jboss/as/quickstarts/threadracing/stage/jaxrs/JAXRSRaceStage.java b/thread-racing/src/main/java/org/jboss/as/quickstarts/threadracing/stage/jaxrs/JAXRSRaceStage.java index 16494c7e84..16ad179232 100644 --- a/thread-racing/src/main/java/org/jboss/as/quickstarts/threadracing/stage/jaxrs/JAXRSRaceStage.java +++ b/thread-racing/src/main/java/org/jboss/as/quickstarts/threadracing/stage/jaxrs/JAXRSRaceStage.java @@ -25,6 +25,7 @@ import jakarta.ws.rs.client.WebTarget; import jakarta.ws.rs.core.Response; import java.util.Map; +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; /** * The JAX-RS 2.0 race stage implements the race's boxes, which a racer uses to do a pit stop. @@ -38,26 +39,31 @@ public void run(Race.Registration registration) throws Exception { // build the REST service uri from race's environment final Map environment = registration.getEnvironment(); final String pitStopURI = new StringBuilder("http://") - .append(environment.get(EnvironmentProperties.SERVER_NAME)) - .append(':') - .append(environment.get(EnvironmentProperties.SERVER_PORT)) - .append(environment.get(EnvironmentProperties.ROOT_PATH)) - .append('/') - .append(BoxApplication.PATH) - .append("/pitStop") - .toString(); + .append(environment.get(EnvironmentProperties.SERVER_NAME)) + .append(':') + .append(environment.get(EnvironmentProperties.SERVER_PORT)) + .append(environment.get(EnvironmentProperties.ROOT_PATH)) + .append('/') + .append(BoxApplication.PATH) + .append("/pitStop") + .toString(); // create and setup the new standard JAX-RS client (and its web target) - final Client client = ClientBuilder.newClient(); - final WebTarget target = client.target(pitStopURI); - // get current time - long now = System.currentTimeMillis(); - // box box box, i.e. send a request to the Box rest service, with the racers name provided as param 'racer' - final Response response = target.path("{racer}").resolveTemplate("racer", registration.getRacer().getName()).request().get(); - if (response.getStatus() != 200) { - throw new IllegalStateException("PIT STOP failure trouble " + response.getStatus()); - } else { - // broadcast a msg indicating the duration of the pit stop operation - registration.broadcast("PIT STOP in " + (System.currentTimeMillis() - now) + "ms"); + final Client client = ((ResteasyClientBuilder) ClientBuilder.newBuilder()) + .build(); + try { + final WebTarget target = client.target(pitStopURI); + // get current time + long now = System.currentTimeMillis(); + // box box box, i.e. send a request to the Box rest service, with the racers name provided as param 'racer' + final Response response = target.path("{racer}").resolveTemplate("racer", registration.getRacer().getName()).request().get(); + if (response.getStatus() != 200) { + throw new IllegalStateException("PIT STOP failure trouble " + response.getStatus()); + } else { + // broadcast a msg indicating the duration of the pit stop operation + registration.broadcast("PIT STOP in " + (System.currentTimeMillis() - now) + "ms"); + } + } finally { + client.close(); } } } diff --git a/thread-racing/src/test/java/org/jboss/as/quickstarts/threadracing/EchoListener.java b/thread-racing/src/test/java/org/jboss/as/quickstarts/threadracing/EchoListener.java new file mode 100644 index 0000000000..e1b8139ebc --- /dev/null +++ b/thread-racing/src/test/java/org/jboss/as/quickstarts/threadracing/EchoListener.java @@ -0,0 +1,96 @@ +package org.jboss.as.quickstarts.threadracing; + + +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +import java.net.http.WebSocket; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +public class EchoListener implements WebSocket.Listener { + + private final RemoteThreadRacingIT test; + + public EchoListener(RemoteThreadRacingIT test) { + this.test = test; + } + + private static final Logger logger = Logger.getLogger(EchoListener.class.getName()); + private boolean connected = false; + private StringBuilder buffer = new StringBuilder(); + private String message = null; + CompletableFuture accumulatedMessage = new CompletableFuture<>(); + + @Override + public void onOpen(WebSocket webSocket) { + logger.info("CONNECTED"); + connected = true; + WebSocket.Listener.super.onOpen(webSocket); + } + + @Override + public CompletionStage onText(WebSocket webSocket, CharSequence data, boolean last) { + logger.info("Receiving Message -->"); + logger.info(String.format("onText received a data: %s", data)); + buffer.append(data); + webSocket.request(1); + if (last) { + if (buffer.toString() != null && !buffer.toString().equals(message)) { + message = buffer.toString(); + accumulatedMessage.complete(buffer.toString()); + buffer = new StringBuilder(); + CompletionStage cf = accumulatedMessage.thenAccept(RemoteThreadRacingIT::addMessage); + accumulatedMessage = new CompletableFuture<>(); + return cf; + } + } + return accumulatedMessage; + } + + public String getMessage() { + return message; + } + + @Override + public void onError(WebSocket webSocket, Throwable error) { + logger.log(Level.SEVERE, "Error!" + webSocket.toString(), error); + WebSocket.Listener.super.onError(webSocket, error); + } + + @Override + public CompletionStage onClose(WebSocket webSocket, int statusCode, String reason) { + logger.info("CLOSING"); + connected = false; + logger.info(String.format("Closed with status %d, and reason: %s", statusCode, reason)); + CompletableFuture.completedFuture(reason).thenAccept(s -> test.stop()); + return WebSocket.Listener.super.onClose(webSocket, statusCode, reason); + } + + public boolean isConnected() { + return connected; + } +} diff --git a/thread-racing/src/test/java/org/jboss/as/quickstarts/threadracing/ProvisionedManagedThreadRacingIT.java b/thread-racing/src/test/java/org/jboss/as/quickstarts/threadracing/ProvisionedManagedThreadRacingIT.java new file mode 100644 index 0000000000..eff33569cb --- /dev/null +++ b/thread-racing/src/test/java/org/jboss/as/quickstarts/threadracing/ProvisionedManagedThreadRacingIT.java @@ -0,0 +1,49 @@ +/* + * 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 org.jboss.as.quickstarts.threadracing; + +import java.net.URI; +import java.net.URISyntaxException; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit5.ArquillianExtension; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +@RunAsClient +@ExtendWith(ArquillianExtension.class) +public class ProvisionedManagedThreadRacingIT extends RemoteThreadRacingIT { + + @Override + protected URI getWebSocketEndpoint() { + String host = getServerHost(); + if (host == null) { + host = "ws://localhost:8080"; + } + try { + return new URI(host + "/race"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + @Test + public void testRace() throws Exception { + race(); + } + +} diff --git a/thread-racing/src/test/java/org/jboss/as/quickstarts/threadracing/RemoteThreadRacingIT.java b/thread-racing/src/test/java/org/jboss/as/quickstarts/threadracing/RemoteThreadRacingIT.java new file mode 100644 index 0000000000..062e293759 --- /dev/null +++ b/thread-racing/src/test/java/org/jboss/as/quickstarts/threadracing/RemoteThreadRacingIT.java @@ -0,0 +1,93 @@ +/* + * 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 org.jboss.as.quickstarts.threadracing; + +import java.io.IOException; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.WebSocket; +import java.util.LinkedHashSet; +import java.util.Set; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + + +public class RemoteThreadRacingIT { + + private static final Set messages = new LinkedHashSet<>(); + private volatile boolean notFinished = true; + + protected URI getWebSocketEndpoint() { + String host = getServerHost(); + if (host == null) { + host = "ws://localhost:8080/thread-racing"; + } + try { + return new URI(host + "/race"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + protected static String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + if (host != null) { + host = host.replaceFirst("http", "ws"); + } + return host; + } + + @Test + public void testRace() throws Exception { + race(); + } + + public void race() throws IOException, InterruptedException { + System.out.println("Endpoint " + getWebSocketEndpoint()); + EchoListener listener = new EchoListener(this); + WebSocket webSocket = HttpClient.newHttpClient() + .newWebSocketBuilder() + .buildAsync(getWebSocketEndpoint(), listener) + .join(); + Assertions.assertTrue(listener.isConnected(), "Connection should be opened"); + while (notFinished) { + webSocket.request(1); + } + webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "Done"); + webSocket.request(1); + Assertions.assertTrue(webSocket.isOutputClosed(), "Connection should be closed"); + Assertions.assertFalse(listener.isConnected(), "Connection should be closed"); + webSocket.abort(); + Assertions.assertTrue(webSocket.isInputClosed(), "Connection should be closed"); + String[] result = messages.toArray(new String[0]); + Assertions.assertEquals("
Please await() the official results ", result[messages.size() - 6]); + } + + public void stop() { + notFinished = false; + } + + public static void addMessage(String message) { + messages.add(message); + } + +} diff --git a/thread-racing/src/test/resources/arquillian.xml b/thread-racing/src/test/resources/arquillian.xml new file mode 100644 index 0000000000..31d4c3cc43 --- /dev/null +++ b/thread-racing/src/test/resources/arquillian.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/todo-backend/README.adoc b/todo-backend/README.adoc index f48799c3bd..50c0d7d128 100644 --- a/todo-backend/README.adoc +++ b/todo-backend/README.adoc @@ -130,7 +130,22 @@ endif::[] === Architecture with S2I -This backend is built using {productName} S2I Builder and Runtime images. When the image is built, it provisions the {productName} application server and all the feature packs it needs for its features: +This backend is built using {productName} S2I Builder and Runtime images. + +ifndef::ProductRelease,EAPXPRelease[] +When the image is built, `org.wildfly.plugins:wildfly-maven-plugin` plugin provisions the {productName} application server and all the feature packs it needs for its features. +The layers are defined in the `pom.xml` file in the `` section of the `org.wildfly.plugins:wildfly-maven-plugin` plugin: + +[source,xml] +---- + + cloud-server + postgresql-datasource + +---- +endif::[] +ifdef::ProductRelease,EAPXPRelease[] +When the image is built, it provisions the {productName} application server and all the feature packs it needs for its features: [source,yaml] ---- @@ -140,6 +155,7 @@ build: - cloud-server - postgresql-datasource ---- +endif::[] The `cloud-server` layer provides everything needed to run the backend on OpenShift. This also includes access to Jakarta EE APIs such as CDI, JAX-RS, JPA, etc. These two layers comes from the {productName} feature pack provided in the @@ -215,6 +231,7 @@ By default, the backend accepts requests from any origin (`*`). This is only sim the allowed origin using the environment variable `CORS_ORIGIN` at runtime. endif::[] +ifdef::ProductRelease[] ==== Configuration with {productName} S2I As we use S2I to build the application, we need to provide environment variables that will be used to configure the CORS filters in Undertow. @@ -230,13 +247,10 @@ We need one more environment variable to specify all the filters we want to enab of prefixes we used for each individual filter (such as `acam` in the example above): * `FILTERS=acao, acam, acah, acac, acma` +endif::[] ifndef::ProductRelease[] - -// Run the Arquillian Tests -include::../shared-doc/run-arquillian-tests.adoc[leveloffset=+1] - -== Run the Backend Locally +== Run the Backend Locally as a Bootable Jar === Package the Backend as a Bootable Jar @@ -254,14 +268,14 @@ We use the `postgresql` docker image to create one: [source,options="nowrap"] ---- -$ docker run --name todos-db \ +$ docker run --name todo-backend-db \ -e POSTGRES_USER=todos \ -e POSTGRES_PASSWORD=mysecretpassword \ -p 5432:5432 \ postgres ---- -This will create a database named `todos-db` that we can connect to on `localhost:5432` with the credentials `todos / mysecretpassword`. +This will create a database named `todo-backend-db` that we can connect to on `localhost:5432` with the credentials `todos / mysecretpassword`. === Run the Bootable Jar Application @@ -297,8 +311,79 @@ $ curl -X POST -H "Content-Type: application/json" -d '{"title": "This is my fi $ curl http://localhost:8080 [{"completed":false,"id":1,"order":0,"title":"This is my first todo item!","url":"https://localhost:8080/1"} ---- + +== Run the Backend Locally + +=== Package the Backend + +The backend is packaged and deployed on a provisioned server: + +[source,options="nowrap"] +---- +$ mvn clean package -Pprovisioned-server +---- + +=== Run a Local PostgreSQL Database + +Before running the backend locally, we need to have a local PostgreSQL database that we can connect to. +We use the `postgresql` docker image to create one: + +[source,options="nowrap"] +---- +$ docker run --name todo-backend-db \ + -e POSTGRES_USER=todos \ + -e POSTGRES_PASSWORD=mysecretpassword \ + -p 5432:5432 \ + postgres +---- + +This will create a database named `todo-backend-db` that we can connect to on `localhost:5432` with the credentials `todos / mysecretpassword`. + +=== Run the Application + +With the PostgreSQL database running, we can start the backend by passing the required environment variables to connect to the database: + +[source,options="nowrap"] +---- +$ JBOSS_HOME=./target/server \ + POSTGRESQL_DATABASE=todos \ + POSTGRESQL_SERVICE_HOST=localhost \ + POSTGRESQL_SERVICE_PORT=5432 \ + POSTGRESQL_USER=todos \ + POSTGRESQL_PASSWORD=mysecretpassword \ + POSTGRESQL_DATASOURCE=ToDos \ + ./target/server/bin/standalone.sh +... +14:41:58,111 INFO [org.jboss.as.server] (Controller Boot Thread) WFLYSRV0010: Deployed "todo-backend.war" (runtime-name : "todo-backend.war") +... +---- + +The backend is running, and we can use the HTTP API to manage a list of todos: + +[source,options="nowrap"] +---- +# get a list of todos +$ curl http://localhost:8080/todo-backend +[] + +# create a todo with the title "This is my first todo item!" +$ curl -X POST -H "Content-Type: application/json" -d '{"title": "This is my first todo item!"}' http://localhost:8080/todo-backend +{"completed":false,"id":1,"order":0,"title":"This is my first todo item!","url":"https://localhost:8080/todo-backend/1"}% + +# get a list of todos with the one that was just created +$ curl http://localhost:8080/todo-backend +[{"completed":false,"id":1,"order":0,"title":"This is my first todo item!","url":"https://localhost:8080/todo-backend/1"} +---- endif::[] +// Run the Arquillian Tests +include::../shared-doc/run-arquillian-functional-tests-remote.adoc[leveloffset=+1] + +[NOTE] +==== +You may also execute those tests against a running bootable jar application, but you will need to add `-Dserver.host=http://localhost:8080` to the command. +==== + == Run the Backend on OpenShift === Prerequisites @@ -306,7 +391,7 @@ endif::[] * You must be logged in OpenShift and have an `oc` client to connect to OpenShift * https://helm.sh[Helm] must be installed to deploy the backend on OpenShift. -Once you have installed Helm, you need to add the repository that provides Helm Charts for {productName}: +Once you have installed Helm, you need to add the repository that provides Helm Charts for {productName} and for postgresql: ifndef::ProductRelease,EAPXPRelease[] [source,options="nowrap"] @@ -316,6 +401,7 @@ $ helm repo add wildfly https://docs.wildfly.org/wildfly-charts/ $ helm search repo wildfly NAME CHART VERSION APP VERSION DESCRIPTION wildfly/wildfly ... ... Build and Deploy WildFly applications on OpenShift +wildfly/wildfly-common ... ... A library chart for WildFly-based applications ---- endif::[] ifdef::ProductRelease[] @@ -339,24 +425,44 @@ jboss-eap/eap-xp3 ... ... A Helm chart to build an ---- endif::[] + +ifdef::ProductRelease,EAPXPRelease[] === Deploy a PostgreSQL Database on OpenShift [source,options="nowrap"] ---- $ oc new-app postgresql-ephemeral \ - -p DATABASE_SERVICE_NAME=todos-db \ + -p DATABASE_SERVICE_NAME=todo-backend-db \ -p POSTGRESQL_DATABASE=todos ---- -This will create a PostgreSQL database named `todos` on OpenShift that can be accessed on the port `5432` on the service `todos-db`. -We don't need to copy the credentials to connect to the database as we will retrieve them later using the `todos-db` secret that was created +This will create a PostgreSQL database named `todos` on OpenShift that can be accessed on the port `5432` on the service `todo-backend-db`. +We don't need to copy the credentials to connect to the database as we will retrieve them later using the `todo-backend-db` secret that was created when the database is deployed. +endif::[] -ifndef::ProductRelease,EAPXPRelease[] +ifndef::ProductRelease[] === Build and Deploy the Backend on OpenShift with Bootable Jar +==== Deploy a PostgreSQL Database on OpenShift + +[source,options="nowrap"] +---- +$ oc new-app postgresql-ephemeral \ + -p DATABASE_SERVICE_NAME=todo-backend-db \ + -p POSTGRESQL_DATABASE=todos +---- + +This will create a PostgreSQL database named `todos` on OpenShift that can be accessed on the port `5432` on the service `todo-backend-db`. +We don't need to copy the credentials to connect to the database as we will retrieve them later using the `todo-backend-db` secret that was created +when the database is deployed. + +==== Build and Deploy the Backend on OpenShift with Bootable Jar using the Helm Chart + The backend will be built and deployed on OpenShift with a Helm Chart for {productName}. +ifndef::ProductRelease,EAPXPRelease[] + [source,options="nowrap",subs="+attributes"] ---- $ helm install todo-backend --set build.ref={WildFlyQuickStartRepoTag} -f https://raw.githubusercontent.com/wildfly/wildfly-charts/main/examples/todo-backend/todo-backend-bootable-jar.yaml wildfly/wildfly @@ -377,8 +483,6 @@ build: endif::[] ifdef::EAPXPRelease[] -=== Build and Deploy the Backend on OpenShift with Bootable Jar - The backend will be built and deployed on OpenShift with a Helm Chart for {productName}. [source,options="nowrap",subs="+attributes"] @@ -405,9 +509,19 @@ endif::[] The backend will be built and deployed on OpenShift with a Helm Chart for {productName}. ifndef::ProductRelease,EAPXPRelease[] +Add the bitnami repository which provides an helm chart for PostgreSQL: +[source,options="nowrap"] +---- +$ helm repo add bitnami https://charts.bitnami.com/bitnami +"bitnami" has been added to your repositories +---- + +Install the full application (database + backend). + [source,options="nowrap",subs="+attributes"] ---- -$ helm install todo-backend --set build.ref={WildFlyQuickStartRepoTag} --set build.s2i.version={productImageVersion} -f https://raw.githubusercontent.com/wildfly/wildfly-charts/main/examples/todo-backend/todo-backend-s2i.yaml wildfly/wildfly +$ helm dependency update todo-backend-chart/ +$ helm install todo-backend todo-backend-chart/ NAME: todo-backend ... STATUS: deployed @@ -437,28 +551,33 @@ REVISION: 1 ---- endif::[] +ifdef::ProductRelease,EAPXPRelease[] The Helm Chart for this quickstart contains all the information to build an image from the source code using S2I: +endif::[] + +ifndef::ProductRelease,EAPXPRelease[] +The Helm Chart for this quickstart contains all the information to build an image from the source code using S2I and install it with the database: -ifndef::ProductRelease[] [source,options="nowrap"] ---- -build: - uri: https://github.com/wildfly/quickstart.git - mode: s2i - s2i: - galleonLayers: - - cloud-server - - postgresql-datasource +dependencies: + - name: postgresql + repository: https://charts.bitnami.com/bitnami + version: ... + - name: wildfly + repository: http://docs.wildfly.org/wildfly-charts/ + version: ... ---- + endif::[] -ifdef::ProductRelease[] +ifdef::EAPXPRelease[] [source,options="nowrap"] ---- build: - uri: https://github.com/jboss-developer/jboss-eap-quickstarts.git + uri: https://github.com/wildfly/quickstart.git mode: s2i s2i: - galleonLayers: + galleonLayers: - cloud-server - postgresql-datasource ---- @@ -498,7 +617,6 @@ $ helm show readme jboss-eap/eap-xp3 ---- endif::[] - === Environment variables for PostgreSQL The Helm Chart also contains the environment variables required to connect to the PostgreSQL database. @@ -513,23 +631,26 @@ deploy: valueFrom: secretKeyRef: key: database-password - name: todos-db + name: todo-backend-db ---- When the application is deployed, the value for the `POSTGRESQL_PASSWORD` will be taken from the key `database-password` -in the secret `todos-db`. +in the secret `todo-backend-db`. Let's wait for the application to be built and deployed: [source,options="nowrap"] ---- -$ oc get deployment/todo-backend -w +$ oc get deployment todo-backend -w NAME READY UP-TO-DATE AVAILABLE AGE todo-backend 0/3 3 0 31s ... todo-backend 3/3 3 3 4m31s ---- +// Testing on Openshift +include::../shared-doc/run-arquillian-integration-tests-with-openshift.adoc[leveloffset=+2] + === Use the todobackend Web Frontend Once the backend is deployed on OpenShift, it can be accessed from the route `todo-backend`. @@ -579,11 +700,11 @@ The PostresSQL database can be deleted from OpenShift by running the commands: [source,options="nowrap"] ---- $ oc delete all -l template=postgresql-ephemeral-template -replicationcontroller "todos-db-1" deleted -service "todos-db" deleted -deploymentconfig.apps.openshift.io "todos-db" deleted -$ oc delete secret todos-db -secret "todos-db" deleted +replicationcontroller "todo-backend-db-1" deleted +service "todo-backend-db" deleted +deploymentconfig.apps.openshift.io "todo-backend-db" deleted +$ oc delete secret todo-backend-db +secret "todo-backend-db" deleted ---- == Conclusion diff --git a/todo-backend/pom.xml b/todo-backend/pom.xml index 33a8c1e96c..4061f9c4c2 100644 --- a/todo-backend/pom.xml +++ b/todo-backend/pom.xml @@ -47,8 +47,11 @@ 27.0.0.Final 8.1.0.Final - 2.0.2.Final + 2.2.1.Final 27.0.0.Final + 27.0.0.Final + 4.0.0.Beta3 + 2.0.0.Alpha4 @@ -172,15 +175,86 @@ - - - ${project.artifactId} - + + + provisioned-server + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly + wildfly-datasources-galleon-pack + ${version.wildfly-datasources-galleon-pack} + + + + cloud-server + postgresql-datasource + + + + + + package + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + + integration-test + verify + + + + ${project.build.directory}/server + todos + localhost + 5432 + todos + mysecretpassword + ToDos + + + **/ProvisionedManagedToDoIT + + + **/ManagedToDoIT + **/RemoteToDoIT + + + + + + + + bootable-jar-openshift + + ${project.artifactId} org.wildfly.plugins @@ -227,10 +301,54 @@ + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly + wildfly-datasources-galleon-pack + ${version.wildfly-datasources-galleon-pack} + + + + cloud-server + postgresql-datasource + + ROOT.war + + + + + + + false + + + + + + + package + + + + + + + + This profile will start a new JBoss EAP instance, and execute the test, shutting it down when done. + Run with: mvn clean verify -Parq-managed --> arq-managed @@ -251,6 +369,20 @@ integration-test verify + + + + + + **/ManagedToDoIT + + + **/ProvisionedManagedToDoIT + **/RemoteToDoIT + + @@ -259,7 +391,7 @@ + Run with: mvn clean verify -Parq-remote --> arq-remote @@ -282,6 +414,15 @@ + + + **/RemoteToDoIT + + + **/ProvisionedManagedToDoIT + **/ManagedToDoIT + + diff --git a/todo-backend/src/main/java/org/wildfly/quickstarts/todos/ToDoDAOImpl.java b/todo-backend/src/main/java/org/wildfly/quickstarts/todos/ToDoDAOImpl.java index ca429e8b56..87e2d45c03 100644 --- a/todo-backend/src/main/java/org/wildfly/quickstarts/todos/ToDoDAOImpl.java +++ b/todo-backend/src/main/java/org/wildfly/quickstarts/todos/ToDoDAOImpl.java @@ -29,8 +29,6 @@ import jakarta.inject.Inject; import jakarta.persistence.EntityManager; import jakarta.persistence.TypedQuery; -import jakarta.ws.rs.core.Context; -import jakarta.ws.rs.core.UriInfo; @Stateful public class ToDoDAOImpl implements ToDoDAO { @@ -38,15 +36,13 @@ public class ToDoDAOImpl implements ToDoDAO { @Inject private EntityManager em; - @Context - UriInfo uriInfo; - @Override public List findAll() { TypedQuery query = em.createQuery("SELECT t FROM ToDo t", ToDo.class); return query.getResultList(); } + @Override public Optional findById(Long id) { ToDo toDo = em.find(ToDo.class, id); return Optional.ofNullable(toDo); @@ -71,4 +67,4 @@ public Optional update(Long id, ToDo newTodo) { } return Optional.empty(); } -} \ No newline at end of file +} diff --git a/todo-backend/src/main/resources/META-INF/persistence.xml b/todo-backend/src/main/resources/META-INF/persistence.xml index a9d9e54e20..dc0e611709 100644 --- a/todo-backend/src/main/resources/META-INF/persistence.xml +++ b/todo-backend/src/main/resources/META-INF/persistence.xml @@ -15,11 +15,11 @@ See the License for the specific language governing permissions and limitations under the License. --> - + https://jakarta.ee/xml/ns/persistence + https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"> java:jboss/datasources/ToDos diff --git a/todo-backend/src/test/java/org/wildfly/quickstarts/todos/AbstractToDoIT.java b/todo-backend/src/test/java/org/wildfly/quickstarts/todos/AbstractToDoIT.java new file mode 100644 index 0000000000..c3c6c860f0 --- /dev/null +++ b/todo-backend/src/test/java/org/wildfly/quickstarts/todos/AbstractToDoIT.java @@ -0,0 +1,66 @@ +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.wildfly.quickstarts.todos; + +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.MediaType; +import java.net.URL; +import java.util.List; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +public abstract class AbstractToDoIT { + + abstract URL getRequestUrl(); + + public void internalCRUDTest() throws Exception { + + WebTarget client = ClientBuilder.newClient().target(getRequestUrl().toURI()); + + GenericType> todosListType = new GenericType>() { + }; + List allTodos = client.request().get(todosListType); + assertEquals(0, allTodos.size()); + + ToDo toDo = new ToDo(); + toDo.setTitle("My First ToDo"); + toDo.setOrder(1); + ToDo persistedTodo = client.request().post(Entity.entity(toDo, MediaType.APPLICATION_JSON_TYPE), ToDo.class); + assertNotNull(persistedTodo.getId()); + + allTodos = client.request().get(todosListType); + assertEquals(1, allTodos.size()); + ToDo fetchedToDo = allTodos.get(0); + assertEquals(toDo.getTitle(), fetchedToDo.getTitle()); + + client.request().delete(); + + allTodos = client.request().get(todosListType); + assertEquals(0, allTodos.size()); + } +} diff --git a/todo-backend/src/test/java/org/wildfly/quickstarts/todos/ToDoIT.java b/todo-backend/src/test/java/org/wildfly/quickstarts/todos/ManagedToDoIT.java similarity index 57% rename from todo-backend/src/test/java/org/wildfly/quickstarts/todos/ToDoIT.java rename to todo-backend/src/test/java/org/wildfly/quickstarts/todos/ManagedToDoIT.java index a66fcabdeb..5a0bdfbcae 100644 --- a/todo-backend/src/test/java/org/wildfly/quickstarts/todos/ToDoIT.java +++ b/todo-backend/src/test/java/org/wildfly/quickstarts/todos/ManagedToDoIT.java @@ -16,17 +16,8 @@ */ package org.wildfly.quickstarts.todos; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import java.net.URL; -import java.util.List; - -import jakarta.ws.rs.client.ClientBuilder; -import jakarta.ws.rs.client.Entity; -import jakarta.ws.rs.client.WebTarget; -import jakarta.ws.rs.core.GenericType; -import jakarta.ws.rs.core.MediaType; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.RunAsClient; @@ -34,20 +25,24 @@ import org.jboss.arquillian.test.api.ArquillianResource; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.asset.StringAsset; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(Arquillian.class) @RunAsClient -public class ToDoIT { +public class ManagedToDoIT extends AbstractToDoIT { + @Deployment public static Archive createTestArchive() { return ShrinkWrap.create(WebArchive.class, "test.war") .addPackage(ToDo.class.getPackage()) .addAsResource("META-INF/test-persistence.xml", "META-INF/persistence.xml") - .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml") + .addAsWebInfResource(new StringAsset("\n" + + ""), "beans.xml") // Deploy our test datasource .addAsWebInfResource("test-ds.xml"); } @@ -57,28 +52,12 @@ public static Archive createTestArchive() { @Test public void testCRUD() throws Exception { + super.internalCRUDTest(); + } - WebTarget client = ClientBuilder.newClient().target(deploymentUrl.toURI()); - - GenericType> todosListType = new GenericType>() {}; - List allTodos = client.request().get(todosListType); - assertEquals(0, allTodos.size()); - - ToDo toDo = new ToDo(); - toDo.setTitle("My First ToDo"); - toDo.setOrder(1); - ToDo persistedTodo = client.request().post(Entity.entity(toDo, MediaType.APPLICATION_JSON_TYPE), ToDo.class); - assertNotNull(persistedTodo.getId()); - - allTodos = client.request().get(todosListType); - assertEquals(1, allTodos.size()); - ToDo fetchedToDo = allTodos.get(0); - assertEquals(toDo.getTitle(), fetchedToDo.getTitle()); - - client.request().delete(); - - allTodos = client.request().get(todosListType); - assertEquals(0, allTodos.size()); + @Override + URL getRequestUrl() { + return deploymentUrl; } } diff --git a/todo-backend/src/test/java/org/wildfly/quickstarts/todos/ProvisionedManagedToDoIT.java b/todo-backend/src/test/java/org/wildfly/quickstarts/todos/ProvisionedManagedToDoIT.java new file mode 100644 index 0000000000..b0c48a7329 --- /dev/null +++ b/todo-backend/src/test/java/org/wildfly/quickstarts/todos/ProvisionedManagedToDoIT.java @@ -0,0 +1,67 @@ +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.wildfly.quickstarts.todos; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +@RunWith(Arquillian.class) +@RunAsClient +public class ProvisionedManagedToDoIT extends AbstractToDoIT { + + private static final String REST_TARGET_URL = "http://localhost:8080/todo-backend"; + + private String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } + + @Override + URL getRequestUrl() { + String host = getServerHost(); + if (host == null) { + host = REST_TARGET_URL; + } + try { + return new URI(host).toURL(); + } catch (URISyntaxException | MalformedURLException ex) { + throw new RuntimeException(ex); + } + } + + @Test + public void testCRUD() throws Exception { + super.internalCRUDTest(); + } +} diff --git a/todo-backend/src/test/java/org/wildfly/quickstarts/todos/RemoteToDoIT.java b/todo-backend/src/test/java/org/wildfly/quickstarts/todos/RemoteToDoIT.java new file mode 100644 index 0000000000..b223cb78e7 --- /dev/null +++ b/todo-backend/src/test/java/org/wildfly/quickstarts/todos/RemoteToDoIT.java @@ -0,0 +1,62 @@ +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.wildfly.quickstarts.todos; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import org.junit.Test; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +public class RemoteToDoIT extends AbstractToDoIT { + + private static final String REST_TARGET_URL = "http://localhost:8080/todo-backend"; + + private String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + return host; + } + + @Override + URL getRequestUrl() { + String host = getServerHost(); + if (host == null) { + host = REST_TARGET_URL; + } + try { + return new URI(host).toURL(); + } catch (URISyntaxException | MalformedURLException ex) { + throw new RuntimeException(ex); + } + } + + @Test + public void testCRUD() throws Exception { + super.internalCRUDTest(); + } +} diff --git a/todo-backend/src/test/resources/META-INF/test-persistence.xml b/todo-backend/src/test/resources/META-INF/test-persistence.xml index c3cd935b1b..65fdbc95ca 100644 --- a/todo-backend/src/test/resources/META-INF/test-persistence.xml +++ b/todo-backend/src/test/resources/META-INF/test-persistence.xml @@ -15,11 +15,11 @@ See the License for the specific language governing permissions and limitations under the License. --> - + 27.0.0.Final + 27.0.0.Final + 4.0.0.Final + 2.0.0.Final @@ -128,6 +130,158 @@ jakarta.websocket-client-api provided + + org.junit.jupiter + junit-jupiter-api + 5.9.1 + test + + + org.junit.jupiter + junit-jupiter-params + 5.9.1 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.9.1 + test + + + + org.jboss.arquillian.junit5 + arquillian-junit5-container + test + + + + org.jboss.arquillian.protocol + arquillian-protocol-servlet-jakarta + test + + + + provisioned-server + + + org.wildfly.arquillian + wildfly-arquillian-container-managed + test + + + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + + cloud-server + + ROOT.war + + + + + package + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + ${project.build.directory}/server + + + **/ProvisionedManagedWebsocketIT + + + **/RemoteWebSocketIT + + + + + + integration-test + verify + + + + + + + + + openshift + + + + org.wildfly.plugins + wildfly-maven-plugin + + + + org.wildfly:wildfly-galleon-pack:${version.server} + + + org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.cloud.fp} + + + + cloud-server + + ROOT.war + + + + + package + + + + + + + + + arq-remote + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${version.failsafe.plugin} + + + **/RemoteWebSocketIT + + + **/ProvisionedManagedWebsocketIT + + + + + + integration-test + verify + + + + + + + + diff --git a/websocket-hello/src/test/java/org/jboss/as/quickstarts/websocket_hello/EchoListener.java b/websocket-hello/src/test/java/org/jboss/as/quickstarts/websocket_hello/EchoListener.java new file mode 100644 index 0000000000..be58e5684f --- /dev/null +++ b/websocket-hello/src/test/java/org/jboss/as/quickstarts/websocket_hello/EchoListener.java @@ -0,0 +1,80 @@ +package org.jboss.as.quickstarts.websocket_hello; + + +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +import java.net.http.WebSocket; +import java.util.concurrent.CompletionStage; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +public class EchoListener implements WebSocket.Listener { + + private static final Logger logger = Logger.getLogger(EchoListener.class.getName()); + private boolean connected = false; + private StringBuilder buffer = new StringBuilder(); + private String message = null; + + @Override + public void onOpen(WebSocket webSocket) { + logger.info("CONNECTED"); + connected = true; + WebSocket.Listener.super.onOpen(webSocket); + } + + @Override + public CompletionStage onText(WebSocket webSocket, CharSequence data, boolean last) { + logger.info("Receiving Message -->"); + logger.info(String.format("onText received a data: %s", data)); + buffer.append(data); + if(last) { + message = buffer.toString(); + buffer = new StringBuilder(); + } + return WebSocket.Listener.super.onText(webSocket, data, last); + } + + public String getMessage() { + return message; + } + + @Override + public void onError(WebSocket webSocket, Throwable error) { + logger.log(Level.SEVERE, "Error!" + webSocket.toString(), error); + WebSocket.Listener.super.onError(webSocket, error); + } + + @Override + public CompletionStage onClose(WebSocket webSocket, int statusCode, String reason) { + logger.info("CLOSING"); + connected = false; + logger.info(String.format("Closed with status %d, and reason: %s", statusCode, reason)); + return WebSocket.Listener.super.onClose(webSocket, statusCode, reason); + } + + public boolean isConnected() { + return connected; + } +} diff --git a/websocket-hello/src/test/java/org/jboss/as/quickstarts/websocket_hello/ProvisionedManagedWebsocketIT.java b/websocket-hello/src/test/java/org/jboss/as/quickstarts/websocket_hello/ProvisionedManagedWebsocketIT.java new file mode 100644 index 0000000000..2e46618bc3 --- /dev/null +++ b/websocket-hello/src/test/java/org/jboss/as/quickstarts/websocket_hello/ProvisionedManagedWebsocketIT.java @@ -0,0 +1,55 @@ +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.jboss.as.quickstarts.websocket_hello; + +import java.net.URI; +import java.net.URISyntaxException; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit5.ArquillianExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +@ExtendWith(ArquillianExtension.class) +@RunAsClient +public class ProvisionedManagedWebsocketIT extends RemoteWebSocketIT { + + @Override + protected URI getWebSocketEndpoint() { + String host = getServerHost(); + if (host == null) { + host = "ws://localhost:8080"; + } + try { + return new URI(host + "/websocket/helloName"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + @Test + public void testConnectOk() throws Exception { + testWebSocket(500); + } +} diff --git a/websocket-hello/src/test/java/org/jboss/as/quickstarts/websocket_hello/RemoteWebSocketIT.java b/websocket-hello/src/test/java/org/jboss/as/quickstarts/websocket_hello/RemoteWebSocketIT.java new file mode 100644 index 0000000000..7252cb70cf --- /dev/null +++ b/websocket-hello/src/test/java/org/jboss/as/quickstarts/websocket_hello/RemoteWebSocketIT.java @@ -0,0 +1,84 @@ +/* + * Copyright 2022 Red Hat, Inc. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.jboss.as.quickstarts.websocket_hello; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.WebSocket; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + + +/** + * + * @author Emmanuel Hugonnet (c) 2022 Red Hat, Inc. + */ +public class RemoteWebSocketIT { + + protected URI getWebSocketEndpoint() { + String host = getServerHost(); + if (host == null) { + host = "ws://localhost:8080/websocket-hello"; + } + try { + return new URI(host + "/websocket/helloName"); + } catch (URISyntaxException ex) { + throw new RuntimeException(ex); + } + } + + protected static String getServerHost() { + String host = System.getenv("SERVER_HOST"); + if (host == null) { + host = System.getProperty("server.host"); + } + if(host != null) { + host= host.replaceFirst("http", "ws"); + } + return host; + } + + @Test + public void testConnectOk() throws Exception { + testWebSocket(2000); + } + + public void testWebSocket(long wait) throws IOException, InterruptedException { + EchoListener listener = new EchoListener(); + WebSocket webSocket = HttpClient.newHttpClient() + .newWebSocketBuilder() + .buildAsync(getWebSocketEndpoint(), listener) + .join(); + Assertions.assertTrue(listener.isConnected(), "Connection should be opened"); + webSocket.sendText("Bart", true); + Thread.sleep(wait); + Assertions.assertEquals("Hello Bart from websocket endpoint", listener.getMessage()); + webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "Done"); + Thread.sleep(wait); + Assertions.assertTrue(webSocket.isOutputClosed(), "Connection should be closed"); + Assertions.assertFalse(listener.isConnected(), "Connection should be closed"); + webSocket.abort(); + Assertions.assertTrue(webSocket.isInputClosed(), "Connection should be closed"); + } + +} diff --git a/websocket-hello/src/test/resources/arquillian.xml b/websocket-hello/src/test/resources/arquillian.xml new file mode 100644 index 0000000000..31d4c3cc43 --- /dev/null +++ b/websocket-hello/src/test/resources/arquillian.xml @@ -0,0 +1,23 @@ + + + + + + +