3.6. Use the Class Loader Programmatically in a Deployment
3.6.1. Programmatically Load Classes and Resources in a Deployment
- Load a Class Using the Class.forName() Method
- You can use the
Class.forName()
method to programmatically load and initialize classes. This method has two signatures.The three argument signature is the recommended way to programmatically load a class. This signature allows you to control whether you want the target class to be initialized upon load. It is also more efficient to obtain and provide the class loader because the JVM does not need to examine the call stack to determine which class loader to use. Assuming the class containing the code is named- Class.forName(String className)
- This signature takes only one parameter, the name of the class you need to load. With this method signature, the class is loaded by the class loader of the current class and initializes the newly loaded class by default.
- Class.forName(String className, boolean initialize, ClassLoader loader)
- This signature expects three parameters: the class name, a boolean value that specifies whether to initialize the class, and the ClassLoader that should load the class.
CurrentClass
, you can obtain the class's class loader usingCurrentClass.class.getClassLoader()
method.The following example provides the class loader to load and initialize theTargetClass
class:Example 3.7. Provide a class loader to load and initialize the TargetClass.
Class<?> targetClass = Class.forName("com.myorg.util.TargetClass", true, CurrentClass.class.getClassLoader());
- Find All Resources with a Given Name
- If you know the name and path of a resource, the best way to load it directly is to use the standard Java development kit Class or ClassLoader API.
- Load a Single Resource
- To load a single resource located in the same directory as your class or another class in your deployment, you can use the
Class.getResourceAsStream()
method.Example 3.8. Load a single resource in your deployment.
InputStream inputStream = CurrentClass.class.getResourceAsStream("targetResourceName");
- Load All Instances of a Single Resource
- To load all instances of a single resource that are visible to your deployment's class loader, use the
Class.getClassLoader().getResources(String resourceName)
method, whereresourceName
is the fully qualified path of the resource. This method returns an Enumeration of allURL
objects for resources accessible by the class loader with the given name. You can then iterate through the array of URLs to open each stream using theopenStream()
method.Example 3.9. Load all instances of a resource and iterate through the result.
Enumeration<URL> urls = CurrentClass.class.getClassLoader().getResources("full/path/to/resource"); while (urls.hasMoreElements()) { URL url = urls.nextElement(); InputStream inputStream = null; try { inputStream = url.openStream(); // Process the inputStream ... } catch(IOException ioException) { // Handle the error } finally { if (inputStream != null) { try { inputStream.close(); } catch (Exception e) { // ignore } } } }
Note
Because the URL instances are loaded from local storage, it is not necessary to use theopenConnection()
or other related methods. Streams are much simpler to use and minimize the complexity of the code.
- Load a Class File From the Class Loader
- If a class has already been loaded, you can load the class file that corresponds to that class using the following syntax:If the class is not yet loaded, you must use the class loader and translate the path:
Example 3.10. Load a class file for a class that has been loaded.
InputStream inputStream = CurrentClass.class.getResourceAsStream(TargetClass.class.getSimpleName() + ".class");
Example 3.11. Load a class file for a class that has not been loaded.
String className = "com.myorg.util.TargetClass" InputStream inputStream = CurrentClass.class.getClassLoader().getResourceAsStream(className.replace('.', '/') + ".class");
3.6.2. Programmatically Iterate Resources in a Deployment
MANIFEST.MF
:
Dependencies: org.jboss.modulesIt is important to note that while these APIs provide increased flexibility, they will also run much more slowly than a direct path lookup.
- List Resources Within a Deployment and Within All Imports
- There are times when it is not possible to look up resources by the exact path. For example, the exact path may not be known or you may need to examine more than one file in a given path. In this case, the JBoss Modules library provides several APIs for iterating all deployment resources. You can iterate through resources in a deployment by utilizing one of two methods.
- Iterate All Resources Found in a Single Module
- The
ModuleClassLoader.iterateResources()
method iterates all the resources within this module class loader. This method takes two arguments: the starting directory name to search and a boolean that specifies whether it should recurse into subdirectories.The following example demonstrates how to obtain the ModuleClassLoader and obtain the iterator for resources in thebin/
directory, recursing into subdirectories.The resultant iterator may be used to examine each matching resource and query its name and size (if available), open a readable stream, or acquire a URL for the resource.Example 3.12. Find resources in the "bin" directory, recursing into subdirectories.
ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = moduleClassLoader.iterateResources("bin",true);
- Iterate All Resources Found in a Single Module and Imported Resources
- The
Module.iterateResources()
method iterates all the resources within this module class loader, including the resources that are imported into the module. This method returns a much larger set than the previous method. This method requires an argument, which is a filter that narrows the result to a specific pattern. Alternatively, PathFilters.acceptAll() can be supplied to return the entire set.Example 3.13. Find the entire set of resources in this module, including imports.
ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Module module = moduleClassLoader.getModule(); Iterator<Resource> moduleResources = module.iterateResources(PathFilters.acceptAll());
- Find All Resources That Match a Pattern
- If you need to find only specific resources within your deployment or within your deployment's full import set, you need to filter the resource iteration. The JBoss Modules filtering APIs give you several tools to accomplish this.
- Examine the Full Set of Dependencies
- If you need to examine the full set of dependencies, you can use the
Module.iterateResources()
method'sPathFilter
parameter to check the name of each resource for a match. - Examine Deployment Dependencies
- If you need to look only within the deployment, use the
ModuleClassLoader.iterateResources()
method. However, you must use additional methods to filter the resultant iterator. ThePathFilters.filtered()
method can provide a filtered view of a resource iterator this case. ThePathFilters
class includes many static methods to create and compose filters that perform various functions, including finding child paths or exact matches, or matching an Ant-style "glob" pattern.
- Additional Code Examples For Filtering Resouces
- The following examples demonstrate how to filter resources based on different criteria.
Example 3.14. Find all files named "messages.properties" in your deployment.
ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = PathFilters.filtered(PathFilters.match("**/messages.properties"), moduleClassLoader.iterateResources("", true));
Example 3.15. Find all files named "messages.properties" in your deployment and imports.
ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Module module = moduleClassLoader.getModule(); Iterator<Resource> moduleResources = module.iterateResources(PathFilters.match("**/message.properties));
Example 3.16. Find all files inside any directory named "my-resources" in your deployment.
ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = PathFilters.filtered(PathFilters.match("**/my-resources/**"), moduleClassLoader.iterateResources("", true));
Example 3.17. Find all files named "messages" or "errors" in your deployment and imports.
ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Module module = moduleClassLoader.getModule(); Iterator<Resource> moduleResources = module.iterateResources(PathFilters.any(PathFilters.match("**/messages"), PathFilters.match("**/errors"));
Example 3.18. Find all files in a specific package in your deployment.
ModuleClassLoader moduleClassLoader = (ModuleClassLoader) TargetClass.class.getClassLoader(); Iterator<Resource> mclResources = moduleClassLoader.iterateResources("path/form/of/packagename", false);