You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by "Will Dazey (JIRA)" <ji...@apache.org> on 2018/02/02 17:36:00 UTC

[jira] [Comment Edited] (OPENJPA-2726) Under certain conditions an Embeddable can be directly admitted into the Datacache map

    [ https://issues.apache.org/jira/browse/OPENJPA-2726?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16350704#comment-16350704 ] 

Will Dazey edited comment on OPENJPA-2726 at 2/2/18 5:35 PM:
-------------------------------------------------------------

Patch looks good to me. Thanks Joe!


was (Author: dazeydev):
Patch looks good to me

> Under certain conditions an Embeddable can be directly admitted into the Datacache map
> --------------------------------------------------------------------------------------
>
>                 Key: OPENJPA-2726
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-2726
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: kernel
>    Affects Versions: 2.2.2
>            Reporter: Jody Grassel
>            Assignee: Jody Grassel
>            Priority: Major
>             Fix For: 2.2.3
>
>         Attachments: OPENJPA-2726_2.2.x.patch
>
>
> A certain sequence of events can result in an Embeddable object instance, with a null identity, being admitted to the DataCache.  This has a number of consequences, ranging from errors by third party datacache implementations which cannot accept a null key value (which the native OpenJPA datacache impl can), to possible data integrity issues since a null key can refer to any kind of object type (since the regular key includes both
> identity and identity type in its information.)
> Consider the following entities:
> @Entity
> public class LeftHand {
>     @Id private long id;   
>     private String strData;
>     @OneToMany private Collection<RightHand> rhList; 
>     ...
> @Entity
> public class RightHand {
>     @Id private long id; 
>     @Basic private String strData;    
>     @Embedded private EmbeddableData emb;
>     ...
>     
> @Embeddable
> public class EmbeddableData {
>     @Basic private String embeddedString;   
>     @Basic(fetch=FetchType.LAZY) private String lazyEmbeddedString;
> After committing the above entities with filled data, the contents of the L2 datacache is as follows:
> this	TestDataCache  (id=42)	
> cm	ConcurrentDataCache$1  (id=43)	
> 	[0]	ConcurrentHashMap$Entry  (id=68)	
> 		key	LongId  (id=73)	
> 		value	DataCachePCDataImpl  (id=74)	
> 			_cache	"default" (id=85)	
> 			_data	Object[4]  (id=88)	
> 				[0]	Long  (id=102)	
> 				[1]	AbstractPCData$ProxyDataList  (id=104)	
> 				[2]	"left hand" (id=110)	
> 				[3]	Long  (id=111)	
> 			_exp	-1	
> 			_fieldImpl	null	
> 			_impl	null	
> 			_loaded	BitSet  (id=91)	
> 			_oid	LongId  (id=73)	
> 			_type	Class<T> (org.apache.openjpa.persistence.cache.jpa.model.LeftHand) (id=94)	
> 			_version	Integer  (id=99)	
> 	[1]	ConcurrentHashMap$Entry  (id=69)	
> 		key	LongId  (id=116)	
> 		value	DataCachePCDataImpl  (id=117)	
> 			_cache	"default" (id=85)	
> 			_data	Object[3]  (id=120)	
> 				[0]	DataCachePCDataImpl  (id=125)	
> 					_cache	"default" (id=85)	
> 					_data	Object[2]  (id=128)	
> 						[0]	"Embedded String" (id=130)	
> 						[1]	"Lazy String" (id=131)	
> 					_exp	-1	
> 					_fieldImpl	null	
> 					_impl	null	
> 					_loaded	BitSet  (id=129)	
> 					_oid	BrokerImpl$StateManagerId  (id=3611)	
> 					_type	Class<T> (org.apache.openjpa.persistence.cache.jpa.model.EmbeddableData) (id=2336)	
> 					_version	null	
> 				[1]	Long  (id=126)	
> 				[2]	"right hand" (id=127)	
> 			_exp	-1	
> 			_fieldImpl	null	
> 			_impl	null	
> 			_loaded	BitSet  (id=121)	
> 			_oid	LongId  (id=116)	
> 			_type	Class<T> (org.apache.openjpa.persistence.cache.jpa.model.RightHand) (id=122)	
> 			_version	null	
> Here we see that the datacache contains two entries, one for LeftHand, one for RightHand.  Completely expected, and at this point Life is Good.
> After purging the persistence context and L2 cache, a query "SELECT lh from LeftHand lh" is executed, and iterating through its result list yields the following L2 datacache state:
> this	TestDataCache  (id=42)	
> cm	ConcurrentDataCache$1  (id=43)	
> 	[0]	ConcurrentHashMap$Entry  (id=3657)	
> 		key	LongId  (id=3660)	
> 		value	DataCachePCDataImpl  (id=3661)	
> 			_cache	"default" (id=85)	
> 			_data	Object[4]  (id=3662)	
> 				[0]	Long  (id=3665)	
> 				[1]	null	
> 				[2]	"left hand" (id=3666)	
> 				[3]	Long  (id=111)	
> 			_exp	-1	
> 			_fieldImpl	null	
> 			_impl	null	
> 			_loaded	BitSet  (id=3667)	
> 			_oid	LongId  (id=3660)	
> 			_type	Class<T> (org.apache.openjpa.persistence.cache.jpa.model.LeftHand) (id=94)	
> 			_version	Long  (id=111)	
> 	[1]	ConcurrentHashMap$Entry  (id=3658)	
> 		key	null	
> 		value	DataCachePCDataImpl  (id=3670)	
> 			_cache	"default" (id=85)	
> 			_data	Object[2]  (id=3671)	
> 				[0]	"Embedded String" (id=3673)	
> 				[1]	"Lazy String" (id=3674)	
> 			_exp	-1	
> 			_fieldImpl	null	
> 			_impl	null	
> 			_loaded	BitSet  (id=3675)	
> 			_oid	null	
> 			_type	Class<T> (org.apache.openjpa.persistence.cache.jpa.model.EmbeddableData) (id=2336)	
> 			_version	null	
> 	[2]	ConcurrentHashMap$Entry  (id=3659)	
> 		key	LongId  (id=3682)	
> 		value	DataCachePCDataImpl  (id=3683)	
> 			_cache	"default" (id=85)	
> 			_data	Object[3]  (id=3686)	
> 				[0]	DataCachePCDataImpl  (id=3688)	
> 					_cache	"default" (id=85)	
> 					_data	Object[2]  (id=3691)	
> 						[0]	"Embedded String" (id=3673)	
> 						[1]	"Lazy String" (id=3674)	
> 					_exp	-1	
> 					_fieldImpl	null	
> 					_impl	null	
> 					_loaded	BitSet  (id=3694)	
> 					_oid	BrokerImpl$StateManagerId  (id=3695)	
> 					_type	Class<T> (org.apache.openjpa.persistence.cache.jpa.model.EmbeddableData) (id=2336)	
> 					_version	null	
> 				[1]	Long  (id=3689)	
> 				[2]	"right hand" (id=3690)	
> 			_exp	-1	
> 			_fieldImpl	null	
> 			_impl	null	
> 			_loaded	BitSet  (id=3687)	
> 			_oid	LongId  (id=3682)	
> 			_type	Class<T> (org.apache.openjpa.persistence.cache.jpa.model.RightHand) (id=122)	
> 			_version	null	
> A specific sequence of events, requiring the embeddable to contain a lazy loaded field (which forces a ROPStoreManager.load() in the AbstractPCData.toEmbeddedData() path results in the DataCacheStoreManager.load() operation attempting to admit the embeddable into the Datacache as if it was an entity type (object ConcurrentHashMap$Entry(id=3658) at index [1].)  The embeddable has no identity of its own, so is inserted into the cache with a null key value.  The OpenJPA datacache impl replaces the null value with an object that represents the null value -- while other datacache implementations attempt to add the key to a regular map instance which results in a NullPointerException.
> The attached patch looks for the attempt to insert a new (embeddable) item into the datacache at updateDataCache() - admission into the datacache is rejected if this condition is met.  I've further modified cacheStateManager() to reject any attempt to admit an entry into the datacache that has a null entity to guard against other unidentified paths which could lead to a similar issue, as a null key identity in a datacache is meaningless.  A unit test has been added to verify that the fix corrects the issue.



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)