diff --git a/appengine-java8/cloudsql/README.md b/appengine-java8/cloudsql/README.md index def7251a81d..adb8e97acaf 100644 --- a/appengine-java8/cloudsql/README.md +++ b/appengine-java8/cloudsql/README.md @@ -1,20 +1,36 @@ # Cloud SQL sample for Google App Engine -This sample demonstrates how to use [Cloud SQL](https://cloud.google.com/sql/) on Google App Engine + +This sample demonstrates how to use [Cloud SQL](https://cloud.google.com/cloudsql/) on Google App +Engine standard Java 8 ## Setup -Before you can run or deploy the sample, you will need to create a [Cloud SQL instance)](https://cloud.google.com/sql/docs/create-instance) -1. Create a new user and database for the application. The easiest way to do this is via the [Google -Developers Console](https://console.cloud.google.com/sql/instances). Alternatively, you can use MySQL tools such as the command line client or workbench. -2. Change the root password (under Access Control) and / or create a new user / password. -3. Create a Database (under Databases) (or use MySQL with `gcloud beta sql connect --user=root`) -4. Note the **Instance connection name** under Overview > properties -(It will look like project:instance for 1st Generation or project:region:zone for 2nd Generation) +* If you haven't already, Download and initialize the [Cloud SDK](https://cloud.google.com/sdk/) + + `gcloud init` + +* If you haven't already, Create an App Engine app within the current Google Cloud Project + + `gcloud app create` + +* If you haven't already, Setup +[Application Default Credentials](https://developers.google.com/identity/protocols/application-default-credentials) + + `gcloud auth application-default login` + + +* [Create an instance](https://cloud.google.com/sql/docs/mysql/create-instance) + +* [Create a Database](https://cloud.google.com/sql/docs/mysql/create-manage-databases) -or +* [Create a user](https://cloud.google.com/sql/docs/mysql/create-manage-users) + +* Note the **Instance connection name** under Overview > properties + +## Running locally ```bash -gcloud sql instances describe | grep connectionName +$ mvn clean appengine:run -DINSTANCE_CONNECTION_NAME=instanceConnectionName -Duser=root -Dpassword=myPassowrd -Ddatabase=myDatabase ``` ## Deploying @@ -24,12 +40,8 @@ $ mvn clean appengine:deploy -DINSTANCE_CONNECTION_NAME=instanceConnectionName - -Dpassword=myPassword -Ddatabase=myDatabase ``` -Or you can update the properties in `pom.xml` -## Running locally +## Cleaning up + +* [Delete your Instance](https://cloud.google.com/sql/docs/mysql/delete-instance) -```bash -$ mvn clean appengine:run -DINSTANCE_CONNECTION_NAME=instanceConnectionName -Duser=root -Dpassword=myPassowrd -Ddatabase=myDatabase -``` -Note - you must use a local mysql instance for the 1st Generation instance and change the local Url -in `src/main/webapp/WEB-INF/appengine-web.xml` to use your local server. diff --git a/appengine-java8/cloudsql/pom.xml b/appengine-java8/cloudsql/pom.xml index b37d7d82e0a..99ce2bcba72 100644 --- a/appengine-java8/cloudsql/pom.xml +++ b/appengine-java8/cloudsql/pom.xml @@ -77,7 +77,7 @@ com.google.cloud.sql mysql-socket-factory - 1.0.2 + 1.0.3 diff --git a/appengine-java8/cloudsql/src/main/java/com/example/appengine/cloudsql/CloudSqlServlet.java b/appengine-java8/cloudsql/src/main/java/com/example/appengine/cloudsql/CloudSqlServlet.java index 11513cb801a..6647b269589 100644 --- a/appengine-java8/cloudsql/src/main/java/com/example/appengine/cloudsql/CloudSqlServlet.java +++ b/appengine-java8/cloudsql/src/main/java/com/example/appengine/cloudsql/CloudSqlServlet.java @@ -16,6 +16,8 @@ package com.example.appengine.cloudsql; +import com.google.common.base.Stopwatch; + import java.io.IOException; import java.io.PrintWriter; import java.net.Inet4Address; @@ -28,6 +30,7 @@ import java.sql.SQLException; import java.sql.Timestamp; import java.util.Date; +import java.util.concurrent.TimeUnit; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; @@ -41,14 +44,26 @@ @WebServlet(name = "CloudSQL", description = "CloudSQL: Write low order IP address to Cloud SQL", urlPatterns = "/cloudsql") public class CloudSqlServlet extends HttpServlet { + Connection conn; @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException { + final String createTableSql = "CREATE TABLE IF NOT EXISTS visits ( visit_id INT NOT NULL " + + "AUTO_INCREMENT, user_ip VARCHAR(46) NOT NULL, timestamp DATETIME NOT NULL, " + + "PRIMARY KEY (visit_id) )"; + final String createVisitSql = "INSERT INTO visits (user_ip, timestamp) VALUES (?, ?)"; + final String selectSql = "SELECT user_ip, timestamp FROM visits ORDER BY timestamp DESC " + + "LIMIT 10"; + String path = req.getRequestURI(); if (path.startsWith("/favicon.ico")) { return; // ignore the request for favicon.ico } + + PrintWriter out = resp.getWriter(); + resp.setContentType("text/plain"); + // store only the first two octets of a users ip address String userIp = req.getRemoteAddr(); InetAddress address = InetAddress.getByName(userIp); @@ -60,51 +75,45 @@ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOExc userIp = userIp.substring(0, userIp.indexOf(".", userIp.indexOf(".") + 1)) + ".*.*"; } - final String createTableSql = "CREATE TABLE IF NOT EXISTS visits ( visit_id INT NOT NULL " - + "AUTO_INCREMENT, user_ip VARCHAR(46) NOT NULL, timestamp DATETIME NOT NULL, " - + "PRIMARY KEY (visit_id) )"; - final String createVisitSql = "INSERT INTO visits (user_ip, timestamp) VALUES (?, ?)"; - final String selectSql = "SELECT user_ip, timestamp FROM visits ORDER BY timestamp DESC " - + "LIMIT 10"; - - PrintWriter out = resp.getWriter(); - resp.setContentType("text/plain"); - String url; - if (System - .getProperty("com.google.appengine.runtime.version").startsWith("Google App Engine/")) { - // Check the System properties to determine if we are running on appengine or not - // Google App Engine sets a few system properties that will reliably be present on a remote - // instance. - url = System.getProperty("ae-cloudsql.cloudsql-database-url"); - try { - // Load the class that provides the new "jdbc:google:mysql://" prefix. - Class.forName("com.mysql.jdbc.GoogleDriver"); - } catch (ClassNotFoundException e) { - throw new ServletException("Error loading Google JDBC Driver", e); - } - } else { - // Set the url with the local MySQL database connection url when running locally - url = System.getProperty("ae-cloudsql.local-database-url"); - } - log("connecting to: " + url); - try (Connection conn = DriverManager.getConnection(url); - PreparedStatement statementCreateVisit = conn.prepareStatement(createVisitSql)) { + Stopwatch stopwatch = Stopwatch.createStarted(); + try (PreparedStatement statementCreateVisit = conn.prepareStatement(createVisitSql)) { conn.createStatement().executeUpdate(createTableSql); statementCreateVisit.setString(1, userIp); statementCreateVisit.setTimestamp(2, new Timestamp(new Date().getTime())); statementCreateVisit.executeUpdate(); try (ResultSet rs = conn.prepareStatement(selectSql).executeQuery()) { + stopwatch.stop(); out.print("Last 10 visits:\n"); while (rs.next()) { String savedIp = rs.getString("user_ip"); String timeStamp = rs.getString("timestamp"); out.print("Time: " + timeStamp + " Addr: " + savedIp + "\n"); } + out.println("Elapsed: " + stopwatch.elapsed(TimeUnit.MILLISECONDS)); } } catch (SQLException e) { throw new ServletException("SQL error", e); } } + + @Override + public void init() throws ServletException { + try { + String url = System.getProperty("cloudsql"); + log("connecting to: " + url); + try { + Class.forName("com.mysql.jdbc.Driver"); + conn = DriverManager.getConnection(url); + } catch (ClassNotFoundException e) { + throw new ServletException("Error loading JDBC Driver", e); + } catch (SQLException e) { + throw new ServletException("Unable to connect to PostGre", e); + } + + } finally { + // Nothing really to do here. + } + } } // [END example] diff --git a/appengine-java8/cloudsql/src/main/webapp/WEB-INF/appengine-web.xml b/appengine-java8/cloudsql/src/main/webapp/WEB-INF/appengine-web.xml index af5c5995e03..bd7a30632f4 100644 --- a/appengine-java8/cloudsql/src/main/webapp/WEB-INF/appengine-web.xml +++ b/appengine-java8/cloudsql/src/main/webapp/WEB-INF/appengine-web.xml @@ -16,10 +16,8 @@ true java8 - - - + diff --git a/appengine-java8/gaeinfo/README.md b/appengine-java8/gaeinfo/README.md index a43199924eb..3c9c13435b6 100644 --- a/appengine-java8/gaeinfo/README.md +++ b/appengine-java8/gaeinfo/README.md @@ -23,19 +23,6 @@ Use either: $ mvn appengine:deploy -## Gradle -### Running locally - - $ gradle appengineRun - -If you do not have gradle installed, you can run using `./gradlew appengineRun`. - -### Deploying - - $ gradle appengineDeploy - -If you do not have gradle installed, you can deploy using `./gradlew appengineDeploy`. - + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.appengine + appengine-postgreSQL-j8 + + + appengine-java8-samples + com.google.cloud + 1.0.0 + .. + + + + + + Project:Region:Instance + root + myPassword + sqldemo + + + 1.8 + 1.8 + + + + + + + + com.google.appengine + appengine-api-1.0-sdk + 1.9.54 + + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + com.google.api-client + google-api-client-appengine + 1.22.0 + + + + + org.postgresql + postgresql + 42.1.1 + + + + com.google.cloud.sql + postgres-socket-factory + 1.0.3 + + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 3.0.0 + + + + + ${basedir}/src/main/webapp/WEB-INF + true + WEB-INF + + + + + + + com.google.cloud.tools + appengine-maven-plugin + 1.3.1 + + true + true + + + + + + diff --git a/appengine-java8/postgres/src/main/java/com/example/appengine/postgresql/PostgreSqlServlet.java b/appengine-java8/postgres/src/main/java/com/example/appengine/postgresql/PostgreSqlServlet.java new file mode 100644 index 00000000000..46d34497463 --- /dev/null +++ b/appengine-java8/postgres/src/main/java/com/example/appengine/postgresql/PostgreSqlServlet.java @@ -0,0 +1,122 @@ +/** + * Copyright 2016 Google Inc. + * + * 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. + */ + +package com.example.appengine.postgresql; + +import com.google.common.base.Stopwatch; + +import java.io.IOException; +import java.io.PrintWriter; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +// With @WebServlet annotation the webapp/WEB-INF/web.xml is no longer required. +@WebServlet(name = "PostgreSQL", + description = "PostgreSQL: Write low order IP address to PostgreSQL", + urlPatterns = "/postgresql") +public class PostgreSqlServlet extends HttpServlet { + + Connection conn; + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, + ServletException { + + final String createTableSql = "CREATE TABLE IF NOT EXISTS visits ( visit_id SERIAL NOT NULL, " + + "user_ip VARCHAR(46) NOT NULL, ts timestamp NOT NULL, " + + "PRIMARY KEY (visit_id) );"; + final String createVisitSql = "INSERT INTO visits (user_ip, ts) VALUES (?, ?);"; + final String selectSql = "SELECT user_ip, ts FROM visits ORDER BY ts DESC " + + "LIMIT 10;"; + + String path = req.getRequestURI(); + if (path.startsWith("/favicon.ico")) { + return; // ignore the request for favicon.ico + } + + PrintWriter out = resp.getWriter(); + resp.setContentType("text/plain"); + + // store only the first two octets of a users ip address + String userIp = req.getRemoteAddr(); + InetAddress address = InetAddress.getByName(userIp); + if (address instanceof Inet6Address) { + // nest indexOf calls to find the second occurrence of a character in a string + // an alternative is to use Apache Commons Lang: StringUtils.ordinalIndexOf() + userIp = userIp.substring(0, userIp.indexOf(":", userIp.indexOf(":") + 1)) + ":*:*:*:*:*:*"; + } else if (address instanceof Inet4Address) { + userIp = userIp.substring(0, userIp.indexOf(".", userIp.indexOf(".") + 1)) + ".*.*"; + } + + Stopwatch stopwatch = Stopwatch.createStarted(); + try (PreparedStatement statementCreateVisit = conn.prepareStatement(createVisitSql)) { + conn.createStatement().executeUpdate(createTableSql); + statementCreateVisit.setString(1, userIp); + statementCreateVisit.setTimestamp(2, new Timestamp(new Date().getTime())); + statementCreateVisit.executeUpdate(); + + try (ResultSet rs = conn.prepareStatement(selectSql).executeQuery()) { + stopwatch.stop(); + out.print("Last 10 visits:\n"); + while (rs.next()) { + String savedIp = rs.getString("user_ip"); + String timeStamp = rs.getString("ts"); + out.println("Time: " + timeStamp + " Addr: " + savedIp); + } + out.println("Elapsed: " + stopwatch.elapsed(TimeUnit.MILLISECONDS)); + } + } catch (SQLException e) { + throw new ServletException("SQL error", e); + } + } + + @Override + public void init() throws ServletException { + try { + String url = System.getProperty("postgresql"); + log("connecting to: " + url); + try { + Class.forName("org.postgresql.Driver"); + conn = DriverManager.getConnection(url); + } catch (ClassNotFoundException e) { + throw new ServletException("Error loading JDBC Driver", e); + } catch (SQLException e) { + throw new ServletException("Unable to connect to PostGre", e); + } + + } finally { + // Nothing really to do here. + } + } +} +// [END example] diff --git a/appengine-java8/postgres/src/main/webapp/WEB-INF/appengine-web.xml b/appengine-java8/postgres/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..40a70a28926 --- /dev/null +++ b/appengine-java8/postgres/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,23 @@ + + + + + true + java8 + + + + + + diff --git a/appengine-java8/postgres/src/main/webapp/WEB-INF/web.xml b/appengine-java8/postgres/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..f6184daf082 --- /dev/null +++ b/appengine-java8/postgres/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,24 @@ + + + + + + + postgresql + + diff --git a/appengine/gaeinfo/README.md b/appengine/gaeinfo/README.md new file mode 100644 index 00000000000..a43199924eb --- /dev/null +++ b/appengine/gaeinfo/README.md @@ -0,0 +1,63 @@ +# Google App Engine Information + +This sample displays what's going on in your app. It dumps the environment and lots more. + +See the [Google App Engine standard environment documentation][ae-docs] for more +detailed instructions. + +[ae-docs]: https://cloud.google.com/appengine/docs/java/ + +## Setup + +Use either: + +* `gcloud init` +* `gcloud auth application-default login` + +## Maven +### Running locally + + $ mvn appengine:run + +### Deploying + + $ mvn appengine:deploy + +## Gradle +### Running locally + + $ gradle appengineRun + +If you do not have gradle installed, you can run using `./gradlew appengineRun`. + +### Deploying + + $ gradle appengineDeploy + +If you do not have gradle installed, you can deploy using `./gradlew appengineDeploy`. + + diff --git a/appengine/gaeinfo/pom.xml b/appengine/gaeinfo/pom.xml new file mode 100644 index 00000000000..180b2cd5703 --- /dev/null +++ b/appengine/gaeinfo/pom.xml @@ -0,0 +1,88 @@ + + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.appengine + gaeinfo-j8 + + + appengine-doc-samples + com.google.cloud + 1.0.0 + .. + + + + + 1.7 + 1.7 + + + + + + com.google.appengine + appengine-api-1.0-sdk + 1.9.54 + + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 3.0.0 + + + + + ${basedir}/src/main/webapp/WEB-INF + true + WEB-INF + + + + + + + com.google.cloud.tools + appengine-maven-plugin + 1.3.1 + + true + true + + + + + + + diff --git a/appengine/gaeinfo/src/main/java/com/example/appengine/standard/GAEInfoServlet.java b/appengine/gaeinfo/src/main/java/com/example/appengine/standard/GAEInfoServlet.java new file mode 100644 index 00000000000..2e4d2f56b34 --- /dev/null +++ b/appengine/gaeinfo/src/main/java/com/example/appengine/standard/GAEInfoServlet.java @@ -0,0 +1,132 @@ +/** + * Copyright 2017 Google Inc. + * + * 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. + */ + +package com.example.appengine.standard; + +import com.google.appengine.api.appidentity.AppIdentityService; +import com.google.appengine.api.appidentity.AppIdentityServiceFactory; +import com.google.appengine.api.utils.SystemProperty; +import com.google.apphosting.api.ApiProxy; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings({"serial"}) +//CHECKSTYLE:OFF +public class GAEInfoServlet extends HttpServlet { + + public void table(PrintWriter p, String title, String c) { + p.print("

" + title + "

"); + p.print(""); + p.print(c); + p.print("
"); + } + + public String tr(String c) { + return "" + c + ""; + } + + public String td(String s) { + return "" + s + ""; + } + + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + resp.setContentType("text/html"); + PrintWriter p = resp.getWriter(); + + + p.print(""); + + final AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService(); + table(p, "AppIdentity", + tr(td("ServiceAccountName") + td(appIdentity.getServiceAccountName()) ) + + tr(td("GCS Bucket") + td( appIdentity.getDefaultGcsBucketName())) + ); + + table(p, "SystemProperties", + tr( td( "appId") + td(SystemProperty.applicationId.get()) ) + + tr(td("appVer") + td( SystemProperty.applicationVersion.get()) ) + + tr(td("version") + td(SystemProperty.version.get()) ) + + tr(td("environment") + td(SystemProperty.environment.get()) ) + ); + + + // Environment Atributes + ApiProxy.Environment env = ApiProxy.getCurrentEnvironment(); + Map attr = env.getAttributes(); + + String c = ""; + for(String key : attr.keySet()) { + Object o = attr.get(key); + + if(o.getClass().getCanonicalName().equals("java.lang.String")) { + c += tr(td(key) + td((String) o)); + } else + c += tr(td(key) + td(o.getClass().getCanonicalName())); + } + table(p, "Environment Attributes", c); + + c = ""; + for (Enumeration e = req.getHeaderNames(); e.hasMoreElements();) { + String key = e.nextElement(); + String val = req.getHeader(key); + c += tr(td(key) + td(val) );; + } + table(p, "Headers", c); + + + Cookie[] cookies = req.getCookies(); + if(cookies != null && cookies.length != 0) { + c = ""; + for (Cookie co : cookies) { + c += tr( td(co.getName()) + td(co.getValue()) + td(co.getComment()) + + td(co.getPath()) + td(Integer.toString(co.getMaxAge())) ); + } + table(p, "Cookies", c); + } + + Properties properties = System.getProperties(); + c = ""; + for(Enumeration e = properties.propertyNames(); e.hasMoreElements();) { + String key = (String) e.nextElement(); + c += tr( td(key) + td((String)properties.get(key))); + } + table(p, "Java SystemProperties", c); + + Map envVar = System.getenv(); + c = ""; + for(String key : envVar.keySet()) { + c += tr(td(key)+td(envVar.get(key))); + } + table(p, "Envirionment Variables", c); + p.print(""); + p.close(); + + } +} +// [END example] diff --git a/appengine/gaeinfo/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/gaeinfo/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..bce740d6fee --- /dev/null +++ b/appengine/gaeinfo/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,22 @@ + + + + + true + true + + diff --git a/appengine/gaeinfo/src/main/webapp/WEB-INF/web.xml b/appengine/gaeinfo/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..a418dec8d60 --- /dev/null +++ b/appengine/gaeinfo/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,35 @@ + + + + + gaeinfo + + + gaeinfo + com.example.appengine.standard.GAEInfoServlet + + + gaeinfo + /gaeinfo + +