Revision: 10034
Author: [email protected]
Date: Tue Apr 19 16:46:49 2011
Log: Created wiki page through web user interface.
http://code.google.com/p/google-web-toolkit/source/detail?r=10034
Added:
/wiki/RequestFactoryMovingParts.wiki
=======================================
--- /dev/null
+++ /wiki/RequestFactoryMovingParts.wiki Tue Apr 19 16:46:49 2011
@@ -0,0 +1,101 @@
+#summary A summary of the bits that make up RequestFactory
+
+* Work in progress *
+
+<wiki:toc level='2' />
+
+= Introduction =
+
+The RequestFactory system is composed of a number of discrete component
pieces. This document will describe the rough functionality of the
RequestFactory components as a aid to developers who wish to work on
RequestFactory or adapt RequestFactory to non-standard deployment
environments. This document assumes a working knowledge of how to use
RequestFactory.
+
+<img src="http://i.imgur.com/WNqrg.jpg" title="If it doesn't fit on a
sticky note, it's too complicated." alt="Schematic drawing of the major
components of RequestFactory"/>
+
+= Flow =
+
+ * Instantiate an instance of a `RequestFactory` via `GWT.create()` or
`RequestFactorySource`
+ * Obtain an instance of `RequestContext` by calling an accessor method
defined within the `RequestFactory`
+ * Use `RequestContext.create()` and `RequestContext.edit()` to
accumulate zero or more *operations* to be applied to domain objects by the
server.
+ * Obtain one or more `Request` objects to accumulate *invocations* on
server code.
+ * The `Request.to()` method provides a `Receiver` that will be
notified of the outcome of the invocation associated with the `Request`.
+ * Call `Request.fire()` or `RequestContext.fire()` to send the
accumulated data to the server.
+ * The accumulated state is transmitted to the server, where the
following operations take place:
+ * All domain objects referred to by the payload will be loaded.
+ * All accumulated operations will be applied to the domain objects.
+ * All method invocations in the payload are executed.
+ * The states of entities referred to in the original payload are
compared to the up-to-date states of the entities after all work has been
performed.
+ * Entities with updated properties are enqueued to be sent back to
the client.
+ * Entities that can be no longer retrieved after all work has been
performed are reported as having been deleted.
+ * The return payload is assembled and sent to the client.
+ * The various `Receivers` attached to `Requests` or the
`RequestContext` are invoked to report success, failure, or validation
violations.
+
+= Parts Glossary =
+
+This section contains a brief discussion of each of the major parts of
RequestFactory, in no particular order.
+
+== Code ==
+
+Depending on the terminology used, this may be called "business logic",
an "RPC service layer", or "domain behavior." Regardless of the
phraseology used, this code exists as either static or instance methods
that are mapped onto a `RequestContext` interface.
+
+RequestFactory assumes that server code will execute in a synchronous,
blocking fashion.
+
+== POJO ==
+
+RequestFactory minimizes the number of assumptions that it makes about
server-side ("domain") objects. Most operations are performed assuming
that domain objects are simply "plain old Java objects" that are
default-instantiable (i.e. a public no-arg constructor) and have pairs of
getters and setters. Setters are not required for immutable properties.
The requirement for default-instantiability can be removed via the use of a
`Locator`.
+
+=== Entity ===
+
+An "Entity" is any object with a well-defined identity and version.
Entities are mapped on the client as `EntityProxy` subtypes, while all
other POJOS can be mapped as `ValueProxy` subtypes.
+
+While entity domain objects need not extend any particular base type or
interface, they must implement the following informal protocol:
+ * The domain type is default-instantiable
+ * `I getId()` must return a stable value
+ * `V getVersion()` must change every time the meaningful state of the
domain object changes. No assumption is made about the semantic meaning of
the value, just that it is non-`equal()` to state version values.
+ * `static Entity find(I id)` is used to retrieve a previously-referenced
entity, using a value returned by `getId()`. The `find()` method may
return `null` to indicate that the entity has been deleted or is otherwise
unavailable.
+
+Domain types that cannot satisfy some or all of the requirements of the
entity protocol may participate as entities by using a `Locator`.
+
+Entities can be transferred in a sparse manner, as any undefined
properties can be later retrieved since the entity has a persistent id. By
default, reference properties are not transferred unless explicitly
specified by a `Request.with()`predicate.
+
+=== Values ===
+
+A "Value" is any other POJO type that does not have a well-defined
identity or version concept. Value types must be default-instantiable, but
do not need to implement any other methods. Value types that are not
default-instantiable may still be used by providing a `Locator` to vend
instances.
+
+All properties of a value type are transferred every time the value is
referenced in a payload, since the value lacks an identity concept.
+
+== !PojoProxy ==
+
+A proxy is a lightweight interface that exposes a subset of the property
accessors of domain types to the RequestFactory client. All
developer-defined proxies must extend either 'EntityProxy'
or 'ValueProxy'. While the two proxy types extend a common `BaseProxy'
type, this type exists solely to reduce API method count and is not
directly usable by developers.
+
+Every proxy must be annotated with a `@ProxyFor` or `@ProxyForName`
annotation to declare which domain type the proxy provides access to. It
is legal for multiple proxy types to be mapped to the same domain type.
+
+Proxies that map non-default-instantiable domain types can define a
`Locator` in their `@ProxyFor` annotation.
+
+It is important to note that the proxy types are required by the server
code. The RequestFactory server code uses the properties defined on the
proxy objects to determine which properties may be accessed by clients and
the `@ProxyFor` annotation to determine the domain type and optional
`Locator`. This level of indirection provides some security against
malicious payloads attempting to manipulate arbitrary domain types.
+
+== Locator ==
+
+A `Locator` can be used to allow types that do not conform to the informal
entity protocol to be used as entities with RequestFactory. Locators are
assumed to be default-instantiable, however this assumption can be modified
by providing an alternate implementation of `ServiceLayer.createLocator()`.
+
+== Persistence layer ==
+
+RequestFactory has no particular assumptions about the persistence system
used by the developer (or even if one is used at all). The actual details
of how any given pojo is persisted is left to the developer and treated as
an implementation detail by RequestFactory.
+
+Many samples include a `persist()` method as one of the first examples of
server code, however this is merely a convention. RequestFactory does not
treat this as a special method.
+
+== Request ==
+== !RequestContext ==
+== !ServiceLocator ==
+
+A `ServiceLocator` is used to provide instance objects for non-static
domain methods. Implementations of `ServiceLocators` are assumed to be
default-instantiable, however this may be changed by providing alternate
implementation of `ServiceLayer.createServiceLocator()`.
+
+== !ServiceLayer ==
+
+The `ServiceLayer` mediates all interactions between the
`SimpleRequestProcessor` and the domain. RequestFactory's default
behaviors may be overridden by providing one or more
`ServiceLayerDecorator` instance to `ServiceLayer.create()`. For instance,
the `ServiceLayer.setProperty()` method can be used to provide access
control for specific users.
+
+Because the API expressed by `ServiceLayer` is intimately tied to the
services required by the `SimpleRequestProcessor`, the API is subject to
change over time. Efforts will be made to keep `ServiceLayerDecorator`
source-compatible, however this API should be treated as only semi-public.
Developers who are advanced enough to take advantage of decorating the
`ServiceLayer` will be able to adapt to changes as they come up.
+
+== !SimpleRequestProcessor ==
+
+= Random notes without a home =
+
+ * The `gwt.rpc.dumpPayload` environment variable can be set to `true`
when attempting to debug RequestFactory behavior.
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors