I have created many annotation in my life and now came to strange case that i need this annotation to do and dont think it is supported by Java at all. Please someone tell me that i am right or wrong.
Here is my annotation :
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface DetailsField {
public String name();
}
And now the question! I would like that the default value of the name() function would be the name of the field it self where I have posted the annotation.
Dont know exactly how the classloader processes the annotations, i am pretty sure that this is not implemented in a standard classloader , but could be maybe achieved by bytecode instrumentation in the time of classloading by a custom classloader ?
(I am pretty sure if this is the only solution i would find a way around , just curious )
Any ideas? Or do i wish too much ?
I think that it is possible to instrument the bytecode (at class loading) to get this working, but this seems like a highly complicated, and possibly non-portable, solution.
The best solution to your problem is to create a class that decorates (a-la the Decorator design pattern) an instance of your annotation with the name calculation logic.
[Edit: Added the name() definition at the interface]
package p1;
import java.lang.annotation.*;
import java.lang.reflect.*;
public class A {
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface DetailsField {
public int n1();
public String name() default "";
}
public static class Nameable implements DetailsField {
private final DetailsField df;
private final Field f;
public Nameable(Field f) {
this.f = f;
this.df = f.getAnnotation(DetailsField.class);
}
#Override
public Class<? extends Annotation> annotationType() {
return df.annotationType();
}
#Override
public String toString() {
return df.toString();
}
#Override
public int n1() {
return df.n1();
}
public String name() {
return f.getName();
}
}
public class B {
#DetailsField(n1=3)
public int someField;
}
public static void main(String[] args) throws Exception {
Field f = B.class.getField("someField");
Nameable n = new Nameable(f);
System.out.println(n.name()); // output: "someField"
System.out.println(n.n1()); // output: "3"
}
}
Related
How to write an aspect or annotation for a method that cannot update any instance variables?
Say for example I have the following java class
public class Foo {
String name;
int id;
public getName() {
return name;
}
}
Now say I want to write an aspect or in general, some annotation call it say #readOnly which can enforce getName() method to not modify either name or id so if do
public class Foo {
String name;
int id;
#readOnly
public getName() {
name = "hello world";
id = 7564;
return name;
}
}
Any invocation of getName() like above should result in an error since it modifies both name and id
The class like below should be just fine since it just doing read of instance variables.
public class Foo {
String name;
int id;
#readOnly
public getName() {
return name + "," + id;
}
}
How about directly throwing a compile error when there is any member write access in any get*() method?
Marker annotation:
package de.scrum_master.app;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
#Retention(RUNTIME)
#Target({ TYPE, FIELD, METHOD })
public #interface ReadOnly {}
Sample class / driver application:
package de.scrum_master.app;
public class Application {
private int id = 1;
private String name = "default";
#ReadOnly
public int getId() {
return id;
}
#ReadOnly
public String getName() {
name = "hello world";
id = 7564;
return name;
}
public String getNameWithoutReadOnly() {
name = "hello world";
id = 7564;
return name;
}
#ReadOnly
public String getNameIndirectly() {
modifyMembers();
return name;
}
private void modifyMembers() {
name = "hello world";
id = 7564;
}
public static void main(String[] args) {
Application application = new Application();
application.getId();
try { application.getName(); }
catch (Exception e) { e.printStackTrace(System.out); }
application.getNameWithoutReadOnly();
try { application.getNameIndirectly(); }
catch (Exception e) { e.printStackTrace(System.out); }
}
}
Aspect declaring compile error:
The following aspect only detects #ReadOnly annotations on methods, not on classes or members. You can extend it if you also need that.
The declare error statement directly throws compile errors when compiling your application with the AspectJ compiler. In Eclipse you would see something like this:
If you also want to detect indirect write access from helper methods called by a getter, you also need the dynamic pointcut with cflow(), but that one only works at runtime, not at compile time, because it inspects the callstack. If you do not need it, just remove it.
package de.scrum_master.aspect;
import de.scrum_master.app.ReadOnly;
public aspect ReadOnlyGetterAspect {
declare error :
set(* *) && withincode(public * get*()) && #withincode(ReadOnly) :
"Setting members from within a getter is forbidden";
before() : set(* *) && cflow(execution(#ReadOnly public * get*())) {
throw new IllegalAccessError("Setting members from within a getter is forbidden");
}
}
BTW, if you want to see the runtime pointcut/advice in action, you need to make the code compile first. So you either need to weaken declare error into declare warning or comment out the two statements causing the compile errors in getName().
If you do the former, your log output will be:
java.lang.IllegalAccessError: Setting members from within a getter is forbidden
at de.scrum_master.aspect.ReadOnlyGetterAspect.ajc$before$de_scrum_master_aspect_ReadOnlyGetterAspect$1$3e55e852(ReadOnlyGetterAspect.aj:11)
at de.scrum_master.app.Application.getName(Application.java:14)
at de.scrum_master.app.Application.main(Application.java:39)
java.lang.IllegalAccessError: Setting members from within a getter is forbidden
at de.scrum_master.aspect.ReadOnlyGetterAspect.ajc$before$de_scrum_master_aspect_ReadOnlyGetterAspect$1$3e55e852(ReadOnlyGetterAspect.aj:11)
at de.scrum_master.app.Application.modifyMembers(Application.java:32)
at de.scrum_master.app.Application.getNameIndirectly(Application.java:27)
at de.scrum_master.app.Application.main(Application.java:42)
If you do the latter (fix the code), of course you will only see the second exception.
I have two separate entities:
public enum Rule implements Validatable, StringRepresentable{
//...
}
and
public inteface Filter extends Validatable, StringRepresentable{
//...
}
Where
public inteface Validatable{
public GenericValidator getValidator();
}
and
public interface StringRepresentable{
public String getStringRepresentation();
}
GenericValidator is an abstract class having a number of subclasses I would not like users to access directly. How should I handle those things better?
I don't understand when it's better to create a class like
public class ValidatorFactory{
public Validator getRuleValidator(Rule r){ ... }
public Validator getFilterValidator(Filter f){ ... }
}
instead of implementing the Validatable interface as I shown earlier.
Couldn't someone explain how can I make a right decision? What potentiall circumstances requires implementing FactoryMethod a bad decision and when it would be really good?
UPD:
public interface Validator{
public ErrorCode validate();
}
public abstract class GenericValidator implements Validator{
//...
}
The ErrorCode class encapsulates the result of the validation (null if valiadtion's completed succsfully).
The Single Responsibility Principle
Construction of Validator is one responsibility, Filter or Rule probably carries another one. This means we should split it and usually we do so encapsulating instantiation logic in a Factory pattern.
Also note that implementing Validatable means being a ValidatorFactory. My answer would be - combine both solutions:
public class FilterImpl implements Filter {
private final Validator validator;
public FilterImpl(Validator validator) {
this.validator = validator;
}
#Override
public getValidator() {
return this.validator;
}
//...
}
public class FilterFactory {
private final ValidatorFactory validatorFactory = new ValidatorFactory();
public Filter createFilter() {
return new FilterImpl(valdatorFactory.createFilterValidator());
}
}
This is called Dependency Injection.
I use this pattern in two major cases:
A) Construction of the object isn't trivial - I don't trust the users of the API to do it correctly
B) There are more implementations and I want to choose the right one myself.
In both these cases I want to hide implementations simply because the user won't know which one to use and/or doesn't know how to construct it properly.
Always aim for simplicity and ease-of-use for your user. Ask yourself these questions:
Is the API easy to understand?
Is the API easy/fun to use?
Is it foolproof? (I have to try quite hard to misuse it)
Validator interface can look like this:
public interface Validator {
public int validate();
}
Filter interface can look like this:
public interface Filter {
public String getParameters(); // some related methods..
public int currentLength();
....
}
Rule interface:
public interface Rule {
public String getRule();
}
FilterValidator can look like this:
public class FilterValidator implements Validator{
private Filter f;
public FilterValidator(Filter f){
this.f = f;
}
#Override
public int validate() {
// validate f and return errorcode
String params = f.getParameters();
int strLength = f.currentLength();
.....
return 0;
}
}
Creating a factory is better to hide the internal logic of validators.
public class ValidatorFactory {
public Validator getRuleValidator(Rule r){
return null;
}
public Validator getFilterValidator(Filter f){
FilterValidator fv = new FilterValidator(f);
return fv;
}
}
Now client will invoke this factoy like this:
public class ClientDemo {
private class MyFilter implements Filter{
private String filterInput;
public MyFilter(String input){
this.filterInput = input;
}
#Override
public String getParameters() {
return null;
}
#Override
public int currentLength() {
return this.filterInput.length();
}
}
public void testValidators(){
ValidatorFactory factory = new ValidatorFactory();
Validator v = factory.getFilterValidator(new MyFilter("filter string goes here..."));
v.validate();
}
}
}
Through the interfaces Rule, Filter you can enforce the behavior you desire from client. Then client can get instances from the factory and pass the rule/filter instances to it for validation.
I can not get annotations of beans, i'm working with spring framework:
Runnable test class:
public class Main {
public static void main(String[] args) {
PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(Test.class,"foo");
Method m=pd.getReadMethod();
System.out.println(m.isAnnotationPresent(Annot.class));
}
}
Bean class;
public class Test {
private String foo;
#Annot
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
Annotation class:
public #interface Annot {
}
The main class get "false" as output... why?
Your annotation is missing a runtime retention policy.
Do the following:
#Retention(RetentionPolicy.RUNTIME)
public #interface Annot {
}
Check out this SO question which explains the default policy and what it does.
To sum the information in that answer, the default retention policy is CLASS, which means that the annotation is in the bytecode, but does not have to be retained when the class is loaded
Just as I was starting to get familiar with interfaces, I came across a stumbling block with abstract classes. In my understanding, they can be used to provide some functionality for subclasses, but forces subclasses to specify undefined functions (if there are any left).
All the examples I came across however only dealt with functionality that could have been static - no reference to instance variables.
I'm trying to hide some common functions like getName() in the abstract class, but be able to define said name in the subclass.
public interface Application {
public String getName();
}
/**
* Specify some default behaviour to keep leaf classes free of common code
*/
public abstract class DefaultApplication implements Application {
public static final String NAME = "DefApp";
#Override
public String getName() {
return NAME;
}
}
public class MyApp extends DefaultApplication {
public static final String NAME = "My App";
}
// Main class
Application myApp = new MyApp();
System.out.println(myApp.getName()); // Prints "DefApp"
I thought that protected String name might work, but this also returns the instance variable in the abstract class. Is the only solution to redefine getName() in each subclass? I wouldn't have minded so much, but this isn't the only case where I'm trying to siphon off methods into the abstract class.
Thanks!
EDIT:
if it's relevant (to suggest other approaches I could consider), Application is a plugin api, and MyApp is an example application provided. DefaultApplication is part of the base project.
You cannot override anything that's static. Static methods do not belong to a particular object, but belong to the class itself instead; when you write return NAME, the compiler reads this as return DefaultApplication.NAME.
In this case, you can either override getName() in each subclass as you already came up with, or you can make the field non-static, and do something like this:
abstract class DefaultApplication implements Application {
private final String name;
protected DefaultApplication(String name) {
this.name = name;
}
protected DefaultApplication() {
this("DefApp");
}
public String getName() {
return name;
}
}
class MyApp extends DefaultApplication {
public MyApp() {
super("My App");
}
}
This will add an extra field to every instance of DefaultApplication but as long as you don't have millions of them, that shouldn't really matter.
The annotations idea interested me, so I figured I'd throw this out here. Here's a really complicated and not exactly recommended way of printing "My App":
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
interface Application {
public String getName();
}
#Inherited
#Retention(RetentionPolicy.RUNTIME)
#interface ApplicationName {
String value();
}
#ApplicationName("DefApp")
abstract class DefaultApplication implements Application {
#Override
public String getName() {
return getClass().getAnnotation(ApplicationName.class).value();
}
}
#ApplicationName("My App")
class MyApp extends DefaultApplication {
}
public class Main {
public static void main(String[] args) {
Application myApp = new MyApp();
System.out.println(myApp.getName());
}
}
Guys is there a way to pass a Annotation as a direct parameter (rather by doing all the reflection overhead)? For example in the following code, I have a annotation Number that holds a int value, I want to pass as a parameter to the addImpl method, how can I do that (other than by reflection)?
Code Snippet:
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
public #interface Number {
int value();
}
public void add(int x2) {
addImpl(#Number(value = 10) lol, x2);
}
public void addImpl(Number a, int b) {
System.out.println(a.value() + b);
}
public static void main(String[] args) {
new TestClass().add(3);
}
Yes, you can pass around annotations like this (just as if they were normal interfaces).
The only thing you can't do is to create instances of that interface at runtime. You can only take existing annotations and pass them around.
import java.lang.annotation.*;
public class Example {
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public static #interface Number {
int value();
}
#Number(value = 42)
public int adder(final int b) throws SecurityException, NoSuchMethodException {
Number number = getClass().getMethod("adder", int.class).getAnnotation(Number.class);
return addImpl(number, b);
}
public int addImpl(final Number a, final int b) {
return a.value() + b;
}
public static void main(final String[] args) throws SecurityException, NoSuchMethodException {
System.out.println(new Example().adder(0));
}
}
You can do it like:
public void add(int x2) {
addImpl(new Number() {
#Override
public int value() {
return 10;
}
#Override
public Class<? extends Annotation> annotationType() {
return Number.class;
}
}, x2);
}
Since Number is basically an interface, you have to create an instance of an anonymous class that implements that interface, and pass that to the method.
Although why you want to do this is beyond me. If you need to pass a value to something, you should really use a class.
To the best of my knowledge, there's no such thing as an "annotation literal" as you want to use it in your add implementation.
I think the closest thing to this would be to declare the method to take a parameter of type java.lang.annotation.Annotation - but then you'd still need to obtain those instances via reflection from the class/method objects.
Number is also a good old interface, you can implement a concrete class.
Guys, this is useful. While a module mostly deals with annotations which are fixed at compile time, sometimes we need to feed it other info obtained at runtime from other sources(like xml, gush!) We can over-architect the thing, or we can simply creat a runtime object of the annotaion type.
If you need to pass annotation in test, you can make mock of it.
For example test of JSR 303 validator could look like this:
public void test() {
final TextLengthValidator validator = new TextLengthValidator();
validator.initialize(mock(TextLength.class));
final boolean valid = validator.isValid("some text", mock(ConstraintValidatorContext.class));
assertThat(valid, is(true));
}