Bug 101150

Summary: ContentSection doesn't have a DomainObjectInstantiator
Product: [Retired] Red Hat Enterprise CMS Reporter: Rafael H. Schloming <rafaels>
Component: otherAssignee: Jon Orris <jorris>
Status: CLOSED WONTFIX QA Contact: Jon Orris <jorris>
Severity: high Docs Contact:
Priority: high    
Version: nightlyCC: goldfish, tross
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: 2006-09-05 17:56:53 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:

Description Rafael H. Schloming 2003-07-29 16:56:23 UTC
The SectionInitializer only registers a DomainObjectInstantiator when it
initially installs the content section. This means on the next server start no
instantiator gets registered for any content sections and everything breaks.

Comment 1 Rafael H. Schloming 2003-07-29 17:09:13 UTC
Another thing I should note is that even if this is fixed the same instantiator
will be registered multiple times (once for each SectionInitializer that is
present in enterprise.init).

Comment 2 Jon Orris 2003-07-29 17:23:46 UTC
Strange that it doesn't appear to affect the server.

The duplicate registration shouldn't be a problem, as the root of the
DomainObjectFactory impl is just a Map, and it'll overwrite the old object.

Given that the following is a common pattern:
        setup.setInstantiator(new ACSObjectInstantiator() {
            public DomainObject doNewInstance(DataObject dataObject) {
                return new ContentSection(dataObject);
            }

Perhaps this could be handled automatically by the DomainObjectFactory.
Something like the following psuedo code:

If instantiator is null
  if type is ACSObject
   registerInstantiator(type,  new ACSObjectInstantiator() {
            public DomainObject doNewInstance(DataObject dataObject) {
                type.reflectionConstructor(dataObject)
            }
  else 
    register a DomainObjectInstantiator


Comment 3 Jon Orris 2003-07-29 18:50:19 UTC
My idea is essentially domain.ReflectionInstantiator, which isn't working anyhow.
See IRC Log:

<danpb> why exactly do we need to register instantiators for all these things ?
<danpb> shouldn't the ReflectionInstantiator registered against ACSObject work ?
<danpb> (for every thing that is an ACSObject only, of course)
<danpb> you'd only need the custom instantiator if you MyObject(DataObject dobj)
constructor wasn't public
<jorris_home> danpb: Interesting. I didn't know about ReflectionInstantiator.
rhs says it doesn't appear to be working for ContentSection
<jorris_home> And it's constructor is public
<danpb> hmm, that's odd
* jorris_home looks at code...
<jorris_home> It doesn't seem as though it's used that way.
ReflectionInstantiator is used by ACSObject instantiator.
<jorris_home> So it is used, indirectly. A specific type, say ContentSection, is
mapped to an anonymous inner class of ACSObjectInstantiator, which may use
ReflectionInstantiator.
<jorris_home> But there doesn't appear, in my brief search, to be any logic in
DomainObjectFactory that says:
<jorris_home> if no instantiator for Type, try a ReflectionInstantiator.
<danpb> no, that logic in in ACSObjectInstantiator
<danpb> hmm
<danpb> ok, what happens is thus:
<danpb> DOF looks up instantiator for ContentSection
<danpb> there isn't one, so it tries its super type
<danpb> evenntually it comes across ACSObjectInstantiator
<danpb> DOF then calls the resolveInstantiator method on this
<danpb> this will return an instance of ReflectionInstantiator to do the work
<danpb> i know this must be working (for some types at least) because I got an
error in it the other day, when my constructor was brokenm
<danpb> so maybe it is an instantiator registered to some type *between*
ACSObject & ContentSection that's screwing things up
<danpb> Application / Resource for example
<jorris_home> Maybe.
<jorris_home> I'm running tests locally to see.
<rhs> It's possible, the exception is thrown on line 137 of DomainObjectFactory.java
<rhs> That means that one of the calls to resolveInstantiator returned null.
<rhs> What is truly screwed up about this is that depending on the type of the
OID or DataObject at the time you pass it into DomainObjectFactory you will get
different instantiators.
<danpb> personally I think the resolverInstantiator bit is just 'smoking crack'
<jorris_home> what is crack?
<jorris_home> ccmbot: hello?
<ccmbot> hi jorris_home
<jorris_home> ccmbot: what is crack?
<ccmbot> jorris_home: Sorry, I've no idea what 'crack' is.
<danpb> once DOF gets an instantiator for a type it should call doNewInstance
immediately
<rhs> That still doesn't solve the problem.
<danpb> no, just makes mee feel better ;-)
<rhs> If I pass in an OID with an ACSObject type I'm going to get a different
answer than if I pass in the same OID with a ContentSection type.
<justin_> off topic but related: that resources are using ACSObjectInstantiator
was never intended.  resources have explicit modeling of type metadata, and they
should use that.  So, I'll probably add a ResourceInstantiator that knows to do
the right thing and change ResourceSetup class to use it (but only after rc1).
<jparsons> I agree with you Justin...I was thinking those same thoughts as I
watch this thread...
<jorris_home> 2003-07-29 14:06:33,506 [ main] WARN  framework.BaseTestCase -
com.arsdigita.cms.ContentSectionTest.testDeleteSection started
<jorris_home> 2003-07-29 14:06:36,906 [ main] INFO  domain.DomainObjectFactory -
Instantiating [com.arsdigita.cms.ContentSection:{id=25005}]
<jorris_home> 2003-07-29 14:06:36,906 [ main] DEBUG domain.DomainObjectFactory -
Initial type ContentSection
<jorris_home> 2003-07-29 14:06:36,906 [ main] DEBUG domain.DomainObjectFactory -
Parent type Application
<jorris_home> 2003-07-29 14:06:36,906 [ main] DEBUG domain.DomainObjectFactory -
Parent type Resource
<jorris_home> 2003-07-29 14:06:36,906 [ main] DEBUG domain.DomainObjectFactory -
Parent type ACSObject
<jorris_home> 2003-07-29 14:06:36,907 [ main] DEBUG domain.DomainObjectFactory -
Final type ACSObject
<jorris_home> 2003-07-29 14:06:36,907 [ main] DEBUG domain.DomainObjectFactory -
Found instantiator com.arsdigita.kernel.ACSObjectInstantiator@5ebee883
<jorris_home> 2003-07-29 14:06:36,908 [ main] DEBUG domain.DomainObjectFactory -
Initial delegate com.arsdigita.kernel.ACSObjectInstantiator@5ebee883
<jorris_home> 2003-07-29 14:06:36,908 [ main] DEBUG kernel.ACSObjectInstantiator
- Resolving type com.arsdigita.cms.ContentSection
<jorris_home> 2003-07-29 14:06:36,908 [ main] DEBUG domain.DomainObjectFactory -
Initial type ContentSection
<jorris_home> 2003-07-29 14:06:36,908 [ main] DEBUG domain.DomainObjectFactory -
Parent type Application
<jorris_home> 2003-07-29 14:06:36,908 [ main] DEBUG domain.DomainObjectFactory -
Parent type Resource
<jorris_home> 2003-07-29 14:06:36,908 [ main] DEBUG domain.DomainObjectFactory -
Parent type ACSObject
<jorris_home> 2003-07-29 14:06:36,909 [ main] DEBUG domain.DomainObjectFactory -
Final type ACSObject
<jorris_home> 2003-07-29 14:06:36,909 [ main] DEBUG domain.DomainObjectFactory -
Found instantiator com.arsdigita.kernel.ACSObjectInstantiator@5ebee883
<jorris_home> 2003-07-29 14:06:36,909 [ main] DEBUG kernel.ACSObjectInstantiator
- Found instantiator: com.arsdigita.kernel.ACSObjectInstantiator@5ebee883 class
com.arsdigita.kernel.ACSObjectInstantiator
<jorris_home> 2003-07-29 14:06:36,909 [ main] DEBUG kernel.ACSObjectInstantiator
- Getting reflection instantiator for null
<jorris_home> 2003-07-29 14:06:36,930 [ main] WARN  domain.ReflectionInstantia
<kdykeman> richardl_home: sounds good.  In the meantime, I'll try to introduce
myself around a bit.
<justin_> what happened between parent traversal one and two?
<rhs> another piece to add to the puzzle, the getRegisteredInstantiator(String)
does something completely different from the getRegisteredInstantiator(ObjectType).
<jorris_home> justin_: parent traversal 2 is the ACSOjbectInstatiator calling
DomainObjectInstantiator.getInstantiator.
<rhs> The former looks up the ObjectType corresponding to the String and then
delegates to getInstantiator
<jorris_home> The null is suggesting that for the object type, the
defaultDomainClass is null
<rhs> The latter simply looks directly in the s_instantiators HashMap.
<rhs> One of them has to be wrong.
<rhs> Although this shouldn't really matter since my grep indicates we never
call the String version, and my guess is the other version is the correct one.
<danpb> rhs: doh, looks like a typo in getRegisteredInstantiator(String) - its
delegating to the wrong method
<danpb> its calling getInstantiator(ObjectType) instead of
getRegisteredInstantiator(ObjectType)
<rhs> I'll fix it.
<rhs> Ok, it's fixed.
<rhs> @34073
<jorris_home> Ok, I think I see the problem.
<jorris_home> 2003-07-29 14:19:18,634 [ main] WARN 
domain.ReflectionInstantiator - cannot create reflection instantiator for null
<jorris_home> java.lang.NullPointerException
<jorris_home>  at java.lang.Class.forName1(Native Method)
<jorris_home>  at java.lang.Class.forName(Class.java(Compiled Code))
<jorris_home>  at
com.arsdigita.domain.ReflectionInstantiator.<init>(ReflectionInstantiator.java:74)
<jorris_home>  at
com.arsdigita.domain.ReflectionInstantiator.getInstantiator(ReflectionInstantiator.java:55)
<jorris_home>  at
com.arsdigita.kernel.ACSObjectInstantiator.resolveInstantiator(ACSObjectInstantiator.java:148)
<jorris_home>  at
com.arsdigita.domain.DomainObjectFactory.newInstance(DomainObjectFactory.java:130)
<jorris_home>  at com.arsdigita.kernel.Resource.retrieveResource(Resource.java:150)
<jorris_home>  at com.arsdigita.kernel.Resource.makeResource(Resource.java:92)
<jorris_home>  at com.arsdigita.kernel.Resource.createResource(Resource.java:66)
<jorris_home>  at com.arsdigita.web.Application.legacyMake(Application.java:168)
<jorris_home> In Resource.makeResource, it sets the objectType for the
DataObject, but not the defaultDomainClass.
<jorris_home> The dataObject gets passed to the resolvers, and ends up in the
ACSObjectResolver, which tries to create a reflectioninstnatiator, which needs
the defaultDomainClass.
<danpb> i was never really clear on why Resource had to manufacture its own
DataObjects in this way rather than using the no-arg/ObjectType/String
constructor like every other domain object in the system
<rhs> It's because DOF has no generic create functionality.
<rhs> So it needs to manually create the data object and then use DOF to
retrieve it.
<justin_> IOW, ecm had generic create-new-app code, which needed to be able to
do App.createApp(c.a.App)
<danpb> but the Resource has the ResourceType, which in turn has the domain
class type
<danpb> so it could use reflection to run the appropriate constructor
<rhs> ResourceType only has the data object type, not the domain class.
<danpb> hmm, that's a PITA

Comment 4 Daniel Berrangé 2003-10-31 10:26:56 UTC
The change 34073 should be backported to 5.2 & 6.0

Comment 5 Archit Shah 2004-01-06 18:53:30 UTC
merged on 6.0.x (38304) and 5.2.x (39045)

Comment 6 David Lawrence 2006-07-18 03:08:22 UTC
QA_READY has been deprecated in favor of ON_QA. Please use ON_QA in the future.
Moving to ON_QA.

Comment 7 Jon Orris 2006-09-05 17:56:53 UTC
Closing old tickets