Namespaces - objectify/objectify GitHub Wiki

Namespaces

Unless you are already a Datastore expert, I recommend that you do not use namespaces. If you are an expert, you probably realize that you don't need them. It's usually just as easy (and a lot more flexible) simply to add an additional indexed field on the thing you're trying to partition by!

If you want to use namespaces anyway, Objectify supports them.

Objectify v5

In the legacy GAE environment supported by Objectify v5, 'namespace' had no API footprint except for a thread-local NamespaceManager. To use a namespace, you would write code like this:

final previous = NamespaceManager.get();
try {
    NamespaceManager.set(nextNamespace);
    // do some work in the namespace
} finally {
    NamespaceManager.set(previous);
}

Objectify v6

The Google's new datastore interface and Objectify 6 support namespaces more thoroughly. You still can define namespaced blocks just like you did before:

try (final Closeable ignored = NamespaceManager.set(nextNamespace)) {
    // do some work in the namespace
}

Alternatively, you can create Keys with explicit namespaces and you can define entity POJOs with explicit namespaces. Some example code:

final Key<Thing> key1 = ObjectifyService.key("someNamespace", Thing.class, 123L);

@Entity
public class Thing {
    @Namespace String namespace;
    @Id Long id;
}

You can also specify namespaces for specific queries/actions:

ofy().namespace("someNamespace").load().type(Foo.class).id(123);

Gotchas

Keys have fixed namespaces

When you create a Key, it will have a namespace - either explicitly on Key creation (if you pass a namespace), or from the NamespaceManager (if one is set), or the datastore default namespace (if you do nothing else). Once that key is created, its namespace does not change. Be careful of this:

final Key<Thing> key = Key.create(Thing.class, 123L);

try (final Closeable ignored = NamespaceManager.set("foo")) {
    ofy().load().key(key);   // Does NOT load an entity from namespace "foo"
    ofy().namespace("foo").load().key(key);   // This will not work either!
    ofy().load().type(Thing.class).id(123L);  // This WILL load from namespace "foo"
}

Null namespace means "use the default".

If you save an entity with a null value for its @Namespace field, Objectify determines the namespace with this chain:

  1. The value set by ofy().namespace(...)
  2. The current value of the NamespaceManager
  3. The datastore default namespace (usually "").

When you load that entity, it will always have a concrete namespace - potentially "" (the empty string).

More Examples

See these test cases

⚠️ **GitHub.com Fallback** ⚠️