I have an #interface annotation type like this -
public #interface someAnnotation {
String someVar() default "var_value";
}
I want to parametrize someVar on a Junit5 test similar to this
#ParametrizedTest
#ValueSource(strings = {"val1","val2"})
#someAnnotation(someVar = ??)
void theTestMethod(String s){
//test something
}
I want the value of s (that is provided by valueSource) to be loaded to someVar. Obviously something like this won't work -
#someAnnotation(someVar = s)
I have also tried using Test Extension by implementing BeforeEachCallback to get ExtensionContext using which someVar can be accessed but I have found no way to get ValueSource values or method parameters values from ExtensionContext. Is there any way to achieve this?
The Java Language Specification section on annotations says, in brief, that element values must not be null and may only be:
constant expressions
class literals
enum constants
arrays whose elements are one of the above
Therefore, what you're asking for isn't permitted by the language.
The only way I know of to achieve this kind of variability over an annotation's values in a test would be to have the test generate source code and compile it on the fly (or, equivalently, generate bytecode directly).
Stylistically, I would argue that unless your #ValueSource has more than ~50 elements, it's simpler and clearer to the reader to just write out each case like:
#Test
#someAnnotation(someVar = "val1")
void theTestMethodVal1(){
theTestMethodHelper("val1");
}
#Test
#someAnnotation(someVar = "val2")
void theTestMethodVal2(){
theTestMethodHelper("val2");
}
void theTestMethodHelper(String s){
//test something
}
All that having been said, it's not clear to me what the goal of tests like this might be.
As is clear from the hard-coding of "val1" and "val2" in the bodies of the above methods, it's much clearer and more concise to simply inline a needed value in the body of a method, rather than jumping through the reflection hoops that would be necessary to read that same value dynamically from an annotation on the method.
Related
Suppose you have some annotation Annot:
#Retention(/*your retention policy*/)
#Target(/*targeted element type*/)
public #interface Annot {
String value() default "Hello World!";
}
And in some related code, say, an annotation processor, you need the default value of the value() Annotation field without having access to a class that is annotated with #Annot. Of course you could simply do
public static final String ANNOT_VALUE_DEFAULT = "Hello World!";
in your processor class, then change the following in #Annot:
String value() default Processor.ANNOT_VALUE_DEFAULT;
(Processor being the class name of your annotation processor). While this works fine with Strings, the change in #Annot fails when your value() type is an enum. It might fail for other values, too, but enum is part of my use case, therefore if this doesn't work, it doesn't matter if other types will work.
Now, of course, the simplest way to resolve this is to simply have the default value specified in #Annot and Processor, separately. But every programmer knows that duplicated constants are not a good idea in general. You might want to automatically reflect changes in one part (e.g. #Annot) in the other parts (e.g. Processor). For this to work, you'd have to be able to do this:
var defaultVal = Annot.value(); // statically (without an instance annotated with #Annot) access default value
So, is this static access in any way possible?
Partial solution
It is not urgent for me to find a solution right now as I already found a semi-convenient workaround (see my answer). Still, because the workaround is a bit "hacky", I want to know if there is a more elegant way to do this.
Workaround
If it turns out that there is no satisfying solution to this, but you, the reader, really need a solution, take a look at this workaround:
So, the problem is that you want to access the default value without being supplied with a class that is annotated with #Annot. Well, who says that you don't have access to such a class? Just add this (preferably package-private) class to your source code:
#Annot
class DefaultAnnotValues {
private static final Annot ANNOT = DefaultAnnotValue.class.getAnnotation(Annot.class);
static SomeEnum value = ANNOT.value();
// add all other enum fields with default values here
private DefaultAnnotValues() {
}
}
Now you can access all default values of your annotation, and when you change a default value in the annotation definition, it will be automatically reflected to wherever you use those defaults.
I need to write an Annotation to exclude certain values from a result set.
Background:
Distinct values are selected from fields and are listed in a ComboBox. Some of the legacy values are Deprecated and I don't want to show them, even if they are returned by JDBC's SELECT DISTINCT(). It's like a mini-framework where people can build select queries by clicking values from ComboBoxes.
I tried the following (the code does not compile - commented lines are the ways I tried to solve the problem):
public enum JobType {
//...
S,
//...
}
public #interface Exclude {
Object[] values(); // Invalid type
Enum[] values(); // Invalid type again
String[] values(); // Accepts but see the following lines
}
#Table(name = "jobs_view")
public class JobSelectionView extends View {
//...
#Exclude(values = {JobType.S.toString()}) // Not a constant expression
#Exclude(values = {JobType.S.name()}) // Not a constant expression ?!?!?!
#Exclude(values = {"S"}) // Works but... come on!
#Enumerated(value = EnumType.STRING)
#Column(name = "type")
private JobType type;
//...
}
I don't like using {"S"}, any suggestions?
But if declare JobType[] values() then I won't be able to reuse the #Exclude for other types of Enum.
This is the best way to do what you want, though. Here's the thing:
The class Enum is, itself, meaningless.
It only gains meaning when subclassed. Let's say you want to add another filter, say Color (your own custom Color enum, not java.awt.Color). Obviously, the thing thing that your filtration class is doing is very different for filtering out JobType than it would be for filtering out Color!
Therefore, the best thing to do would be to have each different time of enum you're trying to filter in it's own argument, e.g.
public #interface Exclude {
JobType[] jobs;
Color[] colors;
Foo[] foos;
Quux[] quuxes;
}
This will accomplish two things:
Make it easy for you to do different filtration behavior for each different filter type.
Make the #Excludes annotation more legibile by sorting the different parameters into different groups.
The Javadoc for Enum.name() says:
Returns the name of this enum constant, exactly as declared in its enum declaration. Most programmers should use the toString() method in preference to this one, as the toString method may return a more user-friendly name. This method is designed primarily for use in specialized situations where correctness depends on getting the exact name, which will not vary from release to release.
I suggest you try to tell the people in your company to read up on the Open/Closed principle and explain why violating it would be particularly damaging in this case.
There is a constructor with three parameters of type enum:
public SomeClass(EnumType1 enum1,EnumType2 enum2, EnumType3 enum3)
{...}
The three parameters of type enum are not allowd to be combined with all possible values:
Example:
EnumType1.VALUE_ONE, EnumType2.VALUE_SIX, EnumType3.VALUE_TWENTY is a valid combination.
But the following combination is not valid:
EnumType1.VALUE_TWO, EnumType2.VALUE_SIX, EnumType3.VALUE_FIFTEEN
Each of the EnumTypes knows with which values it is allowed to be combined:
EnumType1 and the two others implement a isAllowedWith() method to check that as follows:
public enum EnumType1 {
VALUE_ONE,VALUE_TWO,...;
public boolean isAllowedWith(final EnumType2 type) {
switch (this) {
case VALUE_ONE:
return type.equals(Type.VALUE_THREE);
case VALUE_TWO:
return true;
case VALUE_THREE:
return type.equals(Type.VALUE_EIGHT);
...
}
}
I need to run that check at compile time because it is of extreme importance in my project that the combinations are ALWAYS correct at runtime.
I wonder if there is a possibility to run that check with user defined annotations?
Every idea is appreciated :)
The posts above don't bring a solution for compile-time check, here's mine:
Why not use concept of nested Enum.
You would have EnumType1 containing its own values + a nested EnumType2 and this one a nested EnumType3.
You could organize the whole with your useful combination.
You could end up with 3 classes (EnumType1,2 and 3) and each one of each concerned value containing the others with the allowed associated values.
And your call would look like that (with assuming you want EnumType1.VALUE_ONE associated with EnumType2.VALUE_FIFTEEN) :
EnumType1.VALUE_ONE.VALUE_FIFTEEN //second value corresponding to EnumType2
Thus, you could have also: EnumType3.VALUE_SIX.VALUE_ONE (where SIX is known by type3 and ONE by type1).
Your call would be change to something like:
public SomeClass(EnumType1 enumType)
=> sample:
SomeClass(EnumType1.VALUE_ONE.VALUE_SIX.VALUE_TWENTY) //being a valid combination as said
To better clarify it, check at this post: Using nested enum types in Java
So the simplest way to do this is to 1) Define the documentation to explain valid combinations and
2) add the checks in the constructor
If a constructor throws an Exception than that is the responsibility of the invoker. Basically you would do something like this:
public MyClass(enum foo, enum bar, enum baz)
{
if(!validateCombination(foo,bar,baz))
{
throw new IllegalStateException("Contract violated");
}
}
private boolean validateCombination(enum foo, enum bar, enum baz)
{
//validation logic
}
Now this part is absolutely critical. Mark the class a final, it is possible that a partially constructed object can be recovered and abused to break your application. With a class marked as final a malicious program cannot extend the partially constructed object and wreak havoc.
One alternative idea is to write some automated tests to catch this, and hook them into your build process as a compulsory step before packaging/deploying your app.
If you think about what you're trying to catch here, it's code which is legal but wrong. While you could catch that during the compilation phase, this is exactly what tests are meant for.
This would fit your requirement of not being able to build any code with an illegal combination, because the build would still fail. And arguably it would be easier for other developers to understand than writing your own annotation processor...
The only way I know is to work with annotations.
Here is what I do I mean.
Now your constructor accepts 3 parameters:
public SomeClass(EnumType1 enum1,EnumType2 enum2, EnumType3 enum3){}
so you are calling it as following:
SomeClass obj = new SomeClass(EnumTupe1.VALUE1, EnumTupe2.VALUE2, EnumTupe1.VALUE3)
Change the constructor to be private. Create public constructor that accept 1 parameter of any type you want. It may be just a fake parameter.
public SomeClass(Placeholder p)
Now you have to require to call this constructor while each argument is annotated with special annotation. Let's call it TypeAnnotation:
SomeClass obj = new SomeClass(TypeAnnotation(
type1=EnumType1.VALUE1,
type2=EnumTupe2.VALUE2,
type3=EnumTupe1.VALUE3)
p3);
The call is more verbose but this is what we have to pay for compile time validation.
Now, how to define the annotation?
#Documented
#Retention({RetentionPolicy.RUNTIME, RetentionPolicy.SOURCE})
#Target(PARAMETER)
#interface TypeAnnotation {
EnumType1 type1();
EnumType2 type3();
EnumType3 type3();
}
Please pay attention that target is PARAMETER and retention values are RUNTIME and SOURCE.
RUNTIME allows reading this annotation at runtime, while SOURCE allows creating annotation processor that can validate the parameters at runtime.
Now the public constructor will call the 3-parameters private construcor:
public SomeClass(Placeholder p) {
this(readAnnotation(EnumType1.class), readAnnotation(EnumType2.class), readAnnotation(EnumType3.class), )
}
I am not implementing readAnnotation() here: it should be static method that takes stack trace, goes 3 elements back (to caller of the public costructor) and parses annotation TypeAnnotation.
Now is the most interesting part. You have to implement annotation processor.
Take a look here for instructions and here for an example of annotation processor.
You will have to add usage of this annotation processor to your build script and (optionally) to your IDE. In this case you will get real compilation error when your compatibility rules are violated.
I believe that this solution looks too complicated but if you really need this you can do this. It may take a day or so. Good luck.
Well, I am not aware of a compile time check but I do not think it is possible because how can the compiler know which value will be passed to the constructor (In case the value of your enum variable is calculated in runtime (e.g. by an If clause) ?
This can only be validated on runtime by using a validator method as you implemented for the enum types.
Example :
If in your code you have something like this :
EnumType1 enumVal;
if (<some condition>) {
enumVal = EnumType2.VALUE_SIX;
} else {
enumVal = EnumType2.VALUE_ONE;
}
There is no way the compiler can know which of the values will be assigned to enumVal so it won't be able to verify what is passed to the constructor until the if block is evaluated (which can be done only in runtime)
Is there any way to get a classes declared fields (and methods) in the order of declaration using reflection? According to the documentation, the ordering of Methods and Fields returned by getFields(), getDeclaredFields(), etc. is undefined.
Specifying something like an index would be possible using annotation as suggested in Java reflection: Is the order of class fields and methods standardized?
Are there any better options, i.e. not having to specify the index manually?
Now before you ask what I need this for: we have a method that takes a quite big data structure as input and performs a lengthy calculation on it. To create unit tests, we made a method that takes an input object and an output instance and creates the Java source code (setting up input, invoking the calculation method, and asserting the correct results afterwards) as output. This code is much more readable when fields are written in declaration order.
With jdk 6, the reflected fields are in deed in their declaration order. In early jdk that wasn't the case. Apparently enough people have nagged.
Although not guaranteed by javadoc, I would still take this order as granted, and I assume the order will be kept in future jdks too.
In your app, like in most apps, the dependency on the declaration order is mostly vanity - your app won't fail if the order screws up, it just become a little uglier.
I had this as an isolated problem, look at
https://github.com/wmacevoy/kiss/blob/master/src/main/java/kiss/util/Reflect.java
and the method
public static Method[] getDeclaredMethodsInOrder(Class clazz)
It gets the order by looking at the bytecode of the class. If you just want to use the libray, is would be
kiss.util.Reflect.getDeclaredMethodsInOrder(Test.class)
No, not possible with reflection. You could however solve it using a ProcessBuilder and the javap command:
Given a Test.java:
public abstract class Test {
public void method1() {
}
public void method2() {
}
public static void main(String[] args) {
}
public String method3() {
return "hello";
}
abstract void method4();
final int method5() {
return 0;
}
}
The command javap Test prints:
...
public Test();
public void method1();
public void method2();
public static void main(java.lang.String[]);
public java.lang.String method3();
abstract void method4();
final int method5();
...
I'm afraid it's impossible without modifying the compilation process. Normally, the field get written into the classfile in any order and the information about the declaration order gets lost.
Most probably you could use an annotation processor to write the order in an auxiliary file.
It should be quite easy. Look e.g. at interfacegen for an example, how an annotation processor can work. You may want to put the information in the same file, but this is much harder.
You may think about using Javadoc with a custom Doclet, but this requires the source to be available.
There still is no guarantee about the order in the API (methods, fields, but every javadoc output I've ever seen has them in the right order, so I suppose the doclets get them in declaration order.
You won't be able to get the information from the class file. As Adam said in an answer to the refrenced other question:
The elements in the array returned are not sorted and are not in any particular order.
And "no order" includes "no declaration order".
I once used a Java source file parser to get input data for code generators. And this way you'll have fields and methods in declaration order.
Let us say that I want to create a class MyString which is a wrapper for java.lang.String. I have added a new method called reverse.
public class MyString {
private String text=null;
public MyString(String foo){
text=foo;
}
public String reverse(){
// implementation omitted
return reversedString;
}
}
Now String is final. Therefore I cannot extend it. One way to have MyString support all methods that String supports is by providing wrapper method implementations such as the method toCharArray():
public char[] toCharArray(){
// redirect to String member field 'text'
return text.toCharArray();
}
Is there a way I can redirect method calls to the member field without actually having to code the wrapper implementation? Something similar to super?
No, this cannot be done directly.
You could define an interface containing all java.lang.String methods (plus your methods) and implement it with a dynamic proxy redirecting to the string implementation (with all the negative implications of dynamic proxies).
Probably you're better of with a type conversion new MyString(string).reverse() unfortunately Java does not have C#'s extension methods or Scala's implicit type conversions.
There are of course plenty of reverse implementations, for example from the apache commons library. It is implemented in a procedural style:
String reversed = StringUtils.reverse(string);
(I think your reverse method should return MyString not String so you can write: s.reverse().reverse()).
Not sure if I completely understand the question, but ultimately, if you want your MyString to have all the same methods as String, then at some level your class must also have all of the same methods defined. You can't really get around this.
You can probably come up with neat ways so that for every method you don't have to type return text.blah(), something more elegant than that; but I don't see any way how you could avoid having the method definitions in your MyString at all.
You can't do this as you have to write the methods to expose them for use. But, for example, you can use the Netbeans' "Create Delegates..." feature and you get all delegate methods with some mouse clicks.