overriding accesors in entity need tranisent declaration

6 messages Options
Embed this post
Permalink
pdd

overriding accesors in entity need tranisent declaration

Reply Threaded More More options
Print post
Permalink

The orm.xml looks like this,

    <access>PROPERTY</access>

    <mapped-superclass class="UserModelBaseImpl">
        <attributes>
            <id name="id">
                <generated-value strategy="IDENTITY"/>
            </id>
            <basic name="name">
                <column name="firstName" />
            </basic>
            <basic name="lastName"/>
            <basic name="age"/>
            <basic name="wages"/>
            <basic name="active">
                <column name="ACTIVE_"/>
            </basic>
            <transient name="new"/>
        </attributes>
    </mapped-superclass>

    <entity class="UserModelImpl">
        <table name="User"/>
    </entity>

Entity class is defined like this,

public class UserModelImpl extends UserModelBaseImpl {

        public String getName() {
                return super.getName();
        }

        public void setName(String name) {
                super.setName(name);
        }

}

The mapped-superclass UserModelBaseImpl also has getter/setter getName and setName (in addition to other accessors).

The reason for having overriding accessors in the entity, although it may not be apparent from this simple test case, is that the value object is conditionally manipulated.

This fails with an exception,
<openjpa-1.2.1-r752877:753278 fatal user error> org.apache.openjpa.util.MetaDataException: Fields "com.example.model.impl.UserModelImpl.name" are not a default persistent type, and do not have any annotations indicating their persistence strategy.  If you do not want these fields to be persisted, annotate them with @Transient.

It works when name is declared as transient in the entity as shown below,
<entity class="UserModelImpl">
    <table name="User"/>
    <attributes>
        <transient name="name"/>
    </attributes>
</entity>

But now EclipseLink does not work and returns the UserModelImpl objects with name field blank.

So now I am in a situation where this test case works either with OpenJPA or with EclipseLink, but not both.
Would like to know whose bug is it?
pdd

Re: overriding accesors in entity needs tranisent declaration

Reply Threaded More More options
Print post
Permalink
Digging further into this, there is a major difference in the way the entity class is instantiated by EciplseLink versus OpenJPA.
When using eclipselink w/o the transient declaration, the entity class's overridden setters are called (which in turn call super).
While using OpenJPA with transient declaration for overridden accessors, only the setters for the super class are called and the overridden setters are never called. This causes the application to break which depends on the initialization of non-persistent state in the entity class during the set*.

As an example, lets take the above simple test case. If I need to have a non-persistent boolean field in UserModelImpl called adult and wrap it with accessors as isAdult/setAdult. Then I can declare "adult" as a transient and override the setAge/getAge such that the adult value can be set if the age is more than 18, in UserModelImpl entity class.
public void setAge(int age) {
    if(age > 18) {
        adult = true;
    }
    super.setAge(age);
}
This will not work with OpenJPA.
pdd

Re: overriding accesors in entity needs tranisent declaration

Reply Threaded More More options
Print post
Permalink
Can someone help please?
Pinaki Poddar

Re: overriding accesors in entity needs tranisent declaration

Reply Threaded More More options
Print post
Permalink
Hi,
  1. are you enhancing your entities at build-time? If not, try that first. Does enhancement work without warning?

Pinaki
pdd

Re: overriding accesors in entity needs tranisent declaration

Reply Threaded More More options
Print post
Permalink
Here is the output from build-time enhancer.

Buildfile: build.xml

enhance:
 [openjpac] 463  UserAdminTestCase  WARN   [main] openjpa.MetaData - No setter was found for method new in type com.example.model.impl.UserModelBaseImpl while searching for persistent properties. This method will be ignored. If you intended for this to be persistent, please add a corresponding setter, or switch to field access for this type hierarchy.
 [openjpac] 519  UserAdminTestCase  WARN   [main] openjpa.MetaData - Found duplicate metadata or mapping for "class com.example.model.impl.UserModelBaseImpl".  Ignoring.
 [openjpac] 523  UserAdminTestCase  WARN   [main] openjpa.MetaData - Found duplicate metadata or mapping for "class com.example.model.impl.UserModelImpl".  Ignoring.
 [openjpac] 582  UserAdminTestCase  WARN   [main] openjpa.Enhance - Detected the following possible violations of the restrictions placed on property access persistent types:
 [openjpac] "com.example.model.impl.UserModelBaseImpl" uses property access, but its field "id" is accessed directly in method "isNew" defined in "com.example.model.impl.UserModelBaseImpl".
 [openjpac] "com.example.model.impl.UserModelBaseImpl" uses property access, but its field "active" is accessed directly in method "isActive" defined in "com.example.model.impl.UserModelBaseImpl".

BUILD SUCCESSFUL
Total time: 1 second

I am using spring and load-time weaver of spring on tomcat at runtime. That works fine with EclipseLink though.
pdd

Re: overriding accesors in entity needs tranisent declaration

Reply Threaded More More options
Print post
Permalink
Interestingly, Hibernate has similar behavior but little better in the sense that it at least calls the overridden accessors.
https://forum.hibernate.org/viewtopic.php?f=1&t=998837

Can this be fixed?