I have a plugin within i want to access to the class list of my model package from my maven project. Until now i just did this to load the classes into the plugin :
try {
runtimeClasspathElements = project.getRuntimeClasspathElements();
} catch (DependencyResolutionRequiredException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URL[] runtimeUrls = new URL[runtimeClasspathElements.size()];
for (int i = 0; i < runtimeClasspathElements.size(); i++) {
String element = (String) runtimeClasspathElements.get(i);
try {
runtimeUrls[i] = new File(element).toURI().toURL();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
newLoader = new URLClassLoader(runtimeUrls,
Thread.currentThread().getContextClassLoader());
try { class=newLoader.loadClass("com.pkl.bc.personnaldata.model.Personne");
if(class!=null)
System.out.println(class.getCanonicalName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Until here i can see the full name of my class.
System.out.println(class.getDeclaredFields());
System.out.println(class.isAnnotationPresent(EditColumn.class));
for (Field f : class.getDeclaredFields()) {
EditColumn v = f.getAnnotation(EditColumn.class);
if (v != null) {
System.out.println(v.tableName());
System.out.println(v.oldName());
}
}
but i don't get anything, here is the output :
[Ljava.lang.reflect.Field;@398f573b
false
I also tried to use refelctions
Reflections reflections = new Reflections("com.pkl.bc.personnaldata.model.Personne");
Set<Field> annotated = reflections.getFieldsAnnotatedWith(EditColumn.class);
System.out.println(annotated);
this give me an empty list. here is my annotation :
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface EditColumn {
String oldName() default "";
String newName() default "";
String tableName() default "";
}
the annotated field :
@EditColumn(newName = "main_adress", oldName = "adress", tableName = "Personne")
private String main_adress;
I fixed my answer,that your problem is loading different class instance in different ClassLoader when Thread.getContextClassLoader() returns null,because URLClassLoader(urls,parent) when parent is null.you can see the tests that both ways java return a Proxy instance for Annotation Name instance.occurs this problem often someone calls Thread.currentThread().setContextClassLoader(null) in somewhere.so you can solve the problem by checking the contextLoader whether is null.for example:
ClassLoader context=Thread.currentThread().getContextClassLoader();
if(context==null){
context=getClass().getClassLoader();
}
URLClassLoader loader=new URLClassLoader(urls,context);
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Stream;
import static java.lang.String.format;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
/**
* Created by holi on 3/24/17.
*/
public class AnnotationsTest {
private interface StubClass {
Class<?> stubClass() throws ClassNotFoundException;
default <T extends Annotation> T annotation(Class<T> type) throws Exception {
return stubClass().getAnnotation(type);
}
default Annotation[] annotations() throws Exception {
return stubClass().getAnnotations();
}
}
private static final StubClass JAR_WITHIN_ANNOTATION_CLASS = jar("stubs-within-annotation-class.jar");
private static final StubClass JAR_WITHOUT_ANNOTATION_CLASS = jar("stubs-without-annotation-class.jar");
public static StubClass jar(String jar) {
URL jarFile = Objects.requireNonNull(ClassLoader.getSystemResource(jar), format("Jar file not found:%s", jar));
return () -> {
ClassLoader context = Thread.currentThread().getContextClassLoader();
return new URLClassLoader(new URL[]{jarFile}, context).loadClass("Stub");
};
}
private ClassLoader original;
@BeforeEach
void setUp() throws Throwable {
original = Thread.currentThread().getContextClassLoader();
}
@AfterEach
void tearDown() throws Throwable {
Thread.currentThread().setContextClassLoader(original);
}
@Test
void getAnnotationFromJarClassesWillReturnsContextLoaderAnnotationSharedInstanceIfContextLoaderAssociatedWithRuntimeClassLoader() throws Throwable {
Set<Object> annotationsCreated = new HashSet<>();
Set<Object> stubClassCreated = new HashSet<>();
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
Stream.of(JAR_WITHIN_ANNOTATION_CLASS, JAR_WITHOUT_ANNOTATION_CLASS).forEach(asserts(stub -> {
Name it = stub.annotation(Name.class);
assertThat(it, is(instanceOf(Name.class)));
assertThat(it.value(), equalTo("stub"));
annotationsCreated.add(it);
stubClassCreated.add(stub.stubClass());
}));
assertThat(annotationsCreated, hasSize(1));
assertThat(stubClassCreated, hasSize(2));
}
@Test
void getAnnotationFromJarClassesWillReturnsNullIfNoContextLoaderAssociated() throws Throwable {
Thread.currentThread().setContextClassLoader(null);
Stream.of(JAR_WITHIN_ANNOTATION_CLASS, JAR_WITHOUT_ANNOTATION_CLASS).forEach(asserts(it -> {
//create different class instance in each class loader
assertThat(it.stubClass().getName(), equalTo("Stub"));
assertThat(it.annotation(Name.class), is(nullValue()));
}));
assertThat(JAR_WITHOUT_ANNOTATION_CLASS.annotations(), is(emptyArray()));
assertThat(JAR_WITHIN_ANNOTATION_CLASS.annotations(), arrayWithSize(1));
Annotation it = JAR_WITHIN_ANNOTATION_CLASS.annotations()[0];
assertThat(it.annotationType(), is(not(instanceOf(Name.class))));
assertThat(it.annotationType().getName(), equalTo(Name.class.getName()));
assertThat(it.annotationType().getDeclaredMethod("value").invoke(it), equalTo("stub"));
}
private interface Assert<T> {
void assertThat(T value) throws Exception;
}
private <T> Consumer<T> asserts(Assert<T> executor) {
return (value) -> {
try {
executor.assertThat(value);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
RuntimeException wrappedException = new RuntimeException(e);
wrappedException.setStackTrace(e.getStackTrace());
throw wrappedException;
}
};
}
}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Created by holi on 3/24/17.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface Name {
String value();
}
@Name("stub")
public class Stub{
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With