Embeddable constants incorrectly initialize to the same value [message #1824520] |
Thu, 16 April 2020 18:42 |
Farhan Nasim 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 #1826352 is a reply to message #1826171] |
Thu, 23 April 2020 22:03 |
Farhan Nasim Messages: 3 Registered: April 2020 |
Junior Member |
|
|
Thanks for the reply Chris.
Chris Delahunt wrote on Mon, 20 April 2020 15:32Have 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:32Embeddable 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:32If 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.
|
|
|
Powered by
FUDForum. Page generated in 0.03575 seconds