-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue 188 #123
Issue 188 #123
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
|
||
# Example Web App Jetty9 image and GCload data store for session | ||
|
||
This web app demonstrates using the pure jetty9 image configured to use gcloud datastore for sessions. | ||
|
||
|
||
## Initial Setup ## | ||
|
||
First, complete the following steps: | ||
|
||
- [Create your project](https://developers.google.com/appengine/docs/managed-vms/) and have it enabled for Managed VMs. | ||
- Obtain an app key for the Google Places WebService API. | ||
- Download and install [the Beta build of the Google Cloud SDK](https://developers.google.com/cloud/sdk/#Quick_Start). | ||
- Install the Cloud SDK `app-engine-java` component. | ||
- Authenticate wth the gcloud SDK: gcloud auth login. | ||
- Install [Maven](http://maven.apache.org/download.cgi) if you haven't already. | ||
|
||
|
||
|
||
## Providing your Google Places API key ## | ||
|
||
You will need to edit the pom.xml file and replace YOUR_PLACES_APP_KEY with the value of your key: | ||
|
||
<places.appkey>YOUR_PLACES_APP_KEY</places.appkey> | ||
|
||
You then have several options of how to run it: | ||
|
||
## Running locally without the AppEngine environment ## | ||
|
||
The application does not use any AppEngine specific services, so you can run it simply on your local machine by doing: | ||
|
||
mvn jetty:run | ||
|
||
Go to http://localhost:8080 to see the webapp. | ||
|
||
|
||
## Deploying to the cloud as an AppEngine ManagedVM ## | ||
|
||
To automatically stage and deploy the webapp to your project in the cloud do: | ||
|
||
mvn gcloud:deploy | ||
|
||
See here for more information on the [GCloud Maven Plugin](https://github.com/GoogleCloudPlatform/gcloud-maven-plugin). | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
~ Copyright (c) 2013 Google Inc. All Rights Reserved. | ||
~ | ||
~ Licensed under the Apache License, Version 2.0 (the "License"); you | ||
~ may not use this file except in compliance with the License. You may | ||
~ obtain a copy of the License at | ||
~ | ||
~ http://www.apache.org/licenses/LICENSE-2.0 | ||
~ | ||
~ Unless required by applicable law or agreed to in writing, software | ||
~ 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. | ||
--> | ||
|
||
<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> | ||
<packaging>war</packaging> | ||
<version>1.0-SNAPSHOT</version> | ||
|
||
<groupId>com.google.appengine.demos</groupId> | ||
<artifactId>jetty9-gcloud-session</artifactId> | ||
|
||
<properties> | ||
<appengine.target.version>1.9.30</appengine.target.version> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
</properties> | ||
|
||
<dependencies> | ||
<!-- Compile/runtime dependencies --> | ||
<dependency> | ||
<groupId>com.google.appengine</groupId> | ||
<artifactId>appengine-api-1.0-sdk</artifactId> | ||
<version>${appengine.target.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>javax.servlet</groupId> | ||
<artifactId>javax.servlet-api</artifactId> | ||
<version>3.1.0</version> | ||
<type>jar</type> | ||
<scope>provided</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<resources> | ||
<resource> | ||
<targetPath>${project.build.directory}/appengine-staging/jetty-base</targetPath> | ||
<filtering>false</filtering> | ||
<directory>${basedir}/src/main/jetty-base</directory> | ||
<includes> | ||
<include>**</include> | ||
</includes> | ||
</resource> | ||
</resources> | ||
|
||
<!-- needed for enabling compile/reload on save in mordern IDEs...--> | ||
<outputDirectory>target/${project.artifactId}-${project.version}/WEB-INF/classes</outputDirectory> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<version>2.5.1</version> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<configuration> | ||
<source>1.8</source> | ||
<target>1.8</target> | ||
</configuration> | ||
</plugin> | ||
|
||
<plugin> | ||
<groupId>com.google.appengine</groupId> | ||
<artifactId>gcloud-maven-plugin</artifactId> | ||
<version>2.0.9.90.v20151210</version> | ||
<configuration> | ||
<gcloud_directory>/usr/local/google-cloud-sdk</gcloud_directory> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
|
||
</project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
FROM gcr.io/google_appengine/jetty9 | ||
ADD jetty9-gcloud-session-1.0-SNAPSHOT.war $JETTY_BASE/webapps/root.war | ||
ADD jetty-base $JETTY_BASE/ | ||
WORKDIR $JETTY_BASE | ||
RUN java -jar $JETTY_HOME/start.jar --approve-all-licenses --add-to-startd=gcloud-sessions \ | ||
&& chown -R jetty:jetty $JETTY_BASE | ||
RUN ls -lR |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
runtime: custom | ||
vm: true | ||
manual_scaling: | ||
instances: 2 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package com.google.appengine.demos; | ||
|
||
import java.io.IOException; | ||
import java.io.PrintWriter; | ||
import java.util.Collections; | ||
import java.util.Enumeration; | ||
import java.util.Map; | ||
|
||
import javax.servlet.ServletException; | ||
import javax.servlet.http.HttpServlet; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
import javax.servlet.http.HttpSession; | ||
|
||
@SuppressWarnings("serial") | ||
public class DumpServlet extends HttpServlet | ||
{ | ||
@Override | ||
protected void doGet( HttpServletRequest request, | ||
HttpServletResponse response ) throws ServletException, | ||
IOException | ||
{ | ||
response.setContentType("text/html"); | ||
response.setStatus(HttpServletResponse.SC_OK); | ||
|
||
PrintWriter out = response.getWriter(); | ||
|
||
out.printf("<h1>DumpServlet on instance %s</h1>%n",System.getenv("GAE_MODULE_INSTANCE")); | ||
|
||
out.println("<h2>Session:</h2>"); | ||
out.println("<pre>"); | ||
HttpSession session = request.getSession(true); | ||
if (session != null) { | ||
for (Enumeration<String> e = request.getParameterNames(); e.hasMoreElements();) { | ||
String n = e.nextElement(); | ||
session.setAttribute(n, request.getParameter(n)); | ||
} | ||
out.printf("s.id()=%s%n", session.getId()); | ||
out.printf("s.new()=%b%n", session.isNew()); | ||
out.printf("s.last()=%b%n", session.getLastAccessedTime()); | ||
for (Enumeration<String> e = session.getAttributeNames(); e.hasMoreElements();) { | ||
String n = e.nextElement(); | ||
out.printf("%s=%s%n", n, session.getAttribute(n)); | ||
} | ||
} | ||
out.println("</pre>"); | ||
|
||
out.println("<h2>Context Fields:</h2>"); | ||
out.println("<pre>"); | ||
out.printf("serverInfo=%s%n",getServletContext().getServerInfo()); | ||
out.printf("getServletContextName=%s%n",getServletContext().getServletContextName()); | ||
out.printf("virtualServerName=%s%n",getServletContext().getVirtualServerName()); | ||
out.printf("contextPath=%s%n",getServletContext().getContextPath()); | ||
out.printf("version=%d.%d%n",getServletContext().getMajorVersion(),getServletContext().getMinorVersion()); | ||
out.printf("effectiveVersion=%d.%d%n",getServletContext().getEffectiveMajorVersion(),getServletContext().getEffectiveMinorVersion()); | ||
out.println("</pre>"); | ||
|
||
out.println("<h2>Request Methods:</h2>"); | ||
out.println("<pre>"); | ||
out.printf("remoteHost/Addr:port=%s/%s:%d%n",request.getRemoteHost(),request.getRemoteAddr(),request.getRemotePort()); | ||
out.printf("localName/Addr:port=%s/%s:%d%n",request.getLocalName(),request.getLocalAddr(),request.getLocalPort()); | ||
out.printf("scheme=%s method=%s protocol=%s%n",request.getScheme(), request.getMethod(), request.getProtocol()); | ||
out.printf("serverName:serverPort=%s:%d%n",request.getServerName(),request.getServerPort()); | ||
out.printf("requestURI=%s%n",request.getRequestURI()); | ||
out.printf("requestURL=%s%n",request.getRequestURL().toString()); | ||
out.printf("contextPath|servletPath|pathInfo=%s|%s|%s%n",request.getContextPath(),request.getServletPath(),request.getPathInfo()); | ||
out.println("</pre>"); | ||
|
||
out.println("<h2>Request Headers:</h2>"); | ||
out.println("<pre>"); | ||
for (String n : Collections.list(request.getHeaderNames())) | ||
for (String v : Collections.list(request.getHeaders(n))) | ||
out.printf("%s: %s%n",n,v); | ||
out.println("</pre>"); | ||
|
||
out.println("<h2>Response Fields:</h2>"); | ||
out.println("<pre>"); | ||
out.printf("bufferSize=%d%n",response.getBufferSize()); | ||
out.printf("encodedURL(\"/foo/bar\")=%s%n",response.encodeURL("/foo/bar")); | ||
out.printf("encodedRedirectURL(\"/foo/bar\")=%s%n",response.encodeRedirectURL("/foo/bar")); | ||
out.println("</pre>"); | ||
|
||
out.println("<h2>Environment:</h2>"); | ||
out.println("<pre>"); | ||
for (Map.Entry<String,String> e : System.getenv().entrySet()) | ||
out.printf("%s=%s%n",e.getKey(),e.getValue()); | ||
out.println("</pre>"); | ||
|
||
out.println("<h2>System Properties:</h2>"); | ||
out.println("<pre>"); | ||
for (Object n : System.getProperties().keySet()) | ||
out.printf("%s=%s%n",n,System.getProperty(n.toString())); | ||
out.println("</pre>"); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?xml version="1.0"?> | ||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd"> | ||
|
||
<Configure id="Server" class="org.eclipse.jetty.server.Server"> | ||
|
||
<!-- ============================================================================================== --> | ||
<!-- GCloud configuration. --> | ||
<!-- This replaces the file in jetty releases < 9.3.8 with a fix to extract the worker name from --> | ||
<!-- the GAE_MODULE_INSTANCE env variable. This can be removed from jetty-9.3.8 onwards. --> | ||
<!-- ============================================================================================== --> | ||
<New id="gconf" class="org.eclipse.jetty.gcloud.session.GCloudConfiguration"> | ||
<!-- To contact remote gclouddatastore set the following properties in start.ini --> | ||
<!-- Either set jetty.gcloudSession.projectId or use system property/env var DATASTORE_DATASET--> | ||
<Set name="projectId"><Property name="jetty.gcloudSession.projectId"/></Set> | ||
<Set name="p12File"><Property name="jetty.gcloudSession.p12File"/></Set> | ||
<Set name="serviceAccount"><Property name="jetty.gcloudSession.serviceAccount"/></Set> | ||
<Set name="password"><Property name="jetty.gcloudSession.password"/></Set> | ||
</New> | ||
|
||
<!-- ===================================================================== --> | ||
<!-- Configure a GCloudSessionIdManager --> | ||
<!-- ===================================================================== --> | ||
<Set name="sessionIdManager"> | ||
<New id="idMgr" class="org.eclipse.jetty.gcloud.session.GCloudSessionIdManager"> | ||
<Arg> | ||
<Ref id="Server"/> | ||
</Arg> | ||
<Set name="workerName"><Property name="jetty.gcloudSession.workerName"><Default>node<Env name="GAE_MODULE_INSTANCE" default="0"/></Default></Property></Set> | ||
<Set name="config"><Ref id="gconf"/></Set> | ||
</New> | ||
</Set> | ||
|
||
</Configure> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
## The gcloud projectId | ||
## Set this property to connect to remote gcloud datastore. | ||
## Or, set the DATASTORE_DATASET System property/env variable instead. | ||
jetty.gcloudSession.projectId=jetty9-work | ||
|
||
## The p12 file associated with the project. | ||
## Set this property to connect to remote gcloud datastore | ||
jetty.gcloudSession.p12File=etc/jetty9-work-fe328934f681.p12 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. definitely should be a generic name and p12 is wrong format. |
||
|
||
## The serviceAccount for the Datastore. | ||
## Set this property to connect to to remote gcloud datastore | ||
jetty.gcloudSession.serviceAccount=gw-test-service-account@jetty9-work.iam.gserviceaccount.com | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. really good idea not to check these in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doh! will cancel and regenerate new private ones. |
||
|
||
## The password (can be obfuscated). | ||
## Set this property to connect to remote gcloud datastore | ||
jetty.gcloudSession.password=notasecret | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd"> | ||
|
||
<Configure id="testWebapp" class="org.eclipse.jetty.webapp.WebAppContext"> | ||
|
||
<Set name="contextPath">/</Set> | ||
<Set name="war"><Property name="jetty.webapps" default="."/>/root.war</Set> | ||
|
||
<Ref id="Server"> | ||
<Call id="idMgr" name="getSessionIdManager"/> | ||
</Ref> | ||
|
||
<Set name="sessionHandler"> | ||
<New class="org.eclipse.jetty.server.session.SessionHandler"> | ||
<Arg> | ||
<New id="mgr" class="org.eclipse.jetty.gcloud.session.GCloudSessionManager"> | ||
<Set name="sessionIdManager"> | ||
<Ref id="idMgr"/> | ||
</Set> | ||
<Set name="scavengeIntervalSec">600</Set> | ||
<Set name="staleIntervalSec">1</Set> | ||
</New> | ||
</Arg> | ||
</New> | ||
</Set> | ||
</Configure> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# A default java.util.logging configuration. | ||
# (All App Engine logging is through java.util.logging by default). | ||
# | ||
# To use this configuration, copy it into your application's WEB-INF | ||
# folder and add the following to your appengine-web.xml: | ||
# | ||
# <system-properties> | ||
# <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/> | ||
# </system-properties> | ||
# | ||
|
||
# Set the default logging level for all loggers to INFO | ||
.level = INFO |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<!-- | ||
~ Copyright (c) 2013 Google Inc. All Rights Reserved. | ||
~ | ||
~ Licensed under the Apache License, Version 2.0 (the "License"); you | ||
~ may not use this file except in compliance with the License. You may | ||
~ obtain a copy of the License at | ||
~ | ||
~ http://www.apache.org/licenses/LICENSE-2.0 | ||
~ | ||
~ Unless required by applicable law or agreed to in writing, software | ||
~ 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. | ||
--> | ||
|
||
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> | ||
<security-constraint> | ||
<web-resource-collection> | ||
<web-resource-name>secured-resource</web-resource-name> | ||
<url-pattern>/dump/auth/*</url-pattern> | ||
</web-resource-collection> | ||
<auth-constraint> | ||
<role-name>*</role-name> | ||
</auth-constraint> | ||
</security-constraint> | ||
<security-constraint> | ||
<web-resource-collection> | ||
<web-resource-name>data-constraint</web-resource-name> | ||
<url-pattern>/dump/ssl/*</url-pattern> | ||
</web-resource-collection> | ||
<user-data-constraint><transport-guarantee>CONFIDENTIAL</transport-guarantee></user-data-constraint> | ||
</security-constraint> | ||
<security-constraint> | ||
<web-resource-collection> | ||
<web-resource-name>data-constraint</web-resource-name> | ||
<url-pattern>/dump/auth/relax/*</url-pattern> | ||
</web-resource-collection> | ||
</security-constraint> | ||
|
||
<servlet> | ||
<display-name>DumpServlet</display-name> | ||
<servlet-name>DumpServlet</servlet-name> | ||
<servlet-class>com.google.appengine.demos.DumpServlet</servlet-class> | ||
</servlet> | ||
<servlet-mapping> | ||
<servlet-name>DumpServlet</servlet-name> | ||
<url-pattern>/dump/*</url-pattern> | ||
</servlet-mapping> | ||
|
||
<welcome-file-list> | ||
<welcome-file>index.html</welcome-file> | ||
</welcome-file-list> | ||
</web-app> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<h1>Jetty9 GCloud Session Test Webapp</h1> | ||
This webapp demonstrates the use of the GCloud session manager with an | ||
application deployed on the pure Jetty9 GAE image. | ||
|
||
The <a href="/dump/info">Dump Servlet</a> can be used to see both the instance and | ||
session used by each request. You can add request query parameters to the URI to | ||
set session attributes, which should then be seen of subsequent reloads, no matter | ||
which instance is hit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ancient history. S.B. json file now. Though ideally, you get everything from Usable Auth, and just use the JSON to override.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lesv Note sure I'm following you here as to what is ancient history?
The
jetty-gcloud-sessions.xml
is the current way we configure the gcloud session manager in the current jetty release. The change in this PR was to add the Env lookup forGAE_MODULE_INSTANCE
So are you saying that the ancient history is the form of the gcloud data store configuration that jetty is currently using? I think @janbartel has been having issues navigating exactly which are current APIs to use and what exactly is current best practise. So if you have any pointers for "Usable Auth" and the JSON file we should be using to configure, then we will look to update the session manager to use them.
However, without such an update, does the ancient history of this approach negate the value of this example? Ie should we complete this example with the current session manager or wait until we can update the session manager to a more recent version?
Perhaps we should do the example with the JDBC session manager instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All Google services are moving to Usable Auth for 2LO (computer<==>computer). (It automatically does auth in AppEngine, GCP (MVMs, GCE, GKE, inside or outside of Docker containers, etc), and locally.)
Datastore currently uses this, and the way we'll be doing SQL will also require something like this. (as well as MySQL username/pw).
Understandable that you don't support it yet, but it's the direction we are going and we are trying to eliminate the need for files, json or p12 except when you are running outside the environment in which case you can set an environment variable to point to your json credentials.
For the main thrust of your question -- I support going forward with what you have, but we do need to get it to move towards the new APIs / auth. ( @ludo call)