Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 316991 - [Metamodel API] Attribute.getJavaMember() returns null for an embeddable managed type
Summary: [Metamodel API] Attribute.getJavaMember() returns null for an embeddable mana...
Status: RESOLVED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Eclipselink (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows Vista
: P1 normal (vote)
Target Milestone: ---   Edit
Assignee: Nobody - feel free to take it CLA
QA Contact:
URL: http://wiki.eclipse.org/EclipseLink/D...
Whiteboard:
Keywords:
Depends on: 266912
Blocks: 325467
  Show dependency tree
 
Reported: 2010-06-15 20:31 EDT by Roger Suen CLA
Modified: 2022-06-09 10:25 EDT (History)
2 users (show)

See Also:


Attachments
Fix: DI95 getJavaMethod() call on attribute of @Embeddable requires handling for null getMethod by doing reflective call on managedType using method name (13.16 KB, patch)
2010-06-16 11:34 EDT, Michael OBrien CLA
no flags Details | Diff
test persistence unit (19.86 KB, application/x-zip-compressed)
2010-06-16 21:43 EDT, Roger Suen CLA
no flags Details
Updated test patch with support for field/method level access of entity @OneToOne attributes on Entity or MappedSuperclass (unidirectional) (13.82 KB, patch)
2010-06-18 14:42 EDT, Michael OBrien CLA
no flags Details | Diff
Fix: updated dev/test patch with with support for field/method level access of entity @OneToOne attributes on Entity or MappedSuperclass (unidirectional) (34.85 KB, patch)
2010-06-18 16:34 EDT, Michael OBrien CLA
no flags Details | Diff
Fix: DI95: updated dev/test patch with with support for field/method level access of entity @OneToOne attributes on Entity or MappedSuperclass (unidirectional) (42.56 KB, patch)
2010-06-18 20:15 EDT, Michael OBrien CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Roger Suen CLA 2010-06-15 20:31:20 EDT
Build Identifier: eclipselink-2.0.2.v20100323-r6872

The implementation of Attribute.getJavaMember() method always returns null for any attribute of an embeddable managed type.

Reproducible: Always
Comment 1 Michael OBrien CLA 2010-06-15 23:17:11 EDT
>This issue is directly related to DI 95 from 20091017 when i was investigating javaMember code coverage
- except that it involves MethodAttributeAccessors
http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_95:_20091017:_Attribute.getJavaMember.28.29_returns_null_for_a_BasicType_on_a_MappedSuperclass_because_of_an_uninitialized_accessor
"Found this one while testing code coverage for Attribute.getJavaMember. 
It looks like we will need to add to the initialization of the descriptor for MappedSuperclasses that is pending for DI 93 - pkClass initialization in CMP3Policy
The AttributeAccessor on the DirectToField" Mapping is missing the attributeField required by getJavaMember()."


>Embeddable and AggregateCollection handling is lacking
>The test model includes
@Embeddable Observation - however this attribute as collection is commented in GalacticPosition
@Embeddable CompositePK - is not used anywhere
@Embeddable CPUEmbeddedId - is @EmbeddedId on CPU
>see testMetamodelEmbeddedIdDirectlyOnMappedSuperclassRootPassesValidation() 

embedCPUEmbeddedId	EmbeddableTypeImpl<X>  (id=1301)	
	descriptor	RelationalDescriptor  (id=1307)	
	javaClass	Class<T> (org.eclipse.persistence.testing.models.jpa.metamodel.CPUEmbeddedId) (id=1310)	
	members	HashMap<K,V>  (id=1312)	
		size	1	
		table	HashMap$Entry<K,V>[16]  (id=1321)	
			[1]	HashMap$Entry<K,V>  (id=1327)	
				key	"pk_part1" (id=1331)	
				value	SingularAttributeImpl<X,T>  (id=1332)	

>For the following API
            ManagedType<CPUEmbeddedId> embedCPUEmbeddedId = metamodel.managedType(CPUEmbeddedId.class);            
            assertNotNull(embedCPUEmbeddedId);
            assertEquals(Type.PersistenceType.EMBEDDABLE, embedCPUEmbeddedId.getPersistenceType());
            // 316991 Check Embedded Attributes
            Attribute embeddedAttribute = embedCPUEmbeddedId.getAttribute("pk_part1");
            assertNotNull(embeddedAttribute);
            Member aMember = embeddedAttribute.getJavaMember();
            assertNotNull(aMember);
>we get null on the return of
    public Member getJavaMember() {
        AttributeAccessor accessor = getMapping().getAttributeAccessor();
        if (accessor.isMethodAttributeAccessor()) {
            return ((MethodAttributeAccessor) accessor).getGetMethod();

>where the getMethod is null on the accessor
accessor	MethodAttributeAccessor  (id=101)	
	attributeName	"pk_part1" (id=131)	
	getMethod	null	
	getMethodName	"getPk_part1" (id=135)	
	isReadOnly	false	
	isWriteOnly	false	
	setMethod	null	
	setMethodName	"setPk_part1" (id=136)	
aMember	null	
>at
Thread [Thread-4] (Suspended)	
	SingularAttributeImpl<X,T>(AttributeImpl<X,T>).getJavaMember() line: 101	
	MetamodelMetamodelTest.testMetamodelEmbeddedIdDirectlyOnMappedSuperclassRootPassesValidation() line: 341	
	NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
	NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39	
	DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25	
	Method.invoke(Object, Object...) line: 597	
	MetamodelMetamodelTest(TestCase).runTest() line: 168	
	MetamodelMetamodelTest(TestCase).runBare() line: 134	
	MetamodelMetamodelTest(JUnitTestCase).runBare() line: 454	
	TestResult$1.protect() line: 110	
	TestResult.runProtected(Test, Protectable) line: 128	
	TestResult.run(TestCase) line: 113	
	MetamodelMetamodelTest(TestCase).run(TestResult) line: 124	
	TestExecutor.execute(Test) line: 248	
	TestExecutor.runTest(Test) line: 671	
	SynchronizedTestExecutor.run() line: 61	

>Fix: we need the same reflective code from ManagedTypeImpl.initialize() that gets the Member 
using the method or attribute name when the getMethod is missing

                Method aMethod = null;
                String getMethodName = null;
                try {
                    getMethodName = ((MethodAttributeAccessor)mapping.getAttributeAccessor()).getGetMethodName();                 
                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                        aMethod = (Method) AccessController.doPrivileged(new PrivilegedGetDeclaredMethod(
                                this.getManagedTypeImpl().getJavaType(), getMethodName, null));
                    } else {
                        aMethod = PrivilegedAccessHelper.getDeclaredMethod(
                                this.getManagedTypeImpl().getJavaType(), getMethodName, null);
                    }                
                } catch (PrivilegedActionException pae) {
                    pae.printStackTrace();
                } catch (NoSuchMethodException nsfe) {
                    nsfe.printStackTrace();
                }

>Results are
aMethod	Method  (id=136)	
	clazz	Class<T> (org.eclipse.persistence.testing.models.jpa.metamodel.CPUEmbeddedId) (id=115)	
	name	"getPk_part1" (id=148)	
	returnType	Class<T> (int) (id=163)	

>formal patch pending
Comment 2 Michael OBrien CLA 2010-06-16 11:34:39 EDT
Created attachment 172046 [details]
Fix: DI95 getJavaMethod() call on attribute of @Embeddable requires handling for null getMethod by doing reflective call on managedType using method name
Comment 3 Michael OBrien CLA 2010-06-16 14:32:48 EDT
>P1 is the temporary holder for 2.1.1 queued ports
Comment 4 Michael OBrien CLA 2010-06-16 21:04:53 EDT
>Also verify 
Does this occur for all attributes including those from Entities and MappedSuperclasses (also check Basic) 
The fix is for Method level access, verify Field level access for Embeddables - however we should be OK as reflective code already existed for Field level in getJavaMember()
Comment 5 Roger Suen CLA 2010-06-16 21:43:26 EDT
Created attachment 172086 [details]
test persistence unit

The attachment is the original persistence unit I used to test against the metamodel API. All embeddable types are annotated like this:

@Embeddable
@Access(AccessType.FIELD)
public class Address implements Serializable {
...
}
Comment 6 Roger Suen CLA 2010-06-16 21:48:59 EDT
(In reply to comment #5)
> Created an attachment (id=172086) [details]
> test persistence unit
> The attachment is the original persistence unit I used to test against the
> metamodel API. All embeddable types are annotated like this:
> @Embeddable
> @Access(AccessType.FIELD)
> public class Address implements Serializable {
> ...
> }

Here's the code snippet I used to access the java member:

        Object value = null;
        Member member = attribute.getJavaMember();
        if (member instanceof Field) {
            Field field = (Field) member;
            try {
                field.setAccessible(true);
                value = field.get(data);
            } catch (Exception ex) {
                throw new RuntimeException(
                    "Unexpected exception occurred when trying to "
                    + "reflectively get the value of the field: "
                    + field.getName(), ex);
            }
        } else if (member instanceof Method) {
            Method method = (Method) member;
            try {
                method.setAccessible(true);
                value = method.invoke(data, (Object[]) null);
            } catch (Exception ex) {
                throw new RuntimeException(
                    "Unexpected exception occurred when trying to "
                    + "reflectively invoke the method: "
                    + method.toGenericString(), ex);
            }
        } else {
            logger.log(
                Level.SEVERE,
                "Invalid java member [{0}] corresponding to "
                + "the attribute [{1}] of the data [{2}] represented by the "
                + "managed type [{3}]. The attribute value will be "
                + "unavaliable for viewing."
                + "This is possibly an issue of the persistence provider "
                + "implementation. By far, eclipselink 2.0.2 is known to "
                + "return null member for attributes of embeddable type. "
                + "Please check the documentation of the provider for "
                + "more information. ", new Object[] { member,
                    attribute.getName(), data, managedType });
        }
Comment 7 Michael OBrien CLA 2010-06-18 14:42:58 EDT
Created attachment 172243 [details]
Updated test patch with support for field/method level access of entity @OneToOne attributes on Entity or MappedSuperclass (unidirectional)
Comment 8 Michael OBrien CLA 2010-06-18 16:34:50 EDT
Created attachment 172257 [details]
Fix: updated dev/test patch with with support for field/method level access of entity @OneToOne attributes on Entity or MappedSuperclass (unidirectional)
Comment 9 Michael OBrien CLA 2010-06-18 16:43:00 EDT
(In reply to comment #5)
> Created an attachment (id=172086) [details]
> test persistence unit
> The attachment is the original persistence unit I used to test against the
> metamodel API. All embeddable types are annotated like this:
> @Embeddable
> @Access(AccessType.FIELD)
> public class Address implements Serializable {
> ...
> }

>The AccessType may not be set at design time via annotation - it will be determined at runtime.
Also, the null Method returns from getJavaMember() on Embeddables are occuring with accessType.PROPERTY as well - see extended test model patch
Comment 10 Michael OBrien CLA 2010-06-18 20:15:07 EDT
Created attachment 172264 [details]
Fix: DI95: updated dev/test patch with with support for field/method level access of entity @OneToOne attributes on Entity or MappedSuperclass (unidirectional)
Comment 11 Michael OBrien CLA 2010-06-18 23:50:27 EDT
>See SVN Rev# 7636
http://fisheye2.atlassian.com/changelog/eclipselink/?cs=7636
Comment 12 Eclipse Webmaster CLA 2022-06-09 10:14:30 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink
Comment 13 Eclipse Webmaster CLA 2022-06-09 10:25:44 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink