|
1 | | -# Functions Framework API for Java [](https://travis-ci.org/GoogleCloudPlatform/functions-framework-java) |
| 1 | +# Functions Framework for Java [](https://travis-ci.org/GoogleCloudPlatform/functions-framework-java) |
2 | 2 |
|
| 3 | +An open source FaaS (Function as a service) framework for writing portable |
| 4 | +Java functions -- brought to you by the Google Cloud Functions team. |
3 | 5 |
|
4 | | -**This is a placeholder for the Functions Framework for Java. Stay tuned for |
5 | | -updates.** |
| 6 | +The Functions Framework lets you write lightweight functions that run in many |
| 7 | +different environments, including: |
| 8 | + |
| 9 | +* [Google Cloud Functions](https://cloud.google.com/functions/) |
| 10 | +* Your local development machine |
| 11 | +* [Cloud Run and Cloud Run on GKE](https://cloud.google.com/run/) |
| 12 | +* [Knative](https://github.com/knative/)-based environments |
| 13 | + |
| 14 | +## Installation |
| 15 | + |
| 16 | +The Functions Framework for Java requires |
| 17 | +[Java](https://java.com/en/download/help/download_options.xml) and |
| 18 | +[Maven](http://maven.apache.org/install.html) (the `mvn` command). |
| 19 | + |
| 20 | +## Quickstart: Hello, World on your local machine |
| 21 | + |
| 22 | +A function is typically structured as a Maven project. We recommend using an IDE |
| 23 | +that supports Maven to create the Maven project. Add this dependency in the |
| 24 | +`pom.xml` file of your project: |
| 25 | + |
| 26 | +```xml |
| 27 | + <dependency> |
| 28 | + <groupId>com.google.cloud.functions</groupId> |
| 29 | + <artifactId>functions-framework-api</artifactId> |
| 30 | + <version>1.0.0-alpha-2-rc3</version> |
| 31 | + <scope>provided</scope> |
| 32 | + </dependency> |
| 33 | +``` |
| 34 | + |
| 35 | +### Writing an HTTP function |
| 36 | + |
| 37 | +Create a file `src/main/java/com/example/HelloWorld.java` with the following |
| 38 | +contents: |
| 39 | + |
| 40 | +```java |
| 41 | +package com.example; |
| 42 | + |
| 43 | +import com.google.cloud.functions.HttpFunction; |
| 44 | +import com.google.cloud.functions.HttpRequest; |
| 45 | +import com.google.cloud.functions.HttpResponse; |
| 46 | + |
| 47 | +public class HelloWorld implements HttpFunction { |
| 48 | + @Override |
| 49 | + public void service(HttpRequest request, HttpResponse response) |
| 50 | + throws Exception { |
| 51 | + response.getWriter().write("Hello, World\n"); |
| 52 | + } |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | + |
| 57 | +## Quickstart: Create a Background Function |
| 58 | + |
| 59 | +There are two ways to write a Background function, which differ in how the |
| 60 | +payload of the incoming event is represented. In a "raw" background function |
| 61 | +this payload is presented as a JSON-encoded Java string. In a "typed" background |
| 62 | +function the Functions Framework deserializes the JSON payload into a Plain Old |
| 63 | +Java Object (POJO). |
| 64 | + |
| 65 | +### Writing a Raw Background Function |
| 66 | + |
| 67 | +Create a file `src/main/java/com/example/Background.java` with the following |
| 68 | +contents: |
| 69 | + |
| 70 | +```java |
| 71 | +package com.example; |
| 72 | + |
| 73 | +import com.google.cloud.functions.Context; |
| 74 | +import com.google.cloud.functions.RawBackgroundFunction; |
| 75 | +import com.google.gson.Gson; |
| 76 | +import com.google.gson.JsonObject; |
| 77 | +import java.util.logging.Logger; |
| 78 | + |
| 79 | +public class Background implements RawBackgroundFunction { |
| 80 | + private static final Logger logger = |
| 81 | + Logger.getLogger(Background.class.getName()); |
| 82 | + |
| 83 | + @Override |
| 84 | + public void accept(String json, Context context) { |
| 85 | + Gson gson = new Gson(); |
| 86 | + JsonObject jsonObject = gson.fromJson(json, JsonObject.class); |
| 87 | + logger.info("Received JSON object: " + jsonObject); |
| 88 | + } |
| 89 | +} |
| 90 | +``` |
| 91 | + |
| 92 | +### Writing a Typed Background Function |
| 93 | + |
| 94 | +Create a file `src/main/java/com/example/PubSubBackground` with the following |
| 95 | +contents: |
| 96 | + |
| 97 | +```java |
| 98 | +package com.example; |
| 99 | + |
| 100 | +import com.example.PubSubBackground.PubSubMessage; |
| 101 | +import com.google.cloud.functions.BackgroundFunction; |
| 102 | +import com.google.cloud.functions.Context; |
| 103 | +import java.util.Map; |
| 104 | +import java.util.logging.Logger; |
| 105 | + |
| 106 | +public class PubSubBackground implements BackgroundFunction<PubSubMessage> { |
| 107 | + private static final Logger logger = |
| 108 | + Logger.getLogger(PubSubBackground.class.getName()); |
| 109 | + |
| 110 | + @Override |
| 111 | + public void accept(PubSubMessage pubSubMessage, Context context) { |
| 112 | + logger.info("Received message with id " + pubSubMessage.messageId); |
| 113 | + } |
| 114 | + |
| 115 | + public static class PubSubMessage { |
| 116 | + public String data; |
| 117 | + public Map<String, String> attributes; |
| 118 | + public String messageId; |
| 119 | + public String publishTime; |
| 120 | + } |
| 121 | +} |
| 122 | +``` |
| 123 | + |
| 124 | + |
| 125 | +## Running a function with the Maven plugin |
| 126 | + |
| 127 | +The Maven plugin called `function-maven-plugin` allows you to run functions |
| 128 | +on your development machine. |
| 129 | + |
| 130 | +### Configuration in `pom.xml` |
| 131 | + |
| 132 | +You can configure the plugin in `pom.xml`: |
| 133 | + |
| 134 | +```xml |
| 135 | +<plugin> |
| 136 | + <groupId>com.google.cloud.functions</groupId> |
| 137 | + <artifactId>function-maven-plugin</artifactId> |
| 138 | + <version>0.9</version> |
| 139 | + <configuration> |
| 140 | + <functionTarget>com.example.function.Echo</functionTarget> |
| 141 | + </configuration> |
| 142 | +</plugin> |
| 143 | +``` |
| 144 | + |
| 145 | +Then run it from the command line: |
| 146 | + |
| 147 | +```sh |
| 148 | +mvn function:run |
| 149 | +``` |
| 150 | + |
| 151 | +### Configuration on the command line |
| 152 | + |
| 153 | +You can alternatively configure the plugin with properties on the command line: |
| 154 | + |
| 155 | +```sh |
| 156 | + mvn com.google.cloud.functions:function:0.9:run \ |
| 157 | + -Drun.functionTarget=com.example.function.Echo |
| 158 | +``` |
| 159 | + |
| 160 | +### Running the Functions Framework directly |
| 161 | + |
| 162 | +You can also run a function by using the Functions Framework jar directly. |
| 163 | +Copy the Functions Framework jar to a local location like this: |
| 164 | + |
| 165 | +```sh |
| 166 | +mvn dependency:copy \ |
| 167 | + -Dartifact='com.google.cloud.functions.invoker:java-function-invoker:1.0.0-alpha-2-rc3' \ |
| 168 | + -DoutputDirectory=. |
| 169 | +``` |
| 170 | + |
| 171 | +In this example we use the current directory `.` but you can specify any other |
| 172 | +directory to copy to. Then run your function: |
| 173 | + |
| 174 | +```sh |
| 175 | +java -jar java-function-invoker-1.0.0-alpha-2-rc3.jar \ |
| 176 | + --classpath myfunction.jar \ |
| 177 | + --target com.example.HelloWorld |
| 178 | +``` |
| 179 | + |
| 180 | + |
| 181 | +## Functions Framework configuration |
| 182 | + |
| 183 | +There are a number of options that can be used to configure the Functions |
| 184 | +Framework, whether run directly or on the command line. This table summarizes |
| 185 | +them, and the following sections explain them in detail. |
| 186 | + |
| 187 | +| Command-line | `pom.xml` | Maven system property | |
| 188 | +|---------------|--------------------|-----------------------| |
| 189 | +| `--target` | `<functionTarget>` | `run.functionTarget` | |
| 190 | +| `--port` | `<port>` | `run.port` | |
| 191 | +| `--classpath` | - | - | |
| 192 | + |
| 193 | +### Which function to run |
| 194 | + |
| 195 | +A function is a Java class. You must specify the name of that class when running |
| 196 | +the Functions Framework: |
| 197 | + |
| 198 | +``` |
| 199 | +--target com.example.HelloWorld |
| 200 | +<functionTarget>com.example.HelloWorld</functionTarget> |
| 201 | +-Drun.functionTarget=com.example.HelloWorld |
| 202 | +``` |
| 203 | + |
| 204 | +### Which port to listen on |
| 205 | + |
| 206 | +The Functions Framework is an HTTP server that directs incoming HTTP requests to |
| 207 | +the function code. By default this server listens on port 8080. Specify an |
| 208 | +alternative value like this: |
| 209 | + |
| 210 | +``` |
| 211 | +--port 12345 |
| 212 | +<port>12345</port> |
| 213 | +-Drun.port=12345 |
| 214 | +``` |
| 215 | + |
| 216 | +### Function classpath |
| 217 | + |
| 218 | +Function code runs with a classpath that includes the function code itself and |
| 219 | +its dependencies. The Maven plugin automatically computes the classpath based |
| 220 | +on the dependencies expressed in `pom.xml`. When invoking the Functions |
| 221 | +Framework directly, you must use `--classpath` to indicate how to find the code |
| 222 | +and its dependencies. For example: |
| 223 | + |
| 224 | +``` |
| 225 | +java -jar java-function-invoker-1.0.0-alpha-2-rc3.jar \ |
| 226 | + --classpath 'myfunction.jar:/some/directory:/some/library/*' \ |
| 227 | + --target com.example.HelloWorld |
| 228 | +``` |
| 229 | + |
| 230 | +The `--classpath` option works like |
| 231 | +[`java -classpath`](https://docs.oracle.com/en/java/javase/13/docs/specs/man/java.html#standard-options-for-java). |
| 232 | +It is a list of entries separated by `:` (`;` on Windows), where each entry is: |
| 233 | + |
| 234 | +* a directory, in which case class `com.example.Foo` is looked for in a file |
| 235 | + `com/example/Foo.class` under that directory; |
| 236 | +* a jar file, in which case class `com.example.Foo` is looked for in a file |
| 237 | + `com/example/Foo.class` in that jar file; |
| 238 | +* a directory followed by `/*` (`\*` on Windows), in which case each jar file |
| 239 | + in that directory (file called `foo.jar`) is treated the same way as if it |
| 240 | + had been named explicitly. |
| 241 | + |
| 242 | +#### Simplifying the claspath |
| 243 | + |
| 244 | +Specifying the right classpath can be tricky. A simpler alternative is to |
| 245 | +build the function as a "fat jar", where the function code and all its |
| 246 | +dependencies are in a single jar file. Then `--classpath myfatfunction.jar` |
| 247 | +is enough. An example of how this is done is the Functions Framework jar itself, |
| 248 | +as seen |
| 249 | +[here](https://github.com/GoogleCloudPlatform/functions-framework-java/blob/b627f28/invoker/core/pom.xml#L153). |
| 250 | + |
| 251 | +Alternatively, you can arrange for your jar to have its own classpath, as |
| 252 | +described |
| 253 | +[here](https://maven.apache.org/shared/maven-archiver/examples/classpath.html). |
0 commit comments