-
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
Multitenancy #195
Multitenancy #195
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,19 @@ | ||
# Multitenancy Java sample | ||
|
||
Shows the usage of the Namespaces API. | ||
|
||
An App Engine guestbook using Java, Maven, and Objectify. | ||
|
||
Data access using [Objectify](https://github.com/objectify/objectify) | ||
|
||
Please ask questions on [Stackoverflow](http://stackoverflow.com/questions/tagged/google-app-engine) | ||
|
||
## Running Locally | ||
|
||
How do I, as a developer, start working on the project? | ||
|
||
1. `mvn clean appengine:devserver` | ||
|
||
## Deploying | ||
|
||
1. `mvn clean appengine:update -Dappengine.appId=PROJECT -Dappengine.version=VERSION` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<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.example.appengine</groupId> | ||
<artifactId>appengine-multitenancy</artifactId> | ||
|
||
<properties> | ||
<objectify.version>5.1.5</objectify.version> | ||
<guava.version>18.0</guava.version> | ||
</properties> | ||
<parent> | ||
<groupId>com.google.cloud</groupId> | ||
<artifactId>doc-samples</artifactId> | ||
<version>1.0.0</version> | ||
<relativePath>../..</relativePath> | ||
</parent> | ||
|
||
<!-- [START set_versions] --> | ||
<prerequisites> | ||
<maven>3.3.9</maven> | ||
</prerequisites> | ||
<!-- [END set_versions] --> | ||
|
||
<dependencies> | ||
<!-- Compile/runtime dependencies --> | ||
<dependency> | ||
<groupId>com.google.appengine</groupId> | ||
<artifactId>appengine-api-1.0-sdk</artifactId> | ||
<version>${appengine.sdk.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>javax.servlet</groupId> | ||
<artifactId>servlet-api</artifactId> | ||
<version>2.5</version> | ||
<scope>provided</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>jstl</groupId> | ||
<artifactId>jstl</artifactId> | ||
<version>1.2</version> | ||
</dependency> | ||
|
||
<!-- [START Objectify_Dependencies] --> | ||
<dependency> | ||
<groupId>com.google.guava</groupId> | ||
<artifactId>guava</artifactId> | ||
<version>${guava.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.googlecode.objectify</groupId> | ||
<artifactId>objectify</artifactId> | ||
<version>${objectify.version}</version> | ||
</dependency> | ||
<!-- [END Objectify_Dependencies] --> | ||
|
||
<!-- Test Dependencies --> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>4.12</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-all</artifactId> | ||
<version>1.10.19</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.appengine</groupId> | ||
<artifactId>appengine-testing</artifactId> | ||
<version>${appengine.sdk.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.appengine</groupId> | ||
<artifactId>appengine-api-stubs</artifactId> | ||
<version>${appengine.sdk.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.appengine</groupId> | ||
<artifactId>appengine-tools-sdk</artifactId> | ||
<version>${appengine.sdk.version}</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.truth</groupId> | ||
<artifactId>truth</artifactId> | ||
<version>0.28</version> | ||
<scope>test</scope> | ||
</dependency> | ||
|
||
</dependencies> | ||
|
||
<build> | ||
<!-- for hot reload of the web application--> | ||
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes</outputDirectory> | ||
<plugins> | ||
<plugin> | ||
<groupId>com.google.appengine</groupId> | ||
<artifactId>appengine-maven-plugin</artifactId> | ||
<version>${appengine.sdk.version}</version> | ||
<configuration> | ||
<enableJarClasses>false</enableJarClasses> | ||
<!-- Comment in the below snippet to bind to all IPs instead of just localhost --> | ||
<!-- address>0.0.0.0</address> | ||
<port>8080</port --> | ||
<!-- Comment in the below snippet to enable local debugging with a remote debugger | ||
like those included with Eclipse or IntelliJ --> | ||
<!-- jvmFlags> | ||
<jvmFlag>-agentlib:jdwp=transport=dt_socket,address=8000,server=y,suspend=n</jvmFlag> | ||
</jvmFlags --> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/** | ||
* Copyright 2014-2015 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. | ||
*/ | ||
|
||
//[START all] | ||
package com.example.appengine; | ||
|
||
import com.googlecode.objectify.Key; | ||
import com.googlecode.objectify.annotation.Entity; | ||
import com.googlecode.objectify.annotation.Id; | ||
import com.googlecode.objectify.annotation.Index; | ||
import com.googlecode.objectify.annotation.Parent; | ||
|
||
import java.util.Date; | ||
|
||
/** | ||
* The @Entity tells Objectify about our entity. We also register it in {@link OfyHelper} | ||
* Our primary key @Id is set automatically by the Google Datastore for us. | ||
* | ||
* We add a @Parent to tell the object about its ancestor. We are doing this to support many | ||
* guestbooks. Objectify, unlike the AppEngine library requires that you specify the fields you | ||
* want to index using @Index. Only indexing the fields you need can lead to substantial gains in | ||
* performance -- though if not indexing your data from the start will require indexing it later. | ||
* | ||
* NOTE - all the properties are PUBLIC so that can keep the code simple. | ||
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.
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. Maybe, but I find this ugly for published material. People see this stuff as Include code or in an IDE, our code should never be in JavaDocs. |
||
**/ | ||
@Entity | ||
public class Greeting { | ||
@Parent Key<Guestbook> theBook; | ||
@Id public Long id; | ||
|
||
public String authorEmail; | ||
public String authorId; | ||
public String content; | ||
@Index public Date date; | ||
|
||
/** | ||
* Simple constructor just sets the date. | ||
**/ | ||
public Greeting() { | ||
date = new Date(); | ||
} | ||
|
||
/** | ||
* A convenience constructor. | ||
**/ | ||
public Greeting(String book, String content) { | ||
this(); | ||
if ( book != null ) { | ||
theBook = Key.create(Guestbook.class, book); // Creating the Ancestor key | ||
} else { | ||
theBook = Key.create(Guestbook.class, "default"); | ||
} | ||
this.content = content; | ||
} | ||
|
||
public Greeting(String book, String content, String id, String email) { | ||
this(book, content); | ||
authorEmail = email; | ||
authorId = id; | ||
} | ||
|
||
} | ||
//[END all] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/** | ||
* Copyright 2014-2015 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. | ||
*/ | ||
|
||
//[START all] | ||
package com.example.appengine; | ||
|
||
import com.googlecode.objectify.annotation.Entity; | ||
import com.googlecode.objectify.annotation.Id; | ||
|
||
/** | ||
* The @Entity tells Objectify about our entity. We also register it in | ||
* OfyHelper.java -- very important. | ||
* | ||
* This is never actually created, but gives a hint to Objectify about our Ancestor key. | ||
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.
|
||
*/ | ||
@Entity | ||
public class Guestbook { | ||
@Id public String book; | ||
} | ||
//[END all] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* Copyright 2016 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. | ||
*/ | ||
|
||
package com.example.appengine; | ||
|
||
import com.google.appengine.api.NamespaceManager; | ||
import com.google.appengine.api.memcache.MemcacheService; | ||
import com.google.appengine.api.memcache.MemcacheServiceFactory; | ||
import com.google.appengine.api.search.Index; | ||
import com.google.appengine.api.search.IndexSpec; | ||
import com.google.appengine.api.search.SearchService; | ||
import com.google.appengine.api.search.SearchServiceConfig; | ||
import com.google.appengine.api.search.SearchServiceFactory; | ||
import com.google.appengine.api.users.UserServiceFactory; | ||
|
||
import java.io.IOException; | ||
import java.io.PrintWriter; | ||
|
||
import javax.servlet.http.HttpServlet; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
|
||
// [START example] | ||
@SuppressWarnings("serial") | ||
public class MultitenancyServlet extends HttpServlet { | ||
|
||
@Override | ||
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { | ||
String namespace; | ||
|
||
PrintWriter out = resp.getWriter(); | ||
out.println("Code Snippets -- not yet fully runnable as an app"); | ||
|
||
// [START temp_namespace] | ||
// Set the namepace temporarily to "abc" | ||
String oldNamespace = NamespaceManager.get(); | ||
NamespaceManager.set("abc"); | ||
try { | ||
// ... perform operation using current namespace ... | ||
} finally { | ||
NamespaceManager.set(oldNamespace); | ||
} | ||
// [END temp_namespace] | ||
|
||
// [START per_user_namespace] | ||
if (com.google.appengine.api.NamespaceManager.get() == null) { | ||
// Assuming there is a logged in user. | ||
namespace = UserServiceFactory.getUserService().getCurrentUser().getUserId(); | ||
NamespaceManager.set(namespace); | ||
} | ||
// [END per_user_namespace] | ||
String value = "something here"; | ||
|
||
// [START ns_memcache] | ||
// Create a MemcacheService that uses the current namespace by | ||
// calling NamespaceManager.get() for every access. | ||
MemcacheService current = MemcacheServiceFactory.getMemcacheService(); | ||
|
||
// stores value in namespace "abc" | ||
oldNamespace = NamespaceManager.get(); | ||
NamespaceManager.set("abc"); | ||
try { | ||
current.put("key", value); // stores value in namespace “abc” | ||
} finally { | ||
NamespaceManager.set(oldNamespace); | ||
} | ||
// [END ns_memcache] | ||
|
||
// [START specific_memcache] | ||
// Create a MemcacheService that uses the namespace "abc". | ||
MemcacheService explicit = MemcacheServiceFactory.getMemcacheService("abc"); | ||
explicit.put("key", value); // stores value in namespace "abc" | ||
// [END specific_memcache] | ||
|
||
//[START searchns] | ||
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. nit, missing space. |
||
// Set the current namespace to "aSpace" | ||
NamespaceManager.set("aSpace"); | ||
// Create a SearchService with the namespace "aSpace" | ||
SearchService searchService = SearchServiceFactory.getSearchService(); | ||
// Create an IndexSpec | ||
IndexSpec indexSpec = IndexSpec.newBuilder().setName("myIndex").build(); | ||
// Create an Index with the namespace "aSpace" | ||
Index index = searchService.getIndex(indexSpec); | ||
// [END searchns] | ||
|
||
// [START searchns_2] | ||
// Create a SearchServiceConfig, specifying the namespace "anotherSpace" | ||
SearchServiceConfig config = SearchServiceConfig.newBuilder() | ||
.setNamespace("anotherSpace").build(); | ||
// Create a SearchService with the namespace "anotherSpace" | ||
searchService = SearchServiceFactory.getSearchService(config); | ||
// Create an IndexSpec | ||
indexSpec = IndexSpec.newBuilder().setName("myindex").build(); | ||
// Create an Index with the namespace "anotherSpace" | ||
index = searchService.getIndex(indexSpec); | ||
// [END searchns_2] | ||
|
||
} | ||
|
||
|
||
|
||
} | ||
// [END example] |
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.
nit, Missing
<p>
tag. Should be<p>We
.