FAQ
Under 3.0.2, I have a test that creates a local copy of an object in a
new DataContext, makes a change to it, commits the change, and then
verifies that both the old copy and the new copy match. And this
passes.

Under 3.1, the old object does not reflect the new changes, although
the 3.x docs state that it should by default:

http://cayenne.apache.org/docs/3.1/cayenne-guide/performance-tuning.html#caching-and-fresh-data

This appears to be because there's nothing listening for the
postSnapshotsChangeEvent, maybe because there's an error in my
hand-converted modeler test configuration file.

It does look like JavaGroupsBridgeFactory gets instantiated as the
default event bridge factory, although if I don't have it installed
(which I don't) it's replaced by a noop event manager.

Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
cayenne.DataRowStore.snapshot.expiration = 7200
Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
cayenne.DataRowStore.snapshot.size = 10000
Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
cayenne.DataRowStore.remote.notify = false
Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
cayenne.DataRowStore.EventBridge.factory =
org.apache.cayenne.event.JavaGroupsBridgeFactory


So I decided to see whether I could force a refetch for the existing
object in the original database using:

         context.invalidateObjects(this);
         context.prepareForAccess(this, null, false);

prepareForAccess is pulling the old value out of the cachedSnapshots.
  This is rather unexpected since invalidateObjects() claims clears out
the cache. All I see it doing when I step through the values is
resetting the persistence state from committed to hollow. I don't
see anything in stepping through the code which would remove the cache
snapshot for the data context as documented.

     /**
      * Invalidates a Collection of persistent objects. This operation
only applies to the
      * objects already committed to the database and does nothing to
the NEW objects. It
      * would remove each object's snapshot from caches and change
object's state to
      * HOLLOW. On the next access to this object, the object will be refetched.
      */
     void invalidateObjects(Collection<?> objects);


If I manually remove the item from the cache, then it works, even
without prepareForAccess().

         ObjectContext context = getObjectContext();
         DataContext dataContext = (DataContext)context;
         dataContext.getObjectStore().getDataRowCache().forgetSnapshot(this.getObjectId());
         context.invalidateObjects(this);

It seems to me that it's a bug to not invalidate the DataContext
DataRowCache snapshot during invalidateObjects().

Search Discussions

  • Andrus Adamchik at Sep 24, 2013 at 6:16 am

    Under 3.0.2, I have a test that creates a local copy of an object in a
    new DataContext, makes a change to it, commits the change, and then
    verifies that both the old copy and the new copy match. And this
    passes.
    Could be because peer context notifications are now asynchronous and you test runs before the change is propagated? Async context synchronization is used for performance reasons and to avoid deadlocks.
    It does look like JavaGroupsBridgeFactory gets instantiated as the
    default event bridge factory, although if I don't have it installed
    (which I don't) it's replaced by a noop event manager.
    That'll be odd. Has to be something in configs.
    So I decided to see whether I could force a refetch for the existing
    object in the original database using:

    context.invalidateObjects(this);
    context.prepareForAccess(this, null, false);

    prepareForAccess is pulling the old value out of the cachedSnapshots.
    This is rather unexpected since invalidateObjects() claims clears out
    the cache.
    The context does this on invalidate:

       performGenericQuery(new RefreshQuery(objects));

    Which, after local invalidation, is propagated to DataDomain, where shared cache invalidation happens.

    Andrus

    On Sep 23, 2013, at 11:10 PM, Mike Kienenberger wrote:

    Under 3.0.2, I have a test that creates a local copy of an object in a
    new DataContext, makes a change to it, commits the change, and then
    verifies that both the old copy and the new copy match. And this
    passes.

    Under 3.1, the old object does not reflect the new changes, although
    the 3.x docs state that it should by default:

    http://cayenne.apache.org/docs/3.1/cayenne-guide/performance-tuning.html#caching-and-fresh-data

    This appears to be because there's nothing listening for the
    postSnapshotsChangeEvent, maybe because there's an error in my
    hand-converted modeler test configuration file.

    It does look like JavaGroupsBridgeFactory gets instantiated as the
    default event bridge factory, although if I don't have it installed
    (which I don't) it's replaced by a noop event manager.

    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.snapshot.expiration = 7200
    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.snapshot.size = 10000
    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.remote.notify = false
    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.EventBridge.factory =
    org.apache.cayenne.event.JavaGroupsBridgeFactory


    So I decided to see whether I could force a refetch for the existing
    object in the original database using:

    context.invalidateObjects(this);
    context.prepareForAccess(this, null, false);

    prepareForAccess is pulling the old value out of the cachedSnapshots.
    This is rather unexpected since invalidateObjects() claims clears out
    the cache. All I see it doing when I step through the values is
    resetting the persistence state from committed to hollow. I don't
    see anything in stepping through the code which would remove the cache
    snapshot for the data context as documented.

    /**
    * Invalidates a Collection of persistent objects. This operation
    only applies to the
    * objects already committed to the database and does nothing to
    the NEW objects. It
    * would remove each object's snapshot from caches and change
    object's state to
    * HOLLOW. On the next access to this object, the object will be refetched.
    */
    void invalidateObjects(Collection<?> objects);


    If I manually remove the item from the cache, then it works, even
    without prepareForAccess().

    ObjectContext context = getObjectContext();
    DataContext dataContext = (DataContext)context;
    dataContext.getObjectStore().getDataRowCache().forgetSnapshot(this.getObjectId());
    context.invalidateObjects(this);

    It seems to me that it's a bug to not invalidate the DataContext
    DataRowCache snapshot during invalidateObjects().
  • Mike Kienenberger at Sep 24, 2013 at 1:51 pm

    On Tue, Sep 24, 2013 at 2:15 AM, Andrus Adamchik wrote:
    Could be because peer context notifications are now asynchronous and you test runs before the change is propagated? Async context synchronization is used for performance reasons and to avoid deadlocks.
    That was one of my first thoughts, so first I set a breakpoint to
    insure there was enough time to propagate the changes. Then I traced
    through the event notification and found that nothing was registered
    to listening for the events.

    It does look like JavaGroupsBridgeFactory gets instantiated as the
    default event bridge factory, although if I don't have it installed
    (which I don't) it's replaced by a noop event manager.
    That'll be odd. Has to be something in configs.
    The source code indicates that JavaGroups is the default.

         public static final String EVENT_BRIDGE_FACTORY_DEFAULT =
    "org.apache.cayenne.event.JavaGroupsBridgeFactory";

    So, what should I be looking for? I have no event bridge factory
    configured in the cayenne*.xml file. This seems to match the
    tutorial projects as well as a new empty project I set up.
    Furthermore, I see no EventBridgeFactory implementations other than
    JavaGroups, JMS, and XMPP bridge factory implementations in the 3.1
    source, all of which require third-party libraries.

    Is a 3rd-party package required for this to work as advertised?


    On Sep 23, 2013, at 11:10 PM, Mike Kienenberger wrote:

    Under 3.0.2, I have a test that creates a local copy of an object in a
    new DataContext, makes a change to it, commits the change, and then
    verifies that both the old copy and the new copy match. And this
    passes.

    Under 3.1, the old object does not reflect the new changes, although
    the 3.x docs state that it should by default:

    http://cayenne.apache.org/docs/3.1/cayenne-guide/performance-tuning.html#caching-and-fresh-data

    This appears to be because there's nothing listening for the
    postSnapshotsChangeEvent, maybe because there's an error in my
    hand-converted modeler test configuration file.

    It does look like JavaGroupsBridgeFactory gets instantiated as the
    default event bridge factory, although if I don't have it installed
    (which I don't) it's replaced by a noop event manager.

    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.snapshot.expiration = 7200
    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.snapshot.size = 10000
    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.remote.notify = false
    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.EventBridge.factory =
    org.apache.cayenne.event.JavaGroupsBridgeFactory


    So I decided to see whether I could force a refetch for the existing
    object in the original database using:

    context.invalidateObjects(this);
    context.prepareForAccess(this, null, false);

    prepareForAccess is pulling the old value out of the cachedSnapshots.
    This is rather unexpected since invalidateObjects() claims clears out
    the cache. All I see it doing when I step through the values is
    resetting the persistence state from committed to hollow. I don't
    see anything in stepping through the code which would remove the cache
    snapshot for the data context as documented.

    /**
    * Invalidates a Collection of persistent objects. This operation
    only applies to the
    * objects already committed to the database and does nothing to
    the NEW objects. It
    * would remove each object's snapshot from caches and change
    object's state to
    * HOLLOW. On the next access to this object, the object will be refetched.
    */
    void invalidateObjects(Collection<?> objects);


    If I manually remove the item from the cache, then it works, even
    without prepareForAccess().

    ObjectContext context = getObjectContext();
    DataContext dataContext = (DataContext)context;
    dataContext.getObjectStore().getDataRowCache().forgetSnapshot(this.getObjectId());
    context.invalidateObjects(this);

    It seems to me that it's a bug to not invalidate the DataContext
    DataRowCache snapshot during invalidateObjects().
  • Mike Kienenberger at Sep 27, 2013 at 7:33 pm
    This is probably the biggest unresolved issue still facing me, at
    least of those I know about. Is one of the 3rd party packages
    required to make invalidateObjects() work? If not, what should I be
    using in my configuration to replace the default JavaGroups event
    bridge?
    On Tue, Sep 24, 2013 at 9:50 AM, Mike Kienenberger wrote:
    On Tue, Sep 24, 2013 at 2:15 AM, Andrus Adamchik wrote:
    Could be because peer context notifications are now asynchronous and you test runs before the change is propagated? Async context synchronization is used for performance reasons and to avoid deadlocks.
    That was one of my first thoughts, so first I set a breakpoint to
    insure there was enough time to propagate the changes. Then I traced
    through the event notification and found that nothing was registered
    to listening for the events.

    It does look like JavaGroupsBridgeFactory gets instantiated as the
    default event bridge factory, although if I don't have it installed
    (which I don't) it's replaced by a noop event manager.
    That'll be odd. Has to be something in configs.
    The source code indicates that JavaGroups is the default.

    public static final String EVENT_BRIDGE_FACTORY_DEFAULT =
    "org.apache.cayenne.event.JavaGroupsBridgeFactory";

    So, what should I be looking for? I have no event bridge factory
    configured in the cayenne*.xml file. This seems to match the
    tutorial projects as well as a new empty project I set up.
    Furthermore, I see no EventBridgeFactory implementations other than
    JavaGroups, JMS, and XMPP bridge factory implementations in the 3.1
    source, all of which require third-party libraries.

    Is a 3rd-party package required for this to work as advertised?


    On Sep 23, 2013, at 11:10 PM, Mike Kienenberger wrote:

    Under 3.0.2, I have a test that creates a local copy of an object in a
    new DataContext, makes a change to it, commits the change, and then
    verifies that both the old copy and the new copy match. And this
    passes.

    Under 3.1, the old object does not reflect the new changes, although
    the 3.x docs state that it should by default:

    http://cayenne.apache.org/docs/3.1/cayenne-guide/performance-tuning.html#caching-and-fresh-data

    This appears to be because there's nothing listening for the
    postSnapshotsChangeEvent, maybe because there's an error in my
    hand-converted modeler test configuration file.

    It does look like JavaGroupsBridgeFactory gets instantiated as the
    default event bridge factory, although if I don't have it installed
    (which I don't) it's replaced by a noop event manager.

    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.snapshot.expiration = 7200
    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.snapshot.size = 10000
    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.remote.notify = false
    Ebpp DEBUG [main 09-23 15:42:44] DataRowStore: DataRowStore property
    cayenne.DataRowStore.EventBridge.factory =
    org.apache.cayenne.event.JavaGroupsBridgeFactory


    So I decided to see whether I could force a refetch for the existing
    object in the original database using:

    context.invalidateObjects(this);
    context.prepareForAccess(this, null, false);

    prepareForAccess is pulling the old value out of the cachedSnapshots.
    This is rather unexpected since invalidateObjects() claims clears out
    the cache. All I see it doing when I step through the values is
    resetting the persistence state from committed to hollow. I don't
    see anything in stepping through the code which would remove the cache
    snapshot for the data context as documented.

    /**
    * Invalidates a Collection of persistent objects. This operation
    only applies to the
    * objects already committed to the database and does nothing to
    the NEW objects. It
    * would remove each object's snapshot from caches and change
    object's state to
    * HOLLOW. On the next access to this object, the object will be refetched.
    */
    void invalidateObjects(Collection<?> objects);


    If I manually remove the item from the cache, then it works, even
    without prepareForAccess().

    ObjectContext context = getObjectContext();
    DataContext dataContext = (DataContext)context;
    dataContext.getObjectStore().getDataRowCache().forgetSnapshot(this.getObjectId());
    context.invalidateObjects(this);

    It seems to me that it's a bug to not invalidate the DataContext
    DataRowCache snapshot during invalidateObjects().
  • Andrus Adamchik at Nov 4, 2013 at 7:03 am

    On Sep 27, 2013, at 10:32 PM, Mike Kienenberger wrote:

    This is probably the biggest unresolved issue still facing me, at
    least of those I know about. Is one of the 3rd party packages
    required to make invalidateObjects() work? If not, what should I be
    using in my configuration to replace the default JavaGroups event
    bridge?
    You will only need third-party packages (JMS, JGroups, XMPP, etc.) for notification clustering. Notifications within a single JVM are based solely on Cayenne code.

    Andrus
  • Mike Kienenberger at Nov 4, 2013 at 1:30 pm

    On Mon, Nov 4, 2013 at 2:02 AM, Andrus Adamchik wrote:
    You will only need third-party packages (JMS, JGroups, XMPP, etc.) for notification clustering. Notifications within a single JVM are based solely on Cayenne code.
    Where is the code that sets this up for the case of "within a single
    JVM"? As I mentioned before, no notifications are being sent from a
    single JVM configuration because nothing is registered to listen for
    them. I don't see anything in the code base that will listen for
    notifications for a single JVM, and the default event listener for
    Cayenne appears to be JavaGroups (but only if it's in the classpath).

    This is under 3.0 and 3.1.
  • Andrus Adamchik at Nov 4, 2013 at 1:36 pm

    On Nov 4, 2013, at 4:29 PM, Mike Kienenberger wrote:
    On Mon, Nov 4, 2013 at 2:02 AM, Andrus Adamchik wrote:
    You will only need third-party packages (JMS, JGroups, XMPP, etc.) for notification clustering. Notifications within a single JVM are based solely on Cayenne code.
    Where is the code that sets this up for the case of "within a single
    JVM"? As I mentioned before, no notifications are being sent from a
    single JVM configuration because nothing is registered to listen for
    them. I don't see anything in the code base that will listen for
    notifications for a single JVM,
    ObjectStores listen for each other’s events. See ObjectStore.setDataRowCache(..) (BTW this is the code I want to simplify per 'Removing "use shared cache” option’ thread).
    and the default event listener for
    Cayenne appears to be JavaGroups (but only if it's in the classpath).
    You have to actually make some effort to enable cross-VM events (see DataDomain.notifyingRemoteListeners). They are off by default.

    Andrus
  • Mike Kienenberger at Nov 4, 2013 at 1:45 pm

    On Mon, Nov 4, 2013 at 8:36 AM, Andrus Adamchik wrote:
    ObjectStores listen for each other’s events. See ObjectStore.setDataRowCache(..) (BTW this is the code I want to simplify per 'Removing "use shared cache” option’ thread).
    I wonder if I had unchecked "use shared cache" when I was looking into
    this problem.

    I haven't looked at this in a month, so I'll have to go review it
    again. I'll try to find some time to do that today.
  • Mike Kienenberger at Nov 4, 2013 at 3:52 pm
    I reran my tests, and, yes, the invalidateObjects is failing because I
    had sharedCacheEnabled set to false. (I had set it in my java code
    rather than in the model, so it took me awhile to find it.)

                 dataDomain.setSharedCacheEnabled(false);

    Once I change that to true, invalidateObjects works again.

    The problem appears to be in DataDomainQueryAction.interceptRefreshQuery()

                     if (domain.getSharedSnapshotCache() != null) {
                         // send an event for removed snapshots
                         domain.getSharedSnapshotCache().processSnapshotChanges(
                                 context.getObjectStore(),
                                 Collections.EMPTY_MAP,
                                 Collections.EMPTY_LIST,
                                 ids,
                                 Collections.EMPTY_LIST);
                     }

    should have an else statement along these lines.

                    else {
                          // remove snapshots from local ObjectStore only

    context.getObjectStore(),getDataRowCache().processSnapshotChanges(
                                 context.getObjectStore(),
                                 Collections.EMPTY_MAP,
                                 Collections.EMPTY_LIST,
                                 ids,
                                 Collections.EMPTY_LIST);
                   }

    On Mon, Nov 4, 2013 at 8:44 AM, Mike Kienenberger wrote:
    On Mon, Nov 4, 2013 at 8:36 AM, Andrus Adamchik wrote:
    ObjectStores listen for each other’s events. See ObjectStore.setDataRowCache(..) (BTW this is the code I want to simplify per 'Removing "use shared cache” option’ thread).
    I wonder if I had unchecked "use shared cache" when I was looking into
    this problem.

    I haven't looked at this in a month, so I'll have to go review it
    again. I'll try to find some time to do that today.
  • Mike Kienenberger at Nov 4, 2013 at 3:59 pm
    The full patch looks like it would need to be something like this:

    --- framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
        (revision 1524993)
    +++ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
        (working copy)
    @@ -272,6 +272,9 @@
                      // not sending any events - peer contexts will not
    get refreshed
                      if (domain.getSharedSnapshotCache() != null) {
                          domain.getSharedSnapshotCache().clear();
    + } else {
    + // remove snapshots from local ObjectStore only
    + context.getObjectStore().getDataRowCache().clear();
                      }
                      context.getQueryCache().clear();

    @@ -298,8 +301,16 @@
                                  Collections.EMPTY_LIST,
                                  ids,
                                  Collections.EMPTY_LIST);
    + } else {
    + // remove snapshots from local ObjectStore only
    +
    context.getObjectStore().getDataRowCache().processSnapshotChanges(
    + context.getObjectStore(),
    + Collections.EMPTY_MAP,
    + Collections.EMPTY_LIST,
    + ids,
    + Collections.EMPTY_LIST);
                      }

                      GenericResponse response = new GenericResponse();
                      response.addUpdateCount(1);
                      this.response = response;


    On Mon, Nov 4, 2013 at 10:48 AM, Mike Kienenberger wrote:
    I reran my tests, and, yes, the invalidateObjects is failing because I
    had sharedCacheEnabled set to false. (I had set it in my java code
    rather than in the model, so it took me awhile to find it.)

    dataDomain.setSharedCacheEnabled(false);

    Once I change that to true, invalidateObjects works again.

    The problem appears to be in DataDomainQueryAction.interceptRefreshQuery()

    if (domain.getSharedSnapshotCache() != null) {
    // send an event for removed snapshots
    domain.getSharedSnapshotCache().processSnapshotChanges(
    context.getObjectStore(),
    Collections.EMPTY_MAP,
    Collections.EMPTY_LIST,
    ids,
    Collections.EMPTY_LIST);
    }

    should have an else statement along these lines.

    else {
    // remove snapshots from local ObjectStore only

    context.getObjectStore(),getDataRowCache().processSnapshotChanges(
    context.getObjectStore(),
    Collections.EMPTY_MAP,
    Collections.EMPTY_LIST,
    ids,
    Collections.EMPTY_LIST);
    }

    On Mon, Nov 4, 2013 at 8:44 AM, Mike Kienenberger wrote:
    On Mon, Nov 4, 2013 at 8:36 AM, Andrus Adamchik wrote:
    ObjectStores listen for each other’s events. See ObjectStore.setDataRowCache(..) (BTW this is the code I want to simplify per 'Removing "use shared cache” option’ thread).
    I wonder if I had unchecked "use shared cache" when I was looking into
    this problem.

    I haven't looked at this in a month, so I'll have to go review it
    again. I'll try to find some time to do that today.
  • Mike Kienenberger at Nov 4, 2013 at 4:33 pm
    The only concern I have with my patch is whether sending out events
    will cause a problem, or whether it's even necessary to send out
    events when there's no shared snapshot cache. Maybe the snapshot
    should be cleared without sending out the events.
    On Mon, Nov 4, 2013 at 10:59 AM, Mike Kienenberger wrote:
    The full patch looks like it would need to be something like this:

    --- framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
    (revision 1524993)
    +++ framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/DataDomainQueryAction.java
    (working copy)
    @@ -272,6 +272,9 @@
    // not sending any events - peer contexts will not
    get refreshed
    if (domain.getSharedSnapshotCache() != null) {
    domain.getSharedSnapshotCache().clear();
    + } else {
    + // remove snapshots from local ObjectStore only
    + context.getObjectStore().getDataRowCache().clear();
    }
    context.getQueryCache().clear();

    @@ -298,8 +301,16 @@
    Collections.EMPTY_LIST,
    ids,
    Collections.EMPTY_LIST);
    + } else {
    + // remove snapshots from local ObjectStore only
    +
    context.getObjectStore().getDataRowCache().processSnapshotChanges(
    + context.getObjectStore(),
    + Collections.EMPTY_MAP,
    + Collections.EMPTY_LIST,
    + ids,
    + Collections.EMPTY_LIST);
    }

    GenericResponse response = new GenericResponse();
    response.addUpdateCount(1);
    this.response = response;


    On Mon, Nov 4, 2013 at 10:48 AM, Mike Kienenberger wrote:
    I reran my tests, and, yes, the invalidateObjects is failing because I
    had sharedCacheEnabled set to false. (I had set it in my java code
    rather than in the model, so it took me awhile to find it.)

    dataDomain.setSharedCacheEnabled(false);

    Once I change that to true, invalidateObjects works again.

    The problem appears to be in DataDomainQueryAction.interceptRefreshQuery()

    if (domain.getSharedSnapshotCache() != null) {
    // send an event for removed snapshots
    domain.getSharedSnapshotCache().processSnapshotChanges(
    context.getObjectStore(),
    Collections.EMPTY_MAP,
    Collections.EMPTY_LIST,
    ids,
    Collections.EMPTY_LIST);
    }

    should have an else statement along these lines.

    else {
    // remove snapshots from local ObjectStore only

    context.getObjectStore(),getDataRowCache().processSnapshotChanges(
    context.getObjectStore(),
    Collections.EMPTY_MAP,
    Collections.EMPTY_LIST,
    ids,
    Collections.EMPTY_LIST);
    }

    On Mon, Nov 4, 2013 at 8:44 AM, Mike Kienenberger wrote:
    On Mon, Nov 4, 2013 at 8:36 AM, Andrus Adamchik wrote:
    ObjectStores listen for each other’s events. See ObjectStore.setDataRowCache(..) (BTW this is the code I want to simplify per 'Removing "use shared cache” option’ thread).
    I wonder if I had unchecked "use shared cache" when I was looking into
    this problem.

    I haven't looked at this in a month, so I'll have to go review it
    again. I'll try to find some time to do that today.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupuser @
categoriescayenne
postedSep 23, '13 at 8:11p
activeNov 4, '13 at 4:33p
posts11
users2
websitecayenne.apache.org

People

Translate

site design / logo © 2022 Grokbase