Annotation for naming classes to be read by reflection - java

My application allows developers to create some plugins. Сompliance with the requirements determined by base abstract class. Each plugin must have a name. I want to solve this problem by using annotations. So, I defined my own annotation Name as follows:
#Retention(RetentionPolicy.RUNTIME)
public #interface Name {
public String value();
}
I put this annotaion and base abstract class CommonPlugin into separate module and build it as JAR-file to share with developers.
Then I import package and put this annotation before the defenition of me test plugin as follows:
#Name("Test plugin")
public class TestPlugin extends CommonPlugin {
Then I reflect all given plugins through URLClassLoader and can't find necessary annotation at TestPlugin class. But if I define Name annotation into the same package the TestPlugin class is, I can find it. It should be so or am I doing something wrong?

Turning my coment into an answer so it can be accepted.
Make sure that the unqualified name Name refers to the same qualified name in all of your source files. In sources from different packages than the one containing the annotation, there should be a non-wildcard import for Name, and there should be no class with that name in that other package itself.

Related

Swagger Codegen how to reuse generated models?

I'm wondering if there is a way to properly generate models so that the generated models can reference each other?
I have a file structure like this
# Project Structure
/common
- Name.json
/v1
- User.json
/v2
- User.json
My Open API Specification files, both v1 and v2 reference common's Name properly
However the generated code ends up like this:
import v1.Name //created another Name class in v1 package
public class User {
Name name;
//...
}
import v2.Name //created another Name class in v2 package
public class User {
Name name;
//...
}
Ideally I would like to have the generated classes to look something like this
package v1
import common.Name
public class User {
Name name;
}
I have tried the import mappings and type mappings flags but the code generator cannot seem to find the common.Name class during creation of User class.
Any workarounds for this or is this a known limitation of the generator?
Edit: Ah it seems like impossible to have different generated packages in a single generation. So I must break these packages into their projects with their own types then utilize .openapi-ignore or looking at the jar depdendencies that's generated. Darn.

Archunit: How to control usage one class in all other packages

I have class from the different repository which has public methods and has been used in the class with import.
Example:
com.tables.Field class which has public Methods from different repository and has been used in the project.
I want above Field class to be used only by class in the following package com.test.FieldImpl
and should not be used by other packages in the project.
How to write Predicate for this condition
private final ArchRule table_should_access_only_impl = classes().that().
haveFullyQualifiedName("com.tables.Field").should().accessTargetWhere(?);
I think that you're looking for something like this:
ArchRule table_should_access_only_impl = noClasses()
.that().doNotHaveFullyQualifiedName("com.test.FieldImpl")
.should().accessClassesThat().haveFullyQualifiedName("com.tables.Field");
Instead of accessClassesThat, you can also use dependOnClassesThat, which covers more dependencies than just field access or method calls.

java class.getAnnotation(Class<?> class) returns null

I have written an annotation:
#Documented
#Retention(RUNTIME)
#Target(TYPE)
/**
* #author christian
*
*/
public #interface HeraklesObject {
}
I use it in an osgi environment (eclipse oxygen with tycho) in a bundle.
In another bundle (a test fragment to be specific) i check classes from the first bundle for this annotation, using:
class.getAnnotation(HeraklesObject.class)
I am sure, that the queried class has this annotation, but I get always null result.
The retention policy seems right to me, but I am not sure if a class loader issue is present and I don't know how I check this. Or do you see another cause? Thanks
Christian
Try to use
#Retention(RetentionPolicy.RUNTIME)
#Target({ ElementType.TYPE })
Also from How to get class annotation in java?
use
Class newClass = X.class;
for (Annotation annotation : newClass.getDeclaredAnnotations()) {
System.out.println(annotation.toString());
}
Does the bundle with the class whose runtime annotations you want to check contain or import the package with the HeraklesObject annotation class?
A class loader will load a class and, if the class of a runtime annotation class is not visible, just ignore the annotation. So you end up with a silent "failure". So check to make sure the package holding the runtime annotation is visible to the bundle holding the annotated class.
If you use Bnd to build the bundle, it should properly import the runtime annotation's package.

How to write an import statement to refer to a java class in a jar?

How can I refer to a Java class in stdlib1.jar when the directory structure is like this? How to write the import statement?
I want to call a method under stdlib1.jar, I have configured it.
The classes are in the default package. According to this answer, it is not possible to import classes from the default package. So, they have to be moved to another package or you have to use reflection.
You call a method from a class and not from a package.
You don't need to specify the jar when you call a method from a class belonging to it. Which matters is your jar is in the classpath
In your screenshot if the lib makes part of the classpath folders, you can import and use classes from it in your code.
Here the classes of your jar use the default package (no package name) which seems weird for a third-party library. Default package is not recommended since it doesn't allow to naturally reference and use the classes of the archive from the client code.
I am not sure you are using the correct version of the jar. Look at that :
http://grepcode.com/snapshot/repo1.maven.org/maven2/com.googlecode.princeton-java-introduction/stdlib/1.0.1
This contains classes in the edu.princeton.cs package :
With package, you could declare this :
For example :
You could create a class like that and use BinaryIn like that:
package main;
import edu.princeton.cs.BinaryIn;
public class MyClass(){
public static void main(String args[]){
BinaryIn in = new BinaryIn();
}
}

Java annotations fundamentals

I am a newbie to annotations. I have gone through a lot of tutorials explaining the concept of annotations. But nowhere do i find information about defining multiple annotations within a class. So pls give me some insight on defining and accessing multiple annotations.Below is the code where I define two annotations in a class and eclipse IDE presents me an error "The public type SampleAnn must be defined in its own file".. Is the reason for this error because of the java convention that "there should only one public annotation per class in the name of the class-name"?
#Documented
#Target(ElementType.LOCAL_VARIABLE)
#Inherited
#Retention(RetentionPolicy.RUNTIME)
public #interface MethodInfo{
int number1;
}
#Documented
#Target(ElementType.LOCAL_VARIABLE)
#Retention(RetentionPolicy.RUNTIME)
public #interface SampleAnn{
int number2;
}
You are right, you can have only a single top-level class in one file.
But what you can do:
public class MyAnnotations {
public #interface SampleAnn { ... }
public #interface MethodInfo { ... }
}
There should more generally be ONE public CLASS per class file and annotations are no exception. It is also important that any publicly defined entity has the same name as its java file's name, so I don't see how you could have two in the same file.
The annotations need to be in separate compilation units (files).
The regarding top-level classes the specification states:
This restriction implies that there must be at most one such type per
compilation unit. This restriction makes it easy for a Java compiler
to find a named class within a package. In practice, many programmers
choose to put each class or interface type in its own compilation
unit, whether or not it is public or is referred to by code in other
compilation units.
Specification

Categories