@Getter
@EnumToString
public enum TestEnum {
success(200, "OK"),
failure(500, "Failure");
@EnumToStringField
int code;
@EnumToStringField
String msg;
TestEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
//use @EnumToString, automatically generating the toString of the global Enum Class?
public static final String TO_STRING = "[{code=200, msg=OK}, {code=500, msg=Failure}]";
}
As I've never heard about it, I'd bet it's not supported. However, what you want can be done easily using something like
@Getter
@RequiredArgsConstructor
public enum TestEnum {
success(200, "OK"),
failure(500, "Failure");
private final int code;
private final String msg;
public static final String TO_STRING = ""
+ "["
+ Arrays.stream(TestEnum.values())
.map(e -> String.format("{code=%s, msg=%s}", e.code, e,msg))
.collect(Collectors.joining(", "))
+ "]";
}
Untested code. Note that there are countless variants how this could be formatted and your's doesn't match the standard @lombok.ToString, otherwise it'd as simple as
public static final String TO_STRING = Arrays.asList(TestEnum.values()).toString();
You can do this if you write your own toString().
@Maaartinus Use scene description:
import io.swagger.annotations.ApiImplicitParam;
import lombok.Getter;
@Getter
public enum TestEnum {
SUCCESS(200, "OK"),
NOT_FOUND(404, "Not Found"),
FAILURE(500, "Fail");
//I want to generate it automatically to reduce the maintenance of the developer
public static final String TO_STRING = "200=OK, 404=Not Found, 500=Fail";
private final int code;
private final String msg;
TestEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
}
class HelloController {
@ApiImplicitParam(name = "testEnum", value = TestEnum.TO_STRING)
public String query(TestEnum testEnum) {
//……
return null;
}
}
class DemoController {
@ApiImplicitParam(name = "testEnum", value = TestEnum.TO_STRING)
public String query(TestEnum testEnum) {
//……
return null;
}
@ApiImplicitParam(name = "testEnum", value = TestEnum.TO_STRING)
public String demo(TestEnum testEnum) {
//……
return null;
}
}
I want to generate it automatically to reduce the maintenance of the developer. So I want to be able to support @EnumToString. Whether Lombok supports custom annotations or extension development.
Why write a new annotation when the regular one just works?
@Getter
@ToString
@RequiredArgsConstructor
public enum TestEnum {
SUCCESS(200, "OK"),
NOT_FOUND(404, "Not Found"),
FAILURE(500, "Fail");
private final int code;
private final String message;
}
Calling this:
Arrays.stream(TestEnum.values()).forEach(enumValue -> log.debug("Test enum: {}", enumValue));
Results in:
Test enum: TestEnum(code=200, message=OK)
Test enum: TestEnum(code=404, message=Not Found)
Test enum: TestEnum(code=500, message=Fail)
What more do you want?
@randakar I want to expand the development of custom annotations.
There's a separate bug report for composable annotations. This however is not a use case for that.
@randakar I guess, they mean the creation of completely new annotations rather than compositions like @Gettter+@Setter.
@yu120 However, making own annotations is terribly complicated. Lombok may help you with it, but there's no official support for it and AFAIK no documentation. It would be nice, but as Lombok itself has to use unsupported javac and ecj features, it'd be too much work.
@randakar @Maaartinus Hello, I'd like to have the same feature and your solutions can't be used in @yu120 example.
if you consider @yu120 code :
class HelloController {
@ApiImplicitParam(name = "testEnum", value = TestEnum.TO_STRING)
public String query(TestEnum testEnum) {
//……
return null;
}
}
Java Annotation system wants you to have a constant variable for "value" attribute.
If you call a method like "TestEnum.toString()" or all another method, you will have a Java problem like this :
The value for annotation attribute ApiImplicitParam.value must be a constant expression
For this reason, you must call a constant variable without any treatment.
even a concatenation string would not work like this code :
public enum TestEnum {
success(200, "OK"),
failure(500, "Failure");
int code;
String msg;
TestEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
public static final String TO_STRING = "[{code=200," + "msg=OK}" + "{code=500," + " msg=Failure}]";
}
I implemented this new EnumToString feature locally but I can't test it locally.
I have a compilation error even with master branch (without any modification).
I work on Eclipse Oxygen 2 with Java 1.8 on Mac OS and ant 1.10.1.
When i launch "ant compile", I have this error (if you have any idea that can help me I will quickly create my pull request of this feature) :
compile:
[compile:javac] Compiling 2 source files to /Users/dedece35/git_ext/lombok/build/lombok
Compile errors:
----------
1. ERROR in /Users/dedece35/git_ext/lombok/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java (at line 372)
@Override public boolean visit(ArrayInitializer node, ClassScope scope) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The method visit(ArrayInitializer, ClassScope) of type SetGeneratedByVisitor must override or implement a supertype method
----------
2. ERROR in /Users/dedece35/git_ext/lombok/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java (at line 374)
return super.visit(node, scope);
^^^^^
The method visit(AnnotationMethodDeclaration, ClassScope) in the type ASTVisitor is not applicable for the arguments (ArrayInitializer, ClassScope)
----------
BUILD FAILED
/Users/dedece35/git_ext/lombok/build.xml:210: Compilation not successful
Under Eclipse, I have no compilation problem.
i have this problem when I launh "ant compile"
Any solution for this?
Are you sure you are solving this problem in the right place?
You are trying to tell Swagger what your enum looks like, and ApiExplicitParam (https://github.com/swagger-api/swagger-core/wiki/Annotations#apiimplicitparam-apiimplicitparams) is for manual description of parameters.
So in other words: If swagger doesn't automatically do the right thing on discovery, you can correct it. Apparently it doesn't, but is that really a lombok problem? I kinda doubt that.
Lombok is for automatic generation of boilerplate methods you otherwise will have to write over and over again. not for automatic generation of documentation. That's what Swagger and javadoc are for ;-)
To be a little more specific on why I am saying this:
Note the "public static final String TO_STRING" definition.
"FINAL" and "STATIC" together means: This will never change. All instances of this class will have the same value. The JVM can and will put this in a specific part of read-only memory that is shared amongst all instances of the class when it sees something with those modifiers.
So what you want is impossible. You can't have a final static field in an object and then dynamically put data in there that is different per class. The language simply doesn't allow it.
I just want Lombok to support custom annotations to expand the development of some of our own features.
There is a different bugreport for that: https://github.com/rzwitserloot/lombok/issues/557
Please look into that one.
@randakar I use "@ApiImplicitParam(name = "testEnum", value = TestEnum.TO_STRING)" to give you an example ...
if you prefer, I can create my own annotation ... the problem is still remaining
For Example :
class HelloController {
@MyOwnAnnotation(name = "testEnum", value = TestEnum.TO_STRING)
public String query(TestEnum testEnum) {
//……
return null;
}
}
Actually, I have this problem with Swagger, but I have this problem in other domain in my society.
I'm a technical developer leader in my society with an experience of 13 years with Java.
I know "final" and "static" words mean :)
I confirm you that my need is to have a constant like I said containing the list of values of my Enum (like valueOf() method of Enum can give me)
I would want this because I don't want maintain manually this constant and unfortunately this is what I do nowadays.
I forked your lombok repo and if you want I can commit my solution ... but my real problem is that the "ant compile" does'nt work (even if without my modifications) ... have you an idea for that problem (see below) ?
thanks a lot.
@dedece35 On the second look, your problem
SUCCESS(200, "OK"),
NOT_FOUND(404, "Not Found"),
FAILURE(500, "Fail");
//I want to generate it automatically to reduce the maintenance of the developer
public static final String TO_STRING = "200=OK, 404=Not Found, 500=Fail";
seems to have no solution. You need a compile-time constant generated from values only known at runtime. When the lombok-generated constructor gets used, then lombok could generate the constant, but with a custom constructor, there's no way. In general, there can be multiple hand-written constructors and telling what they do is Turing-complete. :laughing:
Lombok could only do something when its generated constructor gets used. The @EnumToString annotation should be configurable as others may want different formatting. I'm afraid, this means a lot of work with little effect. Maybe some workarounds?
I'd bet the simplest solution would be generating a new class on runtime using reflection. Or automatically editing the enum class. You need to incorporate it somehow in the build process. It's pretty ugly, but I did such things several times and it worked rather well.
Maybe writing a test comparing the manually written compile-time constant with the wanted value would do. When it fails, then you have to fix it, but you'll be always reminded.
Another possibility would be make swagger smarter: Instead of
@ApiImplicitParam(name = "testEnum", value = TestEnum.TO_STRING)
it could accept
@ApiImplicitParam(name = "testEnum", valueSupplier = TestEnum.ToStringSupplier.class)
where the supplier would generate the expression. The needed miracle is making swagger get the value by evaluating the supplier.
Most helpful comment
Why write a new annotation when the regular one just works?
Calling this:
Arrays.stream(TestEnum.values()).forEach(enumValue -> log.debug("Test enum: {}", enumValue));Results in:
What more do you want?