You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/07/31 09:40:08 UTC

svn commit: r1508746 - in /isis/site/trunk/content: ./ applib-guide/how-tos/ applib-guide/reference/ components/objectstores/jdo/ core/

Author: danhaywood
Date: Wed Jul 31 07:40:08 2013
New Revision: 1508746

URL: http://svn.apache.org/r1508746
Log:
managed 1-m relationships, contract tests, utility classes

Added:
    isis/site/trunk/content/components/objectstores/jdo/managed-1-to-m-relationships.md
Modified:
    isis/site/trunk/content/applib-guide/how-tos/how-to-04-060-How-to-set-up-and-maintain-bidirectional-relationships.md
    isis/site/trunk/content/applib-guide/reference/Utility.md
    isis/site/trunk/content/components/objectstores/jdo/about.md
    isis/site/trunk/content/core/unittestsupport.md
    isis/site/trunk/content/documentation.md

Modified: isis/site/trunk/content/applib-guide/how-tos/how-to-04-060-How-to-set-up-and-maintain-bidirectional-relationships.md
URL: http://svn.apache.org/viewvc/isis/site/trunk/content/applib-guide/how-tos/how-to-04-060-How-to-set-up-and-maintain-bidirectional-relationships.md?rev=1508746&r1=1508745&r2=1508746&view=diff
==============================================================================
--- isis/site/trunk/content/applib-guide/how-tos/how-to-04-060-How-to-set-up-and-maintain-bidirectional-relationships.md (original)
+++ isis/site/trunk/content/applib-guide/how-tos/how-to-04-060-How-to-set-up-and-maintain-bidirectional-relationships.md Wed Jul 31 07:40:08 2013
@@ -1,6 +1,10 @@
 How to set up and maintain bidirectional relationships
 ------------------------------------------------------
 
+> **Note**: 
+> 
+> If using the [JDO Objectstore](../../components/objectstores/jdo/about.html) then there is generally no need to explicitly maintain bidirectional relationships.  Indeed, doing so may cause subtle errors.  See [here](../../components/objectstores/jdo/managed-1-to-m-relationships.html) for more details.
+
 The modifyXxx() and clearXxx() methods (see ?) can be used to setup
 bidirectional relationships. This is typically done with 1:m
 relationships, eg between Order and OrderLine, or Department and
@@ -8,20 +12,19 @@ Employee.
 
 The recommended way of maintaining a bidirectional relationship is to
 use the 'mutual registration pattern', a write-up of which can be found
-at
-<http://www.two-sdg.demon.co.uk/curbralan/papers/MutualRegistration.pdf>.
+[here](http://www.two-sdg.demon.co.uk/curbralan/papers/MutualRegistration.pdf).
 The general idea is that one side of the relationship is responsible for
 maintaining the associations, while the other side simply delegates.
 
-To implement this in *Isis* for a 1:m relationship, use the addToXxx() /
-removeFromXxx() and modifyXxx() / clearXxx() methods.
+To implement this in *Isis* for a 1:m relationship, use the `addToXxx()` /
+`removeFromXxx()` and the `modifyXxx()` / `clearXxx()` methods.
 
 For example:
 
     public class Department {
-        private List<Employee> employees = new ArrayList<Employee>();
-        public List<Employee> getEmployees() { ... }
-        private void setEmployees(List<Employee> employees) { ... }
+        private SortedSet<Employee> employees = new TreeSet<Employee>();
+        public SortedSet<Employee> getEmployees() { ... }
+        private void setEmployees(SortedSet<Employee> employees) { ... }
         public void addToEmployees(Employee e) {
             if(e == null || employees.contains(e)) return;
             e.setDepartment(this);
@@ -55,8 +58,3 @@ and
         ...
     }
 
-> **Note**
->
-> For some object stores this explicit coding may not be necessary; the
-> object store automatically maintains the relationship.
-

Modified: isis/site/trunk/content/applib-guide/reference/Utility.md
URL: http://svn.apache.org/viewvc/isis/site/trunk/content/applib-guide/reference/Utility.md?rev=1508746&r1=1508745&r2=1508746&view=diff
==============================================================================
--- isis/site/trunk/content/applib-guide/reference/Utility.md (original)
+++ isis/site/trunk/content/applib-guide/reference/Utility.md Wed Jul 31 07:40:08 2013
@@ -1,20 +1,17 @@
-Utility Classes
-===============
+title: Utility Classes
 
 > Simple utility classes for domain objects.
 
 The `org.apache.isis.applib.util` package has a number of simple utility
 classes designed to simplify the coding of some common tasks.
 
-Title creation
---------------
+## Title creation
 
 The `TitleBuffer` utility class is intended to make it easy to construct
 title strings (returned from the `title()` method). For example, it has
 overloaded versions of methods called `append()` and `concat()`.
 
-Reason text creation (for disable and validate methods)
--------------------------------------------------------
+##Reason text creation (for disable and validate methods)
 
 There are two different classes provided to help build reasons returned
 by `disableXxX()` and `validateXxx()` methods:
@@ -36,3 +33,30 @@ For example:
     }
 
 Which you use (if any) is up to you.
+
+##ObjectContracts
+
+The `ObjectContracts` test provides a series of methods to make it easy for your domain objects to:
+
+* implement `Comparable` (eg so can be stored in `java.util.SortedSet`s)
+* implement `toString()`
+* implement `equals()`
+* implement `hashCode()`
+
+For example:
+
+    public class ToDoItem implements Comparable<ToDoItem> {
+
+        public boolean isComplete() { ... }
+        public LocalDate getDueBy() { ... }
+        public String getDescription() { ... }
+        public String getOwnedBy() { ... }
+
+        public int compareTo(final ToDoItem other) {
+            return ObjectContracts.compare(this, other, "complete,dueBy,description");
+        }
+
+        public String toString() {
+            return ObjectContracts.toString(this, "description,complete,dueBy,ownedBy");
+        }
+    } 
\ No newline at end of file

Modified: isis/site/trunk/content/components/objectstores/jdo/about.md
URL: http://svn.apache.org/viewvc/isis/site/trunk/content/components/objectstores/jdo/about.md?rev=1508746&r1=1508745&r2=1508746&view=diff
==============================================================================
--- isis/site/trunk/content/components/objectstores/jdo/about.md (original)
+++ isis/site/trunk/content/components/objectstores/jdo/about.md Wed Jul 31 07:40:08 2013
@@ -8,6 +8,7 @@ The DataNucleus objectstore enables the 
 - [DataNucleus and Maven](datanucleus-and-maven.html)
 - [`persistence.xml` file](persistence_xml.html)
 - [Dates, Blobs and Lazy Loading](dates-blobs-lazy-loading.html)
+- [Managed 1:m bidirectional relationships](managed-1-to-m-relationships.html)
 - [Using a JNDI Datasource](using-jndi-datasource.html)
 - [Workarounds (the `IsisJdoSupport` service)](workarounds.html)
 - [Enabling Logging](enabling-logging.html)

Added: isis/site/trunk/content/components/objectstores/jdo/managed-1-to-m-relationships.md
URL: http://svn.apache.org/viewvc/isis/site/trunk/content/components/objectstores/jdo/managed-1-to-m-relationships.md?rev=1508746&view=auto
==============================================================================
--- isis/site/trunk/content/components/objectstores/jdo/managed-1-to-m-relationships.md (added)
+++ isis/site/trunk/content/components/objectstores/jdo/managed-1-to-m-relationships.md Wed Jul 31 07:40:08 2013
@@ -0,0 +1,41 @@
+Title: Managed 1:m bidirectional relationships
+
+When an object is added to a 1:m bidirectional relationship, the child object must refer to the parent and the child must be added to the parent's children collection.
+
+In general, *Isis* recommends that the mutual registration pattern is ensure that both the parent and child are updated correctly; the framework supports the `modifyXxx()` and `clearXxx()` methods to accomplish this, and this [how-to](../../../applib-guide/how-tos/how-to-04-060-How-to-set-up-and-maintain-bidirectional-relationships.html) describes the boilerplate necessary.  
+
+However, in a relational database, these two operations in the domain object model correspond simply to updating the foreign key of the child table to reference the parent's primary key.
+
+So long as the parent's children collection is a `java.util.Set` (rather than a `Collection` or a `List`), the JDO Objectstore will automatically maintain both sides of the relationship.  All that is necessary is to set the child to refer to the parent.
+  
+For example
+
+    public class Department {
+
+        @javax.jdo.annotations.Persistent(mappedBy="department")
+        private SortedSet<Employee> employees = new TreeSet<Employee>();
+
+        public SortedSet<Employee> getEmployees() { ... }
+        public void setEmployees(SortedSet<Employee> employees) { ... }
+        ...
+    }
+
+and
+
+    public class Employee {
+        private Department department;
+        public Department getDepartment() { ... }
+        public void setDepartment(Department department) { ... }
+        ...
+    }
+
+Contrast the above with the programmatic maintenance described in the [how-to](../../../applib-guide/how-tos/how-to-04-060-How-to-set-up-and-maintain-bidirectional-relationships.html).
+
+> **Note**
+> 
+In fact, not only do you not need to manually maintain the relationship, we have noted on at least [one occasion](http://markmail.org/message/agnwmzocvdfht32f) a subtle error if the code is programmatically added.
+>
+The error in that case was that the same object was contained in the parents collection.  This of course should not happen for a `TreeSet`.  However, JDO/DataNucleus replaces the `TreeSet` with its own implementation, and (either by design or otherwise) this does not enforce `Set` semantics.
+>
+The upshot is that you should NEVER programmatically add the child object to the parent's collection if using JDO Objectstore.
+

Modified: isis/site/trunk/content/core/unittestsupport.md
URL: http://svn.apache.org/viewvc/isis/site/trunk/content/core/unittestsupport.md?rev=1508746&r1=1508745&r2=1508746&view=diff
==============================================================================
--- isis/site/trunk/content/core/unittestsupport.md (original)
+++ isis/site/trunk/content/core/unittestsupport.md Wed Jul 31 07:40:08 2013
@@ -11,13 +11,91 @@ To use, update the `pom.xml`:
     &lt;/dependency&gt;
 </pre>
 
-##Bidirectional Contract Tests [1.3.0-SNAPSHOT]
 
-Automatically tests that bidirectional 1:m or 1:1 associations are being maintained correctly (assuming that they follow the [mutual registration pattern](../applib-guide/how-tos/how-to-04-060-How-to-set-up-and-maintain-bidirectional-relationships.html)
+##SortedSets Contract Test [1.3.0-SNAPSHOT]
+
+This contract test automatically checks that all fields of type `java.util.Collection` are declared as `java.util.SortedSet`.  In other words, it precludes either `java.util.List` or `java.util.Set` from being used as a collection.
+
+
+For example, the following passes the contract test:
+
+    public class Department {
+        
+        private SortedSet<Employee> employees = new TreeSet<Employee>();
+    
+        ...
+    }
+
+whereas this would not:
+
+    public class SomeDomainObject {
+        
+        private List<Employee> employees = new ArrayList<Employee>();
+    
+        ...
+    }
+
+If using the JDO Objectstore then we strongly recommend that you implement this test, for several reasons:
+
+* First, `Set`s align more closely to the relational model than do `List`s.  A `List` must have an additional index to specify order.
+
+* Second, `SortedSet` is preferable to `Set` because then the order is well-defined and predictable (to an end user, to the programmer).
+
+    The [ObjectContracts](../applib-guide/reference/Utility.html) utility class substantially simplifies the task of implementing `Comparable` in your domain classes. 
+
+* Third, if the relationship is bidirectional then JDO/Objectstore will automatically maintain the relationship.  See [here](../components/objectstores/jdo/managed-1-to-m-relationships.html) for further discussion.    
+
+To use the contract test, subclass `SortedSetsContractTestAbstract`, specifying the root package to search for domain classes.
+
+For example:
+
+    public class SortedSetsContractTestAll extends SortedSetsContractTestAbstract {
+    
+        public SortedSetsContractTestAll() {
+            super("org.estatio.dom");
+            withLoggingTo(System.out);
+        }
+    }
+
+##Injected Services Method Contract Test [1.3.0-SNAPSHOT]
+
+It is quite common for some basic services to be injected in a project-specific domain object superclass; for example a `ClockService` might generally be injected everywhere:
+
+    public abstract class EstatioDomainObject {
+        protected ClockService clockService;
+        public void injectClockService(ClockService clockService) {
+            this.clockService = clockService;
+        }
+    }
+
+If a subclass inadvertantly overrides this method and provides its own `ClockService` field, then the field in the superclass will never initialized.  As you might imagine, `NullPointerException`s could then arise.
+
+This contract test automatically checks that the `injectXxx(...)` method, to allow for injected services, is not overridable, ie `final`.
+
+To use the contract test, , subclass `SortedSetsContractTestAbstract`, specifying the root package to search for domain classes.
+
+For example:
+
+    public class InjectServiceMethodMustBeFinalContractTestAll extends InjectServiceMethodMustBeFinalContractTestAbstract {
+    
+        public InjectServiceMethodMustBeFinalContractTestAll() {
+            super("org.estatio.dom");
+            withLoggingTo(System.out);
+        }
+    }
+
+
+##Bidirectional Contract Test [1.3.0-SNAPSHOT]
+
+This contract test automatically checks that bidirectional 1:m or 1:1 associations are being maintained correctly (assuming that they follow the [mutual registration pattern](../applib-guide/how-tos/how-to-04-060-How-to-set-up-and-maintain-bidirectional-relationships.html)
+
+>
+**Note:** 
+>
+If using the [JDO Object Store](../components/objectstores/jdo/about.html), then there is generally no need to programmatically maintain 1:m relationships (indeed it may introduce subtle errors).  For more details, see [here](../components/objectstores/jdo/managed-1-to-m-relationships.html).
+
+>If *not* using the JDO Object Store, note that *Isis* provides [Eclipse templates](../getting-started/editor-templates.html) to help generate the necessary boilerplate.
 
-{note
-Isis provides [Eclipse templates](../getting-started/editor-templates.html) to help generate the necessary boilerplate.
-}
 
 For example, suppose that `ParentDomainObject` and `ChildDomainObject` have a 1:m relationship (`ParentDomainObject#children` / `ChildDomainObject#parent`), and also `PeerDomainObject` has a 1:1 relationship with itself (`PeerDomainObject#next` / `PeerDomainObject#previous`).  
 

Modified: isis/site/trunk/content/documentation.md
URL: http://svn.apache.org/viewvc/isis/site/trunk/content/documentation.md?rev=1508746&r1=1508745&r2=1508746&view=diff
==============================================================================
--- isis/site/trunk/content/documentation.md (original)
+++ isis/site/trunk/content/documentation.md Wed Jul 31 07:40:08 2013
@@ -11,6 +11,7 @@ Title: Documentation
 - [Screencasts](getting-started/screencasts.html)
 - [Wicket/Restful/JDO Archetype](getting-started/quickstart-archetype.html) ([1.0.3](getting-started/release-notes/about.html))
 - [Programming Model and How-tos](applib-guide/about.html)
+- [Applib utility classes](applib-guide/reference/Utility.html)
 - [Static and dynamic layouts](core/dynamic-layouts.html)
 - [Programming Model Cheat Sheet](getting-started/cheat-sheet.html)
 
@@ -191,7 +192,8 @@ Note: this viewer is third-party open so
 - [DataNucleus and Eclipse](components/objectstores/jdo/datanucleus-and-eclipse.html)
 - [DataNucleus and Maven](components/objectstores/jdo/datanucleus-and-maven.html)
 - [`persistence.xml` file](components/objectstores/jdo/persistence_xml.html)
-- [Dates, Blobs and Lazy Loading](components/objectstores/jdo/dates-blobs-lazy-loading.html)
+- [Dates, Blobs and Lazy Loading](components/objectstores/jdo/dates-blobs-lazy-loading.html)
+- [Managed 1:m bidirectional relationships](components/objectstores/jdo/managed-1-to-m-relationships.html)
 - [Using a JNDI Datasource](components/objectstores/jdo/using-jndi-datasource.html)
 - [Workarounds](components/objectstores/jdo/workarounds.html)
 - [Enabling Logging](components/objectstores/jdo/enabling-logging.html)