How to use Java Reflections for the "current" application? - java

The documentation for Reflections gives the first line on how to use Reflections:
Reflections reflections = new Reflections("com.my.project");
Except i don't know the name of the package. This is a piece of library code that should just be able to scan everything in the current package.
What is the Reflections equivalent of the .NET:
//Find all methods in all classes tagged with #Test annotation,
//and add them to a list.
List<MethodInfo> testMethods = new ArrayList<>();
//Enumerate all assemblies in the current application domain
for (Assembly a : AppDomain.currentDomain.getAssemblies()) {
//Look at each type (i.e. class) in the assembly
for (Type t : a.getTypes()) {
...
}
}
in other words, the "current" package? Or in the parlance of .NET
AppDomain.currentDomain
Edit:
Is it a duplicate? No.
Is it not a programming question? No
Does it need details or clarity? No
Does it need more focus? No
Is it opinion based? No
Bonus Reading
Get all methods with a particular annotation in a package (explains what a package is)
How to find annotated methods in a given package? (explains what a package is)
And the final straw:
java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory even though I have the right dependencies

Java's concept of 'package' is much weaker than .net. In Java, the package containing a class is, for most purposes, just the prefix of the classes name.
OSGi, and recent Java versions with Modules, have a stronger model.
If you read down the documentation to https://github.com/ronmamo/reflections#scan, you will see that there are a number of filters that you can apply to control what this library looks at. If you are writing a library, you can either expose that API to your callers and let them tell you what classes to look at, or decide for yourself what to look at. But there is not requirement to have a single focal Java package as far as I see in that documentation.
Calling this.getClass().getPackage().getName() will mean that reflection is only looking at your code, not the rest of the application using your library.

Cannot be done.
Java does not have a reflection system.
Research Effort
Get all methods with a particular annotation in a package (Question isn't about the current package. Accepted answer uses 3rd party library.)
Java seek a method with specific annotation and its annotation element (Question is about a specific class, rather than finding the classes)
How to find annotated methods in a given package?
How to run all methods with a given annotation?
getConstructor with no parameters
Call Methods at Runtime Using Java Reflection
JavaDocs - Invoking Methods
Default access modifier for a Java constructor
Can you find all classes in a package using reflection?
Get all methods with a particular annotation in a package (explains what a package is)
How to find annotated methods in a given package? (explains what a package is)
Additional research effort
java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory even though I have the right dependencies
Oracle: Handling Initialization Status With Event Handlers
how to register a java class if the static initializer isn't called till the class is referenced
Dynamic object registration in Java
getConstructor with no parameters
Load Jar dynamically and register class(es) in applicationContext at runtime
Is it possible to determine descendants solely through Java reflection API?
Call Methods at Runtime Using Java Reflection
JavaDocs - Invoking Methods
At runtime, find all classes in a Java application that extend a base class
Default access modifier for a Java constructor
Find Java classes implementing an interface
Finding all classes implementing a specific interface
How does JUnit find tests?
Book: Unit Testing in Java
[2/28/1998: JUnit 1.0][2]
JUnit Cookbook
How can I get a list of all the implementations of an interface programmatically in Java?
How can I get all Class files in a specific package in Java?
Class Loaders in Java
How can I enumerate all classes in a package and add them to a List?
Java Reflection - Get List of Packages
Getting the list of packages in a java project
Tool to convert java to c# code
Package Initialization in Java
How to write a package-level static initializer in Kotlin?
https://stackoverflow.com/questions/72795950/java-initialize-all-classes-in-package-without-knowing-names
https://github.com/classgraph/classgraph
What is an initialization block?
Package Initialization in Java

Related

Java: find classes with certain base type on program startup

I have a Java program (an Eclipse plug-in to be specific), which is using several JAR files (which I can control). One of the core JAR files defines an abstract class called Strategy. When the user starts the program, the program needs to know all sub classes of Strategy, that are on the program ClassPath.
As I described in this StackOverflow question, I tried to use static initializer blocks on the sub classes, so that they auto-register themselves in a registry. This approach is not working since the static initalizers are not executed before I explicitly use the class.
Is there any other way to find all classes with a certain base type that are on the current ClassPath?
I can think of the following solutions:
traverse all JARs in a specific directory and check the classes they contain
create a file which is loaded on program start-up and read the class names from that
I can implement both of them myself (so I do not ask for any code samples here). I merely want to know if there is another option I am missing. Any in-class solution (like the one I tried with static initializers) would be greatly appreciated.
If you're open to using a third-party library, Reflections seems to be the best fit here. It's a Java runtime metadata analysis library and is like geared to do this. From their website:
Using Reflections you can query your metadata such as:
get all subtypes of some type
get all types/constructos/methods/fields annotated with some annotation, optionally with annotation parameters matching
get all resources matching matching a regular expression
get all methods with specific signature including parameters, parameter annotations and return type
All you need is to create a configured instance of Reflections in your StrategyRegistrar class as
Reflections reflections = new Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage("com.your.app.strategies.pkg"))
.setScanners(new SubTypesScanner())
);
And, then simply fire a query like
Set<Class<? extends Strategy>> strategies =
reflections.getSubTypesOf(com.your.app.strategies.pkg.Strategy.class);

Force a class to implement one of two interfaces that implements another interface

I am not really sure about Java Annotations, but I think they can solve my problem.
I have an java interface "Target". This is an empty interface, so I can give that implementation into an "TargetHolder", which is simply a list of Targets.
Now I only have 2 Types of Targets. Type "Alpha" and type "Beta".
Type "Alpha" has no functionality in common with Type "Beta".
Easiest way would be to just extend "Beta" and "Alpha" from "Target". But with this solution it is possible for a programmer to create a class that extends "Target" only, which must not be possible.
Can I solve that with annotations?
How?
In theory you might be able to implement the checks (at compile time) using an annotation processor. The problem is that javac will only run an annotation processor on a source file if it finds the right kind annotation in the source.
"After scanning the source files and classes on the command line to determine what annotations are present, the compiler queries the processors to determine what annotations they process. When a match is found, the processor will be invoked."
(Javac manual)
But it seems like you want an annotation on an interface to constrain all classes that implement that interface. That means checking all such classes ... but I can't see how you could trigger the running of an annotation processor on a class that has no relevant annotations.
That leaves you with a couple of options:
Implement the checking as (say) a PMD rule.
Write a tool to find the relevant interfaces at runtime, retrieve their annotations, then trawl for all classes that implement the annotated interfaces.
My advice would be to put this into the "too hard" basket. It is probably going to take more time to implement this than you would save in picking up related coding errors earlier. (I'm thinking that the case that you are trying to avoid will be picked up when someone tries to use class. So, you (or your client) should find your (their) incorrect class in testing ...)
How about?
Create a package just for this work. Let us call it target.
Put Target.java in package target - package private.
Put Alpha.java in package target - public
Put Beta.java in package target - public
Compile, jar, and seal package target.
Using Tool like JArchitect allows to enforce design rules.
In your case you can use the following cqlinq query:
warnif count > 0 from t in Types where t.Implement ("Target")
&& (!t.Implement("Alpha")|| !t.Implement("Beta"))
select t

Make the methods of a library not visible for external access but visible for the library

I developed a library and I need that the users of that library can access only to one class ( with a few methods).
For other side I need that this class can access to all library's methods-classes.
One solution is to put all the classes in the same package and make all methods protected but I dont like having a library with different classes for different purposes. (like a class to use video and a class to parse a XML) in the same package.
Now:
com.aracem.library:
- class 1
- class 2
- class 3
- class 4
- class 5
I want something like this
com.aracem.library:
- class 1
com.aracem.library.video
- class 2 video
com.aracem.library.xml
- class 3 xml
- class 4 xml
How can I define the methods of the clas 2 , 3 , 4 (in the example) to let class 1 access to the methods but dont let the users of the library access that methods?
Since java does not have yet any access control mechanism except access modifiers (private, protected, public, or nothing for package-protected access) I can suggest you the following solution.
All classes should be package-protected. To be able to call your own classes from other package create public interfaces in your packages and make your classes to implement these interfaces. The instances of classes should be created by your factory only. Put factory per package. The factory class itself is public.
Now, there is only one possibility for client code to access your classes: instantiate them using your factory. But the factory should check the access rights of caller. It is simple: new Throwable().getStackTrace()[0] returns you the stack trace element of your caller. Examine its package and decide whether you should go on or throw Exception, e.g. SecurityException.
There are other solutions. You can for example wrap all your classes using aspects. For example use AspectJ that performs byte code modification and inserts some code automatically. This code will check the access rights and throw exception as explained above. This solution is probably better but requires you to learn a bit about AspectJ.

How can I run my code upon class load?

Is there a feasible way to get my own code run whenever any class is loaded in Java, without forcing the user explicitly and manually loading all classes with a custom classloader?
Without going too much into the details, whenever a class implementing a certain interface read its annotation that links it with another class, and give the pair to a third class.
Edit: Heck, I'll go to details: I'm doing an event handling library. What I'm doing is having the client code do their own Listener / Event pairs, which need to be registered with my library as a pair. (hm, that wasn't that long after all).
Further Edit: Currently the client code needs to register the pair of classes/interfaces manually, which works pretty well. My intent is to automate this away, and I thought that linking the two classes with annotations would help. Next, I want to get rid of the client code needing to keeping the list of registrations up to date always.
PS: The static block won't do, since my interface is bundled into a library, and the client code will create further interfaces. Thus, abstract classes won't do either, since it must be an interface.
If you want to base the behavior on an interface, you could use a static initializer in that interface.
public interface Foo{
static{
// do initializing here
}
}
I'm not saying it's good practice, but it will definitely initialize the first time one of the implementing classes is loaded.
Update: static blocks in interfaces are illegal. Use abstract classes instead!
Reference:
Initializers (Sun Java Tutorial)
But if I understand you right, you want the initialization to happen once per implementing class. That will be tricky. You definitely can't do that with an interface based solution. You could do it with an abstract base class that has a dynamic initializer (or constructor), that checks whether the requested mapping already exists and adds it if it doesn't, but doing such things in constructors is quite a hack.
I'd say you cleanest options are either to generate Code at build time (through annotation processing with apt or through bytecode analysis with a tool like asm) or to use an agent at class load time to dynamically create the mapping.
Ah, more input. Very good. So clients use your library and provide mappings based on annotations. Then I'd say your library should provide an initializer method, where client code can register classes. Something like this:
YourLibrary.getInstance().registerMappedClasses(
CustomClass1.class,
CustomClass2.class,
CustomClass3.class,
CustomClass4.class
)
Or, even better, a package scanning mechanism (example code to implement this can be found at this question):
YourLibrary.getInstance().registerMappedClassesFromPackages(
"com.mycompany.myclientcode.abc",
"com.mycompany.myclientcode.def"
)
Anyway, there is basically no way to avoid having your clients do that kind of work, because you can't control their build process nor their classloader for them (but you could of course provide guides for classloader or build configuration).
If you want some piece of code to be run on any class loading, you should:
overwrite the ClassLoader, adding your own custom code at the loadClass methods (don't forget forwarding to the parent ClassLoader after or before your custom code).
Define this custom ClassLoader as the default for your system (here you got how to do it: How to set my custom class loader to be the default?).
Run and check it.
Depending on what kind of environment you are, there are chances that not all the classes be loaded trouugh your custom ClassLoader (some utility packages use their own CL, some Java EE containers handle some spacific areas with specific classLoaders, etc.), but it's a kind of aproximation to what you are asking.

Find Java classes implementing an interface [duplicate]

This question already has answers here:
How can I get a list of all the implementations of an interface programmatically in Java?
(11 answers)
Closed 9 years ago.
Some time ago, I came across a piece of code, that used some piece of standard Java functionality to locate the classes that implemented a given interface. I know the functions were hidden in some non-logical place, but they could be used for other classes as the package name implied. Back then I did not need it, so I forgot about it, but now I do, and I can't seem to find the functions again. Where can these functions be found?
Edit: I'm not looking for any IDE functions or anything, but rather something that can be executed within the Java application.
Awhile ago, I put together a package for doing what you want, and more. (I needed it for a utility I was writing). It uses the ASM library. You can use reflection, but ASM turned out to perform better.
I put my package in an open source library I have on my web site. The library is here: http://software.clapper.org/javautil/. You want to start with the with ClassFinder class.
The utility I wrote it for is an RSS reader that I still use every day, so the code does tend to get exercised. I use ClassFinder to support a plug-in API in the RSS reader; on startup, it looks in a couple directory trees for jars and class files containing classes that implement a certain interface. It's a lot faster than you might expect.
The library is BSD-licensed, so you can safely bundle it with your code. Source is available.
If that's useful to you, help yourself.
Update: If you're using Scala, you might find this library to be more Scala-friendly.
Spring can do this for you...
BeanDefinitionRegistry bdr = new SimpleBeanDefinitionRegistry();
ClassPathBeanDefinitionScanner s = new ClassPathBeanDefinitionScanner(bdr);
TypeFilter tf = new AssignableTypeFilter(CLASS_YOU_WANT.class);
s.addIncludeFilter(tf);
s.scan("package.you.want1", "package.you.want2");
String[] beans = bdr.getBeanDefinitionNames();
N.B. The TypeFilter is important if you want the correct results!
You can also use exclusion filters here instead.
The Scanner can be found in the spring-context jar, the registry in spring-beans, the type filter is in spring-core.
I really like the reflections library for doing this.
It provides a lot of different types of scanners (getTypesAnnotatedWith, getSubTypesOf, etc), and it is dead simple to write or extend your own.
The code you are talking about sounds like ServiceLoader, which was introduced in Java 6 to support a feature that has been defined since Java 1.3 or earlier. For performance reasons, this is the recommended approach to find interface implementations at runtime; if you need support for this in an older version of Java, I hope that you'll find my implementation helpful.
There are a couple of implementations of this in earlier versions of Java, but in the Sun packages, not in the core API (I think there are some classes internal to ImageIO that do this). As the code is simple, I'd recommend providing your own implementation rather than relying on non-standard Sun code which is subject to change.
Package Level Annotations
I know this question has already been answered a long time ago but another solution to this problem is to use Package Level Annotations.
While its pretty hard to go find all the classes in the JVM its actually pretty easy to browse the package hierarchy.
Package[] ps = Package.getPackages();
for (Package p : ps) {
MyAno a = p.getAnnotation(MyAno.class)
// Recursively descend
}
Then just make your annotation have an argument of an array of Class.
Then in your package-info.java for a particular package put the MyAno.
I'll add more details (code) if people are interested but most probably get the idea.
MetaInf Service Loader
To add to #erickson answer you can also use the service loader approach. Kohsuke has an awesome way of generating the the required META-INF stuff you need for the service loader approach:
http://weblogs.java.net/blog/kohsuke/archive/2009/03/my_project_of_t.html
You could also use the Extensible Component Scanner (extcos: http://sf.net/projects/extcos) and search all classes implementing an interface like so:
Set<Class<? extends MyInterface>> classes = new HashSet<Class<? extends MyInterface>>();
ComponentScanner scanner = new ComponentScanner();
scanner.getClasses(new ComponentQuery() {
#Override
protected void query() {
select().
from("my.package1", "my.package2").
andStore(thoseImplementing(MyInterface.class).into(classes)).
returning(none());
}
});
This works for classes on the file system, within jars and even for those on the JBoss virtual file system. It's further designed to work within standalone applications as well as within any web or application container.
In full generality, this functionality is impossible. The Java ClassLoader mechanism guarantees only the ability to ask for a class with a specific name (including package), and the ClassLoader can supply a class, or it can state that it does not know that class.
Classes can be (and frequently are) loaded from remote servers, and they can even be constructed on the fly; it is not difficult at all to write a ClassLoader that returns a valid class that implements a given interface for any name you ask from it; a List of the classes that implement that interface would then be infinite in length.
In practice, the most common case is an URLClassLoader that looks for classes in a list of filesystem directories and JAR files. So what you need is to get the URLClassLoader, then iterate through those directories and archives, and for each class file you find in them, request the corresponding Class object and look through the return of its getInterfaces() method.
Obviously, Class.isAssignableFrom() tells you whether an individual class implements the given interface. So then the problem is getting the list of classes to test.
As far as I'm aware, there's no direct way from Java to ask the class loader for "the list of classes that you could potentially load". So you'll have to do this yourself by iterating through the visible jars, calling Class.forName() to load the class, then testing it.
However, it's a little easier if you just want to know classes implementing the given interface from those that have actually been loaded:
via the Java Instrumentation framework, you can call Instrumentation.getAllLoadedClasses()
via reflection, you can query the ClassLoader.classes field of a given ClassLoader.
If you use the instrumentation technique, then (as explained in the link) what happens is that your "agent" class is called essentially when the JVM starts up, and passed an Instrumentation object. At that point, you probably want to "save it for later" in a static field, and then have your main application code call it later on to get the list of loaded classes.
If you were asking from the perspective of working this out with a running program then you need to look to the java.lang.* package. If you get a Class object, you can use the isAssignableFrom method to check if it is an interface of another Class.
There isn't a simple built in way of searching for these, tools like Eclipse build an index of this information.
If you don't have a specific list of Class objects to test you can look to the ClassLoader object, use the getPackages() method and build your own package hierarchy iterator.
Just a warning though that these methods and classes can be quite slow.

Categories

Resources