diff --git a/code-samples/README.md b/code-samples/README.md
new file mode 100644
index 000000000..2b08bf860
--- /dev/null
+++ b/code-samples/README.md
@@ -0,0 +1,7 @@
+# Knative code samples
+
+Find and use Knative code samples to help you get up and running with common use
+cases. Code samples include content from the Knative team and community members.
+
+Browse all code samples to find other languages and use cases that might align
+closer with your goals.
diff --git a/code-samples/community/README.md b/code-samples/community/README.md
new file mode 100644
index 000000000..63a9fda25
--- /dev/null
+++ b/code-samples/community/README.md
@@ -0,0 +1,42 @@
+# Community code samples
+
+Get up and running with one of the community code samples. These samples are
+contributed and maintained by members of the Knative community.
+
+!!! note
+ These samples might become outdated or the original author might be unable
+ to maintain their contribution. If you find that something isn't working,
+ lend a helping hand and fix it in a PR.
+
+[Learn more about the lifespan of samples](https://github.com/knative/docs/blob/main/contribute-to-docs/what-to-contribute/creating-code-samples.md#user-focused-content)
+
+[**See all Knative code samples**](../README.md)
+
+## Interactive Serving sample
+
+Check out this [Katacoda tutorial](https://www.katacoda.com/swapb/scenarios/knative-intro)
+which guides you through installing Knative and the `kn` command line tool, deploying a
+sample container, updating your deployment, and performing a traffic split
+between the two versions.
+
+## Serving samples
+
+Knative Serving sample apps.
+
+| Sample Name | Description | Language(s) |
+| ----------- | ----------- | ----------- |
+| Hello World | A quick introduction to Knative Serving that highlights how to deploy an app. | [Clojure](serving/helloworld-clojure/), [Dart](serving/helloworld-dart/), [Elixir](serving/helloworld-elixir/), [Haskell](serving/helloworld-haskell/), [Java - Micronaut](serving/helloworld-java-micronaut/), [Java - Quarkus](serving/helloworld-java-quarkus/), [R - Go Server](serving/helloworld-r/), [Rust](serving/helloworld-rust/), [Swift](serving/helloworld-swift/), [Vertx](serving/helloworld-vertx/) |
+| Machine Learning | A quick introduction to using Knative Serving to serve machine learning models | [Python - BentoML](serving/machinelearning-python-bentoml)
+
+### Eventing and Eventing Resources samples
+
+_Be the first to contribute an Eventing or Eventing Sources code sample to the
+community collection._
+
+## Client samples
+
+Knative `kn` Client sample workflows and apps.
+
+| Sample Name | Description |
+| ----------- | ----------- |
+| [knfun](https://github.com/maximilien/knfun) | Knative micro-functions (Twitter and Watson APIs) demo using the `kn` client. |
diff --git a/code-samples/community/serving/README.md b/code-samples/community/serving/README.md
new file mode 100644
index 000000000..f47d57e9e
--- /dev/null
+++ b/code-samples/community/serving/README.md
@@ -0,0 +1,3 @@
+# Knative Serving code samples
+
+Community contributed and maintained code samples for Knative Serving.
diff --git a/code-samples/community/serving/helloworld-clojure/.gitignore b/code-samples/community/serving/helloworld-clojure/.gitignore
new file mode 100644
index 000000000..a4cb69a32
--- /dev/null
+++ b/code-samples/community/serving/helloworld-clojure/.gitignore
@@ -0,0 +1,14 @@
+pom.xml
+pom.xml.asc
+*.jar
+*.class
+/lib/
+/classes/
+/target/
+/checkouts/
+.lein-deps-sum
+.lein-repl-history
+.lein-plugins/
+.lein-failures
+.nrepl-port
+.cpcache/
diff --git a/code-samples/community/serving/helloworld-clojure/Dockerfile b/code-samples/community/serving/helloworld-clojure/Dockerfile
new file mode 100644
index 000000000..c7881b1ca
--- /dev/null
+++ b/code-samples/community/serving/helloworld-clojure/Dockerfile
@@ -0,0 +1,17 @@
+# Use the official Clojure image.
+# https://hub.docker.com/_/clojure
+FROM clojure
+
+# Create the project and download dependencies.
+WORKDIR /usr/src/app
+COPY project.clj .
+RUN lein deps
+
+# Copy local code to the container image.
+COPY . .
+
+# Build an uberjar release artifact.
+RUN mv "$(lein uberjar | sed -n 's/^Created \(.*standalone\.jar\)/\1/p')" app-standalone.jar
+
+# Run the web service on container startup.
+CMD ["java", "-jar", "app-standalone.jar"]
diff --git a/code-samples/community/serving/helloworld-clojure/README.md b/code-samples/community/serving/helloworld-clojure/README.md
new file mode 100644
index 000000000..8a9d2406a
--- /dev/null
+++ b/code-samples/community/serving/helloworld-clojure/README.md
@@ -0,0 +1,157 @@
+# Hello World - Clojure
+
+A simple web app written in Clojure that you can use for testing. It reads in an
+env variable `TARGET` and prints "Hello \${TARGET}!". If TARGET is not
+specified, it will use "World" as the TARGET.
+
+## Prerequisites
+
+- A Kubernetes cluster with Knative installed and DNS configured. Follow the
+ [Knative installation instructions](https://knative.dev/docs/install/) if you need to create
+ one.
+- [Docker](https://www.docker.com) installed and running on your local machine,
+ and a Docker Hub account configured (we'll use it for a container registry).
+
+## Recreating the sample code
+
+While you can clone all of the code from this directory, hello world apps are
+generally more useful if you build them step-by-step. The following instructions
+recreate the source files from this folder.
+
+1. Create a new file named `src/helloworld/core.clj` and paste the following
+ code. This code creates a basic web server which listens on port 8080:
+
+ ```clojure
+ (ns helloworld.core
+ (:use ring.adapter.jetty)
+ (:gen-class))
+
+ (defn handler [request]
+ {:status 200
+ :headers {"Content-Type" "text/html"}
+ :body (str "Hello "
+ (if-let [target (System/getenv "TARGET")]
+ target
+ "World")
+ "!\n")})
+
+ (defn -main [& args]
+ (run-jetty handler {:port (if-let [port (System/getenv "PORT")]
+ (Integer/parseInt port)
+ 8080)}))
+ ```
+
+1. In your project directory, create a file named `project.clj` and copy the
+ code below into it. This code defines the project's dependencies and
+ entrypoint.
+
+ ```clojure
+ (defproject helloworld "1.0.0-SNAPSHOT"
+ :description "Hello World - Clojure sample"
+ :dependencies [[org.clojure/clojure "1.9.0"]
+ [ring/ring-core "1.6.3"]
+ [ring/ring-jetty-adapter "1.6.3"]]
+ :main helloworld.core)
+ ```
+
+1. In your project directory, create a file named `Dockerfile` and copy the code
+ block below into it. For detailed instructions on dockerizing a Clojure app,
+ see
+ [the clojure image documentation](https://github.com/docker-library/docs/tree/master/clojure).
+
+ ```docker
+ # Use the official Clojure image.
+ # https://hub.docker.com/_/clojure
+ FROM clojure
+
+ # Create the project and download dependencies.
+ WORKDIR /usr/src/app
+ COPY project.clj .
+ RUN lein deps
+
+ # Copy local code to the container image.
+ COPY . .
+
+ # Build an uberjar release artifact.
+ RUN mv "$(lein uberjar | sed -n 's/^Created \(.*standalone\.jar\)/\1/p')" app-standalone.jar
+
+ # Run the web service on container startup.
+ CMD ["java", "-jar", "app-standalone.jar"]
+ ```
+
+1. Create a new file, `service.yaml` and copy the following service definition
+ into the file. Make sure to replace `{username}` with your Docker Hub
+ username.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-clojure
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-clojure
+ env:
+ - name: TARGET
+ value: "Clojure Sample v1"
+ ```
+
+## Building and deploying the sample
+
+Once you have recreated the sample code files (or used the files in the sample
+folder) you're ready to build and deploy the sample app.
+
+1. Use Docker to build the sample code into a container. To build and push with
+ Docker Hub, run these commands replacing `{username}` with your Docker Hub
+ username:
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-clojure .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-clojure
+ ```
+
+1. After the build has completed and the container is pushed to docker hub, you
+ can deploy the app into your cluster. Ensure that the container image value
+ in `service.yaml` matches the container you built in the previous step. Apply
+ the configuration using `kubectl`:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+1. Now that your service is created, Knative will perform the following steps:
+
+ - Create a new immutable revision for this version of the app.
+ - Network programming to create a route, ingress, service, and load balance
+ for your app.
+ - Automatically scale your pods up and down (including to zero active pods).
+
+1. To find the URL for your service, use
+
+ ```
+ kubectl get ksvc helloworld-clojure --output=custom-columns=NAME:.metadata.name,URL:.status.url
+ NAME URL
+ helloworld-clojure http://helloworld-clojure.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app and see the result. Replace
+ the URL below with the URL returned in the previous command.
+
+ ```bash
+ curl http://helloworld-clojure.default.1.2.3.4.sslip.io
+ Hello World!
+ ```
+
+## Removing the sample app deployment
+
+To remove the sample app from your cluster, delete the service record:
+
+```bash
+kubectl delete --filename service.yaml
+```
diff --git a/code-samples/community/serving/helloworld-clojure/project.clj b/code-samples/community/serving/helloworld-clojure/project.clj
new file mode 100644
index 000000000..af0e473e1
--- /dev/null
+++ b/code-samples/community/serving/helloworld-clojure/project.clj
@@ -0,0 +1,6 @@
+(defproject helloworld "1.0.0-SNAPSHOT"
+ :description "Hello World - Clojure sample"
+ :dependencies [[org.clojure/clojure "1.9.0"]
+ [ring/ring-core "1.6.3"]
+ [ring/ring-jetty-adapter "1.6.3"]]
+ :main helloworld.core)
diff --git a/code-samples/community/serving/helloworld-clojure/service.yaml b/code-samples/community/serving/helloworld-clojure/service.yaml
new file mode 100644
index 000000000..1129961c0
--- /dev/null
+++ b/code-samples/community/serving/helloworld-clojure/service.yaml
@@ -0,0 +1,13 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ name: helloworld-clojure
+ namespace: default
+spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-clojure
+ env:
+ - name: TARGET
+ value: "Clojure Sample v1"
diff --git a/code-samples/community/serving/helloworld-clojure/src/helloworld/core.clj b/code-samples/community/serving/helloworld-clojure/src/helloworld/core.clj
new file mode 100644
index 000000000..7688631e8
--- /dev/null
+++ b/code-samples/community/serving/helloworld-clojure/src/helloworld/core.clj
@@ -0,0 +1,17 @@
+(ns helloworld.core
+ (:use ring.adapter.jetty)
+ (:gen-class))
+
+(defn handler [request]
+ {:status 200
+ :headers {"Content-Type" "text/html"}
+ :body (str "Hello "
+ (if-let [target (System/getenv "TARGET")]
+ target
+ "World")
+ "!\n")})
+
+(defn -main [& args]
+ (run-jetty handler {:port (if-let [port (System/getenv "PORT")]
+ (Integer/parseInt port)
+ 8080)}))
diff --git a/code-samples/community/serving/helloworld-dart/.gitignore b/code-samples/community/serving/helloworld-dart/.gitignore
new file mode 100644
index 000000000..9af85e5b1
--- /dev/null
+++ b/code-samples/community/serving/helloworld-dart/.gitignore
@@ -0,0 +1,4 @@
+# See https://www.dartlang.org/guides/libraries/private-files
+.dart_tool
+.packages
+pubspec.lock
diff --git a/code-samples/community/serving/helloworld-dart/Dockerfile b/code-samples/community/serving/helloworld-dart/Dockerfile
new file mode 100644
index 000000000..db97e409b
--- /dev/null
+++ b/code-samples/community/serving/helloworld-dart/Dockerfile
@@ -0,0 +1,7 @@
+# Use Google's official Dart image.
+# https://hub.docker.com/r/google/dart-runtime/
+FROM google/dart-runtime
+
+# ONBUILD instructions for COPY and pub get is defined in the google/dart-runtime image,
+# allowing you to keep this file very simple, see:
+# https://github.com/dart-lang/dart_docker/blob/master/runtime/Dockerfile.template#L15-L18
diff --git a/code-samples/community/serving/helloworld-dart/README.md b/code-samples/community/serving/helloworld-dart/README.md
new file mode 100644
index 000000000..18744a3d4
--- /dev/null
+++ b/code-samples/community/serving/helloworld-dart/README.md
@@ -0,0 +1,155 @@
+# Hello World - Dart
+
+A simple web app written in the [Dart](https://www.dart.dev) programming language
+that you can use for testing. It reads in the env variable `TARGET` and prints
+`"Hello $TARGET"`. If `TARGET` is not specified, it will use `"World"` as
+`TARGET`.
+
+## Prerequisites
+
+- A Kubernetes cluster with Knative installed and DNS configured. Follow the
+ [Knative installation instructions](https://knative.dev/docs/install/) if you need to create
+ one.
+- [Docker](https://www.docker.com) installed and running on your local machine,
+ and a Docker Hub account configured (we'll use it for a container registry).
+- [dart-sdk](https://www.dart.dev/tools/sdk#install) installed and
+ configured if you want to run the program locally.
+
+## Recreating the sample code
+
+While you can clone all of the code from this directory, it is useful to know
+how to build a hello world Dart application step-by-step. This application can
+be created using the following instructions.
+
+1. Create a new directory and write `pubspec.yaml` as follows:
+
+ ```yaml
+ name: hello_world_dart
+ publish_to: none # let's not accidentally publish this to pub.dartlang.org
+
+ environment:
+ sdk: ">=2.12.0 <3.0.0"
+
+ dependencies:
+ shelf: ^1.0.0
+ ```
+
+2. If you want to run locally, install dependencies. If you only want to run in
+ Docker or Knative, you can skip this step.
+
+ ```bash
+ > pub get
+ ```
+
+3. Create a new file `bin/server.dart` and write the following code:
+
+ ```dart
+ import 'dart:io';
+
+ import 'package:shelf/shelf.dart';
+ import 'package:shelf/shelf_io.dart';
+
+ Future main() async {
+ // Find port to listen on from environment variable.
+ final port = int.parse(Platform.environment['PORT'] ?? '8080');
+
+ // Read $TARGET from environment variable.
+ final target = Platform.environment['TARGET'] ?? 'World';
+
+ Response handler(Request request) => Response.ok('Hello $target');
+
+ // Serve handler on given port.
+ final server = await serve(
+ const Pipeline().addMiddleware(logRequests()).addHandler(handler),
+ InternetAddress.anyIPv4,
+ port,
+ );
+ print('Serving at http://${server.address.host}:${server.port}');
+ }
+ ```
+
+4. Create a new file named `Dockerfile`, this file defines instructions for
+ dockerizing your applications, for dart apps this can be done as follows:
+
+ ```Dockerfile
+ # Use Google's official Dart image.
+ # https://hub.docker.com/r/google/dart-runtime/
+ FROM google/dart-runtime
+ ```
+
+5. Create a new file, `service.yaml` and copy the following service definition
+ into the file. Make sure to replace `{username}` with your Docker Hub
+ username.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-dart
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-dart
+ env:
+ - name: TARGET
+ value: "Dart Sample v1"
+ ```
+
+## Building and deploying the sample
+
+Once you have recreated the sample code files (or used the files in the sample
+folder) you're ready to build and deploy the sample app.
+
+1. Use Docker to build the sample code into a container. To build and push with
+ Docker Hub, run these commands replacing `{username}` with your Docker Hub
+ username:
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-dart .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-dart
+ ```
+
+1. After the build has completed and the container is pushed to docker hub, you
+ can deploy the app into your cluster. Ensure that the container image value
+ in `service.yaml` matches the container you built in the previous step. Apply
+ the configuration using `kubectl`:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+1. Now that your service is created, Knative will perform the following steps:
+
+ - Create a new immutable revision for this version of the app.
+ - Network programming to create a route, ingress, service, and load balance
+ for your app.
+ - Automatically scale your pods up and down (including to zero active pods).
+
+1. To find the URL for your service, use
+
+ ```
+ kubectl get ksvc helloworld-dart --output=custom-columns=NAME:.metadata.name,URL:.status.url
+ NAME URL
+ helloworld-dart http://helloworld-dart.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app and see the result. Replace
+ the URL below with the URL returned in the previous command.
+
+ ```bash
+ curl http://helloworld-dart.default.1.2.3.4.sslip.io
+ Hello Dart Sample v1
+ ```
+
+## Removing the sample app deployment
+
+To remove the sample app from your cluster, delete the service record:
+
+```bash
+kubectl delete --filename service.yaml
+```
diff --git a/code-samples/community/serving/helloworld-dart/bin/server.dart b/code-samples/community/serving/helloworld-dart/bin/server.dart
new file mode 100644
index 000000000..a2b61c08d
--- /dev/null
+++ b/code-samples/community/serving/helloworld-dart/bin/server.dart
@@ -0,0 +1,22 @@
+import 'dart:io';
+
+import 'package:shelf/shelf.dart';
+import 'package:shelf/shelf_io.dart';
+
+Future main() async {
+ // Find port to listen on from environment variable.
+ final port = int.parse(Platform.environment['PORT'] ?? '8080');
+
+ // Read $TARGET from environment variable.
+ final target = Platform.environment['TARGET'] ?? 'World';
+
+ Response handler(Request request) => Response.ok('Hello $target');
+
+ // Serve handler on given port.
+ final server = await serve(
+ const Pipeline().addMiddleware(logRequests()).addHandler(handler),
+ InternetAddress.anyIPv4,
+ port,
+ );
+ print('Serving at http://${server.address.host}:${server.port}');
+}
diff --git a/code-samples/community/serving/helloworld-dart/pubspec.yaml b/code-samples/community/serving/helloworld-dart/pubspec.yaml
new file mode 100644
index 000000000..6f8965d5f
--- /dev/null
+++ b/code-samples/community/serving/helloworld-dart/pubspec.yaml
@@ -0,0 +1,8 @@
+name: hello_world_dart
+publish_to: none # let's not accidentally publish this to pub.dartlang.org
+
+environment:
+ sdk: '>=2.12.0 <3.0.0'
+
+dependencies:
+ shelf: ^1.0.0
diff --git a/code-samples/community/serving/helloworld-dart/service.yaml b/code-samples/community/serving/helloworld-dart/service.yaml
new file mode 100644
index 000000000..68972d105
--- /dev/null
+++ b/code-samples/community/serving/helloworld-dart/service.yaml
@@ -0,0 +1,13 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ name: helloworld-dart
+ namespace: default
+spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-dart
+ env:
+ - name: TARGET
+ value: "Dart Sample v1"
diff --git a/code-samples/community/serving/helloworld-deno/.dockerignore b/code-samples/community/serving/helloworld-deno/.dockerignore
new file mode 100644
index 000000000..6b7b54031
--- /dev/null
+++ b/code-samples/community/serving/helloworld-deno/.dockerignore
@@ -0,0 +1,2 @@
+Dockerfile
+README.md
diff --git a/code-samples/community/serving/helloworld-deno/Dockerfile b/code-samples/community/serving/helloworld-deno/Dockerfile
new file mode 100644
index 000000000..9d8022576
--- /dev/null
+++ b/code-samples/community/serving/helloworld-deno/Dockerfile
@@ -0,0 +1,8 @@
+FROM hayd/alpine-deno:1.0.0-rc2
+WORKDIR /app
+
+# These steps will be re-run upon each file change in your working directory:
+COPY . ./
+
+# Added to ENTRYPOINT of base image.
+CMD ["run", "--allow-env", "--allow-net", "main.ts"]
diff --git a/code-samples/community/serving/helloworld-deno/README.md b/code-samples/community/serving/helloworld-deno/README.md
new file mode 100644
index 000000000..0e1d9e478
--- /dev/null
+++ b/code-samples/community/serving/helloworld-deno/README.md
@@ -0,0 +1,144 @@
+# Hello World - Deno
+
+A simple web app written in Deno.
+
+Follow the steps below to create the sample code and then deploy the app to your
+cluster. You can also download a working copy of the sample, by running the
+following commands:
+
+```bash
+git clone https://github.com/knative/docs.git knative-docs
+cd knative-docs/code-samples/community/hello-world/helloworld-deno
+```
+
+## Before you begin
+
+- A Kubernetes cluster with Knative installed. Follow the
+ [Knative installation instructions](https://knative.dev/docs/install/) if you need to
+ create one.
+- [Docker](https://www.docker.com) installed and running on your local machine,
+ and a Docker Hub account configured (we'll use it for a container registry).
+
+## Recreating the sample code
+
+1. Create a new file named `deps.ts` and paste the following script:
+
+ ```ts
+ export { serve } from "https://deno.land/std@std@0.50.0/http/server.ts";
+ ```
+
+1. Create a new file named `main.ts` and paste the following script:
+
+ ```ts
+ import { serve } from "./deps.ts";
+ import "https://deno.land/x/dotenv/mod.ts";
+
+ const PORT = Deno.env.get('PORT') || 8080;
+ const s = serve(`0.0.0.0:${PORT}`);
+ const body = new TextEncoder().encode("Hello Deno\n");
+
+ console.log(`Server started on port ${PORT}`);
+ for await (const req of s) {
+ req.respond({ body });
+ }
+ ```
+
+1. Create a new file named `Dockerfile` and copy the code block below into it.
+
+ ```docker
+ FROM hayd/alpine-deno:1.0.0-rc2
+ WORKDIR /app
+
+ # These steps will be re-run upon each file change in your working directory:
+ COPY . ./
+
+ # Added to ENTRYPOINT of base image.
+ CMD ["run", "--allow-env", "--allow-net", "main.ts"]
+ ```
+
+1. Create a new file, `service.yaml` and copy the following service definition
+ into the file. Make sure to replace `{username}` with your Docker Hub
+ username.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-deno
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-deno
+ ```
+
+## Building and deploying the sample
+
+Once you have recreated the sample code files (or used the files in the sample
+folder) you're ready to build and deploy the sample app.
+
+1. Use Docker to build the sample code into a container. To build and push with
+ Docker Hub, run these commands replacing `{username}` with your Docker Hub
+ username:
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-deno .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-deno
+ ```
+
+1. After the build has completed and the container is pushed to docker hub, you
+ can deploy the app into your cluster. Ensure that the container image value
+ in `service.yaml` matches the container you built in the previous step. Apply
+ the configuration using `kubectl`:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+1. Now that your service is created, Knative performs the following steps:
+
+ - Create a new immutable revision for this version of the app.
+ - Network programming to create a route, ingress, service, and load balance
+ for your app.
+ - Automatically scale your pods up and down (including to zero active pods).
+
+1. Run the following command to find the domain URL for your service:
+
+ ```bash
+ kubectl get ksvc helloworld-deno --output=custom-columns=NAME:.metadata.name,URL:.status.url
+ ```
+
+ Example:
+
+ ```bash
+ NAME URL
+ helloworld-deno http://helloworld-deno.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app and see the result. Replace
+ the URL below with the URL returned in the previous command.
+
+ ```bash
+ curl http://helloworld-deno.default.1.2.3.4.sslip.io
+ ```
+
+ Example:
+
+ ```bash
+ curl http://helloworld-deno.default.1.2.3.4.sslip.io
+ [1] "Hello R Sample v1!"
+ ```
+
+ > Note: Add `-v` option to get more detail if the `curl` command failed.
+
+## Removing the sample app deployment
+
+To remove the sample app from your cluster, delete the service record:
+
+```bash
+kubectl delete --filename service.yaml
+```
diff --git a/code-samples/community/serving/helloworld-deno/deps.ts b/code-samples/community/serving/helloworld-deno/deps.ts
new file mode 100644
index 000000000..fa3e0d9d8
--- /dev/null
+++ b/code-samples/community/serving/helloworld-deno/deps.ts
@@ -0,0 +1 @@
+export { serve } from "https://deno.land/std@0.50.0/http/server.ts";
diff --git a/code-samples/community/serving/helloworld-deno/main.ts b/code-samples/community/serving/helloworld-deno/main.ts
new file mode 100644
index 000000000..c01c121f2
--- /dev/null
+++ b/code-samples/community/serving/helloworld-deno/main.ts
@@ -0,0 +1,11 @@
+import { serve } from "./deps.ts";
+import "https://deno.land/x/dotenv/mod.ts";
+
+const PORT = Deno.env.get('PORT') || 8080;
+const s = serve(`0.0.0.0:${PORT}`);
+const body = new TextEncoder().encode("Hello Deno\n");
+
+console.log(`Server started on port ${PORT}`);
+for await (const req of s) {
+ req.respond({ body });
+}
diff --git a/code-samples/community/serving/helloworld-deno/service.yaml b/code-samples/community/serving/helloworld-deno/service.yaml
new file mode 100644
index 000000000..e69de29bb
diff --git a/code-samples/community/serving/helloworld-elixir/.gcloudignore b/code-samples/community/serving/helloworld-elixir/.gcloudignore
new file mode 100644
index 000000000..9d29dd250
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/.gcloudignore
@@ -0,0 +1,24 @@
+# For building with Google Cloud Build using the gcloud command line tool.
+# Similar to .gitignore, except we want the /config/*.secrete.exs uploaded for the build.
+
+# App artifacts
+/_build
+/db
+/deps
+/*.ez
+
+# Generated on crash by the VM
+erl_crash.dump
+
+# Generated on crash by NPM
+npm-debug.log
+/assets/package-lock.json
+
+# Static artifacts
+/assets/node_modules
+
+# Since we are building assets from assets/,
+# we ignore priv/static. You may want to comment
+# this depending on your deployment strategy.
+/priv/static/
+
diff --git a/code-samples/community/serving/helloworld-elixir/.gitignore b/code-samples/community/serving/helloworld-elixir/.gitignore
new file mode 100644
index 000000000..3064370c9
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/.gitignore
@@ -0,0 +1,28 @@
+# App artifacts
+/_build
+/db
+/deps
+/*.ez
+
+# Generated on crash by the VM
+erl_crash.dump
+
+# Generated on crash by NPM
+npm-debug.log
+/assets/package-lock.json
+
+# Static artifacts
+/assets/node_modules
+
+# Since we are building assets from assets/,
+# we ignore priv/static. You may want to comment
+# this depending on your deployment strategy.
+/priv/static/
+
+# Files matching config/*.secret.exs pattern contain sensitive
+# data and you should not commit them into version control.
+#
+# Alternatively, you may comment the line below and commit the
+# secrets files as long as you replace their contents by environment
+# variables.
+/config/*.secret.exs
diff --git a/code-samples/community/serving/helloworld-elixir/Dockerfile b/code-samples/community/serving/helloworld-elixir/Dockerfile
new file mode 100644
index 000000000..dd8c663b1
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/Dockerfile
@@ -0,0 +1,38 @@
+FROM elixir:1.6.6-alpine
+
+ARG APP_NAME=hello
+ARG PHOENIX_SUBDIR=.
+ENV MIX_ENV=prod REPLACE_OS_VARS=true TERM=xterm
+WORKDIR /opt/app
+RUN apk update \
+ && apk --no-cache --update add nodejs nodejs-npm \
+ && mix local.rebar --force \
+ && mix local.hex --force
+COPY . .
+
+RUN mix do deps.get, deps.compile, compile
+RUN cd ${PHOENIX_SUBDIR}/assets \
+ && npm install \
+ && ./node_modules/brunch/bin/brunch build -p \
+ && cd .. \
+ && mix phx.digest
+RUN mix release --env=prod --verbose \
+ && mv _build/prod/rel/${APP_NAME} /opt/release \
+ && mv /opt/release/bin/${APP_NAME} /opt/release/bin/start_server
+
+FROM alpine:latest
+RUN apk update && apk --no-cache --update add bash openssl-dev ca-certificates
+
+RUN addgroup -g 1000 appuser && \
+ adduser -S -u 1000 -G appuser appuser
+
+RUN mkdir -p /opt/app/var
+RUN chown appuser /opt/app/var
+
+USER appuser
+
+ENV MIX_ENV=prod REPLACE_OS_VARS=true
+WORKDIR /opt/app
+COPY --from=0 /opt/release .
+ENV RUNNER_LOG_DIR /var/log
+CMD ["/opt/app/bin/start_server", "foreground", "boot_var=/tmp"]
diff --git a/code-samples/community/serving/helloworld-elixir/README.md b/code-samples/community/serving/helloworld-elixir/README.md
new file mode 100644
index 000000000..7f8029fe4
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/README.md
@@ -0,0 +1,293 @@
+# Hello World - Elixir
+
+A simple web application written in [Elixir](https://elixir-lang.org/) using the
+[Phoenix Framework](https://phoenixframework.org/). The application prints all
+environment variables to the main page.
+
+## Set up Elixir and Phoenix Locally
+
+Following the
+[Phoenix Installation Guide](https://hexdocs.pm/phoenix/installation.html) is
+the best way to get your computer set up for developing, building, running, and
+packaging Elixir Web applications.
+
+## Running Locally
+
+To start your Phoenix server:
+
+- Install dependencies with `mix deps.get`
+- Install Node.js dependencies with `cd assets && npm install`
+- Start Phoenix endpoint with `mix phx.server`
+
+Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
+
+## Recreating the sample code
+
+1. Generate a new project.
+
+ ```bash
+ mix phoenix.new helloelixir
+ ```
+
+ When asked, if you want to `Fetch and install dependencies? [Yn]` select `y`
+
+1. Follow the direction in the output to change directories into start your
+ local server with `mix phoenix.server`
+
+1. In the new directory, create a new Dockerfile for packaging your application
+ for deployment
+
+ ```docker
+ # Start from a base image for elixir
+ # Phoenix works best on pre 1.7 at the moment.
+ FROM elixir:1.6.6-alpine
+
+ # Set up Elixir and Phoenix
+ ARG APP_NAME=hello
+ ARG PHOENIX_SUBDIR=.
+ ENV MIX_ENV=prod REPLACE_OS_VARS=true TERM=xterm
+ WORKDIR /opt/app
+
+ # Update nodejs, rebar, and hex.
+ RUN apk update \
+ && apk --no-cache --update add nodejs nodejs-npm \
+ && mix local.rebar --force \
+ && mix local.hex --force
+ COPY . .
+
+ # Download and compile dependencies, then compile Web app.
+ RUN mix do deps.get, deps.compile, compile
+ RUN cd ${PHOENIX_SUBDIR}/assets \
+ && npm install \
+ && ./node_modules/brunch/bin/brunch build -p \
+ && cd .. \
+ && mix phx.digest
+
+ # Create a release version of the application
+ RUN mix release --env=prod --verbose \
+ && mv _build/prod/rel/${APP_NAME} /opt/release \
+ && mv /opt/release/bin/${APP_NAME} /opt/release/bin/start_server
+
+ # Prepare final layer
+ FROM alpine:latest
+ RUN apk update && apk --no-cache --update add bash openssl-dev ca-certificates
+
+ # Add a user so the server will run as a non-root user.
+ RUN addgroup -g 1000 appuser && \
+ adduser -S -u 1000 -G appuser appuser
+ # Pre-create necessary temp directory for erlang and set permissions.
+ RUN mkdir -p /opt/app/var
+ RUN chown appuser /opt/app/var
+ # Run everything else as 'appuser'
+ USER appuser
+
+ ENV MIX_ENV=prod REPLACE_OS_VARS=true
+ WORKDIR /opt/app
+ COPY --from=0 /opt/release .
+ ENV RUNNER_LOG_DIR /var/log
+
+ # Command to execute the application.
+ CMD ["/opt/app/bin/start_server", "foreground", "boot_var=/tmp"]
+ ```
+
+1. Create a new file, `service.yaml` and copy the following Service definition
+ into the file. Make sure to replace `{username}` with your Docker Hub
+ username.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-elixir
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-elixir
+ env:
+ - name: TARGET
+ value: "elixir Sample v1"
+ ```
+
+## Building and deploying the sample
+
+The sample in this directory is ready to build and deploy without changes. You
+can deploy the sample as is, or use you created version following the directions
+above.
+
+1. Generate a new `secret_key_base` in the `config/prod.secret.exs` file.
+ Phoenix applications use a secrets file on production deployments and, by
+ default, that file is not checked into source control. We have provides
+ shell of an example on `config/prod.secret.exs.sample` and you can use the
+ following command to generate a new prod secrets file.
+
+ ```bash
+ SECRET_KEY_BASE=$(elixir -e ":crypto.strong_rand_bytes(48) |> Base.encode64 |> IO.puts")
+ sed "s|SECRET+KEY+BASE|$SECRET_KEY_BASE|" config/prod.secret.exs.sample >config/prod.secret.exs
+ ```
+
+1. Use Docker to build the sample code into a container. To build and push with
+ Docker Hub, run these commands replacing `{username}` with your Docker Hub
+ username:
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-elixir .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-elixir
+ ```
+
+1. After the build has completed and the container is pushed to docker hub, you
+ can deploy the app into your cluster. Ensure that the container image value
+ in `service.yaml` matches the container you built in the previous step.
+ Apply the configuration using `kubectl`:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+1. Now that your service is created, Knative will perform the following steps:
+
+ - Create a new immutable revision for this version of the app.
+ - Network programming to create a route, ingress, service, and load balance
+ for your app.
+ - Automatically scale your pods up and down (including to zero active pods).
+
+1. To find the URL for your service, use
+
+ ```
+ kubectl get ksvc helloworld-elixir --output=custom-columns=NAME:.metadata.name,URL:.status.url
+
+ NAME URL
+ helloworld-elixir http://helloworld-elixir.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app to see the results. Replace
+ `{IP_ADDRESS}` with the address you see returned in the previous step.
+
+ ```bash
+ curl http://helloworld-elixir.default.1.2.3.4.sslip.io
+
+ ...
+ # HTML from your application is returned.
+ ```
+
+ Here is the HTML returned from our deployed sample application:
+
+ ```HTML
+
+
+
+ <%= for key <- Enum.sort(Map.keys(@env)) do %>
+
<%= key %> = <%= Map.get(@env, key) %>
+ <% end %>
+
diff --git a/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/error_helpers.ex b/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/error_helpers.ex
new file mode 100644
index 000000000..fa06eae03
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/error_helpers.ex
@@ -0,0 +1,44 @@
+defmodule HelloWeb.ErrorHelpers do
+ @moduledoc """
+ Conveniences for translating and building error messages.
+ """
+
+ use Phoenix.HTML
+
+ @doc """
+ Generates tag for inlined form input errors.
+ """
+ def error_tag(form, field) do
+ Enum.map(Keyword.get_values(form.errors, field), fn (error) ->
+ content_tag :span, translate_error(error), class: "help-block"
+ end)
+ end
+
+ @doc """
+ Translates an error message using gettext.
+ """
+ def translate_error({msg, opts}) do
+ # When using gettext, we typically pass the strings we want
+ # to translate as a static argument:
+ #
+ # # Translate "is invalid" in the "errors" domain
+ # dgettext "errors", "is invalid"
+ #
+ # # Translate the number of files with plural rules
+ # dngettext "errors", "1 file", "%{count} files", count
+ #
+ # Because the error messages we show in our forms and APIs
+ # are defined inside Ecto, we need to translate them dynamically.
+ # This requires us to call the Gettext module passing our gettext
+ # backend as first argument.
+ #
+ # Note we use the "errors" domain, which means translations
+ # should be written to the errors.po file. The :count option is
+ # set by Ecto and indicates we should also apply plural rules.
+ if count = opts[:count] do
+ Gettext.dngettext(HelloWeb.Gettext, "errors", msg, msg, count, opts)
+ else
+ Gettext.dgettext(HelloWeb.Gettext, "errors", msg, opts)
+ end
+ end
+end
diff --git a/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/error_view.ex b/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/error_view.ex
new file mode 100644
index 000000000..90f183947
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/error_view.ex
@@ -0,0 +1,16 @@
+defmodule HelloWeb.ErrorView do
+ use HelloWeb, :view
+
+ # If you want to customize a particular status code
+ # for a certain format, you may uncomment below.
+ # def render("500.html", _assigns) do
+ # "Internal Server Error"
+ # end
+
+ # By default, Phoenix returns the status message from
+ # the template name. For example, "404.html" becomes
+ # "Not Found".
+ def template_not_found(template, _assigns) do
+ Phoenix.Controller.status_message_from_template(template)
+ end
+end
diff --git a/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/hello_view.ex b/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/hello_view.ex
new file mode 100644
index 000000000..dc29df264
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/hello_view.ex
@@ -0,0 +1,3 @@
+defmodule HelloWeb.HelloView do
+ use HelloWeb, :view
+end
diff --git a/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/layout_view.ex b/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/layout_view.ex
new file mode 100644
index 000000000..59c874284
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/layout_view.ex
@@ -0,0 +1,3 @@
+defmodule HelloWeb.LayoutView do
+ use HelloWeb, :view
+end
diff --git a/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/page_view.ex b/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/page_view.ex
new file mode 100644
index 000000000..9a271179a
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/lib/hello_web/views/page_view.ex
@@ -0,0 +1,3 @@
+defmodule HelloWeb.PageView do
+ use HelloWeb, :view
+end
diff --git a/code-samples/community/serving/helloworld-elixir/mix.exs b/code-samples/community/serving/helloworld-elixir/mix.exs
new file mode 100644
index 000000000..6127c4c80
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/mix.exs
@@ -0,0 +1,44 @@
+defmodule Hello.Mixfile do
+ use Mix.Project
+
+ def project do
+ [
+ app: :hello,
+ version: "0.0.1",
+ elixir: "~> 1.4",
+ elixirc_paths: elixirc_paths(Mix.env),
+ compilers: [:phoenix, :gettext] ++ Mix.compilers,
+ start_permanent: Mix.env == :prod,
+ deps: deps()
+ ]
+ end
+
+ # Configuration for the OTP application.
+ #
+ # Type `mix help compile.app` for more information.
+ def application do
+ [
+ mod: {Hello.Application, []},
+ extra_applications: [:logger, :runtime_tools]
+ ]
+ end
+
+ # Specifies which paths to compile per environment.
+ defp elixirc_paths(:test), do: ["lib", "test/support"]
+ defp elixirc_paths(_), do: ["lib"]
+
+ # Specifies your project dependencies.
+ #
+ # Type `mix help deps` for examples and options.
+ defp deps do
+ [
+ {:phoenix, "~> 1.3.2"},
+ {:phoenix_pubsub, "~> 1.0"},
+ {:phoenix_html, "~> 2.10"},
+ {:phoenix_live_reload, "~> 1.0", only: :dev},
+ {:gettext, "~> 0.11"},
+ {:cowboy, "~> 1.0"},
+ {:distillery, "~> 1.5"}
+ ]
+ end
+end
diff --git a/code-samples/community/serving/helloworld-elixir/mix.lock b/code-samples/community/serving/helloworld-elixir/mix.lock
new file mode 100644
index 000000000..f87e0b7e0
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/mix.lock
@@ -0,0 +1,15 @@
+%{
+ "cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
+ "cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"},
+ "distillery": {:hex, :distillery, "1.5.2", "eec18b2d37b55b0bcb670cf2bcf64228ed38ce8b046bb30a9b636a6f5a4c0080", [:mix], [], "hexpm"},
+ "file_system": {:hex, :file_system, "0.2.5", "a3060f063b116daf56c044c273f65202e36f75ec42e678dc10653056d3366054", [:mix], [], "hexpm"},
+ "gettext": {:hex, :gettext, "0.15.0", "40a2b8ce33a80ced7727e36768499fc9286881c43ebafccae6bab731e2b2b8ce", [:mix], [], "hexpm"},
+ "mime": {:hex, :mime, "1.3.0", "5e8d45a39e95c650900d03f897fbf99ae04f60ab1daa4a34c7a20a5151b7a5fe", [:mix], [], "hexpm"},
+ "phoenix": {:hex, :phoenix, "1.3.2", "2a00d751f51670ea6bc3f2ba4e6eb27ecb8a2c71e7978d9cd3e5de5ccf7378bd", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
+ "phoenix_html": {:hex, :phoenix_html, "2.11.2", "86ebd768258ba60a27f5578bec83095bdb93485d646fc4111db8844c316602d6", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
+ "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.1.5", "8d4c9b1ef9ca82deee6deb5a038d6d8d7b34b9bb909d99784a49332e0d15b3dc", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.0 or ~> 1.2 or ~> 1.3", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"},
+ "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.0.2", "bfa7fd52788b5eaa09cb51ff9fcad1d9edfeb68251add458523f839392f034c1", [:mix], [], "hexpm"},
+ "plug": {:hex, :plug, "1.5.1", "1ff35bdecfb616f1a2b1c935ab5e4c47303f866cb929d2a76f0541e553a58165", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.3", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
+ "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"},
+ "ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"},
+}
diff --git a/code-samples/community/serving/helloworld-elixir/priv/gettext/en/LC_MESSAGES/errors.po b/code-samples/community/serving/helloworld-elixir/priv/gettext/en/LC_MESSAGES/errors.po
new file mode 100644
index 000000000..cdec3a113
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/priv/gettext/en/LC_MESSAGES/errors.po
@@ -0,0 +1,11 @@
+## `msgid`s in this file come from POT (.pot) files.
+##
+## Do not add, change, or remove `msgid`s manually here as
+## they're tied to the ones in the corresponding POT file
+## (with the same domain).
+##
+## Use `mix gettext.extract --merge` or `mix gettext.merge`
+## to merge POT files into PO files.
+msgid ""
+msgstr ""
+"Language: en\n"
diff --git a/code-samples/community/serving/helloworld-elixir/priv/gettext/errors.pot b/code-samples/community/serving/helloworld-elixir/priv/gettext/errors.pot
new file mode 100644
index 000000000..6988141a6
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/priv/gettext/errors.pot
@@ -0,0 +1,10 @@
+## This file is a PO Template file.
+##
+## `msgid`s here are often extracted from source code.
+## Add new translations manually only if they're dynamic
+## translations that can't be statically extracted.
+##
+## Run `mix gettext.extract` to bring this file up to
+## date. Leave `msgstr`s empty as changing them here as no
+## effect: edit them in PO (`.po`) files instead.
+
diff --git a/code-samples/community/serving/helloworld-elixir/rel/config.exs b/code-samples/community/serving/helloworld-elixir/rel/config.exs
new file mode 100644
index 000000000..7452b3f5f
--- /dev/null
+++ b/code-samples/community/serving/helloworld-elixir/rel/config.exs
@@ -0,0 +1,53 @@
+# Import all plugins from `rel/plugins`
+# They can then be used by adding `plugin MyPlugin` to
+# either an environment, or release definition, where
+# `MyPlugin` is the name of the plugin module.
+Path.join(["rel", "plugins", "*.exs"])
+|> Path.wildcard()
+|> Enum.map(&Code.eval_file(&1))
+
+use Mix.Releases.Config,
+ # This sets the default release built by `mix release`
+ default_release: :default,
+ # This sets the default environment used by `mix release`
+ default_environment: Mix.env()
+
+# For a full list of config options for both releases
+# and environments, visit https://hexdocs.pm/distillery/configuration.html
+
+
+# You may define one or more environments in this file,
+# an environment's settings will override those of a release
+# when building in that environment, this combination of release
+# and environment configuration is called a profile
+
+environment :dev do
+ # If you are running Phoenix, you should make sure that
+ # server: true is set and the code reloader is disabled,
+ # even in dev mode.
+ # It is recommended that you build with MIX_ENV=prod and pass
+ # the --env flag to Distillery explicitly if you want to use
+ # dev mode.
+ set dev_mode: true
+ set include_erts: false
+ set cookie: :"Bps5@RVvPgL9c~C~D(DCQ5*Iu!= 4.7 && < 5
+ - scotty
+ - text
+
+ executables:
+ helloworld-haskell-exe:
+ main: Main.hs
+ source-dirs: app
+ ghc-options:
+ - -threaded
+ - -rtsopts
+ - -with-rtsopts=-N
+ ```
+
+1. Create a `app` folder, then create a new file named `Main.hs` in that folder
+ and paste the following code. This code creates a basic web server which
+ listens on port 8080:
+
+ ```haskell
+ {-# LANGUAGE OverloadedStrings #-}
+
+ import Data.Maybe
+ import Data.Monoid ((<>))
+ import Data.Text.Lazy (Text)
+ import Data.Text.Lazy
+ import System.Environment (lookupEnv)
+ import Web.Scotty (ActionM, ScottyM, scotty)
+ import Web.Scotty.Trans
+
+ main :: IO ()
+ main = do
+ t <- fromMaybe "World" <$> lookupEnv "TARGET"
+ pStr <- fromMaybe "8080" <$> lookupEnv "PORT"
+ let p = read pStr :: Int
+ scotty p (route t)
+
+ route :: String -> ScottyM()
+ route t = get "/" $ hello t
+
+ hello :: String -> ActionM()
+ hello t = text $ pack ("Hello " ++ t)
+ ```
+
+1. In your project directory, create a file named `Dockerfile` and copy the code
+ block below into it.
+
+ ```docker
+ # Use the official Haskell image to create a build artifact.
+ # https://hub.docker.com/_/haskell/
+ FROM haskell:8.2.2 as builder
+
+ # Copy local code to the container image.
+ WORKDIR /app
+ COPY . .
+
+ # Build and test our code, then build the “helloworld-haskell-exe” executable.
+ RUN stack setup
+ RUN stack build --copy-bins
+
+ # Use a Docker multi-stage build to create a lean production image.
+ # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
+ FROM fpco/haskell-scratch:integer-gmp
+
+ # Copy the "helloworld-haskell-exe" executable from the builder stage to the production image.
+ WORKDIR /root/
+ COPY --from=builder /root/.local/bin/helloworld-haskell-exe .
+
+ # Run the web service on container startup.
+ CMD ["./helloworld-haskell-exe"]
+ ```
+
+1. Create a new file, `service.yaml` and copy the following service definition
+ into the file. Make sure to replace `{username}` with your Docker Hub
+ username.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-haskell
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-haskell
+ env:
+ - name: TARGET
+ value: "Haskell Sample v1"
+ ```
+
+## Build and deploy this sample
+
+Once you have recreated the sample code files (or used the files in the sample
+folder) you're ready to build and deploy the sample app.
+
+1. Use Docker to build the sample code into a container. To build and push with
+ Docker Hub, enter these commands replacing `{username}` with your Docker Hub
+ username:
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-haskell .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-haskell
+ ```
+
+1. After the build has completed and the container is pushed to Docker Hub, you
+ can deploy the app into your cluster. Ensure that the container image value
+ in `service.yaml` matches the container you built in the previous step. Apply
+ the configuration using `kubectl`:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+1. Now that your service is created, Knative will perform the following steps:
+
+ - Create a new immutable revision for this version of the app.
+ - Network programming to create a route, ingress, service, and load balance
+ for your app.
+ - Automatically scale your pods up and down (including to zero active pods).
+
+1. To find the URL for your service, enter:
+
+ ```
+ kubectl get ksvc helloworld-haskell --output=custom-columns=NAME:.metadata.name,URL:.status.url
+ NAME URL
+ helloworld-haskell http://helloworld-haskell.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app and see the result. Replace
+ the URL below with the URL returned in the previous command.
+
+ ```bash
+ curl http://helloworld-haskell.default.1.2.3.4.sslip.io
+ Hello world: Haskell Sample v1
+ ```
+
+## Removing the sample app deployment
+
+To remove the sample app from your cluster, delete the service record:
+
+```bash
+kubectl delete --filename service.yaml
+```
diff --git a/code-samples/community/serving/helloworld-haskell/app/Main.hs b/code-samples/community/serving/helloworld-haskell/app/Main.hs
new file mode 100644
index 000000000..0e35f7cbf
--- /dev/null
+++ b/code-samples/community/serving/helloworld-haskell/app/Main.hs
@@ -0,0 +1,22 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+import Data.Maybe
+import Data.Monoid ((<>))
+import Data.Text.Lazy (Text)
+import Data.Text.Lazy
+import System.Environment (lookupEnv)
+import Web.Scotty (ActionM, ScottyM, scotty)
+import Web.Scotty.Trans
+
+main :: IO ()
+main = do
+ t <- fromMaybe "World" <$> lookupEnv "TARGET"
+ pStr <- fromMaybe "8080" <$> lookupEnv "PORT"
+ let p = read pStr :: Int
+ scotty p (route t)
+
+route :: String -> ScottyM()
+route t = get "/" $ hello t
+
+hello :: String -> ActionM()
+hello t = text $ pack ("Hello " ++ t)
diff --git a/code-samples/community/serving/helloworld-haskell/package.yaml b/code-samples/community/serving/helloworld-haskell/package.yaml
new file mode 100644
index 000000000..12178e943
--- /dev/null
+++ b/code-samples/community/serving/helloworld-haskell/package.yaml
@@ -0,0 +1,15 @@
+name: helloworld-haskell
+version: 0.1.0.0
+dependencies:
+- base >= 4.7 && < 5
+- scotty
+- text
+
+executables:
+ helloworld-haskell-exe:
+ main: Main.hs
+ source-dirs: app
+ ghc-options:
+ - -threaded
+ - -rtsopts
+ - -with-rtsopts=-N
diff --git a/code-samples/community/serving/helloworld-haskell/service.yaml b/code-samples/community/serving/helloworld-haskell/service.yaml
new file mode 100644
index 000000000..3f339ed99
--- /dev/null
+++ b/code-samples/community/serving/helloworld-haskell/service.yaml
@@ -0,0 +1,13 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ name: helloworld-haskell
+ namespace: default
+spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-haskell
+ env:
+ - name: TARGET
+ value: "Haskell Sample v1"
diff --git a/code-samples/community/serving/helloworld-haskell/stack.yaml b/code-samples/community/serving/helloworld-haskell/stack.yaml
new file mode 100644
index 000000000..e63cd13e1
--- /dev/null
+++ b/code-samples/community/serving/helloworld-haskell/stack.yaml
@@ -0,0 +1,5 @@
+flags: {}
+packages:
+- .
+extra-deps: []
+resolver: lts-10.7
diff --git a/code-samples/community/serving/helloworld-java-micronaut/.dockerignore b/code-samples/community/serving/helloworld-java-micronaut/.dockerignore
new file mode 100644
index 000000000..2f7896d1d
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/.dockerignore
@@ -0,0 +1 @@
+target/
diff --git a/code-samples/community/serving/helloworld-java-micronaut/.gitignore b/code-samples/community/serving/helloworld-java-micronaut/.gitignore
new file mode 100644
index 000000000..c5f0be605
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/.gitignore
@@ -0,0 +1,14 @@
+Thumbs.db
+.DS_Store
+.gradle
+build/
+target/
+out/
+.idea
+*.iml
+*.ipr
+*.iws
+.project
+.settings
+.classpath
+.factorypath
diff --git a/code-samples/community/serving/helloworld-java-micronaut/.mvn/jvm.config b/code-samples/community/serving/helloworld-java-micronaut/.mvn/jvm.config
new file mode 100644
index 000000000..2256175bc
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/.mvn/jvm.config
@@ -0,0 +1 @@
+-Dcom.sun.management.jmxremote -noverify -XX:TieredStopAtLevel=1
diff --git a/code-samples/community/serving/helloworld-java-micronaut/.mvn/wrapper/MavenWrapperDownloader.java b/code-samples/community/serving/helloworld-java-micronaut/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..d475a89ce
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,110 @@
+/*
+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.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/code-samples/community/serving/helloworld-java-micronaut/.mvn/wrapper/maven-wrapper.jar b/code-samples/community/serving/helloworld-java-micronaut/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..08ebbb67f
Binary files /dev/null and b/code-samples/community/serving/helloworld-java-micronaut/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/code-samples/community/serving/helloworld-java-micronaut/.mvn/wrapper/maven-wrapper.properties b/code-samples/community/serving/helloworld-java-micronaut/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..0773086c0
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip
diff --git a/code-samples/community/serving/helloworld-java-micronaut/Dockerfile b/code-samples/community/serving/helloworld-java-micronaut/Dockerfile
new file mode 100644
index 000000000..5178a307d
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/Dockerfile
@@ -0,0 +1,23 @@
+# Use the official maven/Java 8 image to create a build artifact.
+# https://hub.docker.com/_/maven
+FROM maven:3.5-jdk-8-alpine as builder
+
+# Copy local code to the container image.
+WORKDIR /app
+COPY pom.xml .
+COPY src ./src
+
+# Build a release artifact.
+RUN mvn package -DskipTests
+
+# Use AdoptOpenJDK for base image.
+# It's important to use OpenJDK 8u191 or above that has container support enabled.
+# https://hub.docker.com/r/adoptopenjdk/openjdk8
+# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
+FROM adoptopenjdk/openjdk8:jdk8u202-b08-alpine-slim
+
+# Copy the jar to the production image from the builder stage.
+COPY --from=builder /app/target/helloworld-1.0.0-SNAPSHOT.jar /helloworld.jar
+
+# Run the web service on container startup.
+CMD ["java","-jar","/helloworld.jar"]
diff --git a/code-samples/community/serving/helloworld-java-micronaut/README.md b/code-samples/community/serving/helloworld-java-micronaut/README.md
new file mode 100644
index 000000000..940d6e743
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/README.md
@@ -0,0 +1,284 @@
+# Hello World - Java (Micronaut)
+
+Learn how to deploy a simple web app that is written in Java and uses Micronaut.
+
+This samples uses Docker to build locally. The app reads in a `TARGET` env
+variable and then prints "Hello World: \${TARGET}!". If a value for `TARGET` is
+not specified, the "NOT SPECIFIED" default value is used.
+
+Use this sample to walk you through the steps of creating and modifying the
+sample app, building and pushing your container image to a registry, and then
+deploying your app to your Knative cluster.
+
+## Before you begin
+
+You must meet the following requirements to complete this sample:
+
+- A version of the Knative Serving component installed and DNS configured. Follow the
+ [Knative installation instructions](https://knative.dev/docs/install/) if you need
+ to create a Knative cluster.
+- The following software downloaded and install on your loacal machine:
+ - [Java SE 8 or later JDK](http://www.oracle.com/technetwork/java/javase/downloads/index.html).
+ - [Micronaut 1.1](https://micronaut.io/).
+ - [Docker](https://www.docker.com) for building and pushing your container
+ image.
+ - [curl](https://curl.haxx.se/) to test the sample app after deployment.
+- A [Docker Hub](https://hub.docker.com/) account where you can push your
+ container image.
+
+**Tip**: You can clone the [Knatve/docs repo](https://github.com/knative/docs)
+and then modify the source files. Alternatively, learn more by manually creating
+the files yourself.
+
+## Creating and configuring the sample code
+
+To create and configure the source files in the root of your working directory:
+
+1. Create the `pom.xml` file:
+
+ ```xml
+ 4.0.0
+ com.example.micronaut
+ helloworld
+ 1.0.0-SNAPSHOT
+
+ 1.1.0
+ 1.8
+ UTF-8
+ com.example.helloworld.Application
+
+
+
+
+ io.micronaut
+ micronaut-bom
+ ${micronaut.version}
+ pom
+ import
+
+
+
+
+
+ io.micronaut
+ micronaut-inject
+ compile
+
+
+ io.micronaut
+ micronaut-validation
+ compile
+
+
+ io.micronaut
+ micronaut-runtime
+ compile
+
+
+ io.micronaut
+ micronaut-http-client
+ compile
+
+
+ io.micronaut
+ micronaut-http-server-netty
+ compile
+
+
+ ch.qos.logback
+ logback-classic
+ 1.2.3
+ runtime
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.1.0
+
+
+ package
+
+ shade
+
+
+
+
+ ${exec.mainClass}
+
+
+
+
+
+
+
+
+
+
+ ```
+
+1. Create the `HelloWorldController.java` file in the
+ `src/main/java/com/example/helloworld` directory. The
+ `[ROOT]/src/main/java/com/example/helloworld/HelloWorldController.java` file
+ handles requests to the root URI `/`.
+
+ ```java
+ package com.example.helloworld;
+
+ import io.micronaut.http.MediaType;
+ import io.micronaut.http.annotation.Controller;
+ import io.micronaut.http.annotation.Get;
+
+ @Controller("/")
+ public class HelloWorldController {
+
+ @Get(value = "/", produces = MediaType.TEXT_PLAIN)
+ public String index() {
+ String target = System.getenv("TARGET");
+ if (target == null) {
+ target = "NOT SPECIFIED";
+ }
+ return "Hello World: " + target;
+ }
+ }
+ ```
+
+1. The Micronaut application is configured via
+ `src/main/resources/application.yml`:
+
+ ```yaml
+ micronaut:
+ application:
+ name: helloworld-java-micronaut
+ server:
+ port: ${PORT:8080}
+ ```
+
+1. Create the `Dockerfile` file:
+
+ ```docker
+ # Use the official maven/Java 8 image to create a build artifact.
+ # https://hub.docker.com/_/maven
+ FROM maven:3.5-jdk-8-alpine as builder
+
+ # Copy local code to the container image.
+ WORKDIR /app
+ COPY pom.xml .
+ COPY src ./src
+
+ # Build a release artifact.
+ RUN mvn package -DskipTests
+
+ # Use AdoptOpenJDK for base image.
+ # It's important to use OpenJDK 8u191 or above that has container support enabled.
+ # https://hub.docker.com/r/adoptopenjdk/openjdk8
+ # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
+ FROM adoptopenjdk/openjdk8:jdk8u202-b08-alpine-slim
+
+ # Copy the jar to the production image from the builder stage.
+ COPY --from=builder /app/target/helloworld-1.0.0-SNAPSHOT.jar /helloworld.jar
+
+ # Run the web service on container startup.
+ CMD ["java","-jar","/helloworld.jar"]
+ ```
+
+1. Create the `service.yaml` file. You must specify your Docker Hub username in
+ `{username}`. You can also configure the `TARGET`, for example you can modify
+ the `Micronaut Sample v1` value.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-java-micronaut
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-java-micronaut
+ env:
+ - name: TARGET
+ value: "Micronaut Sample v1"
+ ```
+
+## Building and deploying the sample
+
+To build a container image, push your image to the registry, and then deploy
+your sample app to your cluster:
+
+1. Use Docker to build your container image and then push that image to your
+ Docker Hub registry. You must replace the `{username}` variables in the
+ following commands with your Docker Hub username.
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-java-micronaut .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-java-micronaut
+ ```
+
+1. Now that your container image is in the registry, you can deploy it to your
+ Knative cluster by running the `kubectl apply` command:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+ Result: A service name `helloworld-java-micronaut` is created in your cluster
+ along with the following resources:
+
+ - A new immutable revision for the version of the app that you just deployed.
+ - The following networking resources are created for your app:
+ - route
+ - ingress
+ - service
+ - load balancer
+ - Auto scaling is enable to allow your pods to scale up to meet traffic, and
+ also back down to zero when there is no traffic.
+
+## Testing the sample app
+
+To verify that your sample app has been successfully deployed:
+
+1. Retrieve the URL for your service, by running the following `kubectl get`
+ command:
+
+ ```bash
+ kubectl get ksvc helloworld-java-micronaut --output=custom-columns=NAME:.metadata.name,URL:.status.url
+ ```
+
+ Example result:
+
+ ```bash
+ NAME URL
+ helloworld-java-micronaut http://helloworld-java-micronaut.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app and see the result. Replace
+ the URL below with the URL returned in the previous command.
+
+ ```bash
+ curl http://helloworld-java-micronaut.default.1.2.3.4.sslip.io
+ ```
+
+ Example result:
+
+ ```bash
+ Hello World: Micronaut Sample v1
+ ```
+
+Congratulations on deploying your sample Java app to Knative!
+
+## Removing the sample app deployment
+
+To remove the sample app from your cluster, run the following `kubectl delete`
+command:
+
+```bash
+kubectl delete --filename service.yaml
+```
diff --git a/code-samples/community/serving/helloworld-java-micronaut/dependency-reduced-pom.xml b/code-samples/community/serving/helloworld-java-micronaut/dependency-reduced-pom.xml
new file mode 100644
index 000000000..62ceaf326
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/dependency-reduced-pom.xml
@@ -0,0 +1,173 @@
+
+
+ 4.0.0
+ com.example.micronaut
+ helloworld
+ 1.0.0-SNAPSHOT
+
+
+
+
+ maven-compiler-plugin
+ 3.7.0
+
+
+ test-compile
+
+ testCompile
+
+
+
+ -parameters
+
+
+
+ io.micronaut
+ micronaut-inject-java
+ ${micronaut.version}
+
+
+ io.micronaut
+ micronaut-validation
+ ${micronaut.version}
+
+
+
+
+
+
+ ${jdk.version}
+ ${jdk.version}
+ UTF-8
+
+ -parameters
+
+
+
+ io.micronaut
+ micronaut-inject-java
+ ${micronaut.version}
+
+
+ io.micronaut
+ micronaut-validation
+ ${micronaut.version}
+
+
+
+
+
+
+
+
+ maven-shade-plugin
+ 3.1.0
+
+
+ package
+
+ shade
+
+
+
+
+ ${exec.mainClass}
+
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+ java
+
+ -noverify
+ -Dmicronaut.env.deduction=false
+ -XX:TieredStopAtLevel=1
+ -Dcom.sun.management.jmxremote
+ -classpath
+
+ ${exec.mainClass}
+
+
+
+
+ maven-surefire-plugin
+ 2.22.0
+
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.3.1
+ test
+
+
+ apiguardian-api
+ org.apiguardian
+
+
+ opentest4j
+ org.opentest4j
+
+
+ junit-platform-commons
+ org.junit.platform
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.3.1
+ test
+
+
+ junit-platform-engine
+ org.junit.platform
+
+
+ apiguardian-api
+ org.apiguardian
+
+
+
+
+ io.micronaut.test
+ micronaut-test-junit5
+ 1.0.2
+ test
+
+
+ micronaut-test-core
+ io.micronaut.test
+
+
+
+
+
+
+
+ io.micronaut
+ micronaut-bom
+ ${micronaut.version}
+ pom
+ import
+
+
+
+
+ 1.1.0
+ com.example.helloworld.Application
+ UTF-8
+ 1.8
+
+
+
diff --git a/code-samples/community/serving/helloworld-java-micronaut/micronaut-cli.yml b/code-samples/community/serving/helloworld-java-micronaut/micronaut-cli.yml
new file mode 100644
index 000000000..5edd337c4
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/micronaut-cli.yml
@@ -0,0 +1,5 @@
+profile: service
+defaultPackage: com.example.helloworld
+---
+testFramework: junit
+sourceLanguage: java
diff --git a/code-samples/community/serving/helloworld-java-micronaut/mvnw b/code-samples/community/serving/helloworld-java-micronaut/mvnw
new file mode 100644
index 000000000..961a82500
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/mvnw
@@ -0,0 +1,286 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+ # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar"
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ wget "$jarUrl" -O "$wrapperJarPath"
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ curl -o "$wrapperJarPath" "$jarUrl"
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/code-samples/community/serving/helloworld-java-micronaut/mvnw.cmd b/code-samples/community/serving/helloworld-java-micronaut/mvnw.cmd
new file mode 100644
index 000000000..03d90e960
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/mvnw.cmd
@@ -0,0 +1,161 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.0/maven-wrapper-0.4.0.jar"
+FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ echo Found %WRAPPER_JAR%
+) else (
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+ powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
+ echo Finished downloading %WRAPPER_JAR%
+)
+@REM End of extension
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/code-samples/community/serving/helloworld-java-micronaut/pom.xml b/code-samples/community/serving/helloworld-java-micronaut/pom.xml
new file mode 100644
index 000000000..d1a73d8bf
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/pom.xml
@@ -0,0 +1,172 @@
+
+ 4.0.0
+ com.example.micronaut
+ helloworld
+ 1.0.0-SNAPSHOT
+
+ 1.1.0
+ 1.8
+ UTF-8
+ com.example.helloworld.Application
+
+
+
+
+ io.micronaut
+ micronaut-bom
+ ${micronaut.version}
+ pom
+ import
+
+
+
+
+
+ io.micronaut
+ micronaut-inject
+ compile
+
+
+ io.micronaut
+ micronaut-validation
+ compile
+
+
+ io.micronaut
+ micronaut-runtime
+ compile
+
+
+ io.micronaut
+ micronaut-http-client
+ compile
+
+
+ io.micronaut
+ micronaut-http-server-netty
+ compile
+
+
+ ch.qos.logback
+ logback-classic
+ 1.2.3
+ runtime
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+ io.micronaut.test
+ micronaut-test-junit5
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.1.0
+
+
+ package
+
+ shade
+
+
+
+
+ ${exec.mainClass}
+
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+ java
+
+
+ -noverify
+ -Dmicronaut.env.deduction=false
+ -XX:TieredStopAtLevel=1
+ -Dcom.sun.management.jmxremote
+ -classpath
+
+ ${exec.mainClass}
+
+
+
+
+ maven-surefire-plugin
+ 2.22.0
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.7.0
+
+ ${jdk.version}
+ ${jdk.version}
+ UTF-8
+
+ -parameters
+
+
+
+ io.micronaut
+ micronaut-inject-java
+ ${micronaut.version}
+
+
+ io.micronaut
+ micronaut-validation
+ ${micronaut.version}
+
+
+
+
+
+ test-compile
+
+ testCompile
+
+
+
+ -parameters
+
+
+
+ io.micronaut
+ micronaut-inject-java
+ ${micronaut.version}
+
+
+ io.micronaut
+ micronaut-validation
+ ${micronaut.version}
+
+
+
+
+
+
+
+
+
+
diff --git a/code-samples/community/serving/helloworld-java-micronaut/service.yaml b/code-samples/community/serving/helloworld-java-micronaut/service.yaml
new file mode 100644
index 000000000..d01116281
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/service.yaml
@@ -0,0 +1,12 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ name: helloworld-java-micronaut
+spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-java-micronaut
+ env:
+ - name: TARGET
+ value: "Micronaut Sample v1"
diff --git a/code-samples/community/serving/helloworld-java-micronaut/src/main/java/com/example/helloworld/Application.java b/code-samples/community/serving/helloworld-java-micronaut/src/main/java/com/example/helloworld/Application.java
new file mode 100644
index 000000000..090c82105
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/src/main/java/com/example/helloworld/Application.java
@@ -0,0 +1,10 @@
+package com.example.helloworld;
+
+import io.micronaut.runtime.Micronaut;
+
+public class Application {
+
+ public static void main(String[] args) {
+ Micronaut.run(Application.class);
+ }
+}
diff --git a/code-samples/community/serving/helloworld-java-micronaut/src/main/java/com/example/helloworld/HelloWorldController.java b/code-samples/community/serving/helloworld-java-micronaut/src/main/java/com/example/helloworld/HelloWorldController.java
new file mode 100644
index 000000000..09c9f88d8
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/src/main/java/com/example/helloworld/HelloWorldController.java
@@ -0,0 +1,18 @@
+package com.example.helloworld;
+
+import io.micronaut.http.MediaType;
+import io.micronaut.http.annotation.Controller;
+import io.micronaut.http.annotation.Get;
+
+@Controller("/")
+public class HelloWorldController {
+
+ @Get(value = "/", produces = MediaType.TEXT_PLAIN)
+ public String index() {
+ String target = System.getenv("TARGET");
+ if (target == null) {
+ target = "NOT SPECIFIED";
+ }
+ return "Hello World: " + target;
+ }
+}
diff --git a/code-samples/community/serving/helloworld-java-micronaut/src/main/resources/application.yml b/code-samples/community/serving/helloworld-java-micronaut/src/main/resources/application.yml
new file mode 100644
index 000000000..ac027de4e
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/src/main/resources/application.yml
@@ -0,0 +1,5 @@
+micronaut:
+ application:
+ name: helloworld-micronaut
+ server:
+ port: ${PORT:8080}
diff --git a/code-samples/community/serving/helloworld-java-micronaut/src/main/resources/logback.xml b/code-samples/community/serving/helloworld-java-micronaut/src/main/resources/logback.xml
new file mode 100644
index 000000000..6010eb523
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/src/main/resources/logback.xml
@@ -0,0 +1,15 @@
+
+
+
+ true
+
+
+ %cyan(%d{HH:mm:ss.SSS}) %gray([%thread]) %highlight(%-5level) %magenta(%logger{36}) - %msg%n
+
+
+
+
+
+
+
diff --git a/code-samples/community/serving/helloworld-java-micronaut/src/test/java/com/example/helloworld/HelloWorldControllerTest.java b/code-samples/community/serving/helloworld-java-micronaut/src/test/java/com/example/helloworld/HelloWorldControllerTest.java
new file mode 100644
index 000000000..276591653
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-micronaut/src/test/java/com/example/helloworld/HelloWorldControllerTest.java
@@ -0,0 +1,28 @@
+package com.example.helloworld;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import javax.inject.Inject;
+
+import org.junit.jupiter.api.Test;
+
+import io.micronaut.http.HttpResponse;
+import io.micronaut.http.HttpStatus;
+import io.micronaut.http.client.RxHttpClient;
+import io.micronaut.http.client.annotation.Client;
+import io.micronaut.test.annotation.MicronautTest;
+
+@MicronautTest
+public class HelloWorldControllerTest {
+
+ @Inject
+ @Client("/")
+ RxHttpClient client;
+
+ @Test
+ public void testIndex() throws Exception {
+ HttpResponse response = client.toBlocking().exchange("/", String.class);
+ assertEquals(HttpStatus.OK, response.status());
+ assertEquals("Hello World: NOT SPECIFIED", response.body());
+ }
+}
diff --git a/code-samples/community/serving/helloworld-java-quarkus/.dockerignore b/code-samples/community/serving/helloworld-java-quarkus/.dockerignore
new file mode 100644
index 000000000..eb1e37998
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/.dockerignore
@@ -0,0 +1,11 @@
+README.md
+_index.md
+.editorconfig
+.gitignore
+.git
+target/
+.settings
+.idea
+.project
+.classpath
+*.iml
diff --git a/code-samples/community/serving/helloworld-java-quarkus/.editorconfig b/code-samples/community/serving/helloworld-java-quarkus/.editorconfig
new file mode 100644
index 000000000..e8e95b9d1
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/.editorconfig
@@ -0,0 +1,8 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = false
+insert_final_newline = false
diff --git a/code-samples/community/serving/helloworld-java-quarkus/.gitignore b/code-samples/community/serving/helloworld-java-quarkus/.gitignore
new file mode 100644
index 000000000..637139252
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/.gitignore
@@ -0,0 +1,31 @@
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/build/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VScode ###
+.vscode
+
+st
+**/*.log
diff --git a/code-samples/community/serving/helloworld-java-quarkus/.mvn/wrapper/MavenWrapperDownloader.java b/code-samples/community/serving/helloworld-java-quarkus/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 000000000..b20a55a7a
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * 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.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.3";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + " .jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/code-samples/community/serving/helloworld-java-quarkus/.mvn/wrapper/maven-wrapper.jar b/code-samples/community/serving/helloworld-java-quarkus/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 000000000..e89f07c22
Binary files /dev/null and b/code-samples/community/serving/helloworld-java-quarkus/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/code-samples/community/serving/helloworld-java-quarkus/.mvn/wrapper/maven-wrapper.properties b/code-samples/community/serving/helloworld-java-quarkus/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 000000000..dbcb670a5
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=http://repo2.maven.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
+wrapperUrl=http://repo2.maven.org/maven2/io/takari/maven-wrapper/0.5.4/maven-wrapper-0.5.4.jar
diff --git a/code-samples/community/serving/helloworld-java-quarkus/Dockerfile b/code-samples/community/serving/helloworld-java-quarkus/Dockerfile
new file mode 100644
index 000000000..88b9adb5e
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/Dockerfile
@@ -0,0 +1,18 @@
+FROM quay.io/rhdevelopers/quarkus-java-builder as builder
+COPY . /project
+WORKDIR /project
+# uncomment this to set the MAVEN_MIRROR_URL of your choice, to make faster builds
+# ARG MAVEN_MIRROR_URL=
+# e.g.
+#ARG MAVEN_MIRROR_URL=http://192.168.64.1:8081/nexus/content/groups/public
+
+RUN /usr/local/bin/entrypoint-run.sh mvn -DskipTests clean package
+
+FROM fabric8/java-jboss-openjdk8-jdk:1.5.4
+USER jboss
+ENV JAVA_APP_DIR=/deployments
+
+COPY --from=builder /project/target/lib/* /deployments/lib/
+COPY --from=builder /project/target/*-runner.jar /deployments/app.jar
+
+ENTRYPOINT [ "/deployments/run-java.sh" ]
diff --git a/code-samples/community/serving/helloworld-java-quarkus/Dockerfile.native b/code-samples/community/serving/helloworld-java-quarkus/Dockerfile.native
new file mode 100644
index 000000000..27bd8a7e7
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/Dockerfile.native
@@ -0,0 +1,15 @@
+FROM quay.io/rhdevelopers/quarkus-java-builder:graal-1.0.0-rc15 as builder
+COPY . /project
+
+# uncomment this to set the MAVEN_MIRROR_URL of your choice, to make faster builds
+# ARG MAVEN_MIRROR_URL=
+# e.g.
+# ARG MAVEN_MIRROR_URL=http://192.168.64.1:8081/nexus/content/groups/public
+
+RUN /usr/local/bin/entrypoint-run.sh mvn -DskipTests clean package -Pnative
+
+FROM registry.fedoraproject.org/fedora-minimal
+
+COPY --from=builder /project/target/helloworld-java-quarkus-1.0-SNAPSHOT-runner /app
+
+ENTRYPOINT [ "/app" ]
diff --git a/code-samples/community/serving/helloworld-java-quarkus/README.md b/code-samples/community/serving/helloworld-java-quarkus/README.md
new file mode 100644
index 000000000..317b95d29
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/README.md
@@ -0,0 +1,271 @@
+# Hello World - Java (Quarkus)
+
+A simple [JAX-RS REST API](https://github.com/jax-rs) application that is
+written in Java and uses [Quarkus](https://quarkus.io/).
+
+This samples uses Docker to build locally. The app reads in a `TARGET` env
+variable and then prints "Hello World: \${TARGET}!". If a value for `TARGET` is
+not specified, the "NOT SPECIFIED" default value is used.
+
+## Before you begin
+
+You must meet the following requirements to run this sample:
+
+- Have a Kubernetes cluster running with the Knative Serving component
+ installed. For more information, see the
+ [Knative installation instructions](https://knative.dev/docs/install/).
+- An installed version of the following tools:
+ - [Docker](https://www.docker.com)
+ - [Java SE 8 or later JDK](https://www.eclipse.org/openj9/)
+ - [Maven](https://maven.apache.org/download.cgi)
+- A [Docker Hub account](https://hub.docker.com/) to which you are able to
+ upload your sample's container image.
+
+## Getting the code
+
+You can either clone a working copy of the sample code from the repository, or
+following the steps in the
+[Recreating the sample code](#recreating-the-sample-code) to walk through the
+steps of updating all the files.
+
+### Cloning the sample code
+
+Use this method to clone and then immediate run the sample. To clone the sample
+code, run the following commands:
+
+```bash
+git clone https://github.com/knative/docs.git knative/docs
+cd knative/docs/code-samples/community/serving/helloworld-java-quarkus
+```
+
+You are now ready to [run the sample locally](#locally-testing-your-sample).
+
+### Recreating the sample code
+
+Use the following steps to obtain an incomplete copy of the sample code for
+which you update and create the necessary build and configuration files:
+
+1. From the console, create a new empty web project using the Maven archetype
+ commands:
+
+ ```bash
+ mvn io.quarkus:quarkus-maven-plugin:0.13.3:create \
+ -DprojectGroupId=com.redhat.developer.demos \
+ -DprojectArtifactId=helloworld-java-quarkus \
+ -DclassName="com.redhat.developer.demos.GreetingResource" \
+ -Dpath="/"
+ ```
+
+1. Update the `GreetingResource` class in
+ `src/main/java/com/redhat/developer/demos/GreetingResource.java` to handle
+ the "/" mapping and also add a `@ConfigProperty` field to provide the TARGET
+ environment variable:
+
+ ```java
+ package com.redhat.developer.demos;
+
+ import javax.ws.rs.GET;
+ import javax.ws.rs.Path;
+ import javax.ws.rs.Produces;
+ import javax.ws.rs.core.MediaType;
+ import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+ @Path("/")
+ public class GreeterResource {
+ @ConfigProperty(name = "TARGET", defaultValue="World")
+ String target;
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String greet() {
+ return "Hello " + target + "!";
+ }
+ }
+ ```
+
+1. Update `src/main/resources/application.properties` to configuration the
+ application to default to port 8080, but allow the port to be overridden by
+ the `PORT` environmental variable:
+
+ ```
+ # Configuration file
+ # key = value
+
+ quarkus.http.port=${PORT:8080}
+ ```
+
+1. Update `src/test/java/com/redhat/developer/demos/GreetingResourceTest.java`
+ test to reflect the change:
+
+ ```java
+ package com.redhat.developer.demos;
+
+ import io.quarkus.test.junit.QuarkusTest;
+ import org.junit.jupiter.api.Test;
+
+ import static io.restassured.RestAssured.given;
+ import static org.hamcrest.CoreMatchers.is;
+
+ @QuarkusTest
+ public class GreetingResourceTest {
+
+ @Test
+ public void testHelloEndpoint() {
+ given()
+ .when().get("/")
+ .then()
+ .statusCode(200)
+ .body(is("Hello World!"));
+ }
+ }
+
+ ```
+
+1. Remove `src/main/resources/META-INF/resources/index.html` file since it's
+ unncessary for this example.
+
+ ```bash
+ rm src/main/resources/META-INF/resources/index.html
+ ```
+
+1. Remove `.dockerignore` file since it's unncessary for this example.
+
+ ```bash
+ rm .dockerignore
+ ```
+
+1. In your project directory, create a file named `Dockerfile` and copy the code
+ block below into it.
+
+ ```docker
+ FROM quay.io/rhdevelopers/quarkus-java-builder:graal-1.0.0-rc15 as builder
+ COPY . /project
+ WORKDIR /project
+ # uncomment this to set the MAVEN_MIRROR_URL of your choice, to make faster builds
+ # ARG MAVEN_MIRROR_URL=
+ # e.g.
+ #ARG MAVEN_MIRROR_URL=http://192.168.64.1:8081/nexus/content/groups/public
+
+ RUN /usr/local/bin/entrypoint-run.sh mvn -DskipTests clean package
+
+ FROM fabric8/java-jboss-openjdk8-jdk:1.5.4
+ USER jboss
+ ENV JAVA_APP_DIR=/deployments
+
+ COPY --from=builder /project/target/lib/* /deployments/lib/
+ COPY --from=builder /project/target/*-runner.jar /deployments/app.jar
+
+ ENTRYPOINT [ "/deployments/run-java.sh" ]
+ ```
+
+ If you want to build Quarkus native image, then copy the following code block
+ in to file called `Dockerfile.native`
+
+ ```docker
+ FROM quay.io/rhdevelopers/quarkus-java-builder:graal-1.0.0-rc15 as builder
+ COPY . /project
+ # uncomment this to set the MAVEN_MIRROR_URL of your choice, to make faster builds
+ # ARG MAVEN_MIRROR_URL=
+ # e.g.
+ # ARG MAVEN_MIRROR_URL=http://192.168.64.1:8081/nexus/content/groups/public
+
+ RUN /usr/local/bin/entrypoint-run.sh mvn -DskipTests clean package -Pnative
+
+ FROM registry.fedoraproject.org/fedora-minimal
+
+ COPY --from=builder /project/target/helloworld-java-quarkus-runner /app
+
+ ENTRYPOINT [ "/app" ]
+ ```
+
+1. Create a new file, `service.yaml` and copy the following service definition
+ into the file. Make sure to replace `{username}` with your Docker Hub
+ username.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-java-quarkus
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-java-quarkus
+ env:
+ - name: TARGET
+ value: "Quarkus Sample v1"
+ ```
+
+## Locally testing your sample
+
+1. Run the application locally:
+
+ ```bash
+ ./mvnw compile quarkus:dev
+ ```
+
+ Go to `http://localhost:8080/` to see your `Hello World!` message.
+
+## Building and deploying the sample
+
+Once you have recreated the sample code files (or used the files in the sample
+folder) you're ready to build and deploy the sample app.
+
+1. Use Docker to build the sample code into a container. To build and push with
+ Docker Hub, run these commands replacing `{username}` with your Docker Hub
+ username:
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-java-quarkus .
+
+ # (OR)
+ # Build the container on your local machine - Quarkus native mode
+ docker build -t {username}/helloworld-java-quarkus -f Dockerfile.native .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-java-quarkus
+ ```
+
+1. After the build has completed and the container is pushed to docker hub, you
+ can deploy the app into your cluster. Ensure that the container image value
+ in `service.yaml` matches the container you built in the previous step. Apply
+ the configuration using `kubectl`:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+1. Now that your service is created, Knative will perform the following steps:
+
+ - Create a new immutable revision for this version of the app.
+ - Network programming to create a route, ingress, service, and load balancer
+ for your app.
+ - Automatically scale your pods up and down (including to zero active pods).
+
+1. To find the URL for your service, use
+
+ ```bash
+ kubectl get ksvc helloworld-java-quarkus
+
+ NAME URL
+ helloworld-java-quarkus http://helloworld-java-quarkus.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app and see the result. Replace
+ the URL below with the URL returned in the previous command.
+
+ ```bash
+ curl http://helloworld-java-quarkus.default.1.2.3.4.sslip.io
+
+ Namaste Knative World!
+ ```
+
+## Removing the sample app deployment
+
+To remove the sample app from your cluster, delete the service record:
+
+```bash
+kubectl delete --filename service.yaml
+```
diff --git a/code-samples/community/serving/helloworld-java-quarkus/mvnw b/code-samples/community/serving/helloworld-java-quarkus/mvnw
new file mode 100644
index 000000000..eefb60d67
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/mvnw
@@ -0,0 +1,305 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# 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.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+# JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+# M2_HOME - location of maven2's installed home dir
+# MAVEN_OPTS - parameters passed to the Java VM when running Maven
+# e.g. to debug Maven itself, use
+# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+ if [ -f /etc/mavenrc ] ; then
+ . /etc/mavenrc
+ fi
+
+ if [ -f "$HOME/.mavenrc" ] ; then
+ . "$HOME/.mavenrc"
+ fi
+
+fi
+
+# OS specific support. $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+ CYGWIN*) cygwin=true ;;
+ MINGW*) mingw=true;;
+ Darwin*) darwin=true
+ # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+ # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+ if [ -z "$JAVA_HOME" ]; then
+ if [ -x "/usr/libexec/java_home" ]; then
+ export JAVA_HOME="`/usr/libexec/java_home`"
+ else
+ export JAVA_HOME="/Library/Java/Home"
+ fi
+ fi
+ ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+ if [ -r /etc/gentoo-release ] ; then
+ JAVA_HOME=`java-config --jre-home`
+ fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+ ## resolve links - $0 may be a link to maven's home
+ PRG="$0"
+
+ # need this for relative symlinks
+ while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG="`dirname "$PRG"`/$link"
+ fi
+ done
+
+ saveddir=`pwd`
+
+ M2_HOME=`dirname "$PRG"`/..
+
+ # make it fully qualified
+ M2_HOME=`cd "$M2_HOME" && pwd`
+
+ cd "$saveddir"
+ # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --unix "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME="`(cd "$M2_HOME"; pwd)`"
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+ javaExecutable="`which javac`"
+ if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+ # readlink(1) is not available as standard on Solaris 10.
+ readLink=`which readlink`
+ if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+ if $darwin ; then
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+ else
+ javaExecutable="`readlink -f \"$javaExecutable\"`"
+ fi
+ javaHome="`dirname \"$javaExecutable\"`"
+ javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+ JAVA_HOME="$javaHome"
+ export JAVA_HOME
+ fi
+ fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+ if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ else
+ JAVACMD="`which java`"
+ fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+ echo "Error: JAVA_HOME is not defined correctly." >&2
+ echo " We cannot execute $JAVACMD" >&2
+ exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+ echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+ if [ -z "$1" ]
+ then
+ echo "Path not specified to find_maven_basedir"
+ return 1
+ fi
+
+ basedir="$1"
+ wdir="$1"
+ while [ "$wdir" != '/' ] ; do
+ if [ -d "$wdir"/.mvn ] ; then
+ basedir=$wdir
+ break
+ fi
+ # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+ if [ -d "${wdir}" ]; then
+ wdir=`cd "$wdir/.."; pwd`
+ fi
+ # end of workaround
+ done
+ echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+ if [ -f "$1" ]; then
+ echo "$(tr -s '\n' ' ' < "$1")"
+ fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+ exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found .mvn/wrapper/maven-wrapper.jar"
+ fi
+else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+ fi
+ if [ -n "$MVNW_REPOURL" ]; then
+ jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.3/maven-wrapper-0.5.3.jar"
+ else
+ jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.3/maven-wrapper-0.5.3.jar"
+ fi
+ while IFS="=" read key value; do
+ case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+ esac
+ done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Downloading from: $jarUrl"
+ fi
+ wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+ if $cygwin; then
+ wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+ fi
+
+ if command -v wget > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found wget ... using wget"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ wget "$jarUrl" -O "$wrapperJarPath"
+ else
+ wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+ fi
+ elif command -v curl > /dev/null; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Found curl ... using curl"
+ fi
+ if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+ curl -o "$wrapperJarPath" "$jarUrl" -f
+ else
+ curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+ fi
+
+ else
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo "Falling back to using Java to download"
+ fi
+ javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+ # For Cygwin, switch paths to Windows format before running javac
+ if $cygwin; then
+ javaClass=`cygpath --path --windows "$javaClass"`
+ fi
+ if [ -e "$javaClass" ]; then
+ if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Compiling MavenWrapperDownloader.java ..."
+ fi
+ # Compiling the Java class
+ ("$JAVA_HOME/bin/javac" "$javaClass")
+ fi
+ if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+ # Running the downloader
+ if [ "$MVNW_VERBOSE" = true ]; then
+ echo " - Running MavenWrapperDownloader.java ..."
+ fi
+ ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+ fi
+ fi
+ fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+ echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+ [ -n "$M2_HOME" ] &&
+ M2_HOME=`cygpath --path --windows "$M2_HOME"`
+ [ -n "$JAVA_HOME" ] &&
+ JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+ [ -n "$CLASSPATH" ] &&
+ CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+ [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+ MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+ $MAVEN_OPTS \
+ -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+ "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+ ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/code-samples/community/serving/helloworld-java-quarkus/mvnw.cmd b/code-samples/community/serving/helloworld-java-quarkus/mvnw.cmd
new file mode 100644
index 000000000..77b451d83
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/mvnw.cmd
@@ -0,0 +1,172 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.3/maven-wrapper-0.5.3.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+ IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+ echo Found %WRAPPER_JAR%
+) else (
+ if not "%MVNW_REPOURL%" == "" (
+ SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.3/maven-wrapper-0.5.3.jar"
+ )
+ echo Couldn't find %WRAPPER_JAR%, downloading it ...
+ echo Downloading from: %DOWNLOAD_URL%
+
+ powershell -Command "&{"^
+ "$webclient = new-object System.Net.WebClient;"^
+ "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+ "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+ "}"^
+ "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+ "}"
+ echo Finished downloading %WRAPPER_JAR%
+)
+@REM End of extension
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%
diff --git a/code-samples/community/serving/helloworld-java-quarkus/pom.xml b/code-samples/community/serving/helloworld-java-quarkus/pom.xml
new file mode 100644
index 000000000..1bebc82bf
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/pom.xml
@@ -0,0 +1,113 @@
+
+
+ 4.0.0
+ com.redhat.developer.demos
+ helloworld-java-quarkus
+ 1.0-SNAPSHOT
+
+ 2.22.0
+ 0.13.3
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ io.quarkus
+ quarkus-bom
+ ${quarkus.version}
+ pom
+ import
+
+
+
+
+
+ io.quarkus
+ quarkus-resteasy
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+ ${quarkus.version}
+
+
+
+ build
+
+
+
+
+
+ maven-surefire-plugin
+ ${surefire-plugin.version}
+
+
+ org.jboss.logmanager.LogManager
+
+
+
+
+
+
+
+ native
+
+
+ native
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+ ${quarkus.version}
+
+
+
+ native-image
+
+
+ true
+
+
+
+
+
+ maven-failsafe-plugin
+ ${surefire-plugin.version}
+
+
+
+ integration-test
+ verify
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+
+
+
+
+
+
+
+
+
+
diff --git a/code-samples/community/serving/helloworld-java-quarkus/service.yaml b/code-samples/community/serving/helloworld-java-quarkus/service.yaml
new file mode 100644
index 000000000..f0d1cf19b
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/service.yaml
@@ -0,0 +1,12 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ name: helloworld-java-quarkus
+spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/saturnism/helloworld-java-quarkus
+ env:
+ - name: TARGET
+ value: "Quarkus Sample v1"
diff --git a/code-samples/community/serving/helloworld-java-quarkus/src/main/java/com/redhat/developer/demos/GreetingResource.java b/code-samples/community/serving/helloworld-java-quarkus/src/main/java/com/redhat/developer/demos/GreetingResource.java
new file mode 100644
index 000000000..0a28286f6
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/src/main/java/com/redhat/developer/demos/GreetingResource.java
@@ -0,0 +1,19 @@
+package com.redhat.developer.demos;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+@Path("/")
+public class GreetingResource {
+ @ConfigProperty(name = "target", defaultValue="World")
+ String target;
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String hello() {
+ return "Hello " + target + "!";
+ }
+}
diff --git a/code-samples/community/serving/helloworld-java-quarkus/src/main/resources/application.properties b/code-samples/community/serving/helloworld-java-quarkus/src/main/resources/application.properties
new file mode 100644
index 000000000..cac8f0b2c
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+# Configuration file
+# key = value
+
+quarkus.http.port=${PORT:8080}
diff --git a/code-samples/community/serving/helloworld-java-quarkus/src/test/java/com/redhat/developer/demos/GreetingResourceTest.java b/code-samples/community/serving/helloworld-java-quarkus/src/test/java/com/redhat/developer/demos/GreetingResourceTest.java
new file mode 100644
index 000000000..ef4208dcf
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/src/test/java/com/redhat/developer/demos/GreetingResourceTest.java
@@ -0,0 +1,21 @@
+package com.redhat.developer.demos;
+
+import io.quarkus.test.junit.QuarkusTest;
+import org.junit.jupiter.api.Test;
+
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.is;
+
+@QuarkusTest
+public class GreetingResourceTest {
+
+ @Test
+ public void testHelloEndpoint() {
+ given()
+ .when().get("/")
+ .then()
+ .statusCode(200)
+ .body(is("Hello World!"));
+ }
+
+}
diff --git a/code-samples/community/serving/helloworld-java-quarkus/src/test/java/com/redhat/developer/demos/NativeGreetingResourceIT.java b/code-samples/community/serving/helloworld-java-quarkus/src/test/java/com/redhat/developer/demos/NativeGreetingResourceIT.java
new file mode 100644
index 000000000..6fc3fa41f
--- /dev/null
+++ b/code-samples/community/serving/helloworld-java-quarkus/src/test/java/com/redhat/developer/demos/NativeGreetingResourceIT.java
@@ -0,0 +1,9 @@
+package com.redhat.developer.demos;
+
+import io.quarkus.test.junit.SubstrateTest;
+
+@SubstrateTest
+public class NativeGreetingResourceIT extends GreetingResourceTest {
+
+ // Execute the same tests but in native mode.
+}
diff --git a/code-samples/community/serving/helloworld-r/.dockerignore b/code-samples/community/serving/helloworld-r/.dockerignore
new file mode 100644
index 000000000..6b7b54031
--- /dev/null
+++ b/code-samples/community/serving/helloworld-r/.dockerignore
@@ -0,0 +1,2 @@
+Dockerfile
+README.md
diff --git a/code-samples/community/serving/helloworld-r/Dockerfile b/code-samples/community/serving/helloworld-r/Dockerfile
new file mode 100644
index 000000000..7906d2164
--- /dev/null
+++ b/code-samples/community/serving/helloworld-r/Dockerfile
@@ -0,0 +1,26 @@
+# Use the official Golang image to create a build artifact.
+# This is based on Debian and sets the GOPATH to /go.
+# https://hub.docker.com/_/golang
+FROM golang:1.12 as builder
+
+# Copy local code to the container image.
+WORKDIR /go/src/github.com/knative/docs/helloworld-r
+COPY invoke.go .
+
+# Build the command inside the container.
+# (You may fetch or manage dependencies here,
+# either manually or with a tool like "godep".)
+RUN CGO_ENABLED=0 GOOS=linux go build -v -o invoke
+
+# The official R base image
+# https://hub.docker.com/_/r-base
+# Use a Docker multi-stage build to create a lean production image.
+# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
+FROM r-base:3.6.0
+
+# Copy Go binary
+COPY --from=builder /go/src/github.com/knative/docs/helloworld-r/invoke /invoke
+COPY HelloWorld.R .
+
+# Run the web service on container startup.
+CMD ["/invoke"]
diff --git a/code-samples/community/serving/helloworld-r/HelloWorld.R b/code-samples/community/serving/helloworld-r/HelloWorld.R
new file mode 100644
index 000000000..eddb231cc
--- /dev/null
+++ b/code-samples/community/serving/helloworld-r/HelloWorld.R
@@ -0,0 +1,5 @@
+#!/bin/Rscript
+TARGET <- Sys.getenv("TARGET", "World")
+
+message = paste("Hello ", TARGET, "!", sep = "")
+print(message)
diff --git a/code-samples/community/serving/helloworld-r/README.md b/code-samples/community/serving/helloworld-r/README.md
new file mode 100644
index 000000000..3ba50d976
--- /dev/null
+++ b/code-samples/community/serving/helloworld-r/README.md
@@ -0,0 +1,192 @@
+# Hello World - R
+
+A simple web app that executes an R script. The R script reads an env
+variable `TARGET` and prints `Hello ${TARGET}!`. If the `TARGET` environment
+variable is not specified, the script uses `World`.
+
+Follow the steps below to create the sample code and then deploy the app to your
+cluster. You can also download a working copy of the sample, by running the
+following commands:
+
+```bash
+git clone https://github.com/knative/docs.git knative-docs
+cd knative-docs/code-samples/community/serving/hello-world/helloworld-r
+```
+
+## Before you begin
+
+- A Kubernetes cluster with Knative installed. Follow the
+ [Knative installation instructions](https://knative.dev/docs/install/) if you need to
+ create one.
+- [Docker](https://www.docker.com) installed and running on your local machine,
+ and a Docker Hub account configured (we'll use it for a container registry).
+
+## Recreating the sample code
+
+1. Create a new file named `HelloWorld.R` and paste the following script:
+
+ ```R
+ #!/usr/bin/Rscript
+ TARGET <- Sys.getenv("TARGET", "World")
+
+ message = paste("Hello ", TARGET, "!", sep = "")
+ print(message)
+ ```
+
+1. Create a new file named `invoke.go` and paste the following code. We use a
+ basic web server written in Go to execute the shell script:
+
+ ```go
+ package main
+
+ import (
+ "fmt"
+ "log"
+ "net/http"
+ "os"
+ "os/exec"
+ )
+
+ func handler(w http.ResponseWriter, r *http.Request) {
+ cmd := exec.CommandContext(r.Context(), "Rscript", "HelloWorld.R")
+ cmd.Stderr = os.Stderr
+ out, err := cmd.Output()
+ if err != nil {
+ w.WriteHeader(500)
+ }
+ w.Write(out)
+ }
+
+ func main() {
+ http.HandleFunc("/", handler)
+
+ port := os.Getenv("PORT")
+ if port == "" {
+ port = "8080"
+ }
+
+ log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
+ }
+ ```
+
+1. Create a new file named `Dockerfile` and copy the code block below into it.
+
+ ```docker
+ # Use the official Golang image to create a build artifact.
+ # This is based on Debian and sets the GOPATH to /go.
+ # https://hub.docker.com/_/golang
+ FROM golang:1.12 as builder
+
+ # Copy local code to the container image.
+ WORKDIR /go/src/github.com/knative/docs/helloworld-r
+ COPY invoke.go .
+
+ # Build the command inside the container.
+ # (You may fetch or manage dependencies here,
+ # either manually or with a tool like "godep".)
+ RUN CGO_ENABLED=0 GOOS=linux go build -v -o invoke
+
+ # The official R base image
+ # https://hub.docker.com/_/r-base
+ # Use a Docker multi-stage build to create a lean production image.
+ # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
+ FROM r-base:3.6.0
+
+ # Copy Go binary
+ COPY --from=builder /go/src/github.com/knative/docs/helloworld-r/invoke /invoke
+ COPY HelloWorld.R .
+
+ # Run the web service on container startup.
+ CMD ["/invoke"]
+ ```
+
+
+1. Create a new file, `service.yaml` and copy the following service definition
+ into the file. Make sure to replace `{username}` with your Docker Hub
+ username.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-r
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-r
+ env:
+ - name: TARGET
+ value: "R Sample v1"
+ ```
+
+## Building and deploying the sample
+
+Once you have recreated the sample code files (or used the files in the sample
+folder) you're ready to build and deploy the sample app.
+
+1. Use Docker to build the sample code into a container. To build and push with
+ Docker Hub, run these commands replacing `{username}` with your Docker Hub
+ username:
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-r .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-r
+ ```
+
+1. After the build has completed and the container is pushed to docker hub, you
+ can deploy the app into your cluster. Ensure that the container image value
+ in `service.yaml` matches the container you built in the previous step. Apply
+ the configuration using `kubectl`:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+1. Now that your service is created, Knative performs the following steps:
+
+ - Create a new immutable revision for this version of the app.
+ - Network programming to create a route, ingress, service, and load balance
+ for your app.
+ - Automatically scale your pods up and down (including to zero active pods).
+
+1. Run the following command to find the domain URL for your service:
+
+ ```bash
+ kubectl get ksvc helloworld-r --output=custom-columns=NAME:.metadata.name,URL:.status.url
+ ```
+
+ Example:
+
+ ```bash
+ NAME URL
+ helloworld-r http://helloworld-r.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app and see the result. Replace
+ the URL below with the URL returned in the previous command.
+
+ ```bash
+ curl http://helloworld-r.default.1.2.3.4.sslip.io
+ ```
+
+ Example:
+
+ ```bash
+ curl http://helloworld-r.default.1.2.3.4.sslip.io
+ [1] "Hello R Sample v1!"
+ ```
+
+ > Note: Add `-v` option to get more detail if the `curl` command failed.
+
+## Removing the sample app deployment
+
+To remove the sample app from your cluster, delete the service record:
+
+```bash
+kubectl delete --filename service.yaml
+```
diff --git a/code-samples/community/serving/helloworld-r/invoke.go b/code-samples/community/serving/helloworld-r/invoke.go
new file mode 100644
index 000000000..174d7b569
--- /dev/null
+++ b/code-samples/community/serving/helloworld-r/invoke.go
@@ -0,0 +1,30 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "os"
+ "os/exec"
+)
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ cmd := exec.CommandContext(r.Context(), "Rscript", "HelloWorld.R")
+ cmd.Stderr = os.Stderr
+ out, err := cmd.Output()
+ if err != nil {
+ w.WriteHeader(500)
+ }
+ w.Write(out)
+}
+
+func main() {
+ http.HandleFunc("/", handler)
+
+ port := os.Getenv("PORT")
+ if port == "" {
+ port = "8080"
+ }
+
+ log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
+}
diff --git a/code-samples/community/serving/helloworld-r/service.yaml b/code-samples/community/serving/helloworld-r/service.yaml
new file mode 100644
index 000000000..42cf8ab76
--- /dev/null
+++ b/code-samples/community/serving/helloworld-r/service.yaml
@@ -0,0 +1,13 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ name: helloworld-r
+ namespace: default
+spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-r
+ env:
+ - name: TARGET
+ value: "R Sample v1"
diff --git a/code-samples/community/serving/helloworld-rserver/Dockerfile b/code-samples/community/serving/helloworld-rserver/Dockerfile
new file mode 100644
index 000000000..3b3c450ec
--- /dev/null
+++ b/code-samples/community/serving/helloworld-rserver/Dockerfile
@@ -0,0 +1,13 @@
+# The official R base image
+# https://hub.docker.com/_/r-base
+FROM r-base:3.6.0
+
+# Copy local code to the container image.
+WORKDIR /usr/src/app
+COPY . .
+
+# Install R packages
+RUN Rscript -e "install.packages('plumber', repos='http://cran.us.r-project.org/')"
+
+# Run the web service on container startup.
+CMD ["Rscript", "server.R"]
diff --git a/code-samples/community/serving/helloworld-rserver/HelloWorld.R b/code-samples/community/serving/helloworld-rserver/HelloWorld.R
new file mode 100644
index 000000000..f09d12f34
--- /dev/null
+++ b/code-samples/community/serving/helloworld-rserver/HelloWorld.R
@@ -0,0 +1,9 @@
+#' HelloWorld function
+#' @get /
+#' @html
+function() {
+ TARGET <- Sys.getenv("TARGET", "World")
+
+ message = paste("Hello ", TARGET, "!", sep = "")
+ print(message)
+}
diff --git a/code-samples/community/serving/helloworld-rserver/README.md b/code-samples/community/serving/helloworld-rserver/README.md
new file mode 100644
index 000000000..66177bea3
--- /dev/null
+++ b/code-samples/community/serving/helloworld-rserver/README.md
@@ -0,0 +1,163 @@
+# Hello World - R server
+
+A simple web app created with R package, [plumber](https://www.rplumber.io).
+plumber creates a REST API by adding annotations to your R code. The R script
+reads an environment variable `TARGET` and prints `Hello ${TARGET}!`. If the
+`TARGET` environment variable is not specified, the script uses `World`.
+
+Follow the steps below to create the sample code and then deploy the app to your
+cluster. You can also download a working copy of the sample, by running the
+following commands:
+
+```bash
+git clone https://github.com/knative/docs.git knative-docs
+cd knative-docs/code-samples/community/serving/hello-world/helloworld-r
+```
+
+## Before you begin
+
+- A Kubernetes cluster with Knative installed. Follow the
+ [Knative installation instructions](https://knative.dev/docs/install/) if you need to
+ create one.
+- [Docker](https://www.docker.com) installed and running on your local machine,
+ and a Docker Hub account configured (we'll use it for a container registry).
+
+## Recreating the sample code
+
+1. Create a new file named `HelloWorld.R` and paste the following script:
+
+ ```R
+ #' HelloWorld function
+ #' @get /
+ #' @html
+ function() {
+ TARGET <- Sys.getenv("TARGET", "World")
+
+ message = paste("Hello ", TARGET, "!", sep = "")
+ print(message)
+ }
+ ```
+
+ This file defines the endpoint `/`, using plumber annotations.
+
+1. Create a new file named `server.R` and paste the following code:
+
+ ```R
+ library(plumber) # https://www.rplumber.io/
+
+ # Translate the HelloWorld file into a Plumber API
+ r <- plumb("HelloWorld.R")
+ # Get the PORT env var
+ PORT <- strtoi(Sys.getenv("PORT", 8080))
+ # Run the API
+ r$run(port=PORT, host="0.0.0.0")
+ ```
+
+1. Create a new file named `Dockerfile` and paste the following code:
+
+ ```docker
+ # The official R base image
+ # https://hub.docker.com/_/r-base
+ FROM r-base:3.6.0
+
+ # Copy local code to the container image.
+ WORKDIR /usr/src/app
+ COPY . .
+
+ # Install R packages
+ RUN Rscript -e "install.packages('plumber', repos='http://cran.us.r-project.org/')"
+
+ # Run the web service on container startup.
+ CMD ["Rscript", "server.R"]
+ ```
+
+
+1. Create a new file, `service.yaml` and copy the following service definition
+ into the file. Make sure to replace `{username}` with your Docker Hub
+ username.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-rserver
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-rserver
+ env:
+ - name: TARGET
+ value: "R Server Sample v1"
+ ```
+
+## Building and deploying the sample
+
+Once you have recreated the sample code files (or used the files in the sample
+folder) you're ready to build and deploy the sample app.
+
+1. Use Docker to build the sample code into a container. To build and push with
+ Docker Hub, run these commands replacing `{username}` with your Docker Hub
+ username:
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-rserver .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-rserver
+ ```
+
+1. After the build has completed and the container is pushed to docker hub, you
+ can deploy the app into your cluster. Ensure that the container image value
+ in `service.yaml` matches the container you built in the previous step. Apply
+ the configuration using `kubectl`:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+1. Now that your service is created, Knative performs the following steps:
+
+ - Create a new immutable revision for this version of the app.
+ - Network programming to create a route, ingress, service, and load balance
+ for your app.
+ - Automatically scale your pods up and down (including to zero active pods).
+
+1. Run the following command to find the domain URL for your service:
+
+ ```bash
+ kubectl get ksvc helloworld-r --output=custom-columns=NAME:.metadata.name,URL:.status.url
+ ```
+
+ Example:
+
+ ```bash
+ NAME URL
+ helloworld-r http://helloworld-r.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app and see the result. Replace
+ the URL below with the URL returned in the previous command.
+
+ ```bash
+ curl http://helloworld-rserver.default.1.2.3.4.sslip.io
+ ```
+
+ Example:
+
+ ```bash
+ curl http://helloworld-rserver.default.1.2.3.4.sslip.io
+ [1] "Hello R Sample v1!"
+ ```
+
+ > Note: Add `-v` option to get more detail if the `curl` command failed.
+
+## Removing the sample app deployment
+
+To remove the sample app from your cluster, delete the service record:
+
+```bash
+kubectl delete --filename service.yaml
+```
diff --git a/code-samples/community/serving/helloworld-rserver/server.R b/code-samples/community/serving/helloworld-rserver/server.R
new file mode 100644
index 000000000..5c05dba0f
--- /dev/null
+++ b/code-samples/community/serving/helloworld-rserver/server.R
@@ -0,0 +1,8 @@
+library(plumber) # https://www.rplumber.io/
+
+# Translate the HelloWorld file into a Plumber API
+r <- plumb("HelloWorld.R")
+# Get the PORT env var
+PORT <- strtoi(Sys.getenv("PORT", 8080))
+# Run the API
+r$run(port=PORT, host="0.0.0.0")
diff --git a/code-samples/community/serving/helloworld-rserver/service.yaml b/code-samples/community/serving/helloworld-rserver/service.yaml
new file mode 100644
index 000000000..ba61afc55
--- /dev/null
+++ b/code-samples/community/serving/helloworld-rserver/service.yaml
@@ -0,0 +1,13 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ name: helloworld-rserver
+ namespace: default
+spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-rserver
+ env:
+ - name: TARGET
+ value: "R Server Sample v1"
diff --git a/code-samples/community/serving/helloworld-rust/Cargo.toml b/code-samples/community/serving/helloworld-rust/Cargo.toml
new file mode 100644
index 000000000..cec0a9aa7
--- /dev/null
+++ b/code-samples/community/serving/helloworld-rust/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "hellorust"
+version = "0.0.0"
+edition = "2018"
+publish = false
+
+[dependencies]
+hyper = { version = "0.14.7", features = ["full"]}
+tokio = { version = "1.5.0", features = ["macros", "rt-multi-thread"] }
+pretty_env_logger = "0.4.0"
diff --git a/code-samples/community/serving/helloworld-rust/Dockerfile b/code-samples/community/serving/helloworld-rust/Dockerfile
new file mode 100644
index 000000000..4daf9b26b
--- /dev/null
+++ b/code-samples/community/serving/helloworld-rust/Dockerfile
@@ -0,0 +1,13 @@
+# Use the official Rust image.
+# https://hub.docker.com/_/rust
+FROM rust:1.51.0
+
+# Copy local code to the container image.
+WORKDIR /usr/src/app
+COPY . .
+
+# Install production dependencies and build a release artifact.
+RUN cargo install --path .
+
+# Run the web service on container startup.
+CMD ["hellorust"]
diff --git a/code-samples/community/serving/helloworld-rust/README.md b/code-samples/community/serving/helloworld-rust/README.md
new file mode 100644
index 000000000..8f9cdc948
--- /dev/null
+++ b/code-samples/community/serving/helloworld-rust/README.md
@@ -0,0 +1,184 @@
+# Hello World - Rust
+
+A simple web app written in Rust that you can use for testing. It reads in an
+env variable `TARGET` and prints "Hello \${TARGET}!". If
+
+TARGET is not specified, it will use "World" as the TARGET.
+
+## Prerequisites
+
+- A Kubernetes cluster with Knative installed and DNS configured. Follow the
+ [Knative installation instructions](https://knative.dev/docs/install/) if you need to create
+ one.
+- [Docker](https://www.docker.com) installed and running on your local machine,
+ and a Docker Hub account configured (we'll use it for a container registry).
+
+## Steps to recreate the sample code
+
+While you can clone all of the code from this directory, hello world apps are
+generally more useful if you build them step-by-step. The following instructions
+recreate the source files from this folder.
+
+1. Create a new file named `Cargo.toml` and paste the following code:
+
+ ```toml
+ [package]
+ name = "hellorust"
+ version = "0.0.0"
+ edition = "2018"
+ publish = false
+
+ [dependencies]
+ hyper = { version = "0.14.7", features = ["full"]}
+ tokio = { version = "1.5.0", features = ["macros", "rt-multi-thread"] }
+ pretty_env_logger = "0.4.0"
+ ```
+
+1. Create a `src` folder, then create a new file named `main.rs` in that folder
+ and paste the following code. This code creates a basic web server which
+ listens on port 8080:
+
+ ```rust
+ use hyper::{
+ server::conn::AddrStream,
+ service::{make_service_fn, service_fn},
+ Body, Request, Response, Server,
+ };
+ use std::convert::Infallible;
+ use std::env;
+
+ #[tokio::main]
+ async fn main() {
+ pretty_env_logger::init();
+
+ let mut port: u16 = 8080;
+ match env::var("PORT") {
+ Ok(p) => {
+ match p.parse::() {
+ Ok(n) => {
+ port = n;
+ }
+ Err(_e) => {}
+ };
+ }
+ Err(_e) => {}
+ };
+ let addr = ([0, 0, 0, 0], port).into();
+
+ let make_svc = make_service_fn(|_socket: &AddrStream| async move {
+ Ok::<_, Infallible>(service_fn(move |_: Request| async move {
+ let mut hello = "Hello ".to_string();
+ match env::var("TARGET") {
+ Ok(target) => {
+ hello.push_str(&target);
+ }
+ Err(_e) => hello.push_str("World"),
+ };
+ Ok::<_, Infallible>(Response::new(Body::from(hello)))
+ }))
+ });
+
+ let server = Server::bind(&addr).serve(make_svc);
+
+ println!("Listening on http://{}", addr);
+ if let Err(e) = server.await {
+ eprintln!("server error: {}", e);
+ }
+ }
+ ```
+
+1. In your project directory, create a file named `Dockerfile` and copy the code
+ block below into it.
+
+ ```docker
+ # Use the official Rust image.
+ # https://hub.docker.com/_/rust
+ FROM rust:1.51.0
+
+ # Copy local code to the container image.
+ WORKDIR /usr/src/app
+ COPY . .
+
+ # Install production dependencies and build a release artifact.
+ RUN cargo install --path .
+
+ # Run the web service on container startup.
+ CMD ["hellorust"]
+ ```
+
+1. Create a new file, `service.yaml` and copy the following service definition
+ into the file. Make sure to replace `{username}` with your Docker Hub
+ username.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-rust
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-rust
+ env:
+ - name: TARGET
+ value: "Rust Sample v1"
+ ```
+
+## Build and deploy this sample
+
+Once you have recreated the sample code files (or used the files in the sample
+folder) you're ready to build and deploy the sample app.
+
+1. Use Docker to build the sample code into a container. To build and push with
+ Docker Hub, enter these commands replacing `{username}` with your Docker Hub
+ username:
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-rust .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-rust
+ ```
+
+1. After the build has completed and the container is pushed to Docker Hub, you
+ can deploy the app into your cluster. Ensure that the container image value
+ in `service.yaml` matches the container you built in the previous step. Apply
+ the configuration using `kubectl`:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+1. Now that your service is created, Knative will perform the following steps:
+
+ - Create a new immutable revision for this version of the app.
+ - Network programming to create a route, ingress, service, and load balance
+ for your app.
+ - Automatically scale your pods up and down (including to zero active pods).
+
+1. To find the URL for your service, enter:
+
+ ```bash
+ kubectl get ksvc helloworld-rust --output=custom-columns=NAME:.metadata.name,URL:.status.url
+ NAME URL
+ helloworld-rust http://helloworld-rust.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app and see the result. Replace
+ the URL below with the URL returned in the previous command.
+
+ ```bash
+ curl http://helloworld-rust.default.1.2.3.4.sslip.io
+ Hello World!
+ ```
+
+## Removing the sample app deployment
+
+To remove the sample app from your cluster, delete the service record:
+
+```bash
+kubectl delete --filename service.yaml
+```
diff --git a/code-samples/community/serving/helloworld-rust/service.yaml b/code-samples/community/serving/helloworld-rust/service.yaml
new file mode 100644
index 000000000..e6c2b0807
--- /dev/null
+++ b/code-samples/community/serving/helloworld-rust/service.yaml
@@ -0,0 +1,13 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ name: helloworld-rust
+ namespace: default
+spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-rust
+ env:
+ - name: TARGET
+ value: "Rust Sample v1"
diff --git a/code-samples/community/serving/helloworld-rust/src/main.rs b/code-samples/community/serving/helloworld-rust/src/main.rs
new file mode 100644
index 000000000..0015c9c96
--- /dev/null
+++ b/code-samples/community/serving/helloworld-rust/src/main.rs
@@ -0,0 +1,46 @@
+use hyper::{
+ server::conn::AddrStream,
+ service::{make_service_fn, service_fn},
+ Body, Request, Response, Server,
+};
+use std::convert::Infallible;
+use std::env;
+
+#[tokio::main]
+async fn main() {
+ pretty_env_logger::init();
+
+ let mut port: u16 = 8080;
+ match env::var("PORT") {
+ Ok(p) => {
+ match p.parse::() {
+ Ok(n) => {
+ port = n;
+ }
+ Err(_e) => {}
+ };
+ }
+ Err(_e) => {}
+ };
+ let addr = ([0, 0, 0, 0], port).into();
+
+ let make_svc = make_service_fn(|_socket: &AddrStream| async move {
+ Ok::<_, Infallible>(service_fn(move |_: Request| async move {
+ let mut hello = "Hello ".to_string();
+ match env::var("TARGET") {
+ Ok(target) => {
+ hello.push_str(&target);
+ }
+ Err(_e) => hello.push_str("World"),
+ };
+ Ok::<_, Infallible>(Response::new(Body::from(hello)))
+ }))
+ });
+
+ let server = Server::bind(&addr).serve(make_svc);
+
+ println!("Listening on http://{}", addr);
+ if let Err(e) = server.await {
+ eprintln!("server error: {}", e);
+ }
+}
diff --git a/code-samples/community/serving/helloworld-swift/.swift-version b/code-samples/community/serving/helloworld-swift/.swift-version
new file mode 100644
index 000000000..bf77d5496
--- /dev/null
+++ b/code-samples/community/serving/helloworld-swift/.swift-version
@@ -0,0 +1 @@
+4.2
diff --git a/code-samples/community/serving/helloworld-swift/Dockerfile b/code-samples/community/serving/helloworld-swift/Dockerfile
new file mode 100644
index 000000000..932d09b7d
--- /dev/null
+++ b/code-samples/community/serving/helloworld-swift/Dockerfile
@@ -0,0 +1,13 @@
+# Use the official Swift image.
+# https://hub.docker.com/_/swift
+FROM swift:4.2
+
+# Copy local code to the container image.
+WORKDIR /app
+COPY . .
+
+# Install dependencies and build.
+RUN swift build -c release
+
+# Run the web service on container startup.
+CMD [ ".build/release/HelloSwift"]
diff --git a/code-samples/community/serving/helloworld-swift/Package.swift b/code-samples/community/serving/helloworld-swift/Package.swift
new file mode 100644
index 000000000..be32db153
--- /dev/null
+++ b/code-samples/community/serving/helloworld-swift/Package.swift
@@ -0,0 +1,16 @@
+// swift-tools-version:4.0
+
+import PackageDescription
+
+let package = Package(
+ name: "HelloSwift",
+ dependencies: [
+ .package(url: "https://github.com/httpswift/swifter.git", .upToNextMajor(from: "1.4.5"))
+ ],
+ targets: [
+ .target(
+ name: "HelloSwift",
+ dependencies: ["Swifter"],
+ path: "./Sources")
+ ]
+)
diff --git a/code-samples/community/serving/helloworld-swift/README.md b/code-samples/community/serving/helloworld-swift/README.md
new file mode 100644
index 000000000..7d1350ec3
--- /dev/null
+++ b/code-samples/community/serving/helloworld-swift/README.md
@@ -0,0 +1,164 @@
+# Hello World - Swift
+
+A simple web app written in Swift that you can use for testing. The app reads in
+an env variable `TARGET` and prints "Hello \${TARGET}!". If TARGET is not
+specified, the app uses "World" as the TARGET.
+
+## Prerequisites
+
+- You must have a Kubernetes cluster with Knative installed and DNS configured.
+ If you need to create a cluster, follow the
+ [Knative installation instructions](https://knative.dev/docs/install/).
+- You must have [Docker](https://www.docker.com) installed and running on your
+ local machine, and a Docker Hub account configured (used for container
+ registry).
+
+## Recreating the sample code
+
+While you can clone all of the code from this directory, it might be more useful
+if you build this app step-by-step. The following instructions recreate the
+source files from this folder.
+
+1. Create a the `Package.swift` to declare your package and its dependencies.
+ This app uses [Swifter](https://github.com/httpswift/swifter), a tiny http
+ server engine for Swift.
+
+ ```swift
+ // swift-tools-version:4.0
+
+ import PackageDescription
+
+ let package = Package(
+ name: "HelloSwift",
+ dependencies: [
+ .package(url: "https://github.com/httpswift/swifter.git", .upToNextMajor(from: "1.4.5"))
+ ],
+ targets: [
+ .target(
+ name: "HelloSwift",
+ dependencies: ["Swifter"],
+ path: "./Sources")
+ ]
+ )
+ ```
+
+1. Add the web server code to a file named `main.swift` in a
+ `Sources/HelloSwift/` folder:
+
+ ```swift
+ import Swifter
+ import Dispatch
+ import Foundation
+
+ let server = HttpServer()
+ server["/"] = { r in
+ let target = ProcessInfo.processInfo.environment["TARGET"] ?? "World"
+ return HttpResponse.ok(.html("Hello \(target)"))
+ }
+
+ let semaphore = DispatchSemaphore(value: 0)
+ do {
+ let port = UInt16(ProcessInfo.processInfo.environment["PORT"] ?? "8080")
+ try server.start(port!, forceIPv4: true)
+ print("Server has started ( port = \(try server.port()) ). Try to connect now...")
+ semaphore.wait()
+ } catch {
+ print("Server start error: \(error)")
+ semaphore.signal()
+ }
+ ```
+
+1. In your project directory, create a file named `Dockerfile` and copy the code
+ block below into it.
+
+ ```Dockerfile
+ # Use the official Swift image.
+ # https://hub.docker.com/_/swift
+ FROM swift:4.2
+
+ # Copy local code to the container image.
+ WORKDIR /app
+ COPY . .
+
+ # Install dependencies and build.
+ RUN swift build -c release
+
+ # Run the web service on container startup.
+ CMD [ ".build/release/HelloSwift"]
+ ```
+
+1. Create a new file, `service.yaml`, and copy the following service definition
+ into the file. Replace `{username}` with your Docker Hub username.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-swift
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-swift
+ env:
+ - name: TARGET
+ value: "Swift"
+ ```
+
+## Building and deploying the sample
+
+Once you have recreated the sample code files (or used the files in the sample
+folder) you're ready to build and deploy the sample app.
+
+1. Use Docker to build the sample code into a container. To build and push with
+ Docker Hub, run these commands, replacing `{username}` with your Docker Hub
+ username:
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-swift .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-swift
+ ```
+
+1. After the build has completed and the container is pushed to Docker Hub, you
+ can deploy the app into your cluster. Ensure that the container image value
+ in the `service.yaml` file matches the container you built in the previous
+ step. Apply the configuration using the `kubectl` command:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+1. Now that your service is created, Knative performs the following steps:
+
+ - Creates a new immutable revision for this version of the app.
+ - Network programming to create a route, ingress, service, and load balancing
+ for your app.
+ - Automatically scales your pods up and down (including to zero active pods).
+
+1. To find the URL for your service, use the following command:
+
+ ```
+ kubectl get ksvc helloworld-swift --output=custom-columns=NAME:.metadata.name,URL:.status.url
+ NAME URL
+ helloworld-swift http://helloworld-swift.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app and see the result. Replace
+ the URL below with the URL returned in the previous command.
+
+ ```bash
+ curl http://helloworld-swift.default.1.2.3.4.sslip.io
+ Hello Swift
+ ```
+
+## Removing the sample app deployment
+
+To remove the sample app from your cluster, delete the service record:
+
+```bash
+kubectl delete --filename service.yaml
+```
diff --git a/code-samples/community/serving/helloworld-swift/Sources/HelloSwift/main.swift b/code-samples/community/serving/helloworld-swift/Sources/HelloSwift/main.swift
new file mode 100644
index 000000000..da76a1bf5
--- /dev/null
+++ b/code-samples/community/serving/helloworld-swift/Sources/HelloSwift/main.swift
@@ -0,0 +1,20 @@
+import Swifter
+import Dispatch
+import Foundation
+
+let server = HttpServer()
+server["/"] = { r in
+ let target = ProcessInfo.processInfo.environment["TARGET"] ?? "World"
+ return HttpResponse.ok(.html("Hello \(target)"))
+}
+
+let semaphore = DispatchSemaphore(value: 0)
+do {
+ let port = UInt16(ProcessInfo.processInfo.environment["PORT"] ?? "8080")
+ try server.start(port!, forceIPv4: true)
+ print("Server has started ( port = \(try server.port()) ). Try to connect now...")
+ semaphore.wait()
+} catch {
+ print("Server start error: \(error)")
+ semaphore.signal()
+}
diff --git a/code-samples/community/serving/helloworld-swift/service.yaml b/code-samples/community/serving/helloworld-swift/service.yaml
new file mode 100644
index 000000000..699f8be61
--- /dev/null
+++ b/code-samples/community/serving/helloworld-swift/service.yaml
@@ -0,0 +1,13 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ name: helloworld-swift
+ namespace: default
+spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-swift
+ env:
+ - name: TARGET
+ value: "Swift"
diff --git a/code-samples/community/serving/helloworld-vertx/Dockerfile b/code-samples/community/serving/helloworld-vertx/Dockerfile
new file mode 100644
index 000000000..2080225e7
--- /dev/null
+++ b/code-samples/community/serving/helloworld-vertx/Dockerfile
@@ -0,0 +1,7 @@
+# Use fabric8's s2i Builder image.
+# https://hub.docker.com/r/fabric8/s2i-java
+FROM fabric8/s2i-java:2.0
+
+# Copy the JAR file to the deployment directory.
+ENV JAVA_APP_DIR=/deployments
+COPY target/helloworld-1.0.0-SNAPSHOT.jar /deployments/
diff --git a/code-samples/community/serving/helloworld-vertx/README.md b/code-samples/community/serving/helloworld-vertx/README.md
new file mode 100644
index 000000000..373e473b6
--- /dev/null
+++ b/code-samples/community/serving/helloworld-vertx/README.md
@@ -0,0 +1,252 @@
+# Hello World - Eclipse Vert.x
+
+Learn how to deploy a simple web app that is written in Java and uses Eclipse
+Vert.x. This samples uses Docker to build locally. The app reads in a `TARGET`
+env variable and then prints "Hello World: \${TARGET}!". If a value for `TARGET`
+is not specified, the "NOT SPECIFIED" default value is used.
+
+Use this sample to walk you through the steps of creating and modifying the
+sample app, building and pushing your container image to a registry, and then
+deploying your app to your Knative cluster.
+
+## Before you begin
+
+You must meet the following requirements to complete this sample:
+
+- A version of the Knative Serving component installed and running on your
+ Kubernetes cluster. Follow the
+ [Knative installation instructions](https://knative.dev/docs/install/) if you need to
+ create a Knative cluster.
+- The following software downloaded and install on your loacal machine:
+ - [Java SE 8 or later JDK](http://www.oracle.com/technetwork/java/javase/downloads/index.html).
+ - [Eclipse Vert.x v3.5.4](https://vertx.io/).
+ - [Docker](https://www.docker.com) for building and pushing your container
+ image.
+ - [curl](https://curl.haxx.se/) to test the sample app after deployment.
+- A [Docker Hub](https://hub.docker.com/) account where you can push your
+ container image.
+
+**Tip**: You can clone the [Knative/docs repo](https://github.com/knative/docs)
+and then modify the source files. Alternatively, learn more by manually creating
+the files yourself.
+
+## Creating and configuring the sample code
+
+To create and configure the source files in the root of your working directory:
+
+1. Create the `pom.xml` file:
+
+ ```xml
+
+ 4.0.0
+ com.example.vertx
+ helloworld
+ 1.0.0-SNAPSHOT
+
+
+
+ io.vertx
+ vertx-core
+ ${version.vertx}
+
+
+ io.vertx
+ vertx-rx-java2
+ ${version.vertx}
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.8.0
+
+ 1.8
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.0
+
+
+ package
+
+ shade
+
+
+
+
+
+ io.vertx.core.Launcher
+ com.example.helloworld.HelloWorld
+
+
+
+
+
+
+
+
+
+
+
+
+ 3.5.4
+
+
+ ```
+
+1. Create the `HelloWorld.java` file in the
+ `src/main/java/com/example/helloworld` directory. The
+ `[ROOT]/src/main/java/com/example/helloworld/HelloWorld.java` file creates a
+ basic web server that listens on port `8080`.
+
+ ```java
+ package com.example.helloworld;
+
+ import io.reactivex.Flowable;
+ import io.vertx.reactivex.core.AbstractVerticle;
+ import io.vertx.reactivex.core.http.HttpServer;
+ import io.vertx.reactivex.core.http.HttpServerRequest;
+
+ public class HelloWorld extends AbstractVerticle {
+
+ public void start() {
+
+ final HttpServer server = vertx.createHttpServer();
+ final Flowable requestFlowable = server.requestStream().toFlowable();
+
+ requestFlowable.subscribe(httpServerRequest -> {
+
+ String target = System.getenv("TARGET");
+ if (target == null) {
+ target = "NOT SPECIFIED";
+ }
+
+ httpServerRequest.response().setChunked(true)
+ .putHeader("content-type", "text/plain")
+ .setStatusCode(200) // OK
+ .end("Hello World: " + target);
+ });
+
+ server.listen(8080);
+ }
+ }
+ ```
+
+1. Create the `Dockerfile` file:
+
+ ```docker
+ # Use fabric8's s2i Builder image.
+ # https://hub.docker.com/r/fabric8/s2i-java
+ FROM fabric8/s2i-java:2.0
+
+ # Copy the JAR file to the deployment directory.
+ ENV JAVA_APP_DIR=/deployments
+ COPY target/helloworld-1.0.0-SNAPSHOT.jar /deployments/
+ ```
+
+1. Create the `service.yaml` file. You must specify your Docker Hub username in
+ `{username}`. You can also configure the `TARGET`, for example you can modify
+ the `Eclipse Vert.x Sample v1` value.
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: helloworld-vertx
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-vertx
+ env:
+ - name: TARGET
+ value: "Eclipse Vert.x Sample v1"
+ ```
+
+## Building and deploying the sample
+
+To build a container image, push your image to the registry, and then deploy
+your sample app to your cluster:
+
+1. Use Docker to build your container image and then push that image to your
+ Docker Hub registry. You must replace the `{username}` variables in the
+ following commands with your Docker Hub username.
+
+ ```bash
+ # Build the container on your local machine
+ docker build -t {username}/helloworld-vertx .
+
+ # Push the container to docker registry
+ docker push {username}/helloworld-vertx
+ ```
+
+1. Now that your container image is in the registry, you can deploy it to your
+ Knative cluster by running the `kubectl apply` command:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+ Result: A service name `helloworld-vertx` is created in your cluster along
+ with the following resources:
+
+ - A new immutable revision for the version of the app that you just deployed.
+ - The following networking resources are created for your app:
+ - route
+ - ingress
+ - service
+ - load balancer
+ - Auto scaling is enable to allow your pods to scale up to meet traffic, and
+ also back down to zero when there is no traffic.
+
+## Testing the sample app
+
+To verify that your sample app has been successfully deployed:
+
+1. Retrieve the URL for your service, by running the following `kubectl get`
+ command:
+
+ ```bash
+ kubectl get ksvc helloworld-vertx --output=custom-columns=NAME:.metadata.name,URL:.status.url
+ ```
+
+ Example result:
+
+ ```bash
+ NAME URL
+ helloworld-vertx http://helloworld-vertx.default.1.2.3.4.sslip.io
+ ```
+
+1. Now you can make a request to your app and see the result. Replace
+ the URL below with the URL returned in the previous command.
+
+ ```bash
+ curl http://helloworld-vertx.default.1.2.3.4.sslip.io
+ ```
+
+ Example result:
+
+ ```bash
+ Hello World: Eclipse Vert.x Sample v1
+ ```
+
+Congratulations on deploying your sample Java app to Knative!
+
+## Removing the sample app deployment
+
+To remove the sample app from your cluster, run the following `kubectl delete`
+command:
+
+```bash
+kubectl delete --filename service.yaml
+```
diff --git a/code-samples/community/serving/helloworld-vertx/pom.xml b/code-samples/community/serving/helloworld-vertx/pom.xml
new file mode 100644
index 000000000..bc2403a30
--- /dev/null
+++ b/code-samples/community/serving/helloworld-vertx/pom.xml
@@ -0,0 +1,64 @@
+
+ 4.0.0
+ com.example.vertx
+ helloworld
+ 1.0.0-SNAPSHOT
+
+
+
+ io.vertx
+ vertx-core
+ ${version.vertx}
+
+
+ io.vertx
+ vertx-rx-java2
+ ${version.vertx}
+
+
+
+
+
+
+ maven-compiler-plugin
+ 3.8.0
+
+ 1.8
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 3.2.0
+
+
+ package
+
+ shade
+
+
+
+
+
+ io.vertx.core.Launcher
+ com.example.helloworld.HelloWorld
+
+
+
+
+
+
+
+
+
+
+
+
+ 3.5.4
+
+
diff --git a/code-samples/community/serving/helloworld-vertx/service.yaml b/code-samples/community/serving/helloworld-vertx/service.yaml
new file mode 100644
index 000000000..d14ae2e99
--- /dev/null
+++ b/code-samples/community/serving/helloworld-vertx/service.yaml
@@ -0,0 +1,12 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ name: helloworld-vertx
+spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/helloworld-vertx
+ env:
+ - name: TARGET
+ value: "Eclipse Vert.x Sample v1"
diff --git a/code-samples/community/serving/helloworld-vertx/src/main/java/com/example/helloworld/HelloWorld.java b/code-samples/community/serving/helloworld-vertx/src/main/java/com/example/helloworld/HelloWorld.java
new file mode 100644
index 000000000..53d8d9868
--- /dev/null
+++ b/code-samples/community/serving/helloworld-vertx/src/main/java/com/example/helloworld/HelloWorld.java
@@ -0,0 +1,30 @@
+package com.example.helloworld;
+
+import io.reactivex.Flowable;
+import io.vertx.reactivex.core.AbstractVerticle;
+import io.vertx.reactivex.core.http.HttpServer;
+import io.vertx.reactivex.core.http.HttpServerRequest;
+
+public class HelloWorld extends AbstractVerticle {
+
+ public void start() {
+
+ final HttpServer server = vertx.createHttpServer();
+ final Flowable requestFlowable = server.requestStream().toFlowable();
+
+ requestFlowable.subscribe(httpServerRequest -> {
+
+ String target = System.getenv("TARGET");
+ if (target == null) {
+ target = "NOT SPECIFIED";
+ }
+
+ httpServerRequest.response().setChunked(true)
+ .putHeader("content-type", "text/plain")
+ .setStatusCode(200) // OK
+ .end("Hello World: " + target);
+ });
+
+ server.listen(8080);
+ }
+}
diff --git a/code-samples/community/serving/machinelearning-python-bentoml/README.md b/code-samples/community/serving/machinelearning-python-bentoml/README.md
new file mode 100644
index 000000000..1982b9a17
--- /dev/null
+++ b/code-samples/community/serving/machinelearning-python-bentoml/README.md
@@ -0,0 +1,249 @@
+# Hello World - Python BentoML
+
+A simple machine learning model with API serving that is written in python and
+using [BentoML](https://github.com/bentoml/BentoML). BentoML is an open source
+framework for high performance ML model serving, which supports all major machine
+learning frameworks including Keras, Tensorflow, PyTorch, Fast.ai, XGBoost and etc.
+
+This sample will walk you through the steps of creating and deploying a machine learning
+model using python. It will use BentoML to package a classifier model trained
+on the Iris dataset. Afterward, it will create a container image and
+deploy the image to Knative.
+
+Knative deployment guide with BentoML is also available in the
+[BentoML documentation](https://docs.bentoml.org/en/latest/deployment/knative.html)
+
+## Before you begin
+
+- A Kubernetes cluster with Knative installed. Follow the
+ [Knative installation instructions](https://knative.dev/docs/install/) if you need to
+ create one.
+- [Docker](https://www.docker.com) installed and running on your local machine,
+ and a Docker Hub account configured. Docker Hub will be used for a container registry).
+- Python 3.6 or above installed and running on your local machine.
+ - Install `scikit-learn` and `bentoml` packages:
+
+ ```bash
+ pip install scikit-learn
+ pip install bentoml
+ ```
+
+## Recreating sample code
+
+Run the following code on your local machine, to train a machine learning model and deploy it
+as API endpoint with Knative Serving.
+
+1. BentoML creates a model API server, via prediction service abstraction. In
+ `iris_classifier.py`, it defines a prediction service that requires a scikit-learn
+ model, asks BentoML to figure out the required pip dependencies, also defines an
+ API, which is the entry point for accessing this machine learning service.
+
+ ```python
+ from bentoml import env, artifacts, api, BentoService
+ from bentoml.handlers import DataframeHandler
+ from bentoml.artifact import SklearnModelArtifact
+
+ @env(auto_pip_dependencies=True)
+ @artifacts([SklearnModelArtifact('model')])
+ class IrisClassifier(BentoService):
+
+ @api(DataframeHandler)
+ def predict(self, df):
+ return self.artifacts.model.predict(df)
+ ```
+
+1. In `main.py`, it uses the classic
+ [iris flower data set](https://en.wikipedia.org/wiki/Iris_flower_data_set)
+ to train a classification model which can predict the species of an iris flower with
+ given data and then save the model with BentoML to local disk.
+
+ ```python
+ from sklearn import svm
+ from sklearn import datasets
+
+ from iris_classifier import IrisClassifier
+
+ if __name__ == "__main__":
+ # Load training data
+ iris = datasets.load_iris()
+ X, y = iris.data, iris.target
+
+ # Model Training
+ clf = svm.SVC(gamma='scale')
+ clf.fit(X, y)
+
+ # Create a iris classifier service instance
+ iris_classifier_service = IrisClassifier()
+
+ # Pack the newly trained model artifact
+ iris_classifier_service.pack('model', clf)
+
+ # Save the prediction service to disk for model serving
+ saved_path = iris_classifier_service.save()
+ ```
+
+1. Run the `main.py` file to train and save the model:
+
+ ```bash
+ python main.py
+ ```
+
+1. Use BentoML CLI to check saved model's information.
+
+ ```bash
+ bentoml get IrisClassifier:latest
+ ```
+
+ Example:
+
+ ```bash
+ > bentoml get IrisClassifier:latest
+ {
+ "name": "IrisClassifier",
+ "version": "20200305171229_0A1411",
+ "uri": {
+ "type": "LOCAL",
+ "uri": "/Users/bozhaoyu/bentoml/repository/IrisClassifier/20200305171229_0A1411"
+ },
+ "bentoServiceMetadata": {
+ "name": "IrisClassifier",
+ "version": "20200305171229_0A1411",
+ "createdAt": "2020-03-06T01:12:49.431011Z",
+ "env": {
+ "condaEnv": "name: bentoml-IrisClassifier\nchannels:\n- defaults\ndependencies:\n- python=3.7.3\n- pip\n",
+ "pipDependencies": "bentoml==0.6.2\nscikit-learn",
+ "pythonVersion": "3.7.3"
+ },
+ "artifacts": [
+ {
+ "name": "model",
+ "artifactType": "SklearnModelArtifact"
+ }
+ ],
+ "apis": [
+ {
+ "name": "predict",
+ "handlerType": "DataframeHandler",
+ "docs": "BentoService API",
+ "handlerConfig": {
+ "orient": "records",
+ "typ": "frame",
+ "input_dtypes": null,
+ "output_orient": "records"
+ }
+ }
+ ]
+ }
+ }
+ ```
+
+4. Test run API server. BentoML can start an API server from the saved model. Use
+ BentoML CLI command to start an API server locally and test it with the `curl` command.
+
+ ```bash
+ bentoml serve IrisClassifier:latest
+ ```
+
+ In another terminal window, make `curl` request with sample data to the API server
+ and get prediction result:
+
+ ```bash
+ curl -v -i \
+ --header "Content-Type: application/json" \
+ --request POST \
+ --data '[[5.1, 3.5, 1.4, 0.2]]' \
+ 127.0.0.1:5000/predict
+ ```
+
+## Building and deploying the sample
+
+BentoML supports creating an API server docker image from its saved model directory, where
+a Dockerfile is automatically generated when saving the model.
+
+1. To build an API model server docker image, replace `{username}` with your Docker Hub
+ username and run the following commands.
+
+ ```bash
+ # jq might not be installed on your local system, please follow jq install
+ # instruction at https://stedolan.github.io/jq/download/
+ saved_path=$(bentoml get IrisClassifier:latest -q | jq -r ".uri.uri")
+
+ # Build the container on your local machine
+ docker build - t {username}/iris-classifier $saved_path
+
+ # Push the container to docker registry
+ docker push {username}/iris-classifier
+ ```
+
+1. In `service.yaml`, replace `{username}` with your Docker hub username:
+
+ ```yaml
+ apiVersion: serving.knative.dev/v1
+ kind: Service
+ metadata:
+ name: iris-classifier
+ namespace: default
+ spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/iris-classifier
+ ports:
+ - containerPort: 5000 # Port to route to
+ livenessProbe:
+ httpGet:
+ path: /healthz
+ initialDelaySeconds: 3
+ periodSeconds: 5
+ readinessProbe:
+ httpGet:
+ path: /healthz
+ initialDelaySeconds: 3
+ periodSeconds: 5
+ failureThreshold: 3
+ timeoutSeconds: 60
+ ```
+
+1. Deploy the Service to Knative Serving with `kubectl` by running the command:
+
+ ```bash
+ kubectl apply --filename service.yaml
+ ```
+
+1. Now that your service is created, Knative performs the following steps:
+
+ - Create a new immutable revision for this version of the app.
+ - Network programming to create a route, ingress, service, and load
+ balance for your application.
+ - Automatically scale your pods up and down (including to zero active
+ pods).
+
+1. Run the following command to find the domain URL for your service:
+
+ ```bash
+ kubectl get ksvc iris-classifier --output=custom-columns=NAME:.metadata.name,URL:.status.url
+
+ NAME URL
+ iris-classifier http://iris-classifer.default.example.com
+ ```
+
+1. Replace the request URL with the URL return in the previous command, and execute the
+ command to get prediction result from the deployed model API endpoint.
+
+ ```bash
+ curl -v -i \
+ --header "Content-Type: application/json" \
+ --request POST \
+ --data '[[5.1, 3.5, 1.4, 0.2]]' \
+ http://iris-classifier.default.example.com/predict
+
+ [0]
+ ```
+
+## Removing the sample app deployment
+
+To remove the application from your cluster, delete the service record:
+
+ ```bash
+ kubectl delete --filename service.yaml
+ ```
diff --git a/code-samples/community/serving/machinelearning-python-bentoml/iris_classifier.py b/code-samples/community/serving/machinelearning-python-bentoml/iris_classifier.py
new file mode 100644
index 000000000..c94c386f8
--- /dev/null
+++ b/code-samples/community/serving/machinelearning-python-bentoml/iris_classifier.py
@@ -0,0 +1,11 @@
+from bentoml import env, artifacts, api, BentoService
+from bentoml.handlers import DataframeHandler
+from bentoml.artifact import SklearnModelArtifact
+
+@env(auto_pip_dependencies=True)
+@artifacts([SklearnModelArtifact('model')])
+class IrisClassifier(BentoService):
+
+ @api(DataframeHandler)
+ def predict(self, df):
+ return self.artifacts.model.predict(df)
diff --git a/code-samples/community/serving/machinelearning-python-bentoml/main.py b/code-samples/community/serving/machinelearning-python-bentoml/main.py
new file mode 100644
index 000000000..b5bb8c0c7
--- /dev/null
+++ b/code-samples/community/serving/machinelearning-python-bentoml/main.py
@@ -0,0 +1,22 @@
+from sklearn import svm
+from sklearn import datasets
+
+from iris_classifier import IrisClassifier
+
+if __name__ == "__main__":
+ # Load training data
+ iris = datasets.load_iris()
+ X, y = iris.data, iris.target
+
+ # Model Training
+ clf = svm.SVC(gamma='scale')
+ clf.fit(X, y)
+
+ # Create a iris classifier service instance
+ iris_classifier_service = IrisClassifier()
+
+ # Pack the newly trained model artifact
+ iris_classifier_service.pack('model', clf)
+
+ # Save the prediction service to disk for model serving
+ saved_path = iris_classifier_service.save()
diff --git a/code-samples/community/serving/machinelearning-python-bentoml/service.yaml b/code-samples/community/serving/machinelearning-python-bentoml/service.yaml
new file mode 100644
index 000000000..732a9756f
--- /dev/null
+++ b/code-samples/community/serving/machinelearning-python-bentoml/service.yaml
@@ -0,0 +1,24 @@
+apiVersion: serving.knative.dev/v1
+kind: Service
+metadata:
+ name: iris-classifier
+ namespace: default
+spec:
+ template:
+ spec:
+ containers:
+ - image: docker.io/{username}/iris-classifier
+ ports:
+ - containerPort: 5000 # Port to route to
+ livenessProbe:
+ httpGet:
+ path: /healthz
+ initialDelaySeconds: 3
+ periodSeconds: 5
+ readinessProbe:
+ httpGet:
+ path: /healthz
+ initialDelaySeconds: 3
+ periodSeconds: 5
+ failureThreshold: 3
+ timeoutSeconds: 60
diff --git a/community/contributing/images/logo/cmyk/knative-logo-cmyk.ai b/community/contributing/images/logo/cmyk/knative-logo-cmyk.ai
index 1ed2feec7..a511e62b2 100644
--- a/community/contributing/images/logo/cmyk/knative-logo-cmyk.ai
+++ b/community/contributing/images/logo/cmyk/knative-logo-cmyk.ai
@@ -1,5 +1,5 @@
-%PDF-1.5
%
-1 0 obj
<>/OCGs[5 0 R]>>/Pages 3 0 R/Type/Catalog>>
endobj
2 0 obj
<>stream
+%PDF-1.5
%
+1 0 obj
<>/OCGs[5 0 R]>>/Pages 3 0 R/Type/Catalog>>
endobj
2 0 obj
<>stream
@@ -199,21 +199,21 @@
-
endstream
endobj
3 0 obj
<>
endobj
7 0 obj
<>/Resources<>/ExtGState<>/Properties<>>>/Thumb 12 0 R/TrimBox[0.0 0.0 792.0 612.0]/Type/Page>>
endobj
8 0 obj
<>stream
+
endstream
endobj
3 0 obj
<>
endobj
7 0 obj
<>/Resources<>/ExtGState<>/Properties<>>>/Thumb 12 0 R/TrimBox[0.0 0.0 792.0 612.0]/Type/Page>>
endobj
8 0 obj
<>stream
HlVKF)$/| !l>ouEVԼ_>ל~