Proofread Scripting with jbang guide

Proofread Scripting with jbang guide

////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////
= Quarkus - Scripting with Quarkus
:extension-status: preview

Quarkus provides integration with https://jbang.dev[jbang] which allows you to write Java scripts/applications requiring no Maven nor Gradle to get running.

In this guide, we will see how you can write a REST application using just a single Java file.

include::./status-include.adoc[]

== Prerequisites

To complete this guide, you need:

* less than 5 minutes
* https://jbang.dev/download[jbang v0.40.3+]
* an IDE
* GraalVM installed if you want to run in native mode

== Solution

Normally we would link to a Git repository to clone but in this case there is no additional files than the following:

[source,java,subs=attributes+]
----
//usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS io.quarkus:quarkus-resteasy:999-SNAPSHOT
//JAVAC_OPTIONS -parameters
//JAVA_OPTIONS -Djava.util.logging.manager=org.jboss.logmanager.LogManager

import io.quarkus.runtime.Quarkus;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jboss.resteasy.annotations.jaxrs.PathParam;
import org.jboss.logging.Logger;

@Path("/hello")
@ApplicationScoped
public class quarkusapp {

    @GET
    public String sayHello() {
        return "hello";
    }

    public static void main(String[] args) {
        Quarkus.run(args);
    }

    @Inject
    GreetingService service;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public String greeting(@PathParam String name) {
        return service.greeting(name);
    }

    @ApplicationScoped
    static public class GreetingService {

        public String greeting(String name) {
            return "hello " + name;
        }
    }
}
----

== Architecture

In this guide, we create a straightforward application serving a `hello` endpoint with a single source file, no additional build files like `pom.xml` or `build.gradle` needed. To demonstrate dependency injection, this endpoint uses a `greeting` bean.

image::getting-started-architecture.png[alt=Architecture]

== Creating the initial file

First, we need a Java file. jbang lets you create an initial version using:

[source,shell,subs=attributes+]
----
jbang scripting/quarkusapp.java
cd scripting
----

This command generates a .java file that you can directly run on Linux and macOS, i.e. `./quarkusapp.java` - on Windows you need to use `jbang quarkusapp.java`.

This initial version will print `Hello World` when run.

Once generated, look at the `quarkusapp.java`.

You will find at the top a line looking like this:

[source,java]
----
//usr/bin/env jbang "$0" "$@" ; exit $?
----

This line is what on Linux and macOS allows you to run it as a script. On Windows this line is ignored.

The next line

[source,java]
----
// //DEPS <dependency1> <dependency2>
----

Is illustrating how you add dependencies to this script. This is a feature of `jbang`.

Go ahead and update this line to include the `quarkus-resteasy` dependency like so:

[source,shell,subs=attributes+]
----
//DEPS io.quarkus:quarkus-resteasy:{quarkus-version}
----

Now, run `jbang quarkusapp.java` and you will see `jbang` resolving this dependency and building the jar with help from Quarkus' jbang integration.

[source,shell,subs=attributes+]
----
$ jbang quarkusapp.java
❯ jbang quarkusapp.java
[jbang] Resolving dependencies...
[jbang]     Resolving io.quarkus:quarkus-resteasy:{quarkus-version}...Done
[jbang] Dependencies resolved
[jbang] Building jar...
[jbang] Post build with io.quarkus.launcher.JBangIntegration
Aug 30, 2020 5:40:55 AM org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 3.1.1.Final
Aug 30, 2020 5:40:56 AM io.quarkus.deployment.QuarkusAugmentor run
INFO: Quarkus augmentation completed in 722ms
Hello World
----

For now the application does nothing new.

[TIP]
.How do I edit this file and get content assist ?
====
As there is nothing but a `.java` file, most IDE's does not handle content assist well.
To work around that you can run `jbang edit quarkusapp.java` which will print out a directory that will have a temporary project setup you can use in your IDE.

On Linux/macOS you can run `<idecommand> `jbang edit quarkusapp.java``.

If you add dependencies while editing you can get jbang to automatically refresh
the IDE project using `jbang edit --live=<idecommand> quarkusapp.java`.
====

=== The JAX-RS resources

Now let us replace the class with one that uses Quarkus features:

[source,java]
----
import io.quarkus.runtime.Quarkus;
import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/hello")
@ApplicationScoped
public class quarkusapp {

    @GET
    public String sayHello() {
        return "hello";
    }

    public static void main(String[] args) {
        Quarkus.run(args);
    }
}
----

It's a very simple class with a main method that starts Quarkus with a REST endpoint, returning "hello" to requests on "/hello".

[TIP]
.Why is the `main` method there ?
====
A `main` method is currently needed for the `jbang` integration to work - we might remove this requirement in the future.
====

== Running the application

Now when you run the application you will see Quarkus start up.

Use: `jbang quarkusapp.java`:

[source,shell,subs=attributes+]
----
$ jbang quarkusapp.java
 jbang quarkusapp.java
[jbang] Building jar...
[jbang] Post build with io.quarkus.launcher.JBangIntegration
Aug 30, 2020 5:49:01 AM org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 3.1.1.Final
Aug 30, 2020 5:49:02 AM io.quarkus.deployment.QuarkusAugmentor run
INFO: Quarkus augmentation completed in 681ms
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2020-08-30 05:49:03,255 INFO  [io.quarkus] (main) Quarkus {quarkus-version} on JVM started in 0.638s. Listening on: http://0.0.0.0:8080
2020-08-30 05:49:03,272 INFO  [io.quarkus] (main) Profile prod activated.
2020-08-30 05:49:03,272 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]
----

Once started, you can request the provided endpoint:

[source,shell]
----
$ curl -w "\n" http://localhost:8080/hello
hello
----

Hit `CTRL+C` to stop the application, or keep it running and enjoy the blazing fast hot-reload.

[TIP]
.Automatically add newline with `curl -w "\n"`
====
We are using `curl -w "\n"` in this example to avoid your terminal printing a '%' or put both result and next command prompt on the same line.
====

[TIP]
.Why is `quarkus-resteasy` not resolved ?
====
In this second run you should not see a line saying it is resolving `quarkus-resteasy` as jbang caches the dependency resolution between runs.
If you want to clear the caches to force resolution use `jbang cache clear`.
====

== Using injection

Dependency injection in Quarkus is based on ArC which is a CDI-based dependency injection solution tailored for Quarkus' architecture.
You can learn more about it in the link:cdi-reference[Contexts and Dependency Injection guide].

ArC comes as a dependency of `quarkus-resteasy` so you already have it handy.

Let's modify the application and add a companion bean.

Normally you would add a separate class, but as we are aiming to have it all in one file you will add a
nested class.

Add the following *inside* the `quarkusapp` class body.

[source, java]
----
@ApplicationScoped
static public class GreetingService {

    public String greeting(String name) {
        return "hello " + name;
    }

}
----

[TIP]
.Use of nested static public classes
====
We are using a nested static public class instead of a top level class for two reasons:

  1. jbang currently does not support multiple source files
  2. All Java frameworks relying on introspection have challenges using top level classes as they are not as visible as public classes; and in Java there can only be one top level public class in a file.

====

Edit the `quarksapp` class to inject the `GreetingService` and create a new endpoint using it, you should end up with something like:

[source, java]
----
//usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS io.quarkus:quarkus-resteasy:999-SNAPSHOT

import io.quarkus.runtime.Quarkus;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jboss.resteasy.annotations.jaxrs.PathParam;

@Path("/hello")
@ApplicationScoped
public class quarkusapp {

    @GET
    public String sayHello() {
        return "hello from Quarkus with jbang.dev";
    }

    public static void main(String[] args) {
        Quarkus.run(args);
    }

    @Inject
    GreetingService service;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public String greeting(@PathParam String name) {
        return service.greeting(name);
    }

    @ApplicationScoped
    static public class GreetingService {

        public String greeting(String name) {
            return "hello " + name;
        }
    }
}
----

Now when you run `jbang quarkusapp.java` you can check what the new end point returns:

[source,shell,subs=attributes+]
----
$ curl -w "\n" http://localhost:8080/hello/greeting/quarkus
hello null
----

Now that is unexpected, why is it returning `hello null` and not `hello quarkus`?

The reason is that JAX-RS `@PathParam` relies on the `-parameters` compiler flag to be set to be able to map `{name}` to the `name` parameter.

We fix that by adding the following comment instruction to the file:

[source,shell,subs=attributes+]
----
//JAVAC_OPTIONS -parameters
----

Now when you run with `jbang quarkusapp.java` the end point should return what you expect:

[source,shell,subs=attributes+]
----
$ curl -w "\n" http://localhost:8080/hello/greeting/quarkus
hello quarkus
----

== Debugging

To debug the application you use `jbang --debug quarkusapp.java` and you can use your IDE to connect on port 4004; if you want to use the
more traditonal Quarkus debug port you can use `jbang --debug=5005 quarkusapp.java`.

Note: `jbang` debugging always suspends thus you need to connect the debugger to have the application run.

== Logging

To use logging in Quarkus scripting with jbang you do as usual, with configuring a logger, i.e.

[source,java]
----
public static final Logger LOG = Logger.getLogger(quarkusapp.class);
----

To get it to work you need to add a Java option to ensure the logging is initialized properly, i.e.

[source,java]
----
//JAVA_OPTIONS -Djava.util.logging.manager=org.jboss.logmanager.LogManager
----

With that in place running `jbang quarkusapp.java` will log and render as expected.

== Configuring Application

You can use `//Q:CONFIG <property>=<value>` to set up static configuration for your application.

I.e. if you wanted to add the `smallrye-openapi` and `swagger-ui` extensions and have the Swagger UI always show up you would add the following:

[source,java,subs=attributes+]
----
//DEPS io.quarkus:quarkus-smallrye-openapi:{quarkus-version}
//DEPS io.quarkus:quarkus-swagger-ui:{quarkus-version}
//Q:CONFIG quarkus.swagger-ui.always-include=true
----

Now during build the `quarkus.swagger-ui.always-include` will be generated into the resulting jar and `http://0.0.0.0:8080/swagger-ui` will be available when run.

== Running as a native application

If you have the `native-image` binary installed and `GRAALVM_HOME` set, you can get the native executable built and run using `jbang --native quarkusapp.java`:

[source,shell,subs=attributes+]
----
$ jbang --native quarkusapp
 jbang --native quarkusapp.java
[jbang] Building jar...
[jbang] Post build with io.quarkus.launcher.JBangIntegration
Aug 30, 2020 6:21:15 AM org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 3.1.1.Final
Aug 30, 2020 6:21:16 AM io.quarkus.deployment.pkg.steps.JarResultBuildStep buildNativeImageThinJar
INFO: Building native image source jar: /var/folders/yb/sytszfld4sg8vwr1h0w20jlw0000gn/T/quarkus-jbang3291688251685023074/quarkus-application-native-image-source-jar/quarkus-application-runner.jar
Aug 30, 2020 6:21:16 AM io.quarkus.deployment.pkg.steps.NativeImageBuildStep build
INFO: Building native image from /var/folders/yb/sytszfld4sg8vwr1h0w20jlw0000gn/T/quarkus-jbang3291688251685023074/quarkus-application-native-image-source-jar/quarkus-application-runner.jar
Aug 30, 2020 6:21:16 AM io.quarkus.deployment.pkg.steps.NativeImageBuildStep checkGraalVMVersion
INFO: Running Quarkus native-image plugin on GraalVM Version 20.1.0 (Java Version 11.0.7)
Aug 30, 2020 6:21:16 AM io.quarkus.deployment.pkg.steps.NativeImageBuildStep build
INFO: /Users/max/.sdkman/candidates/java/20.1.0.r11-grl/bin/native-image -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-Dsun.nio.ch.maxUpdateArraySize=100 -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory -J-Dvertx.disableDnsResolver=true -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=1 -J-Duser.language=en -J-Dfile.encoding=UTF-8 --initialize-at-build-time= -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy\$BySpaceAndTime -H:+JNI -jar quarkus-application-runner.jar -H:FallbackThreshold=0 -H:+ReportExceptionStackTraces -H:-AddAllCharsets -H:EnableURLProtocols=http --no-server -H:-UseServiceLoaderFeature -H:+StackTrace quarkus-application-runner

Aug 30, 2020 6:22:31 AM io.quarkus.deployment.QuarkusAugmentor run
INFO: Quarkus augmentation completed in 76010ms
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2020-08-30 06:22:32,012 INFO  [io.quarkus] (main) Quarkus {quarkus-version} native started in 0.017s. Listening on: http://0.0.0.0:8080
2020-08-30 06:22:32,013 INFO  [io.quarkus] (main) Profile prod activated.
2020-08-30 06:22:32,013 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]
----

This native build will take some time on first run but any subsequent runs (without changing `quarkusapp.java`) will be close to instant:

[source,shell,subs=attributes+]
----
$ jbang --native quarkusapp.java
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2020-08-30 06:23:36,846 INFO  [io.quarkus] (main) Quarkus {quarkus-version} native started in 0.015s. Listening on: http://0.0.0.0:8080
2020-08-30 06:23:36,846 INFO  [io.quarkus] (main) Profile prod activated.
2020-08-30 06:23:36,846 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]
----

=== Conclusion

If you want to get started with Quarkus or write something quickly, Quarkus Scripting with jbang lets you do that. No Maven, no Gradle - just a Java file. In this guide we outlined the very basics on using Quarkus with jbang; if you want to learn more about what jbang can do go see https://jbang.dev.

////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////
= Quarkus - Scripting with Quarkus
:extension-status: preview

Quarkus provides integration with https://jbang.dev[jbang]] which allows you to write java scripts/applications requiring no maven nor gradle to get running.

In this guide, we will see how you can write a REST application using just a singe java file.

include::./status-include.adoc[]

== Prerequisites

To complete this guide, you need:

* less than 5 minutes
* https://jbang.dev/download[jbang v0.40.3+]
* an IDE
* GraalVM installed if you want to run in native mode

== Solution

Normally we would link to a Git repository to clone but in this case there is no additional files than the following:

[source,java,subs=attributes+]
----
//usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS io.quarkus:quarkus-resteasy:999-SNAPSHOT
//JAVAC_OPTIONS -parameters
//JAVA_OPTIONS -Djava.util.logging.manager=org.jboss.logmanager.LogManager

import io.quarkus.runtime.Quarkus;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jboss.resteasy.annotations.jaxrs.PathParam;
import org.jboss.logging.Logger;

@Path("/hello")
@ApplicationScoped
public class quarkusapp {

    @GET
    public String sayHello() {
        return "hello";
    }

    public static void main(String[] args) {
        Quarkus.run(args);
    }

    @Inject
    GreetingService service;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public String greeting(@PathParam String name) {
        return service.greeting(name);
    }

    @ApplicationScoped
    static public class GreetingService {

        public String greeting(String name) {
            return "hello " + name;
        }
    }
}
----

== Architecture

In this guide, we create a straightforward application serving a `hello` endpoint with a single source file, no additional build files like `pom.xml` or `build.gradle` needed. To demonstrate dependency injection, this endpoint uses a `greeting` bean.

image::getting-started-architecture.png[alt=Architecture]

== Creating the initial file

First, we need a java file. jbang lets you create an initial version using:

[source,shell,subs=attributes+]
----
jbang scripting/quarkusapp.java
cd scripting
----

This command generates a .java file that you can directly run on Linux and OS X, i.e. `./quarkusapp.java` - on Windows you need to use `jbang quarkusapp.java`

This initial version will print `Hello World` when run.

Once generated, look at the `quarkusapp.java`.

You will find at the top a line looking like this:

[source,java]
----
//usr/bin/env jbang "$0" "$@" ; exit $?
----

This line is what on Linux and OS X allows you to run it as a script. On Windows this line is ignored.

The next line

[source,java]
----
// //DEPS <dependency1> <dependency2>
----

Is illustrating how you add dependencies to this script. This is a feature of `jbang`.

Go ahead and update this line to include the `quarkus-resteasy` dependency like so:

[source,shell,subs=attributes+]
----
//DEPS io.quarkus:quarkus-resteasy:{quarkus-version}
----

Now, run `jbang quarkusapp.java` and you will see `jbang` resolving this dependency and building the jar with help from Quarkus jbang integration.

[source,shell,subs=attributes+]
----
$ jbang quarkusapp.java
❯ jbang quarkusapp.java
[jbang] Resolving dependencies...
[jbang]     Resolving io.quarkus:quarkus-resteasy:{quarkus-version}...Done
[jbang] Dependencies resolved
[jbang] Building jar...
[jbang] Post build with io.quarkus.launcher.JBangIntegration
Aug 30, 2020 5:40:55 AM org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 3.1.1.Final
Aug 30, 2020 5:40:56 AM io.quarkus.deployment.QuarkusAugmentor run
INFO: Quarkus augmentation completed in 722ms
Hello World
----

For now the application does nothing new.

[TIP]
.How do I edit this file and get content assist ?
====
As there is nothing but a `.java` file most IDE's does not handle content assist well.
To work around that you can run `jbang edit quarkusapp.java` which will print out a directory that will have a temporary project setup you can use in your IDE.

On Linux/OSX you can run `<idecommand> `jbang edit quarkusapp.java``.

If you add dependencies while editing you can get jbang to automatically refresh
the IDE project using `jbang edit --live=<idecommand> quarkusapp.java`.
====

=== The JAX-RS resources

Now let us replace the class with one that uses Quarkus features.

[source,java]
----
import io.quarkus.runtime.Quarkus;
import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/hello")
@ApplicationScoped
public class quarkusapp {

    @GET
    public String sayHello() {
        return "hello";
    }

    public static void main(String[] args) {
        Quarkus.run(args);
    }
}
----

It's a very simple class with a main method that starts Quarkus with a REST endpoint, returning "hello" to requests on "/hello".

[TIP]
.Why is the `main` method there ?
====
A `main` method is currently needed for the `jbang` integration to work - will be possible to remove in the future.
====

== Running the application

Now when youn run the application you will see Quarkus start up.

Use: `jbang quarkusapp.java`:

[source,shell,subs=attributes+]
----
$ jbang quarkusapp.java
 jbang quarkusapp.java
[jbang] Building jar...
[jbang] Post build with io.quarkus.launcher.JBangIntegration
Aug 30, 2020 5:49:01 AM org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 3.1.1.Final
Aug 30, 2020 5:49:02 AM io.quarkus.deployment.QuarkusAugmentor run
INFO: Quarkus augmentation completed in 681ms
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2020-08-30 05:49:03,255 INFO  [io.quarkus] (main) Quarkus {quarkus-version} on JVM started in 0.638s. Listening on: http://0.0.0.0:8080
2020-08-30 05:49:03,272 INFO  [io.quarkus] (main) Profile prod activated.
2020-08-30 05:49:03,272 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]
----

Once started, you can request the provided endpoint:

```
$ curl -w "\n" http://localhost:8080/hello
hello
```

Hit `CTRL+C` to stop the application, or keep it running and enjoy the blazing fast hot-reload.

[TIP]
.Automatically add newline with `curl -w "\n"`
====
We are using `curl -w "\n"` in this example to avoid your terminal printing a '%' or put both result and next command prompt on the same line.
====

[TIP]
.Why is `quarkus-resteasy` not resolved ?
====
In this second run you should not see a line saying it is resolving `quarkus-resteasy` as jbang caches the dependency resolution between runs.
If you want to clear the caches to force resolution use `jbang cache clear`
====

== Using injection

Dependency injection in Quarkus is based on ArC which is a CDI-based dependency injection solution tailored for Quarkus' architecture.
You can learn more about it in the link:cdi-reference[Contexts and Dependency Injection guide].

ArC comes as a dependency of `quarkus-resteasy` so you already have it handy.

Let's modify the application and add a companion bean.

Normally you would add a separate class, but as we are aiming to have it all in one file you will add a
nested class.

Add the following *inside* the `quarkusapp` class body.

[source, java]
----
@ApplicationScoped
static public class GreetingService {

    public String greeting(String name) {
        return "hello " + name;
    }

}
----

[TIP]
.Use of nested static public classes
====
We are using a nested static public class instead of a top level class for two reasons:

  1. jbang currently does not currently support multiple source files
  2. All Java frameworks relying on introspection have challenges using top level classes as they are not as visible as public classes; and in java there can only be one top level public class in a file.

====

Edit the `quarksapp` class to inject the `GreetingService` and create a new endpoint using it, you should end up with something like:

[source, java]
----
//usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS io.quarkus:quarkus-resteasy:999-SNAPSHOT

import io.quarkus.runtime.Quarkus;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jboss.resteasy.annotations.jaxrs.PathParam;

@Path("/hello")
@ApplicationScoped
public class quarkusapp {

    @GET
    public String sayHello() {
        return "hello from Quarkus with jbang.dev";
    }

    public static void main(String[] args) {
        Quarkus.run(args);
    }

    @Inject
    GreetingService service;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/greeting/{name}")
    public String greeting(@PathParam String name) {
        return service.greeting(name);
    }

    @ApplicationScoped
    static public class GreetingService {

        public String greeting(String name) {
            return "hello " + name;
        }
    }
}
----

Now when you run `jbang quarkusapp.java` you can check what the new end point returns:

[source,shell,subs=attributes+]
----
$ curl -w "\n" http://localhost:8080/hello/greeting/quarkus
hello null
----

Now that is unexpected, why is it returning `hello null` and not `hello quarkus` ?

The reason is that JAX-RS `@PathParam` relies on the `-parameters` compiler flag to be set to be able to map `{name}` to the `name` parameter.

We fix that by adding the following comment instruction to the file:

[source,shell,subs=attributes+]
----
//JAVAC_OPTIONS -parameters
----

Now when you run with `jbang quarkusapp.java` the end point should return what you expect:

[source,shell,subs=attributes+]
----
$ curl -w "\n" http://localhost:8080/hello/greeting/quarkus
hello quarkus
----

== Debugging

To debug the application you use `jbang --debug quarkusapp.java` and you can use your IDE to connect on port 4004; if you want to use the
more traditonal Quarkus debug port you can use `jbang --debug=5005 quarkusapp.java`.

Note: `jbang` debugging always suspends thus you need to connect the debugger to have the application run.

== Logging

To use logging in Quarkus scripting with jbang you do as usual, with configuring a logger, i.e.

[source,java]
----
public static final Logger LOG = Logger.getLogger(quarkusapp.class);
----

To get it to work you need to add a java option to ensure the logging is initialized properly, i.e.

[source,java]
----
//JAVA_OPTIONS -Djava.util.logging.manager=org.jboss.logmanager.LogManager
----

With that in place running `jbang quarkusapp.java` will log and render as expected.

== Configuring Application

You can use `//Q:CONFIG <property>=<value>` to setup static configuration for your application.

i.e. if you wanted to add the `smallrye-openapi` and `swagger-ui` and have the swagger-ui always show up you would add the following:

[source,java,subs=attributes+]
----
//DEPS io.quarkus:quarkus-smallrye-openapi:{quarkus-version}
//DEPS io.quarkus:quarkus-swagger-ui:{quarkus-version}
//Q:CONFIG quarkus.swagger-ui.always-include=true
----

Now during build the `quarkus.swagger-ui.always-include` will be generated into the resulting jar and `http://0.0.0.0:8080/swagger-ui` will be available when run.

== Running as a native application

If you have `native-image` binary installed and GRAALVM_HOME set you can get native binary built and run using `jbang --native quarkusapp.java`:

[source,shell,subs=attributes+]
----
$ jbang --native quarkusapp
 jbang --native quarkusapp.java
[jbang] Building jar...
[jbang] Post build with io.quarkus.launcher.JBangIntegration
Aug 30, 2020 6:21:15 AM org.jboss.threads.Version <clinit>
INFO: JBoss Threads version 3.1.1.Final
Aug 30, 2020 6:21:16 AM io.quarkus.deployment.pkg.steps.JarResultBuildStep buildNativeImageThinJar
INFO: Building native image source jar: /var/folders/yb/sytszfld4sg8vwr1h0w20jlw0000gn/T/quarkus-jbang3291688251685023074/quarkus-application-native-image-source-jar/quarkus-application-runner.jar
Aug 30, 2020 6:21:16 AM io.quarkus.deployment.pkg.steps.NativeImageBuildStep build
INFO: Building native image from /var/folders/yb/sytszfld4sg8vwr1h0w20jlw0000gn/T/quarkus-jbang3291688251685023074/quarkus-application-native-image-source-jar/quarkus-application-runner.jar
Aug 30, 2020 6:21:16 AM io.quarkus.deployment.pkg.steps.NativeImageBuildStep checkGraalVMVersion
INFO: Running Quarkus native-image plugin on GraalVM Version 20.1.0 (Java Version 11.0.7)
Aug 30, 2020 6:21:16 AM io.quarkus.deployment.pkg.steps.NativeImageBuildStep build
INFO: /Users/max/.sdkman/candidates/java/20.1.0.r11-grl/bin/native-image -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-Dsun.nio.ch.maxUpdateArraySize=100 -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory -J-Dvertx.disableDnsResolver=true -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=1 -J-Duser.language=en -J-Dfile.encoding=UTF-8 --initialize-at-build-time= -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy\$BySpaceAndTime -H:+JNI -jar quarkus-application-runner.jar -H:FallbackThreshold=0 -H:+ReportExceptionStackTraces -H:-AddAllCharsets -H:EnableURLProtocols=http --no-server -H:-UseServiceLoaderFeature -H:+StackTrace quarkus-application-runner

Aug 30, 2020 6:22:31 AM io.quarkus.deployment.QuarkusAugmentor run
INFO: Quarkus augmentation completed in 76010ms
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2020-08-30 06:22:32,012 INFO  [io.quarkus] (main) Quarkus {quarkus-version} native started in 0.017s. Listening on: http://0.0.0.0:8080
2020-08-30 06:22:32,013 INFO  [io.quarkus] (main) Profile prod activated.
2020-08-30 06:22:32,013 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]
----

This native build will take some time on first run but any subsequent runs (without changing `quarkusapp.java`) will be close to instant:

[source,shell,subs=attributes+]
----
$ jbang --native quarkusapp.java
__  ____  __  _____   ___  __ ____  ______
 --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
 -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
2020-08-30 06:23:36,846 INFO  [io.quarkus] (main) Quarkus {quarkus-version} native started in 0.015s. Listening on: http://0.0.0.0:8080
2020-08-30 06:23:36,846 INFO  [io.quarkus] (main) Profile prod activated.
2020-08-30 06:23:36,846 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]
----

=== Conclusion

If you want to get started with Quarkus or write something quickly, Quarkus Scripting with jbang lets you do that. No Maven, no Gradle - just a java file. In this guide we outlined the very basics on using Quarkus with jbang; if you want to learn more about what jbang can do go see https://jbang.dev.


HZN-352: Reviewer fixes

HZN-352: Reviewer fixes

// Allow GitHub image rendering
:imagesdir: ../../images

[[gi-install-cassandra-debian]]
==== Installing on Debian-based systems

This section describes how to install the latest _Cassandra 2.1.x_ release on a _Debian_-based system for _Newts_.
The first step is to add the _DataStax_ community repository and install the required _GPG Key_ to verify the integrity of the _DEB packages_.
Installation of the package is done with _apt_ and the _Cassandra_ service is added to the runlevel configuration.

NOTE: This description was built on _Debian 8_ and _Ubuntu 14.04 LTS_.

.Add the DataStax repository
[source, bash]
----
vi /etc/apt/sources.list.d/cassandra.sources.list
----

.Content of the cassandra.sources.list file
[source, bash]
----
deb http://debian.datastax.com/community stable main
----

.Install GPG key to verify DEB packages
[source, bash]
----
wget -O - http://debian.datastax.com/debian/repo_key | apt-key add -
----

.Install latest Cassandra 2.1.x package
[source, bash]
----
apt-get update
apt-get install dsc21=2.1.8-1 cassandra=2.1.8
----

The _Cassandra_ service is added to the runlevel configuration and is automatically started after installing the package.

TIP: Verify whether the _Cassandra_ service is automatically started after rebooting the server.

// Allow GitHub image rendering
:imagesdir: ../../images

[[gi-install-cassandra-debian]]
==== Installing on Debian-based systems

This section describes how to install the latest _Cassandra 2.1.x_ release on a _Debian_ based systems for _Newts_.
The first steps add the _DataStax_ community repository and install the required _GPG Key_ to verify the integrity of the _DEB packages_.
Installation of the package is done with _apt_ and the _Cassandra_ service is added to the run level configuration.

NOTE: This description is build on _Debian 8_ and _Ubuntu 14.04 LTS_.

.Add DataStax repository
[source, bash]
----
vi /etc/apt/sources.list.d/cassandra.sources.list
----

.Content of the cassandra.sources.list file
[source, bash]
----
deb http://debian.datastax.com/community stable main
----

.Install GPG key to verify DEB packages
[source, bash]
----
wget -O - http://debian.datastax.com/debian/repo_key | apt-key add -
----

.Install latest Cassandra 2.1.x package
[source, bash]
----
apt-get update
apt-get install dsc21=2.1.8-1 cassandra=2.1.8
----

The _Cassandra_ service is added to the run level configuration and is automatically started after installing the package.

TIP: Verify if the _Cassandra_ service is automatically started after rebooting the server.


Add migration note for remote cluster settings (#33632)

The remote cluster settings search.remote.* have been renamed to
cluster.remote.* and are automatically upgraded in the cluster state on
gateway recovery, and on put. This commit adds a note to the migration
docs for these changes.

[[breaking_60_settings_changes]]
=== Settings changes

==== Remove support for elasticsearch.json and elasticsearch.yaml configuration file

The configuration file found in the Elasticsearch config directory could previously have
a `.yml`, `.yaml` or `.json` extension. Only `elasticsearch.yml` is now supported.

==== Duplicate keys in configuration file

In previous versions of Elasticsearch, the configuration file was allowed to
contain duplicate keys. For example:

[source,yaml]
--------------------------------------------------
node:
  name: my-node

node
  attr:
    rack: my-rack
--------------------------------------------------

In Elasticsearch 6.0.0, this is no longer permitted. Instead, this must be
specified in a single key as:

[source,yaml]
--------------------------------------------------
node:
  name: my-node
  attr:
    rack: my-rack
--------------------------------------------------

==== Coercion of boolean settings

Previously, Elasticsearch recognized the strings `true`, `false`, `on`, `off`, `yes`, `no`, `0`, `1` as booleans. Elasticsearch 6.0
recognizes only `true` and `false` as boolean and will throw an error otherwise. For backwards compatibility purposes, during the 6.x series
index settings on pre-6.0 indices will continue to work. Note that this does not apply to node-level settings that are stored
in `elasticsearch.yml`.

==== Snapshot settings

The internal setting `cluster.routing.allocation.snapshot.relocation_enabled` that allowed shards with running snapshots to be reallocated to
different nodes has been removed. Enabling this setting could cause allocation issues if a shard got allocated off a node and then
reallocated back to this node while a snapshot was running.

==== Store throttling settings

Store throttling has been removed. As a consequence, the
`indices.store.throttle.type` and `indices.store.throttle.max_bytes_per_sec`
cluster settings and the `index.store.throttle.type` and
`index.store.throttle.max_bytes_per_sec` index settings are not
recognized anymore.

==== Store settings

The `default` `index.store.type` has been removed. If you were using it, we
advise that you simply remove it from your index settings and Elasticsearch
will use the best `store` implementation for your operating system.

==== Network settings

The blocking TCP client, blocking TCP server, and blocking HTTP server have been removed.
As a consequence, the `network.tcp.blocking_server`, `network.tcp.blocking_client`,
`network.tcp.blocking`,`transport.tcp.blocking_client`, `transport.tcp.blocking_server`,
and `http.tcp.blocking_server` settings are not recognized anymore.

The previously unused settings `transport.netty.max_cumulation_buffer_capacity`,
`transport.netty.max_composite_buffer_components` and
`http.netty.max_cumulation_buffer_capacity` have been removed.

==== Similarity settings

The `base` similarity is now ignored as coords and query normalization have
been removed. If provided, this setting will be ignored and issue a
deprecation warning.

==== Script Settings

All of the existing scripting security settings have been removed.  Instead
they are replaced with `script.allowed_types` and `script.allowed_contexts`.

==== Discovery Settings

The `discovery.type` settings no longer supports the values `gce`, `azure` and `ec2`.
Integration with these platforms should be done by setting the `discovery.zen.hosts_provider` setting to
one of those values.

==== Cross-cluster search settings renamed

The cross-cluster search remote cluster connection infrastructure is also used
in cross-cluster replication. This means that the setting names
`search.remote.*` used for configuring cross-cluster search belie the fact that
they also apply to other situations where a connection to a remote cluster as
used.  Therefore, these settings have been renamed from `search.remote.*` to
`cluster.remote.*`. For backwards compatibility purposes, we will fallback to
`search.remote.*` if `cluster.remote.*` is not set. For any such settings stored
in the cluster state, or set on dynamic settings updates, we will automatically
upgrade the setting from `search.remote.*` to `cluster.remote.*`. The fallback
settings will be removed in 8.0.0.


add missing documentation about SimpleUuidGenerator

[[UuidGenerator-UuidGenerator]]
= UuidGenerator

Starting with *Camel 2.5*, Camel supports 3rd party UUID generator(s).
This is useful, if e.g. your messaging provider does not support UUID's
with a length of 36 characters (like Websphere MQ). Another useful
scenario is to use a simple counter for testing purpose. With this it is
easier to correlate the exchanges in the log/debugger.

Camel uses UUIDs in the exchange and message ids, and other unique ids
it uses.

You only have to implement `org.apache.camel.spi.UuidGenerator` and tell
Camel, that it should use your custom implementation:

[[UuidGenerator-ConfiguringfromJavaDSL]]
== Configuring from Java DSL

[source,java]
----
getContext().setUuidGenerator(new MyCustomUuidGenerator());
----

Warning: You should not change the UUID generator at runtime (it should only be
set once)!

[[UuidGenerator-ConfiguringfromSpringDSL]]
== Configuring from XML DSL

Camel will configure this UUID generator by doing a lookup in the Spring
bean registry to find the bean of the type
`org.apache.camel.spi.UuidGenerator`.

[source,xml]
----
<bean id="simpleUuid" class="org.apache.camel.support.SimpleUuidGenerator" />

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start" />
    <to uri="mock:result" />
  </route>
</camelContext>
----

[[UuidGenerator-Providedimplementations]]
== Provided implementations

Camel comes with three implementations of
`org.apache.camel.spi.UuidGenerator`:

* `org.apache.camel.support.SimpleUuidGenerator` - This implementation uses
internally a `java.util.concurrent.atomic.AtomicLong` and increases the
ID for every call by one. Starting with 1 as the first id.
* `org.apache.camel.support.VanillaUuidGenerator` - This implementation uses
a random generated seed and a counter which increments by one. This generator
is not unique per host or JVM.
* `org.apache.camel.impl.engine.DefaultUuidGenerator` - This implementation
uses a fast unique UUID generation that is cluster safe (similar to uuid
generator in ActiveMQ). This is the default implementation in use by Camel.

[[UuidGenerator-UuidGenerator]]
= UuidGenerator

Starting with *Camel 2.5*, Camel supports 3rd party UUID generator(s).
This is useful, if e.g. your messaging provider does not support UUID's
with a length of 36 characters (like Websphere MQ). Another useful
scenario is to use a simple counter for testing purpose. With this it is
easier to correlate the exchanges in the log/debugger.

Camel uses UUIDs in the exchange and message ids, and other unique ids
it uses.

You only have to implement `org.apache.camel.spi.UuidGenerator` and tell
Camel, that it should use your custom implementation:

[[UuidGenerator-ConfiguringfromJavaDSL]]
== Configuring from Java DSL

[source,java]
----
getContext().setUuidGenerator(new MyCustomUuidGenerator());
----

Warning: You should not change the UUID generator at runtime (it should only be
set once)!

[[UuidGenerator-ConfiguringfromSpringDSL]]
== Configuring from XML DSL

Camel will configure this UUID generator by doing a lookup in the Spring
bean registry to find the bean of the type
`org.apache.camel.spi.UuidGenerator`.

[source,xml]
----
<bean id="simpleUuid" class="org.apache.camel.support.SimpleUuidGenerator" />

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
  <route>
    <from uri="direct:start" />
    <to uri="mock:result" />
  </route>
</camelContext>
----

[[UuidGenerator-Providedimplementations]]
== Provided implementations

Camel comes with two implementations of
`org.apache.camel.spi.UuidGenerator`:

* `org.apache.camel.support.SimpleUuidGenerator` - This implementation use
internally a `java.util.concurrent.atomic.AtomicLong` and increase the
ID for every call by one. Starting with 1 as the first id.
* `org.apache.camel.impl.engine.DefaultUuidGenerator` - This implementation
use a fast unique UUID generation that is cluster safe (similar to uuid generator in ActiveMQ)


small wording changes

small wording changes

= AWS China(Beijing) Region Tips
Keito Fukuda <keito.fukuda@fastretailing.com>
:toc:

Hi, there, my name is Keito Fukuda, a lead technical architect at Fast Retailing.
Today I would like to talk about AWS China(Beijing) region since it is very unique from other AWS regions and you may want to know the discrepancies in advance of you starting to use it without making some efforts to figure it out on your own.

== Fast Retailing
Let me start with a little bit talking about our company Fast Retailing as there are some chances that you hear very first time and have no idea about us.
We Fast Retailing is one of global leading apparel companies and a holding company which owns various global apparel brands underneath such as UNIQLO, GU, they are born in Japan but spreading out to global markets. Theory, JBrand, they are originally from US but both have global penetration and large number of funs all over the world. Last but not least, Comptoir des Cotonniers and Princesse tam tam, which are from France.
As we have global reachability, of course we aggressively take advantage of AWS and its global regions for our systems. We as of today utilize Tokyo, Singapore, Virginia, California, Sydney, Ireland, Frankfrut, then of course China(Beijing) regions to provide our services to our global customers as well as systems to our global employees. Especially China(Beijing) region is pretty important for us as it is our 2nd biggest market, besides there are some challenges due to some unique legal and infrastructure restrictions.

== Web Service to China
As described above, when we provide a web service in mainland China, there are some difficulties. I will quickly list up 2 significant challenges below and talk about them one by one in the following section.

. ICP Recordal/License
. Great Firewall

=== ICP Recordal/License
As you all may know, if you provide a web service in mainland China, it is necessary to acquire an ICP(Internet Content Provider) recordal or license from the China government. This recordal/license requires us to have a legal entity inside of China and go though required procedure. In addition, once you acquired it, you are supposed to put it at the bottom of all of your web pages.
We Fast Retailing do hold several ICP recordals for our brands to provide web contents in mainland China as you can see below.

[format="csv", options="header"]
.Fast Retailing ICP Recordal List
|===
Domain, Recordal No.
uniqlo.com, 沪ICP备09003223号-4
uniqlo.cn, 沪ICP备09003223号-1
gu-global.com, 沪ICP备13017798号-1
fastretailing.com, 沪ICP备09003223号-3
|===

image::http://fastretailing.github.io/blog/images/china_icp_footer.png

=== Great Firewall
This is another very well-known unique restriction in mainland China. You can find what it is and how it works in somewhere online(Please just google it or just jump to https://en.wikipedia.org/wiki/Great_Firewall[wikipedia]). But in a nutshell, all inbound/outbound traffics on HTTP(80)/HTTPs(443) are monitored and can be blocked at DNS level by China government.
Especially when traffic goes out of mainland China, it is monitored and makes traffic roundtrip extremely slow.
Even network traffic completes inside of China, it is still unstable especially if traffic goes beyond a boundary between North side dominated by China telecom and South side dominated by China Unicom. Because of these reasons, when you provide web contents from somewhere outside of mainland China, you need to pay attention on huge network latency in your system architecture design. This is the biggest reason which would make you want to have a completely independent infrastructure inside of mainland China to overcome network latency issue and be able to provide sufficient user experience to your China customers or employees.

= AWS China(Beijing) Region Uniqueness
Okay, then let me deep dive on what are the differences exactly from here. Because of the China unique restrictions described in the prior section, when you set up your web service in AWS China(Beijing) region, there are several consideration points you need to keep in mind. Here I will tell you each one of them which we have discovered so far through our operation in China(Beijing) region.

== Account
First of all, let me talk about AWS account. This is one of things which work in different way from all other AWS regions. In order to use China region, you need a completely independent account, which is dedicated only for China region and given only when you are authorized by AWS. Unlike global AWS account, you cannot create your account on the fly by yourself. You first need to submit your information https://www.amazonaws.cn/en/sign-up/[here], then have to wait to get it verified and authorized.

== Billing
Even if you have multi accounts, one of great features for billing which you can use in Global account is `Consolidated Billing`, which allows you to consolidate all billings associated with all your accounts and let you make a single payment at once. However unfortunately this does not cover AWS China account. Once you get a China account, you need to register your billing information separately from your Global account and it cannot be consolidated.

== Support Plan
Similar to billing, as we cannot consolidate our China account with any other Global accounts, even if you already subscribe https://aws.amazon.com/premiumsupport/[AWS support plan], that support can not be applied and cover your China account. If you need intensive support from AWS, you have to subscribe https://www.amazonaws.cn/en/support-plans/[another support plan] dedicated only for your China account.

== Service Availability
When it comes to AWS service coverage and availability. As of writing, 2015/08/20, there are plenty of services we can already use as listed below.
EC2, S3, StorageGateway, Glacier, VPC, Direct Connect, IAM, Trusted Advisor, CloudTrail, CloudWatch, DynamoDB, ElasticCache, RDS, CloudFormation, EMR, Kinesis, SNS, SQS, SWF
image::http://fastretailing.github.io/blog/images/china_service_list.png
We are really looking forward to Lambda support and API Gateway as we will be heavily relying on these 2 services down the road. I hope they will become available even in China region soon.
Another AWS service which everybody needs but is not available yet is `CloudFront`. As I said, even if you have your system up and running in mainland China, there would be still some network instability you and your system users might face. This would make you want to have CDN(Contents Delivery Network) between your users and your system inside of China. As `CloudFront` is not ready yet in China region, we Fast Retailing utilize both `Akamai` and `China Cache` as CDN in front of our systems.
For more details and the latest information, please refer to http://docs.amazonaws.cn/en_us/aws/latest/userguide/services.html[the official online document] maintained by AWS.

== ICP Recordal/License
As mentioned above, it is a regulation to acquire an ICP recordal/license whenever you provide web contents over HTTP(80)/HTTPs(443) in mainland China. This is the reason that even after you set up your web service on top of EC2, S3 or whatever, you still cannot access to your web service from the Internet. Very first time when we found that HTTP/HTTPs GET cannot be completed even after our system is completely ready, we really freaked out and had no idea what was happening...(yes, we should have read through all instructions upfront). You would get 403(Forbidden) response without your ICP license No. associated on your China account. In order to get this done, you can either reach out to your AWS counterpart to get a help on this or directly send an email to `Sinnet`, who is an IDC-licensed provider responsible for supporting and verifying ICP recordal/license for AWS customers, at `My Account` on your own to have them register it. This registration process and getting your ICP recordal/license verified would take around a week(in our case, 5 business days). Then you would finally get your web service all ready.
image::http://fastretailing.github.io/blog/images/china_icp_license.png

== MFA
Of course, protecting your account is one of very important thing you are also responsible for. In our case, we have a strict internal regulation to enable MFA(Multi Factor Authentication) to all AWS administrative accounts. In other word, we have been simply counting on MFA for all of our Global accounts. However, unfortunately MFA is not available yet in China account, which was actually huge surprise for us. We cannot simply rely on it like all other accounts to make your account secure. I guess only one thing we can do for now then is to make your administrative account password as complex as possible, and that is what we do as of today. We are now pushing AWS team really hard to get it ready. Let's wait without losing the hope.

== AMI
Do you share and reuse your AMI across accounts or regions? Unfortunately that is another restriction in China account. We Fast Retailing also heavily rely on AMI to make infra set-up as fast and efficient as possible. AMI is just awesome. Having said that, we are not allowed to copy an AMI taken in other global regions or your other accounts. So basically you need to set up your system from middleware setup to deploying your app codes all on your own at very first time. Once you set it up, you can take an AMI out of it and use it to spin up another instance you need.
In addition, as you can easily imagine, yes, you cannot take advantage of AWS Marketplace either. This would sometimes make huge implication to your setup operation.
As for Community AMI, there are some Community AMIs already available even in China region, but they are completely separated from Community AMIs under Global accounts. You would find only very limited AMIs there. So it is recommended to check availability of an Community AMI you would like to use in China account first.

== Auto-Recovery
We do generally set Auto-Recovery on EC2 instances, especially when our EC2 based system cannot be run together with multi-instances and it is really difficult to have high-availability. Auto-Recovery brings us huge help in minimizing down-time of your system without any manual operation on the fly in case your instance somehow goes down. However unfortunately, Auto-Recovery is not ready yet in China region.

== Admin Console
I hope you do not have any problem in reading English, then you are totally fine. However unlike Global accounts which support multi-languages in admin console. Admin console of China account is only in English and Simplified Chinese as of today. You can change the language in `Console Preferences`. This is another difference from Global account.
image::http://fastretailing.github.io/blog/images/china_admin_console.png

== Conclusion
Today, I touched on AWS China(Beijing) region and described all uniquenesses you should be aware of prior you start using it. As you saw above, there are many differences compared to all other global regions which you usually use. Some differences may be filled in the future, but there are still some differences even AWS cannot do anything on due to China legal regulation. I hope you were able to at least get a sense of idea how different it is and what you need to keep in mind.

= AWS China(Beijing) Region Tips
Keito Fukuda <keito.fukuda@fastretailing.com>
:toc:

Hi, there, my name is Keito Fukuda, a lead technical architect at Fast Retailing.
Today I would like to talk about AWS China(Beijing) region since it is very unique from other AWS regions and you may want to know the discrepancies in advance of you starting to use it without making some efforts to figure it out on your own.

== Fast Retailing
Let me start with a little bit talking about our company Fast Retailing as there are some chances that you hear very first time and have no idea about us.
We Fast Retailing is one of global leading apparel companies and a holding company which owns various global apparel brands underneath such as UNIQLO, GU, they are born in Japan but spreading out to global markets. Theory, JBrand, they are originally from US but both have global penetration and large number of funs all over the world. Last but not least, Comptoir des Cotonniers and Princesse tam tam, which are from France.
As we have global reachability, of course we aggressively take advantage of AWS and its global regions for our systems. We as of today utilize Tokyo, Singapore, Virginia, California, Sydney, Ireland, Frankfrut, then of course China(Beijing) regions to provide our services to our global customers as well as systems to our global employees. Especially China(Beijing) region is pretty important for us as it is our 2nd biggest market, besides there are some challenges due to some unique legal and infrastructure restrictions.

== Web Service to China
As described above, when we provide a web service in mainland China, there are some difficulties. I will quickly list up 2 significant challenges below and talk about them one by one in the following section.

. ICP Recordal/License
. Great Firewall

=== ICP Recordal/License
As you all may know, if you provide a web service in mainland China, it is necessary to acquire an ICP(Internet Content Provider) recordal or license from the China government. This recordal/license requires us to have a legal entity inside of China and go though required procedure. In addition, once you acquired it, you are supposed to put it at the bottom of all of your web pages.
We Fast Retailing do hold several ICP recordals for our brands to provide web contents in mainland China as you can see below.

[format="csv", options="header"]
.Fast Retailing ICP Recordal List
|===
Domain, Recordal No.
uniqlo.com, 沪ICP备09003223号-4
uniqlo.cn, 沪ICP备09003223号-1
gu-global.com, 沪ICP备13017798号-1
fastretailing.com, 沪ICP备09003223号-3
|===

image::http://fastretailing.github.io/blog/images/china_icp_footer.png

=== Great Firewall
This is another very well-known unique restriction in mainland China. You can find what it is and how it works in somewhere online(Please just google it or just jump to https://en.wikipedia.org/wiki/Great_Firewall[wikipedia]). But in a nutshell, all inbound/outbound traffics on HTTP(80)/HTTPs(443) are monitored and can be blocked at DNS level by China government.
Especially when traffic goes out of mainland China, it is monitored and makes traffic roundtrip extremely slow.
Even network traffic completes inside of China, it is still unstable especially if traffic goes beyond a boundary between North side dominated by China telecom and South side dominated by China Unicom. Because of these reasons, when you provide web contents from somewhere outside of mainland China, you need to pay attention on huge network latency in your system architecture design. This is the biggest reason which would make you want to have a completely independent infrastructure inside of mainland China to overcome network latency issue and be able to provide sufficient user experience to your China customers or employees.

= AWS China(Beijing) Region Uniqueness
Okay, then let me deep dive on what are the differences exactly from here. Because of the China unique restrictions described in the prior section, when you set up your web service in AWS China(Beijing) region, there are several consideration points you need to keep in mind. Here I will tell you each one of them which we have discovered so far through our operation in China(Beijing) region.

== Account
First of all, let me talk about AWS account. This is one of things which work in different way from all other AWS regions. In order to use China region, you need a completely independent account, which is dedicated only for China region and given only when you are authorized by AWS. Unlike global AWS account, you cannot create your account on the fly by yourself. You first need to submit your information https://www.amazonaws.cn/en/sign-up/[here], then have to wait to get it verified and authorized.

== Billing
Even if you have multi accounts, one of great features for billing which you can use in Global account is `Consolidated Billing`, which allows you to consolidate all billings associated with all your accounts and let you make a single payment at once. However unfortunately this does not cover AWS China account. Once you get a China account, you need to register your billing information separately from your Global account and it cannot be consolidated.

== Support Plan
Similar to billing, as we cannot consolidate our China account with any other Global accounts, even if you already subscribe https://aws.amazon.com/premiumsupport/[AWS support plan], that support can not be applied and cover your China account. If you need intensive support from AWS, you have to subscribe https://www.amazonaws.cn/en/support-plans/[another support plan] dedicated only for your China account.

== Service Availability
When it comes to AWS service coverage and availability. As of writing, 2015/08/20, there are plenty of services we can already use as listed below.
EC2, S3, StorageGateway, Glacier, VPC, Direct Connect, IAM, Trusted Advisor, CloudTrail, CloudWatch, DynamoDB, ElasticCache, RDS, CloudFormation, EMR, Kinesis, SNS, SQS, SWF
image::http://fastretailing.github.io/blog/images/china_service_list.png
We are really looking forward to Lambda support and API Gateway as we will be heavily relying on these 2 services down the road. I hope they will become available even in China region soon.
Another AWS service which everybody needs but is not available yet is `CloudFront`. As I said, even if you have your system up and running in mainland China, there would be still some network instability you and your system users might face. This would make you want to have CDN(Contents Delivery Network) between your users and your system inside of China. As `CloudFront` is not ready yet in China region, we Fast Retailing utilize both `Akamai` and `China Cache` as CDN in front of our systems.
For more details and the latest information, please refer to http://docs.amazonaws.cn/en_us/aws/latest/userguide/services.html[the official online document] maintained by AWS.

== ICP Recordal/License
As mentioned above, it is a regulation to acquire an ICP recordal/license whenever you provide web contents over HTTP(80)/HTTPs(443) in mainland China. This is the reason that even after you set up your web service on top of EC2, S3 or whatever, you still cannot access to your web service from the Internet. Very first time when we found that HTTP/HTTPs GET cannot be completed even after our system is completely ready, we really freaked out and had no idea what was happening...(yes, we should have read through all instructions upfront). You would get 403(Forbidden) response without your ICP license No. associated on your China account. In order to get this done, you can either reach out to your AWS counterpart to get a help on this or send an email to `Sinnet`, who is an IDC-licensed provider responsible for supporting and verifying ICP recordal/license for AWS customers, to have them register it on account setting page on your own. This registration process and getting your ICP recordal/license verified would take around a week(in our case, 5 business days). Then you would finally get your web service all ready.
image::http://fastretailing.github.io/blog/images/china_icp_license.png

== MFA
Of course, protecting your account is one of very important thing you are also responsible for. In our case, we have a strict internal regulation to enable MFA(Multi Factor Authentication) to all AWS administrative accounts. In other word, we have been simply counting on MFA for all of our Global accounts. However, unfortunately MFA is not available yet in China account, which was actually huge surprise for us. We cannot simply rely on it like all other accounts to make your account secure. I guess only one thing we can do for now then is to make your administrative account password as complex as possible, and that is what we do as of today. We are now pushing AWS team really hard to get it ready. Let's wait without losing the hope.

== AMI
Do you share and reuse your AMI across accounts or regions? Unfortunately that is another restriction in China account. We Fast Retailing also heavily rely on AMI to make infra set-up as fast and efficient as possible. AMI is just awesome. Having said that, we are not allowed to copy an AMI taken in other global regions or your other accounts. So basically you need to set up your system from middleware setup to deploying your app codes all on your own at very first time. Once you set it up, you can take an AMI out of it and use it to spin up another instance you need.
In addition, as you can easily imagine, yes, you cannot take advantage of AWS Marketplace either. This would sometimes make huge implication to your setup operation.
As for Community AMI, there are some Community AMIs already available even in China region, but they are completely separated from Community AMIs under Global accounts. You would find only very limited AMIs there. So it is recommended to check availability of an Community AMI you would like to use in China account first.

== Auto-Recovery
We do generally set Auto-Recovery on EC2 instances, especially when our EC2 based system cannot be run together with multi-instances and it is really difficult to have high-availability. Auto-Recovery brings us huge help in minimizing down-time of your system without any manual operation on the fly in case your instance somehow goes down. However unfortunately, Auto-Recovery is not ready yet in China region.

== Admin Console
I hope you do not have any problem in reading English, then you are totally fine. However unlike Global accounts which support multi-languages in admin console. Admin console of China account is only in English as of today. This is another difference from Global account.
image::http://fastretailing.github.io/blog/images/china_admin_console.png

== Conclusion
Today, I touched on AWS China(Beijing) region and described all uniquenesses you should be aware of prior you start using it. As you saw above, there are many differences compared to all other global regions which you usually use. Some differences may be filled in the future, but there are still some differences even AWS cannot do anything on due to China legal regulation. I hope you were able to at least get a sense of idea how different it is and what you need to keep in mind.