| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ad8ae9e commit 4d65354
9 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,62 @@ | |||
| 1 | + # App Engine Flexible Environment - Web Socket Example | ||
| 2 | + This sample demonstrates how to use [Websockets](https://tools.ietf.org/html/rfc6455) on [Google App Engine Flexible Environment](https://cloud.google.com/appengine/docs/flexible/java/) using Java. | ||
| 3 | + The sample uses the [native Jetty WebSocket Server API](http://www.eclipse.org/jetty/documentation/9.4.x/jetty-websocket-server-api.html) to create a server-side socket | ||
| 4 | + and the [native Jetty WebSocket Client API](http://www.eclipse.org/jetty/documentation/9.4.x/jetty-websocket-client-api.html). | ||
| 5 | + | ||
| 6 | + ## Sample application workflow | ||
| 7 | + | ||
| 8 | + 1. The sample application creates a server socket using the endpoint `/echo`. | ||
| 9 | + 1. The homepage (`/`) provides a form to submit a text message to the server socket. This creates a client-side socket | ||
| 10 | + and sends the message to the server. | ||
| 11 | + 1. The server on receiving the message, echoes the message back to the client. | ||
| 12 | + 1. The message received by the client is stored in an in-memory cache and is viewable on the homepage. | ||
| 13 | + | ||
| 14 | + The sample also provides a Javascript [client](src/main/webapp/js_client.jsp)(`/js_client.jsp`) that you can use to test against the Websocket server. | ||
| 15 | + | ||
| 16 | + ## Setup | ||
| 17 | + | ||
| 18 | + - [Install](https://cloud.google.com/sdk/) and initialize GCloud SDK. This will | ||
| 19 | + ``` | ||
| 20 | + gcloud init | ||
| 21 | + ``` | ||
| 22 | + - If this is your first time creating an app engine application | ||
| 23 | + ``` | ||
| 24 | + gcloud appengine create | ||
| 25 | + ``` | ||
| 26 | + | ||
| 27 | + ## Local testing | ||
| 28 | + | ||
| 29 | + Run using the [Jetty Maven plugin](http://www.eclipse.org/jetty/documentation/9.4.x/jetty-maven-plugin.html). | ||
| 30 | + ``` | ||
| 31 | + mvn jetty:run | ||
| 32 | + ``` | ||
| 33 | + You can then direct your browser to `http://localhost:8080/` | ||
| 34 | + | ||
| 35 | + To test the Javascript client, access `http://localhost:8080/js_client.jsp` | ||
| 36 | + | ||
| 37 | + ## App Engine Flex Deployment | ||
| 38 | + | ||
| 39 | + #### `app.yaml` Configuration | ||
| 40 | + | ||
| 41 | + App Engine Flex deployment configuration is provided in [app.yaml](src/main/appengine/app.yaml). | ||
| 42 | + | ||
| 43 | + Set the environment variable `JETTY_MODULES_ENABLE:websocket` to enable the Jetty websocket module on the Jetty server. | ||
| 44 | + | ||
| 45 | + Manual scaling is set to a single instance as we are using an in-memory cache of messages for this sample application. | ||
| 46 | + | ||
| 47 | + For more details on configuring your `app.yaml`, please refer to [this resource](https://cloud.google.com/appengine/docs/flexible/nodejs/configuring-your-app-with-app-yaml). | ||
| 48 | + | ||
| 49 | + #### Deploy | ||
| 50 | + | ||
| 51 | + The sample application is packaged as a war, and hence will be automatically run using the [Java 8/Jetty 9 with Servlet 3.1 Runtime](https://cloud.google.com/appengine/docs/flexible/java/dev-jetty9). | ||
| 52 | + | ||
| 53 | + ``` | ||
| 54 | + mvn appengine:deploy | ||
| 55 | + ``` | ||
| 56 | + You can then direct your browser to `https://YOUR_PROJECT_ID.appspot.com/` | ||
| 57 | + | ||
| 58 | + To test the Javascript client, access `https://YOUR_PROJECT_ID.appspot.com/js_client.jsp` | ||
| 59 | + | ||
| 60 | + Note: This application constructs a Web Socket URL using `getWebSocketAddress` | ||
| 61 | + in the [SendServlet Class](src/main/java/com/example/flexible/websocket/jettynative/SendServlet.java) | ||
| 62 | + . The application assumes the latest version of the service. | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,92 @@ | |||
| 1 | + <!-- | ||
| 2 | + Copyright 2018 Google LLC | ||
| 3 | + | ||
| 4 | + Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + you may not use this file except in compliance with the License. | ||
| 6 | + You may obtain a copy of the License at | ||
| 7 | + | ||
| 8 | + http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + | ||
| 10 | + Unless required by applicable law or agreed to in writing, software | ||
| 11 | + distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + See the License for the specific language governing permissions and | ||
| 14 | + limitations under the License. | ||
| 15 | + --> | ||
| 16 | + <project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| 17 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| 18 | + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| 19 | + <modelVersion>4.0.0</modelVersion> | ||
| 20 | + | ||
| 21 | + <groupId>org.eclipse.jetty.demo</groupId> | ||
| 22 | + <artifactId>native-jetty-websocket-example</artifactId> | ||
| 23 | + <version>1.0-SNAPSHOT</version> | ||
| 24 | + <packaging>war</packaging> | ||
| 25 | + | ||
| 26 | + <!-- | ||
| 27 | + The parent pom defines common style checks and testing strategies for our samples. | ||
| 28 | + Removing or replacing it should not effect the execution of the samples in anyway. | ||
| 29 | + --> | ||
| 30 | + <parent> | ||
| 31 | + <groupId>com.google.cloud.samples</groupId> | ||
| 32 | + <artifactId>shared-configuration</artifactId> | ||
| 33 | + <version>1.0.10</version> | ||
| 34 | + </parent> | ||
| 35 | + | ||
| 36 | + <properties> | ||
| 37 | + <maven.compiler.target>1.8</maven.compiler.target> | ||
| 38 | + <maven.compiler.source>1.8</maven.compiler.source> | ||
| 39 | + <failOnMissingWebXml>false</failOnMissingWebXml> <!-- REQUIRED --> | ||
| 40 | + <appengine.maven.plugin>1.3.1</appengine.maven.plugin> | ||
| 41 | + <jetty.version>9.4.4.v20170414</jetty.version> | ||
| 42 | + </properties> | ||
| 43 | + | ||
| 44 | + <dependencies> | ||
| 45 | + <dependency> | ||
| 46 | + <groupId>javax.servlet</groupId> | ||
| 47 | + <artifactId>javax.servlet-api</artifactId> | ||
| 48 | + <version>3.1.0</version> | ||
| 49 | + <type>jar</type> | ||
| 50 | + <scope>provided</scope> | ||
| 51 | + </dependency> | ||
| 52 | + <!-- To run websockets client --> | ||
| 53 | + <dependency> | ||
| 54 | + <groupId>org.eclipse.jetty.websocket</groupId> | ||
| 55 | + <artifactId>websocket-client</artifactId> | ||
| 56 | + <version>${jetty.version}</version> | ||
| 57 | + </dependency> | ||
| 58 | + <dependency> | ||
| 59 | + <groupId>org.eclipse.jetty.websocket</groupId> | ||
| 60 | + <artifactId>websocket-servlet</artifactId> | ||
| 61 | + <version>${jetty.version}</version> | ||
| 62 | + <scope>provided</scope> | ||
| 63 | + </dependency> | ||
| 64 | + <dependency> | ||
| 65 | + <groupId>com.google.guava</groupId> | ||
| 66 | + <artifactId>guava</artifactId> | ||
| 67 | + <version>23.0</version> | ||
| 68 | + </dependency> | ||
| 69 | + </dependencies> | ||
| 70 | + | ||
| 71 | + <build> | ||
| 72 | + <!-- for hot reload of the web application --> | ||
| 73 | + <outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes | ||
| 74 | + </outputDirectory> | ||
| 75 | + <plugins> | ||
| 76 | + <!-- for deployment of web application --> | ||
| 77 | + <plugin> | ||
| 78 | + <groupId>com.google.cloud.tools</groupId> | ||
| 79 | + <artifactId>appengine-maven-plugin</artifactId> | ||
| 80 | + <version>${appengine.maven.plugin}</version> | ||
| 81 | + <configuration> | ||
| 82 | + </configuration> | ||
| 83 | + </plugin> | ||
| 84 | + <!-- for local testing of web application --> | ||
| 85 | + <plugin> | ||
| 86 | + <groupId>org.eclipse.jetty</groupId> | ||
| 87 | + <artifactId>jetty-maven-plugin</artifactId> | ||
| 88 | + <version>${jetty.version}</version> | ||
| 89 | + </plugin> | ||
| 90 | + </plugins> | ||
| 91 | + </build> | ||
| 92 | + </project> | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,33 @@ | |||
| 1 | + # Copyright 2018 Google LLC | ||
| 2 | + # | ||
| 3 | + # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 4 | + # you may not use this file except in compliance with the License. | ||
| 5 | + # You may obtain a copy of the License at | ||
| 6 | + # | ||
| 7 | + # http://www.apache.org/licenses/LICENSE-2.0 | ||
| 8 | + # | ||
| 9 | + # Unless required by applicable law or agreed to in writing, software | ||
| 10 | + # distributed under the License is distributed on an "AS IS" BASIS, | ||
| 11 | + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 12 | + # See the License for the specific language governing permissions and | ||
| 13 | + # limitations under the License. | ||
| 14 | + | ||
| 15 | + runtime: java | ||
| 16 | + env: flex | ||
| 17 | + manual_scaling: | ||
| 18 | + instances: 1 | ||
| 19 | + | ||
| 20 | + handlers: | ||
| 21 | + - url: /.* | ||
| 22 | + script: this field is required, but ignored | ||
| 23 | + | ||
| 24 | + env_variables: | ||
| 25 | + JETTY_MODULES_ENABLE: websocket | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + # For applications which can take advantage of session affinity | ||
| 29 | + # (where the load balancer will attempt to route multiple connections from | ||
| 30 | + # the same user to the same App Engine instance), uncomment the folowing: | ||
| 31 | + | ||
| 32 | + # network: | ||
| 33 | + # session_affinity: true | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,62 @@ | |||
| 1 | + /* | ||
| 2 | + * Copyright 2018 Google LLC | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | + package com.example.flexible.websocket.jettynative; | ||
| 18 | + | ||
| 19 | + import java.util.Collection; | ||
| 20 | + import java.util.Collections; | ||
| 21 | + import java.util.concurrent.ConcurrentLinkedDeque; | ||
| 22 | + import java.util.logging.Logger; | ||
| 23 | + import org.eclipse.jetty.websocket.api.Session; | ||
| 24 | + import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; | ||
| 25 | + import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; | ||
| 26 | + import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; | ||
| 27 | + import org.eclipse.jetty.websocket.api.annotations.WebSocket; | ||
| 28 | + | ||
| 29 | + /** | ||
| 30 | + * Basic Echo Client Socket. | ||
| 31 | + */ | ||
| 32 | + @WebSocket(maxTextMessageSize = 64 * 1024) | ||
| 33 | + public class ClientSocket { | ||
| 34 | + private Logger logger = Logger.getLogger(ClientSocket.class.getName()); | ||
| 35 | + private Session session; | ||
| 36 | + // stores the messages in-memory. | ||
| 37 | + // Note : this is currently an in-memory store for demonstration, | ||
| 38 | + // not recommended for production use-cases. | ||
| 39 | + private static Collection<String> messages = new ConcurrentLinkedDeque<>(); | ||
| 40 | + | ||
| 41 | + @OnWebSocketClose | ||
| 42 | + public void onClose(int statusCode, String reason) { | ||
| 43 | + logger.fine("Connection closed: " + statusCode + ":" + reason); | ||
| 44 | + this.session = null; | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + @OnWebSocketConnect | ||
| 48 | + public void onConnect(Session session) { | ||
| 49 | + this.session = session; | ||
| 50 | + } | ||
| 51 | + | ||
| 52 | + @OnWebSocketMessage | ||
| 53 | + public void onMessage(String msg) { | ||
| 54 | + logger.fine("Message Received : " + msg); | ||
| 55 | + messages.add(msg); | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + // Retrieve all received messages. | ||
| 59 | + public static Collection<String> getReceivedMessages() { | ||
| 60 | + return Collections.unmodifiableCollection(messages); | ||
| 61 | + } | ||
| 62 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,33 @@ | |||
| 1 | + /* | ||
| 2 | + * Copyright 2018 Google LLC | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | + package com.example.flexible.websocket.jettynative; | ||
| 18 | + | ||
| 19 | + import javax.servlet.annotation.WebServlet; | ||
| 20 | + import org.eclipse.jetty.websocket.servlet.WebSocketServlet; | ||
| 21 | + import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; | ||
| 22 | + | ||
| 23 | + /* | ||
| 24 | + * Server-side WebSocket registered as /echo servlet. | ||
| 25 | + */ | ||
| 26 | + @SuppressWarnings("serial") | ||
| 27 | + @WebServlet(name = "Echo WebSocket Servlet", urlPatterns = { "/echo" }) | ||
| 28 | + public class EchoServlet extends WebSocketServlet { | ||
| 29 | + @Override | ||
| 30 | + public void configure(WebSocketServletFactory factory) { | ||
| 31 | + factory.register(ServerSocket.class); | ||
| 32 | + } | ||
| 33 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments