-
Notifications
You must be signed in to change notification settings - Fork 4
Remote
Highchair remote is a wrapper for Google App Engine's Remote API, allowing any Java application to transparently access App Engine services. You could use it to write raw Entity
s to a remote application just as easily as you could write highchair entities. Note that remotes allow you interface with any GAE service supported by the Remote API, not just the data store.
The remote module wraps the Remote API, which is provided by the GAE sdk in the jar appengine-remote-api.jar
. This is its only dependency, and unfortunately it's not published in the maven repositories. This can cause surprising failures, but sbt
at least makes it easy to manage such dependencies (see manual dependency management). Even though it's easily worked around, it is an unnecessary hurdle. I've opened an issue; please go vote it up.
In order to use the Remote API, the application must be configured to support remote calls. This requires wiring a GAE-provided servlet in your web.xml
. Details here.
A Remote
instance must be initialized against an application for which you have an administrative account. You provide the application id and port as a tuple, and an administrative account with its password as another tuple:
val remote = Remote("localhost" -> 8080, "[email protected]" -> "foopass")
This example would run against a local development server. However, the remote module contains a pre-configured instance for an application on localhost:8080 (the default): Remote.local
.
See the Remote API documentation for full details.
Assuming Person
is a defined highchair entity, instances can be persisted to a remote data store using a remote block:
val me = Person(None, "Chris", "Aaron", "Lewis", 30)
implicit val ds = DatastoreServiceFactory.getDatastoreService
remote {
Person.put(me)
}
Note that neither the me
or ds
instances needed to be created within the remote block.
Calls to remote
result in an Either[Throwable, A]
, where A
is the result type of the block. This allows you to sanely retrieve results, if you want them on success, as well as deal with any failures. Continuing with the Person
example, suppose we have the following functions for generating an error or welcome view fragment, respectively:
val errorReponse = (e: Throwable) => <h3>Please Try Again Later!</h3>
val welcomeResponse = (p: Person) => <h3>Welcome {p.firstName}!</h3>
This makes it easy to fold
a remote result into a view fragment:
remote {
Person.put(me)
} fold (errorReponse, welcomeResponse)
Remote
s allow you to scope remote calls such that when the block terminates, subsequent service calls will resume local bindings. This is achieved through the loan pattern. Therefore, you don't need to worry about remote calls wreaking havoc, even if they fail; cleanup happens automatically in all scenarios.