Bug 118416

Summary: Category root object map associations are not bi-directional
Product: [Retired] Red Hat Web Application Framework Reporter: Daniel BerrangĂ© <berrange>
Component: otherAssignee: Vadim Nasardinov <vnasardinov>
Status: CLOSED RAWHIDE QA Contact:
Severity: high Docs Contact:
Priority: medium    
Version: nightlyCC: archit.shah
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2004-04-06 14:39:10 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 113496    
Attachments:
Description Flags
current failing patch none

Description Daniel Berrangé 2004-03-16 15:48:35 UTC
Description of problem:
The UseContext object forms a mapping between a root category and an
object (typically, but not always, an application). This map is formed
by two associations, one between Cateory & UseContext, the other
between UseContext and ACSObject. Unfortunately both of  these
associations are uni-directional starting from the UseContext. This
makes it impossible to take, for example, a colleciton of Application
objects and join across the use context to their root categories. This
is very important when using metadata driven tools such as the
DomainObjectXMLRenderer.


Version-Release number of selected component (if applicable):


How reproducible:


Steps to Reproduce:
1. Try to write code that follows the assocation from an ACSObject,
across the usecontext, to the root category
2.
3.
  
Actual results:

Expected results:


Additional info:
The associations shoudl be defined as standlone blocks, something like

association {
  UseContext[0..1] ownerUseContext = join cat_categories.category_id
                                       to
cat_root_cat_object_map.category_id;
  Category[1..1] rootCategory = join cat_root_cat_object_map.category_id
                                  to cat_categories.category_id;
}

association {
  UseContext[0..1] rootUseContext = join acs_objects.object_id
                                      to
cat_root_cat_object_map.object_id;
  ACSObject[1..1] categoryOwner = join cat_root_cat_object_map.object_id
                                    to acs_objects.object_id;
}

Comment 1 Vadim Nasardinov 2004-03-17 20:46:57 UTC
Created attachment 98613 [details]
current failing patch

Apply this patch and observe IsolatedTest fail, when called like so:

$ ant -Djunit.suite=CategorizationSuite.class \
  -Djunit.test=IsolatedTest.class runtests

Comment 2 Vadim Nasardinov 2004-03-17 21:10:24 UTC
(Cc'ing Archit.)

I can't get this thing to work.  I changed Category.pdl like so:

|object type UseContext {
|    BigDecimal[1..1] id = cat_root_cat_object_map.id;
|
|    String[0..1] useContext = cat_root_cat_object_map.use_context;
|
|    unique (categoryOwner, useContext);
|    object key (id);
|}
|
|association {
|    UseContext[0..1] ownerUseContext = join cat_categories.category_id
|                                         to cat_root_cat_object_map.category_id;
|
|    Category[1..1] rootCategory = join cat_root_cat_object_map.category_id
|                                    to cat_categories.category_id;
|}
|
|association {
|    UseContext[0..1] rootUseContext = join acs_objects.object_id
|                                        to cat_root_cat_object_map.object_id;
|
|    ACSObject[1..1] categoryOwner = join cat_root_cat_object_map.object_id
|                                      to acs_objects.object_id;
|}

As far as I can tell, this shouldn't require any changes to
Category.java.  From the "UseContext" perspective, the logical model
hasn't changed.  (From the "ACSObject" or "Category" perspective, it
has.  These objects have acquired the attributes "rootUseContext" and
"ownerUseContext" respectively.)

The testGetRootCategories test in UseContextTest fails.

|$ p4 print //core-platform/dev/.../UseContextTest.java#4 | \
|  grep -v '//core' | cat -n - | head -n 86 | tail -n 8
|    79      public void testGetRootCategories() {
|    80          Map map = new HashMap(3);
|    81          Category.setRootForObject(group1, root1, CTX1);
|    82          map.put(CTX1, root1);
|    83          Category.setRootForObject(group1, root2, CTX2);
|    84          map.put(CTX2, root2);
|    85          Category.setRootForObject(group1, root3, CTX3);
|    86          map.put(CTX3, root3);


What happens is, the call to setRootForObject at line 81 generates an
insert into cat_root_cat_object_map.  A similar call to the same
method at line 83 generates no inserts.  Trying to force a flush by
calling save() results in the following error:

    Unable to send all events to database for object
      [com.arsdigita.categorization.UseContext:{id=25008}]
    because these required properties are null:
      [com.arsdigita.categorization.UseContext:{id=25007}].categoryOwner

The error makes no sense to me.  In this particular example, 25008 is
the id of the "UseContext" object created by call to setRootForObject
at line 83, whereas 25007 is the id of the "UseContext" object created
at line 81.  Watching the logs, I do see a successful insertion of the
25007 object into cat_root_cat_object_map.

Attachment 98613 [details] (see comment #1) contains a patch with the described
changes to Category.pdl and some instrumentation to help diagnose the
error.  You should be able the patch by fixing the paths in the three
places to reflect your particular p4 layout, and then running

$ patch -p0 < use-context.patch


P.S.
    Either I'm doing something really dumb, or it's a persistence edge
    case that we haven't seen before, due to the fact that we don't
    have a similar PDL model anywhere else in our code.  Note that in
    both association blocks, the multiplicities of both ends of the
    association are no greater than 1.  One end is 0..1 while the
    other is 1..1.  I could find only two other places in our code
    where a somewhat similar logical model is employed.

    In //core-platform/dev/pdl/com/arsdigita/web/Application.pdl,

        association {
            PackageInstance[0..1] packageInstance =
            Application[0..1] application =
        }

    In //cms/dev/pdl/com/arsdigita/content-section/Folder.pdl,

        association {
            ContentItem[0..1] index = 
            Folder[0..1] indexed = 
        }

    In all other cases, at least of the ends of the association has a
    multiplicity of 0..n.


Comment 3 Vadim Nasardinov 2004-03-18 17:16:27 UTC
Ok, Archit figured it out.  The multiplicities were wrong.  In both
cases, we should have
   UseContext[0..n]

instead of
   UseContext[0..n]

I'm going to ask Dennis to give me write permission on the trunk,
so I can commit this change.


(This is like the third or fourth time I forget to change 
multiplicities correctly when converting an object type to an
association block.)

Comment 4 Vadim Nasardinov 2004-03-18 17:24:54 UTC
I meant,
  "instead of UseContext[0..1]"