Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » Embeddable constants incorrectly initialize to the same value(Following a read query, constants with multiple values initialize to the same value: the first value read from database, even if the constants have already been initialized.)
Embeddable constants incorrectly initialize to the same value [message #1824520] Thu, 16 April 2020 18:42 Go to next message
Farhan Nasim is currently offline Farhan NasimFriend
Messages: 3
Registered: April 2020
Junior Member
1. I have the following embeddable type used by many entities as fields.

@Embeddable
public final class EntityState {

    public final static EntityState Active = new EntityState("ACTIVE");
    public final static EntityState Archived = new EntityState("ARCHIVED");

    private String state;

    private EntityState() {
    }

    private EntityState(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    @Override
    public boolean equals(Object obj) {

        if (!(obj instanceof EntityState)) {
            return false;
        }

        EntityState state = (EntityState) obj;

        return state.getState().equals(this.getState());
    }

    @Override
    public int hashCode() {
        return state.hashCode();
    }

    @Override
    public String toString() {
        return state;
    }
}


2. EntityState can take only two states, namely Active and Archived; all other values are invalid. Two constants (Active with state ACTIVE and Archived with state ARCHIVED) are introduced and public constructors are forbidden to ensure safety.

3.Strangely, however, following a read query, both of the constants (EntityState.Active and EntityState.Archived) initialize to the same state value: the first value read from database, even if the constants have already been initialized.

Say, some entity has an embedded field, entityState, of type EntityState and database contains several instances of the entity with entityState being possibly both Active and Archived. Upon a read query, through JPA EntityManager, if the first entity's entityState value is ARCHIVED, then both of the constants initialize with state ARCHIVED; vice-versa is also the case.

4. I am using EclipseLink 2.5.0 in a Java EE 7.0 application.

5. Preparing a sample project illustrating the issue. Meanwhile, please share your thoughts if there are any.
Re: Embeddable constants incorrectly initialize to the same value [message #1824538 is a reply to message #1824520] Fri, 17 April 2020 06:24 Go to previous messageGo to next message
Farhan Nasim is currently offline Farhan NasimFriend
Messages: 3
Registered: April 2020
Junior Member
1. Have uploaded the test project as promised in the last post: https://github.com/fnasimbd/java-ee/tree/master/eclipselink-issue

2. The following test method in the test class in the project explains the issue.

    @Test
    @UsingDataSet("datasets/integration-test-data.json")
    public void constant_initialization_issue_test() {

        System.out.println("ACTIVE: " + EntityState.Active);      // - constants are initialized.
        System.out.println("ARCHIVED: " + EntityState.Archived);  // - both outputs correct respective values (ACTIVE and ARCHIVED).

        List<TestEntity> testEntity = testEntityRepository.findAll();

        System.out.println("ACTIVE: " + EntityState.Active);      // - both constants incorrectly output the same value (either ACTIVE or ARCHIVED).
        System.out.println("ARCHIVED: " + EntityState.Archived);  // - though constants had been initialized earlier.

        assertThat(testEntity).isNotNull().hasSize(2);
        assertThat(testEntity.get(1).getState().getState()).isEqualTo("ARCHIVED");
    }
}


3. The consequence of the issue is huge: the two distinct constants contain the same value and one of them is incorrect and that incorrect value may make it to database.
Re: Embeddable constants incorrectly initialize to the same value [message #1826171 is a reply to message #1824538] Mon, 20 April 2020 15:32 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris DelahuntFriend
Messages: 1389
Registered: July 2009
Senior Member
Have you tried not initiating the TestEntity state to the Active EntityState.Active instance in the default constructor? While I don't know what is going on, seems that would cause issues, as JPA uses reflection to access and set values within your entities, and this would cause an Embedded EntityState instance to already exist in the TestEntity it must build from the database. Embeddable objects are not allowed to be shared amongst different objects - they must be privately owned to avoid issues.

If you want a fixed, static set of states, you should be using an enum.
Re: Embeddable constants incorrectly initialize to the same value [message #1826352 is a reply to message #1826171] Thu, 23 April 2020 22:03 Go to previous message
Farhan Nasim is currently offline Farhan NasimFriend
Messages: 3
Registered: April 2020
Junior Member
Thanks for the reply Chris.

Chris Delahunt wrote on Mon, 20 April 2020 15:32
Have you tried not initiating the TestEntity state to the Active EntityState.Active instance in the default constructor? While I don't know what is going on, seems that would cause issues, as JPA uses reflection to access and set values within your entities, and this would cause an Embedded EntityState instance to already exist in the TestEntity it must build from the database.


That exactly have been the issue. While building the domain object TestEntity from database, EclipseLink creates an instance with field EntityState.Active (due to the initialization in the default constructor) and mutates the constant (though seemingly immutable, without public constructors or setters) with the value in database afterwards.

Chris Delahunt wrote on Mon, 20 April 2020 15:32
Embeddable objects are not allowed to be shared amongst different objects - they must be privately owned to avoid issues.


You are right. I should have been aware of that earlier. The pattern is vulnerable in other ORMs too I suppose as they also instrument objects with reflection, thus immutability is of little help.

Chris Delahunt wrote on Mon, 20 April 2020 15:32
If you want a fixed, static set of states, you should be using an enum.


Thanks for the suggestion. I am also considering that. Learning the details.
Previous Topic:Classes with @MappedSuperclass use a lot of memory
Next Topic:Deadlock exception while using jpa with eclipselink on SQL Server
Goto Forum:
  


Current Time: Mon Dec 09 07:55:01 GMT 2024

Powered by FUDForum. Page generated in 0.03575 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top