From: Fabio M. (JIRA) <nh...@gm...> - 2011-05-17 21:22:47
|
[ http://216.121.112.228/browse/NH-2568?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Fabio Maulo resolved NH-2568. ----------------------------- Resolution: Fixed Fix Version/s: 3.2.0Beta1 Thanks Jeff to put all this effort in this issue which was so important (blocker) for your own commercial project. We really appreciate the attitude and overall the clear test you provides. P.S. Today I took a chamomile. > Create Custom Persister for Collection Type inherited from OneToManyPersister > ----------------------------------------------------------------------------- > > Key: NH-2568 > URL: http://216.121.112.228/browse/NH-2568 > Project: NHibernate > Issue Type: Improvement > Components: Core > Affects Versions: 3.0.0.GA > Reporter: Jeff Greenland > Priority: Minor > Fix For: 3.2.0Beta1 > > > Encountered issue where setting a Persister Type on a collection property (specifically a type of List) would throw a NullPointerException when NHibernate initialized. Our persister, called MyPersister as a test, extended OneToManyPersister and only had a constructor defined which matched the constructor in the base class (OneToManyPersister). Here's our analysis as to why it looks like a bug: > Tracing through the code revealed that a constructor was not found on MyPersister matching the expected arguments. Those arguments are defined on line 34 of PersisterFactory.cs for CollectionPersister types and are Mapping.Collection, ICacheConcurrencyStrategy, and ISessionFactoryImplementor. > In the CreateCollectionPersister() method (line 68), if there is no persister class defined, it calls the OneToManyPersister implementation of ICollectionPersister with Mapping.Collection, ICacheConcurrencyStrategy, Configuration, and ISessionFactoryImplementor parameters. However, if a custom persister class is defined, it calls the Create() method (line 124) with the Configuration parameter missing, and consequently the Create() method does not invoke a matching constructor with that parameter. > It seems to us that since the default persister class of OneToManyPersister accepts the 4 argument constructor, and if you specified a custom persister that extends OneToManyPersister, the custom persister should accept the same 4 arguments. In other words, if I specify a custom persister on my class as OneToManyPersister (the same as the default), NHibernate would fail to initialize because it couldn't construct OneToManyPersister. > Looks related to NH-1957, which appears to have been immediately closed. I've included our diff below that seems to have fixed the issue. > Diff: > Index: PersisterFactory.cs > =================================================================== > --- PersisterFactory.cs (revision 31412) > +++ PersisterFactory.cs (revision 31413) > @@ -31,14 +31,15 @@ > > // TODO: is it really necessary to provide Configuration to CollectionPersisters ? Should it not be enough with associated class ? > // or why does ClassPersister's not get access to configuration ? > - private static readonly System.Type[] CollectionPersisterConstructorArgs = new System.Type[] > + private static readonly System.Type[] CollectionPersisterConstructorArgs = new System.Type[] > { > typeof(Mapping.Collection), > typeof(ICacheConcurrencyStrategy), > + typeof(Configuration), > typeof(ISessionFactoryImplementor) > }; > > - /// <summary> > + /// <summary> > /// Creates a built in Entity Persister or a custom Persister. > /// </summary> > public static IEntityPersister CreateClassPersister(PersistentClass model, ICacheConcurrencyStrategy cache, > @@ -78,10 +79,11 @@ > } > else > { > - return Create(persisterClass, model, cache, factory); > + return (ICollectionPersister) Create(persisterClass, model, cache, cfg, factory); > } > } > > + > /// <summary> > /// Creates a specific Persister - could be a built in or custom persister. > /// </summary> > @@ -122,7 +124,7 @@ > } > > public static ICollectionPersister Create(System.Type persisterClass, Mapping.Collection model, > - ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) > + ICacheConcurrencyStrategy cache, Configuration cfg, ISessionFactoryImplementor factory) > { > ConstructorInfo pc; > try > @@ -136,8 +138,8 @@ > > try > { > - return (ICollectionPersister) pc.Invoke(new object[] {model, cache, factory}); > - } > + return (ICollectionPersister)pc.Invoke(new object[] { model, cache, cfg, factory }); > + } > catch (TargetInvocationException tie) > { > Exception e = tie.InnerException; > @@ -155,5 +157,6 @@ > throw new MappingException("Could not instantiate collection persister " + persisterClass.Name, e); > } > } > + > } > } -- This message is automatically generated by JIRA. - If you think it was sent incorrectly contact one of the administrators: http://216.121.112.228/secure/Administrators.jspa - For more information on JIRA, see: http://www.atlassian.com/software/jira |