Open daniel-shuy opened 3 years ago
You can use @FieldNameConstants
for this:
@FieldNameConstants
public enum Permissions {
@FieldNameConstants.Include READ_USERS,
@FieldNameConstants.Include WRITE_USERS,
;
}
I don't know if this is intended, I was acutally supprised that it seems to be okay to add annotations to enum values.
In general I think that it would be way better if you could define your own annotation that accepts an enum attribute (@YourWithMockUser(roles = Permissions.READ_USERS)
) and lombok maps that one to the string based annotation (@WithMockUser(roles = "READ_USERS")
). This might be an extension to the already quite complex meta-annotation feature request.
@Rawi01 I just tried that with the latest Lombok version (1.18.18
) and it didn't work for me (I can annotate an enum value with @FieldNameConstants.Include
, but it won't generate a constant for it). What version did you try with?
In general I think that it would be way better if you could define your own annotation that accepts an enum attribute...
I don't think that javac allows enum
s as annotation attributes, in fact it will only allow constants
This is one of the important feature for our projects for maintainability. As for all enums we do create which is requested by requestor. I would request lombok team to build this feature.
@daniel-shuy I just tried it again using 1.18.20 and it works in Eclipse and in javac
it but it is marked as error in IntelliJ. It still works if you simply run it. Do you think it would be sufficient if we simply extend @FieldNameConstants
to also pick up the enum
values?
@pkordis-r7 You can use enums in annotations: JLS
@ravidesai47 Can you share an example why you need this feature? So far there only is @WithMockUser
and some usage examples would be nice and might increase the prority of this feature request :smile:
@Rawi01
I just tried it again using 1.18.20 and it works in Eclipse and in javac it but it is marked as error in IntelliJ. It still works if you simply run it.
Interesting, looks like its an issue with the lombok-intellij-plugin
. But then again, as you previously mentioned, it seems to be an unintended feature.
Do you think it would be sufficient if we simply extend @FieldNameConstants to also pick up the enum values?
Sure, whatever works. Maybe @FieldNameConstants
can be extended with a flag to include static fields (which includes enum values)?
Can you share an example why you need this feature? So far there only is @WithMockUser and some usage examples would be nice and might increase the prority of this feature request π
I don't know about @ravidesai47's use case, but I can add one more if it might help increase the priority of this request π
Another example is when using Jackson's polymorphic serialization/deserialization with logical type names (JsonTypeInfo.Id.NAME
), eg.
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME)
@JsonSubTypes( {
@JsonSubTypes.Type(value = Automobile.class),
@JsonSubTypes.Type(value = Plane.class),
@JsonSubTypes.Type(value = Ship.class),
})
@Data
abstract class Vehicle {
private Double latitude;
private Double longitude;
}
enum VehicleType {
AUTOMOBILE,
PLANE,
SHIP,
;
}
@JsonTypeName(VehicleType.AUTOMOBILE) // does not compile!
class Automobile extends Vehicle {
private Integer wheelCount;
}
This will cause the Automobile
class to be serialized with a "@type": "AUTOMOBILE"
field, which can then be used by a typed client (eg. Java, TypeScript, etc) to correctly deserialize it to the right class.
Why is there a need for an enum? There is currently no way to get all subclasses of Vehicle
. It may eventually be possible if Java's sealed classes (added in Java 15) copies Kotlin's KClass#sealedSubclasses, but I'm not holding my breath (this may be another feature that Lombok could implement). Enum#values()
provides us a way to get all VehicleType
s.
My use-case is related to jackson json polymorphism. We have lot of json polymorphed objects which has a polymorphism based on Enum which requires this feature to generated auto-generated name fields. We create enum name text fields in all such enums to use them in @JsonSubTypes annotation. It becomes maintenance headache as each time new enum is added, removed or modified we need to change the respective TEXT field. Enum value has a significance in object hence we can't replace name based strategy to any other strategy. If client is written in Angular, react it might not understand java types either.
Example:
@JsonTypeInfo(use = Id.NAME, include = As.EXISTING_PROPERTY, property = "vehicleType", visible = true)
@JsonSubTypes( {
@JsonSubTypes.Type(value = Automobile.class, name = AUTOMOBILE_TEXT),
@JsonSubTypes.Type(value = Plane.class, name = PLANE_TEXT),
@JsonSubTypes.Type(value = Ship.class, name = SHIP_TEXT),
})
@Data
abstract class Vehicle {
private VehicleType vehicleType;
private Double latitude;
private Double longitude;
}
enum VehicleType {
AUTOMOBILE,
PLANE,
SHIP,
;
public static final String AUTOMOBILE_TEXT = "AUTOMOBILE";
public static final String PLANE_TEXT = "PLANE";
public static final String SHIP_TEXT = "SHIP";
}
Hope this helps in increasing priority of this feature.
I am sure many more developers and organizations must be interested in this feature as it adds a lot of value to Json Polymorphed code for sure. I am not sure about other use-cases. As I have came across the mentioned use-case only till now. This use-case is valid across every organization I have worked for.
@ravidesai47 oh wow, I'm surprised we have the same use case π
@daniel-shuy I think this is very common use-case in all complex systems.
@daniel-shuy I think it needs to be discussed in https://groups.google.com/g/project-lombok forum. Someone from team project lombok would be able to help there increasing priority of this feature.
+1 I have exactly the same use case with jackson json polymorphism (and some on others annotations).
+1 This feature is needed to reference particular enum value in OpenApi descriptions as they're also annotations-based Strings with same limitations
@Schema(title = "Your enum property",
description = """
Yada-yada. \s
The property appeared on Jan 1, 2023. \s
For the legacy entities, special value \s
""" + YourEnumType.LEGACY.name() + " is returned",
required = true,
example = YourEnumType.USEFUL_EXAMPLE_VALUE.name()) // NB! also useful!
@NotNull
YourEnumType yourEnumType;
+1 we have a very similar use case. Does this feature have a shot?
+1
+1
The solution, @Rawi01 suggested can be used in IntelliJ if you set onlyExplicitlyIncluded=true
:
@FieldNameConstants(onlyExplicitlyIncluded = true)
public enum Role{
@FieldNameConstants.Include ADMIN,
@FieldNameConstants.Include USER
}
private String foo(){
return Role.Fields.USER;
}
The solution, @Rawi01 suggested can be used in IntelliJ if you set
onlyExplicitlyIncluded=true
:@FieldNameConstants(onlyExplicitlyIncluded = true) public enum Role{ @FieldNameConstants.Include ADMIN, @FieldNameConstants.Include USER } private String foo(){ return Role.Fields.USER; }
It works! π€―
Describe the feature Currently, there are 2 main ways to define String constants in Java:
Enums can be enumerated (using
Enum#values()
,EnumSet
, etc), and provides better typesafety (enum method parameters, exhaustive switch case with Java 13 Enhanced Switch), but the main issue is that it cannot be used as a String constant in annotation parameters (becauseEnum#name()
is not a compile time constant).WIth static final constants, for Android, some of the typesafety can be supplemented with Android's TypeDef annotations (eg. @StringDef), but for non-Android environments, there is no alternative. Manually definiting a Collection to enumerate static final constants is also error prone. A
HashSet
/HashMap
is also slower than anEnumSet
/EnumMap
.I suggest to create an annotation called
@EnumNameConstants
(inspired by @FieldNameConstants), that when annotated on an enum, will generate an inner type with string constants of the name of each enum value. eg.should generate
This will provide all the advantages of using enums, while removing its greatest limitation.
Describe the target audience Example use case:
Additional context