You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The semantics of @Value.Default in @Value.Modifiable and @Value.Immutable have an adverse effect in cases where values generated by @Value.Default methods are not the same. For instance automatically generated Ids.
In the case of the immutable object: If the ID is not set during construction by the builder the value will be cached and this test will always pass:
finalChangingIdTypeimmutableChangingIdTypeSet=ImmutableChangingIdType.builder().setId("KnownID").build();
//This will passAssert.assertEquals(immutableChangingIdTypeSet.getId() , immutableChangingIdTypeSet.getId());
finalChangingIdTypeimmutableChangingIdType=ImmutableChangingIdType.builder().build();
//This will also pass with an autogenerated idAssert.assertEquals(immutableChangingIdType.getId() , immutableChangingIdType.getId());
In the case of the Modifiable object: If the ID is not set then the value returned by the method will not be cached and this test will fail:
finalChangingIdTypemodifiableChangingIdTypeSet=ModifiableChangingIdType.create().setId("KnownID");
//this test will pass:Assert.assertEquals(modifiableChangingIdTypeSet.getId() , modifiableChangingIdTypeSet.getId())
finalChangingIdTypemodifiableChangingIdType=ModifiableChangingIdType.create();
//this test will fail, a new id will be generated each timeAssert.assertEquals(modifiableChangingIdType.getId() , modifiableChangingIdType.getId())
My proposal would be that it should be possible to have the result of the default method cached. The caching in Modifiables should be controlled by an annotation or an annotation parameter in order to maintain backwards compatibility.
In fact the current approach is consistent, but the Immutable object will call and set the @Value.Default during initialization, while the modifiable object will not. Thus any method marked with @Value.Default will be called until the setter is called.
Some non elegant work-arounds I have found to this is to set the value in the default method if a setter exists or manually setting the @Value.Default properties when using a Modifiable.
It would be nice to have an elegant solution to this.
The text was updated successfully, but these errors were encountered:
SpyrosKou
changed the title
Effects of different behavious of @Value.Default in @Value.Modifiable and @Value.Immutable
Adverse Effects of different behavious of @Value.Default in @Value.Modifiable and @Value.Immutable
Feb 5, 2020
@Value.Default
public String getId()
{
final String id=UUID.randomUUID().toString();
try {
final Method setIdMethod = this.getClass().getMethod("setId", String.class);
if (setIdMethod != null) {
setIdMethod.invoke(this, id);
}
} catch (final Exception e) {
//Ignore on purpose.
}
}
This workaround tries to call the setId(String) method if available by using reflection.
This way the getId() will always return the same value when called.
If this approach is not used the getId() will always return a new id as each call will result to an invocation of the UUID.randomUUID().toString();
Using @Value.Lazy or @Value.Derived is not an option as it does not allow setting the value, which is needed e.g. in seriliazation.
The downside is apart from the non optimal performance of reflection and try/catch that this has to be manually maintained.
For instance the name of the "getId" should be maintained in sync with any potential Style updates.
The semantics of
@Value.Default
in@Value.Modifiable
and@Value.Immutable
have an adverse effect in cases where values generated by@Value.Default
methods are not the same. For instance automatically generated Ids.In the case of the immutable object: If the ID is not set during construction by the builder the value will be cached and this test will always pass:
In the case of the Modifiable object: If the ID is not set then the value returned by the method will not be cached and this test will fail:
My proposal would be that it should be possible to have the result of the default method cached. The caching in Modifiables should be controlled by an annotation or an annotation parameter in order to maintain backwards compatibility.
In fact the current approach is consistent, but the Immutable object will call and set the
@Value.Default
during initialization, while the modifiable object will not. Thus any method marked with@Value.Default
will be called until the setter is called.Some non elegant work-arounds I have found to this is to set the value in the default method if a setter exists or manually setting the
@Value.Default
properties when using a Modifiable.It would be nice to have an elegant solution to this.
The text was updated successfully, but these errors were encountered: