Chapter 11. Detach and Attach

11.1. Configuring detachability
11.2. Detachable behavior
11.3. Detach and Attach Callbacks

A common use case for an application running in a servlet or application server is to "detach" objects from all server resources, modify them, and then "attach" them again. For example, a servlet might store persistent data in a user session between a modification based on a series of web forms. Between each form request, the web container might decide to serialize the session, requiring that the stored persistent state be disassociated from any other resources. Similarly, a client/server or EJB application might transfer persistent objects to a client via serialization, allow the client to modify their state, and then have the client return the modified data in order to be saved. This is sometimes referred to as the "data transfer object" or "value object" pattern, and it allows fine-grained manipulation of data objects without incurring the overhead of multiple remote method invocations (which is one of the things that often makes entity bean-based solutions slow). Version 1 of the JDO specification does not provide direct support for this pattern or any detached modification, since persistent object updates can only take place when the instance is associated with a persistence manager that has a transaction running.

Kodo provides support for this pattern by introducing detach and attach APIs that allow a user to detach a persistent instance, modify the detached instance, and attach the instance back into a persistence manager (either the same one that detached the instance, or a new one). The changes will then be applied to the existing instance from the datastore. Very similar APIs are being considered for inclusion in the JDO 2.0 specification, so they may become standard in the future.

11.1. Configuring detachability

In order to be able to detach a persistent instance, the metadata for the class must declare that it is eligible for detachment by using the detachable extension. Changes to this extension require that the class be re-enhanced. This is because detachability requires that the enhancer add additional fields to the class to hold information about the persistent instance's object id and state. The simplest example of the detachable extension is:

public class DetachExample
    implements java.io.Serializable
{
    private String someField;
}



<?xml version="1.0"?>
<jdo>
  <package name="com.somecompany">
    <class name="DetachExample">
      <extension vendor-name="kodo" key="detachable" value="true"/>
    </class>
  </package>
</jdo>

As mentioned previously, when a class is declared to be detachable, the Kodo enhancer will add additional fields to the enhanced version of the class. One of these fields is of type java.lang.Object, and holds an object that refers to the class' state, so that version checking can be done when the object is re-attached. If the persistent class does not use application identity, then a second String field will be added that will be used to store the stringified object id of the instance that was detached.

It is possible to define one or both of these fields and declare them the metadata for your class, which will prevent the enhancer from adding the default fields to the class, and will keep your enhanced class serialization-compatible with the unenhanced version (in case the client tier only has the unenhanced class definition to work with). The detached-objectid-field and detached-state-field class-level metadata extensions declare these fields. These fields must not be managed by JDO (they must have their persistence-modifier attribute set to "none").

public class DetachExample
    implements java.io.Serializable
{
    private String someField;
    private String detachedObjectId;
    private Object detachedState;
}


<?xml version="1.0"?>
<jdo>
  <package name="com.somecompany">
    <class name="DetachExample">
      <extension vendor-name="kodo" key="detachable" value="true"/>
      <extension vendor-name="kodo" key="detached-objectid-field"
        value="detachedObjectId"/>
      <extension vendor-name="kodo" key="detached-state-field"
        value="detachedState"/>

      <!-- string fields are normally managed by default, so explicitly set -->
      <!-- this field to unmanaged; we don't need to worry about the        -->
      <!-- detachedState fields because fields of type java.lang.Object     -->
      <!-- are not managed by default -->
      <field name="detachedObjectId" persistence-modifier="none"/>
    </class>
  </package>
</jdo>