You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@beam.apache.org by ke...@apache.org on 2022/04/20 17:01:30 UTC

[beam-starter-java] branch main updated: Initial commit (#1)

This is an automated email from the ASF dual-hosted git repository.

kenn pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/beam-starter-java.git


The following commit(s) were added to refs/heads/main by this push:
     new 4646249  Initial commit (#1)
4646249 is described below

commit 464624959c0cf14422b3ce17103ec37d06edef9c
Author: David Cavazos <dc...@google.com>
AuthorDate: Wed Apr 20 10:01:26 2022 -0700

    Initial commit (#1)
---
 .github/workflows/PULL_REQUEST_TEMPLATE.md |  12 +++
 .github/workflows/test.yaml                |  50 +++++++++
 .gitignore                                 |  21 ++++
 CONTRIBUTING.md                            |  69 ++++++++++++
 LICENSE                                    |  37 ++++++-
 NOTICE                                     |   5 +
 README.md                                  | 166 +++++++++++++++++++++++++++++
 build.gradle                               |  51 +++++++++
 build.sbt                                  |  29 +++++
 pom.xml                                    | 117 ++++++++++++++++++++
 project/plugins.sbt                        |  15 +++
 src/main/java/com/example/App.java         |  40 +++++++
 src/test/java/com/example/AppTest.java     |  20 ++++
 13 files changed, 631 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/PULL_REQUEST_TEMPLATE.md b/.github/workflows/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..82c36f8
--- /dev/null
+++ b/.github/workflows/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,12 @@
+**Please** add a meaningful description for your change here
+
+------------------------
+
+Thank you for your contribution! Follow this checklist to help us incorporate your contribution quickly and easily:
+
+ - [ ] I agree that my contributions are licensed with both [Apache ASL2](../../LICENSE-APACHE) and [MIT](../../LICENSE-MIT).
+ - [ ] [**Choose reviewer(s)**](https://beam.apache.org/contribute/#make-your-change) and mention them in a comment (`R: @username`).
+ - [ ] Format the pull request title like `[BEAM-XXX] Fixes bug in ApproximateQuantiles`, where you replace `BEAM-XXX` with the appropriate JIRA issue, if applicable. This will automatically link the pull request to the issue.
+ - [ ] If this contribution is large, please file an Apache [Individual Contributor License Agreement](https://www.apache.org/licenses/icla.pdf).
+
+See the [`CONTRIBUTING.md`](../../CONTRIBUTING.md) guide for more information.
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
new file mode 100644
index 0000000..b93db98
--- /dev/null
+++ b/.github/workflows/test.yaml
@@ -0,0 +1,50 @@
+# Copyright 2022 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+name: Test
+
+on: push
+
+jobs:
+  Gradle:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - uses: actions/setup-java@v2
+      with:
+        distribution: 'temurin'
+        java-version: '11'
+        cache: 'gradle'
+    - run: gradle assemble --info
+    - run: gradle test --info
+    - run: java -jar build/pipeline.jar --inputText="🎉"
+
+  sbt:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - uses: actions/setup-java@v2
+      with:
+        distribution: 'temurin'
+        java-version: '11'
+    - run: sbt -v 'Test / compile' assembly
+    - run: sbt -v test
+    - run: java -jar build/pipeline.jar --inputText="🎉"
+
+  Maven:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - uses: actions/setup-java@v2
+      with:
+        distribution: 'temurin'
+        java-version: '11'
+        cache: 'maven'
+    - run: mvn -DskipTests test-compile package
+    - run: mvn test
+    - run: java -jar target/beam-java-starter-1-jar-with-dependencies.jar --inputText="🎉"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2e5dcb3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+# Build directories
+build/
+target/
+
+# IDEs
+.classpath
+.project
+.settings/
+.vscode/
+
+# Gradle
+.gradle/
+bin/
+
+# sbt
+.bloop/
+.bsp/
+.metals/
+project/*
+!project/plugins.sbt
+.scalafmt.conf
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..f0c9006
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,69 @@
+# Contributing
+
+🎉🎊 Thanks for taking the time to contribute! 🎉🎊
+
+There are many ways to contribute, here are some.
+
+## Filing an issue
+
+If there's any issue you encounter or anything that needs to be fixed, feel free to [create JIRA issue](https://issues.apache.org/jira/secure/CreateIssue!default.jspa).
+
+## Contributing to this starter project
+
+If this is your first time contributing to a GitHub repo,
+we recommmend going through the
+[GitHub quickstart](https://docs.github.com/en/get-started/quickstart/hello-world).
+
+It's a good idea to discuss your plans with the Beam community through the dev@beam.apache.org mailing list before doing any changes.
+
+Here's a small overview of the process.
+
+1. [Fork the repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo).
+
+1. Clone the repo.
+
+    ```sh
+    export GITHUB_USERNAME="my-github-username"
+
+    git clone git@github.com:$GITHUB_USERNAME/beam-starter-java.git
+    ```
+
+1. Set the [upstream remote branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/configuring-a-remote-for-a-fork).
+
+    ```sh
+    cd beam-starter-java
+    git remote add upstream git@github.com:apache/beam-starter-java.git
+    ```
+
+1. Create and change to a new branch.
+
+    ```sh
+    git checkout -B my-branch-name
+    ```
+
+1. Modify the code! 😱
+
+1. Run the tests. For steps on how to run them see the [`README.md`](README.md).
+
+1. Commit and push your changes to your branch in `origin`.
+
+    ```sh
+    git commit -m "one line description of your changes"
+    git push
+    ```
+
+1. [Create a Pull Request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request).
+
+1. Add reviewers, and [address review comments](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests).
+
+1. Once it's approved, we can merge the Pull Request.
+
+For more information about proposing changes to a GitHub repository, see the
+[Propose changes](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches)
+page in the GitHub docs.
+
+## Contributing to Apache Beam
+
+For information on how to contribute to
+[Apache Beam](https://github.com/apache/beam), see to the
+[Contribution guide](https://beam.apache.org/contribute/).
diff --git a/LICENSE b/LICENSE
index 261eeb9..c7e6385 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,3 +1,38 @@
+This software is distributed under the terms of both the MIT license and the
+Apache License (Version 2.0).
+
+
+MIT license
+
+Copyright 2022 Google LLC
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+
+Apache 2 license
+
                                  Apache License
                            Version 2.0, January 2004
                         http://www.apache.org/licenses/
@@ -198,4 +233,4 @@
    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.
+   limitations under the License.
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..454af2e
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+Apache Beam
+Copyright [2022-] The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2aed355
--- /dev/null
+++ b/README.md
@@ -0,0 +1,166 @@
+# Apache Beam starter for Java
+
+If you want to clone this repository to start your own project,
+you can choose the license you prefer and feel free to delete anything related to the license you are dropping.
+
+## Before you begin
+
+Make sure you have a [Java](https://en.wikipedia.org/wiki/Java_%28programming_language%29) development environment ready.
+If you don't, an easy way to install it is with [`sdkman`](https://sdkman.io).
+
+> ℹī¸ Apache Beam currently only supports Java 8 (LTS) and Java 11 (LTS).
+>
+> ⚠ī¸ **[Java 8 ends its active support in March 2022](https://endoflife.date/java)**, so we recommend using Java 11 (LTS) until Java 17 (LTS) is supported.
+
+```sh
+# Install sdkman.
+curl -s "https://get.sdkman.io" | bash
+
+# Make sure you have Java 11 installed.
+sdk install java 11.0.12-tem
+```
+
+## Source file structure
+
+This is a very basic Apache Beam project to help you get started.
+
+There are only two source files:
+
+* [`src/main/java/com/example/App.java`](src/main/java/com/example/App.java): the application source file, containing the [`main` method](src/main/java/com/example/App.java). The _main class_ is `com.example.App`.
+* [`src/test/java/com/example/AppTest.java`](src/test/java/com/example/AppTest.java): tests for the `App.java` file.
+
+> ℹī¸ Most build tools expect all the Java source files to be under `src/main/java/` and tests to be under `src/test/java/` by default.
+
+### Option A: Gradle
+
+[Gradle](https://gradle.org) is a build tool focused on flexibility and performance.
+
+This is a build tool widely used by many projects.
+
+```sh
+sdk install gradle
+```
+
+A basic Gradle setup consists of a [`build.gradle`](build.gradle) file written in [Groovy](https://groovy-lang.org) or [Kotlin](https://kotlinlang.org).
+
+```sh
+# To do a simple run.
+gradle run
+
+# To run passing command line arguments.
+gradle run -Pargs=--inputText="🎉"
+
+# To run the tests.
+gradle test --info
+```
+
+To build a self-contained jar file, we need to configure the [`jar`](https://docs.gradle.org/current/dsl/org.gradle.api.tasks.bundling.Jar.html) task in the [`build.gradle`](build.gradle) file.
+
+```sh
+# Build a self-contained jar.
+gradle jar
+
+# Run the jar application.
+java -jar build/pipeline.jar --inputText="🎉"
+```
+
+### Option B: sbt
+
+[`sbt` (Scala Build Tool)](https://www.scala-sbt.org/index.html) is a type-safe build tool for Scala and Java projects.
+Since it's type-safe, most errors are caught before the build starts.
+
+This is probably the simplest option, but isn't as widely used as Gradle.
+
+```sh
+sdk install sbt
+```
+
+A basic `sbt` setup consists of a [`build.sbt`](build.sbt) file written in a Scala-based DSL, and optionally a [`project/plugins.sbt`](project/plugins.sbt) file.
+
+```sh
+# To do a simple run.
+sbt run
+
+# To run passing command line arguments.
+sbt 'run --inputText="🎉"'
+
+# To run the tests.
+sbt test
+```
+
+To build a self-contained jar file, we need to import [`sbt-assembly`](https://github.com/sbt/sbt-assembly) in the [`project/plugins.sbt`](project/plugins.sbt) file and configure it in the [`build.sbt`](build.sbt) file.
+
+```sh
+# Build a self-contained jar.
+sbt assembly
+
+# Run the jar application.
+java -jar build/pipeline.jar --inputText="🎉"
+```
+
+### Option C: Apache Maven _(not recommended)_
+
+[Apache Maven](http://maven.apache.org) is a project management and comprehension tool based on the concept of a project object model (POM).
+
+This is by far the trickiest to configure, but many older projects still use it.
+
+If you are starting a new project, we recommend using Gradle or `sbt` instead.
+
+> ℹī¸ If you have an existing Maven project, consider looking at a [Gradle vs Maven comparison](https://gradle.org/maven-vs-gradle), as well as Gradle's [Migrating builds from Apache Maven](https://docs.gradle.org/current/userguide/migrating_from_maven.html) guide.
+
+```sh
+sdk install maven
+```
+
+A basic Apache Maven setup consists of a [`pom.xml`](pom.xml) file written in [XML](https://www.w3schools.com/xml).
+
+To run the app through Maven, we need to configure [`exec-maven-plugin`](http://www.mojohaus.org/exec-maven-plugin) in the [`pom.xml`](pom.xml) file.
+
+```sh
+# To do a simple run.
+mvn compile exec:java
+
+# To run passing command line arguments.
+mvn compile exec:java -Dexec.args=--inputText="🎉"
+
+# To run the tests.
+mvn test
+```
+
+To build a self-contained jar file, we need to configure [`maven-assembly-plugin`](https://people.apache.org/~epunzalan/maven-assembly-plugin/index.html) in the [`pom.xml`](pom.xml) file.
+
+```sh
+# Build a self-contained jar.
+mvn package
+
+# Run the jar application.
+java -jar target/beam-java-starter-1-jar-with-dependencies.jar --inputText="🎉"
+```
+
+## GitHub Actions automated testing
+
+This project already comes with automated testing via [GitHub Actions](https://github.com/features/actions).
+
+To configure it, look at the [`.github/workflows/test.yaml`](.github/workflows/test.yaml) file.
+
+## Using other runners
+
+To keep this template small, it only includes the [Direct Runner](https://beam.apache.org/documentation/runners/direct/).
+
+For a comparison of what each runner currently supports, look at the [Beam Capability Matrix](https://beam.apache.org/documentation/runners/capability-matrix/).
+
+To add a new runner, visit the runner's page for instructions on how to include it.
+
+## Contributing
+
+Thank you for your interest in contributing!
+All contributions are welcome! 🎉🎊
+
+Please refer to the [`CONTRIBUTING.md`](CONTRIBUTING.md) file for more information.
+
+# License
+
+This software is distributed under the terms of both the MIT license and the
+Apache License (Version 2.0).
+
+See [LICENSE](LICENSE) for details.
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..a8bd176
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,51 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+plugins {
+    id 'application'
+}
+
+repositories {
+    mavenCentral()
+}
+
+application {
+    mainClass = 'com.example.App'
+}
+
+test {
+    // JUnit 5 testing integration.
+    useJUnitPlatform()
+}
+
+def beamVersion = '2.33.0'
+dependencies {
+    // App dependencies.
+    implementation "org.apache.beam:beam-sdks-java-core:${beamVersion}"
+    implementation "org.apache.beam:beam-runners-direct-java:${beamVersion}"
+    implementation "org.slf4j:slf4j-jdk14:1.7.32"
+
+    // Tests dependencies.
+    testImplementation "org.junit.jupiter:junit-jupiter:5.8.1"
+}
+
+// Package a self-contained jar file.
+jar {
+    baseName = 'pipeline'
+    destinationDirectory = file('build')
+    manifest {
+        attributes 'Main-Class': 'com.example.App'
+    }
+    exclude 'META-INF/*.SF'
+    exclude 'META-INF/*.DSA'
+    exclude 'META-INF/*.RSA'
+    duplicatesStrategy = DuplicatesStrategy.INCLUDE
+    from {
+        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
+    }
+}
diff --git a/build.sbt b/build.sbt
new file mode 100644
index 0000000..5e94af5
--- /dev/null
+++ b/build.sbt
@@ -0,0 +1,29 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mainClass := Some("com.example.App")
+
+val beamVersion = "2.33.0"
+libraryDependencies ++= Seq(
+  // App dependencies.
+  "org.apache.beam" % "beam-sdks-java-core" % beamVersion,
+  "org.apache.beam" % "beam-runners-direct-java" % beamVersion,
+  "org.slf4j" % "slf4j-jdk14" % "1.7.32",
+
+  // Test dependencies.
+  "net.aichler" % "jupiter-interface" % JupiterKeys.jupiterVersion.value % Test,
+  "org.junit.jupiter" % "junit-jupiter" % "5.8.1" % Test
+)
+
+// Package self-contained jar file.
+assembly / assemblyOutputPath := file("build/pipeline.jar")
+assembly / assemblyMergeStrategy := {
+  case PathList("META-INF")      => MergeStrategy.discard
+  case x if x.endsWith(".class") => MergeStrategy.first
+  case x                         => (assembly / assemblyMergeStrategy).value(x)
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..c0e15fe
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  Copyright 2022 Google LLC
+
+  Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+  https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+  <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+  option. This file may not be copied, modified, or distributed
+  except according to those terms.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" 
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>com.example</groupId>
+  <artifactId>beam-java-starter</artifactId>
+  <version>1</version>
+
+  <properties>
+    <maven.compiler.source>11</maven.compiler.source>
+    <maven.compiler.target>11</maven.compiler.target>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+
+    <beam.version>2.33.0</beam.version>
+    <junit.version>5.8.1</junit.version>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.8.1</version>
+      </plugin>
+
+      <!-- Run the app through mvn. -->
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>exec-maven-plugin</artifactId>
+        <version>3.0.0</version>
+        <configuration>
+          <mainClass>com.example.App</mainClass>
+          <cleanupDaemonThreads>false</cleanupDaemonThreads>
+        </configuration>
+      </plugin>
+
+      <!-- JUnit 5 testing integration. -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <version>3.0.0-M5</version>
+        <dependencies>
+          <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <version>${junit.version}</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+
+      <!-- Package self-contained jar file. -->
+      <plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>3.3.0</version>
+				<executions>
+				  <execution>
+					<phase>package</phase> 
+					<goals>
+						<goal>single</goal>
+					</goals>
+				  </execution>
+				</executions>
+				<configuration>
+					<archive>
+					  <manifest>
+              <mainClass>com.example.App</mainClass>
+					  </manifest>
+					</archive>
+					<descriptorRefs>
+						<descriptorRef>jar-with-dependencies</descriptorRef>
+					</descriptorRefs>
+				</configuration>
+			</plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <!-- App dependencies -->
+    <dependency>
+      <groupId>org.apache.beam</groupId>
+      <artifactId>beam-sdks-java-core</artifactId>
+      <version>${beam.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.beam</groupId>
+      <artifactId>beam-runners-direct-java</artifactId>
+      <version>${beam.version}</version>
+      <scope>runtime</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-jdk14</artifactId>
+      <version>1.7.32</version>
+    </dependency>
+
+    <!-- Test dependencies -->
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <version>${junit.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
diff --git a/project/plugins.sbt b/project/plugins.sbt
new file mode 100644
index 0000000..eb3a0d6
--- /dev/null
+++ b/project/plugins.sbt
@@ -0,0 +1,15 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+resolvers += Resolver.jcenterRepo
+
+// Assemble self-contained jar files.
+addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "1.1.0")
+
+// JUnit 5 testing integration.
+addSbtPlugin("net.aichler" % "sbt-jupiter-interface" % "0.9.0")
diff --git a/src/main/java/com/example/App.java b/src/main/java/com/example/App.java
new file mode 100644
index 0000000..20e7afe
--- /dev/null
+++ b/src/main/java/com/example/App.java
@@ -0,0 +1,40 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+package com.example;
+
+import org.apache.beam.sdk.Pipeline;
+import org.apache.beam.sdk.options.Default;
+import org.apache.beam.sdk.options.Description;
+import org.apache.beam.sdk.options.PipelineOptionsFactory;
+import org.apache.beam.sdk.options.StreamingOptions;
+import org.apache.beam.sdk.transforms.Create;
+import org.apache.beam.sdk.transforms.MapElements;
+import org.apache.beam.sdk.values.TypeDescriptors;
+
+public class App {
+	public interface Options extends StreamingOptions {
+		@Description("Input text to print.")
+		@Default.String("My input text")
+		String getInputText();
+
+		void setInputText(String value);
+	}
+
+	public static void main(String[] args) {
+		var options = PipelineOptionsFactory.fromArgs(args).withValidation().as(Options.class);
+
+		var pipeline = Pipeline.create(options);
+		pipeline.apply("Create elements", Create.of("Hello", "World!", options.getInputText())).apply("Print elements",
+				MapElements.into(TypeDescriptors.strings()).via(x -> {
+					System.out.println(x);
+					return x;
+				}));
+		pipeline.run();
+	}
+}
\ No newline at end of file
diff --git a/src/test/java/com/example/AppTest.java b/src/test/java/com/example/AppTest.java
new file mode 100644
index 0000000..c7a47e3
--- /dev/null
+++ b/src/test/java/com/example/AppTest.java
@@ -0,0 +1,20 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+package com.example;
+
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+
+public class AppTest {
+	@Test
+	public void appRuns() {
+		App.main(new String[] {});
+		assertEquals(1 + 1, 2);
+	}
+}