The ability to atomically either select or create a uniquely
keyed object (see the section called “Atomic Create or Select” for more
details) is supported in the secondary store notifiers by a series of
notifier calls depending on whether the object exists in shared memory
after the Query<T>.query
method is called. If the
object exists, no other notifier entry points are called. If the object
does not exist, the object is created in shared memory by the
TIBCO ActiveSpaces® Transactions
runtime and then the
Record<T>.created
notifier is called.
This behavior is shown in Example 10.6, “Atomic create or select”.
Example 10.6. Atomic create or select
// $Revision: 1.1.2.2 $ package com.kabira.snippets.store; import com.kabira.platform.KeyFieldValueList; import com.kabira.platform.KeyManager; import com.kabira.platform.KeyQuery; import com.kabira.platform.LockMode; import com.kabira.platform.Transaction; import com.kabira.platform.annotation.Key; import com.kabira.platform.annotation.Managed; import com.kabira.store.KeyField; import com.kabira.store.Query; import com.kabira.store.Record; import java.util.ArrayList; /** * Secondary store notifier behavior with an atomic select or create query * <p> * <h2> Target Nodes</h2> * <ul> * <li> <b>domainnode</b> = A * </ul> */ public class AtomicCreateSelect { @Managed @Key(name = "ByName", unique = true, ordered = true, fields = { "m_name" }) private static class A { private A(final String name) { m_name = name; } String getName() { return m_name; } private final String m_name; }; private static class RecordNotifier extends Record<A> { public RecordNotifier() { super(A.class); } @Override public void created(A a) { System.out.println("INFO:\tCreated " + a.getName()); } } private static class QueryNotifier extends Query<A> { public QueryNotifier() { super(A.class, "ByName"); } @Override public void query(Class<? extends A> klass, LockMode lockMode, ArrayList<KeyField> queryData) { assert queryData.size() == 1 : queryData.size(); assert queryData.get(0).name.equals("m_name") : queryData.get(0); assert queryData.get(0).value instanceof String : queryData.get(0); String value = (String) queryData.get(0).value; if (m_create == true) { System.out.println("INFO:\tQuery creating object for " + value); new A(value); m_create = false; } else { System.out.println("INFO:\tQuery NOT creating object for " + value); } } @Override public void queryMinimum(Class<? extends A> klass, LockMode lm, ArrayList<KeyField> al) { assert false : "queryMinimum"; } @Override public void queryMaximum(Class<? extends A> klass, LockMode lm, ArrayList<KeyField> al) { assert false : "queryMaximum"; } private boolean m_create = true; } /** * Main entry point * @param args Not used */ public static void main (final String [ ] args) { new Transaction("Initialize") { @Override protected void run() { new RecordNotifier(); new QueryNotifier(); } }.execute(); new Transaction("Create or Select") { @Override protected void run() { KeyManager<A> km = new KeyManager<>(); KeyQuery<A> kq = km.createKeyQuery(A.class, "ByName"); KeyFieldValueList values = new KeyFieldValueList(); values.add("m_name", "foo"); kq.defineQuery(values); System.out.println("INFO: " + kq); A a = kq.getOrCreateSingleResult(LockMode.WRITELOCK, null); System.out.println("INFO: Returned " + a.getName()); values.clear(); values.add("m_name", "bar"); kq.defineQuery(values); System.out.println("INFO: " + kq); a = kq.getOrCreateSingleResult(LockMode.WRITELOCK, null); System.out.println("INFO: Returned " + a.getName()); } }.execute(); } }
Example 10.6, “Atomic create or select” outputs these message when run (annotation added):
# # Query<T>.query creates object in shared memory # INFO: select obj from com.kabira.snippets.store.AtomicCreateSelect$A using ByName where (m_name == foo); Java constructor: (none) INFO: Query creating object for foo INFO: Returned foo # # Query<T>.query does not create object in shared memory # Object is created by the runtime and the Record<T>created # notifier is called # INFO: select obj from com.kabira.snippets.store.AtomicCreateSelect$A using ByName where (m_name == bar); Java constructor: (none) INFO: Query NOT creating object for bar INFO: Returned bar INFO: Created bar