Skip to content

Commit 5bde734

Browse files
committed
Add some content to the Functions Framework README, explaining how to
write a function and how to run one with the Maven Plugin. PiperOrigin-RevId: 295150234
1 parent c532816 commit 5bde734

File tree

1 file changed

+251
-3
lines changed

1 file changed

+251
-3
lines changed

README.md

Lines changed: 251 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,253 @@
1-
# Functions Framework API for Java [![Build Status](https://travis-ci.org/GoogleCloudPlatform/functions-framework-java.svg?branch=master)](https://travis-ci.org/GoogleCloudPlatform/functions-framework-java)
1+
# Functions Framework for Java [![Build Status](https://travis-ci.org/GoogleCloudPlatform/functions-framework-java.svg?branch=master)](https://travis-ci.org/GoogleCloudPlatform/functions-framework-java)
22

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.
35

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

Comments
 (0)