Burningwave Core is based on the concept of component and component container. A component is a dynamic object that perform functionality related to the domain it belong to. A component container contains a set of dynamic components and could be of two types:
- static component container
- dynamic component container
More than one dynamic container can be created, while only one static container can exists.
Static component container
It is represented by the org.burningwave.core.assembler.StaticComponentContainer class that provides the following fields for each component supplied:
public static final org.burningwave.core.concurrent.QueuedTasksExecutor.Group BackgroundExecutor; public static final org.burningwave.core.jvm.BufferHandler BufferHandler; public static final org.burningwave.core.classes.FieldAccessor ByFieldOrByMethodPropertyAccessor; public static final org.burningwave.core.classes.FieldAccessor ByMethodOrByFieldPropertyAccessor; public static final org.burningwave.core.Cache Cache; public static final org.burningwave.core.classes.Classes Classes; public static final org.burningwave.core.classes.Classes.Loaders ClassLoaders; public static final org.burningwave.core.classes.Constructors Constructors; public static final io.github.toolfactory.jvm.Driver Driver; public static final org.burningwave.core.io.FileSystemHelper FileSystemHelper; public static final org.burningwave.core.classes.Fields Fields; public static final org.burningwave.core.iterable.Properties GlobalProperties; public static final org.burningwave.core.iterable.IterableObjectHelper IterableObjectHelper; public static final io.github.toolfactory.jvm.Info JVMInfo; public static final org.burningwave.core.ManagedLogger.Repository ManagedLoggerRepository; public static final org.burningwave.core.classes.Members Members; public static final org.burningwave.core.classes.Methods Methods; public static final org.burningwave.core.classes.Modules Modules; //Null on JDK 8 public static final org.burningwave.core.Objects Objects; public static final org.burningwave.core.Strings.Paths Paths; public static final org.burningwave.core.io.Resources Resources; public static final org.burningwave.core.classes.SourceCodeHandler SourceCodeHandler; public static final org.burningwave.core.io.Streams Streams; public static final org.burningwave.core.Strings Strings; public static final org.burningwave.core.concurrent.Synchronizer Synchronizer; public static final org.burningwave.core.SystemProperties SystemProperties; public static final org.burningwave.core.concurrent.Thread.Holder ThreadHolder; public static final org.burningwave.core.concurrent.Thread.Supplier ThreadSupplier;
… That can be used within your application, simply adding a static import to your compilation unit, i.e.:
import static org.burningwave.core.assembler.StaticComponentContainer.ClassLoaders; import static org.burningwave.core.assembler.StaticComponentContainer.ManagedLoggerRepository; public class UseOfStaticComponentsExample { public void yourMethod(){ ManagedLoggerRepository.logInfo( UseOfStaticComponentsExample.class::getName, "Master class loader is {}", ClassLoaders.getMaster(Thread.currentThread().getContextClassLoader()) ); } }
Configuration
The configuration of this type of container is done via burningwave.static.properties file that must be located in the base path of your class path: the library looks for all files with this name and merges them according to to the property priority-of-this-configuration
contained within it which is optional but becomes mandatory if in the base class paths there are multiple files with the file name indicated above. It is possible to change the file name of the configuration file through the method org.burningwave.core.assembler.StaticComponentContainer.Configuration.Default.setFileName
before using the static component container or if you need to integrate the configuration properties into Spring you can follow this guide. If no configuration file is found, the library programmatically sets the default configuration with following values:
background-executor.all-tasks-monitoring.enabled=\ true background-executor.all-tasks-monitoring.interval=\ 30000 background-executor.all-tasks-monitoring.logger.enabled=\ false background-executor.all-tasks-monitoring.minimum-elapsed-time-to-consider-a-task-as-probable-dead-locked=\ 300000 #Other possible values are: 'mark as probable dead locked', #'interrupt', 'kill'. It is also possible to combine these values, e.g.: #background-executor.all-tasks-monitoring.probable-dead-locked-tasks-handling.policy=\ # mark as probable dead locked, kill background-executor.all-tasks-monitoring.probable-dead-locked-tasks-handling.policy=\ log only background-executor.queued-task-executor[0].name=\ Low priority tasks background-executor.queued-task-executor[0].priority=\ 1 background-executor.queued-task-executor[1].name=\ Normal priority tasks background-executor.queued-task-executor[1].priority=\ 5 background-executor.queued-task-executor[2].name=\ High priority tasks background-executor.queued-task-executor[2].priority=\ 10 background-executor.task-creation-tracking.enabled=\ ${background-executor.all-tasks-monitoring.enabled} banner.additonal-informations=\ ${Implementation-Title} ${Implementation-Version} banner.additonal-informations.retrieve-from-manifest-file-with-implementation-title=\ Burningwave Core banner.hide=\ false banner.file=\ org/burningwave/banner.bwb buffer-handler.default-buffer-size=\ 1024 buffer-handler.default-allocation-mode=\ ByteBuffer::allocateDirect group-name-for-named-elements=\ Burningwave iterable-object-helper.default-values-separator=\ ; iterable-object-helper.parallel-iteration.applicability.default-minimum-collection-size=\ 2 iterable-object-helper.parallel-iteration.applicability.max-runtime-thread-count-threshold=\ autodetect iterable-object-helper.parallel-iteration.applicability.output-collection-enabled-types=\ java.util.concurrent.ConcurrentHashMap$CollectionView;\ java.util.Collections$SynchronizedCollection;\ java.util.concurrent.CopyOnWriteArrayList;\ java.util.concurrent.CopyOnWriteArraySet;\ java.util.concurrent.BlockingQueue;\ java.util.concurrent.ConcurrentSkipListSet;\ java.util.concurrent.ConcurrentSkipListMap$EntrySet;\ java.util.concurrent.ConcurrentSkipListMap$KeySet;\ java.util.concurrent.ConcurrentSkipListMap$Values; #This property is optional and it is possible to use a custom JVM Driver which implements #the io.github.toolfactory.jvm.Driver interface. #Other possible values are: io.github.toolfactory.jvm.DefaultDriver, #org.burningwave.jvm.HybridDriver, org.burningwave.jvm.NativeDriver jvm.driver.type=\ org.burningwave.jvm.DynamicDriver jvm.driver.init=\ false #With this value the library will search if org.slf4j.Logger is present and, in this case, #the SLF4JManagedLoggerRepository will be instantiated, otherwise #the SimpleManagedLoggerRepository will be instantiated managed-logger.repository=\ autodetect #to increase performance set it to false managed-logger.repository.enabled=\ true managed-logger.repository.logging.warn.disabled-for=\ org.burningwave.core.assembler.ComponentContainer$ClassLoader;\ org.burningwave.core.classes.MemoryClassLoader;\ org.burningwave.core.classes.PathScannerClassLoader; modules.export-all-to-all=\ true #mandatory if more burningwave.static.properties file are in the class paths priority-of-this-configuration=0 resource-releaser.enabled=true synchronizer.all-threads-monitoring.enabled=\ false synchronizer.all-threads-monitoring.interval=\ 90000 thread-supplier.default-daemon-flag-value=\ true thread-supplier.default-thread-priority=\ 5 thread-supplier.max-detached-thread-count=\ ${thread-supplier.max-poolable-thread-count} thread-supplier.max-detached-thread-count.elapsed-time-threshold-from-last-increase-for-gradual-decreasing-to-initial-value=\ 30000 thread-supplier.max-detached-thread-count.increasing-step=\ autodetect thread-supplier.max-poolable-thread-count=\ autodetect thread-supplier.poolable-thread-request-timeout=\ 6000
If in your custom burningwave.static.properties file one of this default properties is not found, the relative default value here in the box above is assumed. Here an example of a burningwave.static.properties file.
It is represented by the org.burningwave.core.assembler.ComponentContainer class that provides the following methods for each component supplied:
public ByteCodeHunter getByteCodeHunter(); public ClassFactory getClassFactory(); public ClassHunter getClassHunter(); public ClassPathHelper getClassPathHelper(); public ClassPathHunter getClassPathHunter(); public CodeExecutor getCodeExecutor(); public FunctionalInterfaceFactory getFunctionalInterfaceFactory(); public JavaMemoryCompiler getJavaMemoryCompiler(); public PathHelper getPathHelper(); public PathScannerClassLoader getPathScannerClassLoader();
… That can be used within your application, simply as follow:
package org.burningwave.core.examples.componentcontainer; import org.burningwave.core.assembler.ComponentContainer; import org.burningwave.core.assembler.ComponentSupplier; import org.burningwave.core.classes.ClassFactory; import org.burningwave.core.classes.ClassHunter; import org.burningwave.core.io.PathHelper; import java.util.Properties; public class RetrievingDynamicComponentContainerAndComponents { public static void execute() throws Throwable { //In this case we are retrieving the singleton component container instance ComponentSupplier componentSupplier = ComponentContainer.getInstance(); //In this case we are creating a component container by using a custom configuration file ComponentSupplier customComponentSupplier = ComponentContainer.create("your-custom-properties-file.properties"); //In this case we are creating a component container programmatically by using a custom properties object Properties configProps = new Properties(); configProps.put(ClassFactory.Configuration.Key.DEFAULT_CLASS_LOADER, Thread.currentThread().getContextClassLoader()); configProps.put(ClassHunter.Configuration.Key.DEFAULT_PATH_SCANNER_CLASS_LOADER, componentSupplier.getPathScannerClassLoader()); ComponentSupplier customComponentSupplier2 = ComponentContainer.create(configProps); PathHelper pathHelper = componentSupplier.getPathHelper(); ClassFactory classFactory = customComponentSupplier.getClassFactory(); ClassHunter classHunter = customComponentSupplier2.getClassHunter(); } }
Configuration
The configuration of this type of container can be done via Properties file or programmatically via a Properties object. If you use the singleton instance obtained via ComponentContainer.getInstance()
method, you must create a burningwave.properties file and put it on base path of your class path project: the library looks for all files with this name and merges them according to to the property priority-of-this-configuration
contained within it which is optional but becomes mandatory if in the base class paths there are multiple files with the file name indicated above. It is possible to change the file name of the configuration file through the method org.burningwave.core.assembler.ComponentContainer.Configuration.Default.setFileName
before using the component container or if you need to integrate the configuration properties into Spring you can follow this guide. If no configuration file is found, the library programmatically sets the default configuration with following values:
byte-code-hunter.default-path-scanner-class-loader=\ (Supplier<PathScannerClassLoader>)() -> ((ComponentSupplier)parameter[0]).getPathScannerClassLoader() #This variable is empty by default and can be valorized by developer and it is #included by 'byte-code-hunter.default-path-scanner-class-loader.supplier.imports' property byte-code-hunter.default-path-scanner-class-loader.supplier.additional-imports= byte-code-hunter.default-path-scanner-class-loader.supplier.imports=\ ${code-executor.common.imports};\ ${byte-code-hunter.default-path-scanner-class-loader.supplier.additional-imports};\ org.burningwave.core.classes.PathScannerClassLoader; byte-code-hunter.default-path-scanner-class-loader.supplier.name=\ org.burningwave.core.classes.DefaultPathScannerClassLoaderRetrieverForByteCodeHunter byte-code-hunter.new-isolated-path-scanner-class-loader.search-config.check-file-option=\ ${hunters.default-search-config.check-file-option} class-factory.byte-code-hunter.search-config.check-file-option=\ ${hunters.default-search-config.check-file-option} #default classloader used by the ClassFactory to load generated classes class-factory.default-class-loader=\ (Supplier<ClassLoader>)() -> ((ComponentSupplier)parameter[0]).getPathScannerClassLoader() #This variable is empty by default and can be valorized by developer and it is #included by 'class-factory.default-class-loader.supplier.imports' property class-factory.default-class-loader.supplier.additional-imports= class-factory.default-class-loader.supplier.imports=\ ${code-executor.common.imports};\ ${class-factory.default-class-loader.supplier.additional-imports};\ org.burningwave.core.classes.PathScannerClassLoader; class-factory.default-class-loader.supplier.name=\ org.burningwave.core.classes.DefaultClassLoaderRetrieverForClassFactory class-hunter.default-path-scanner-class-loader=\ (Supplier<PathScannerClassLoader>)() -> ((ComponentSupplier)parameter[0]).getPathScannerClassLoader() #This variable is empty by default and can be valorized by developer and it is #included by 'class-hunter.default-path-scanner-class-loader.supplier.imports' property class-hunter.default-path-scanner-class-loader.supplier.additional-imports= class-hunter.default-path-scanner-class-loader.supplier.imports=\ ${code-executor.common.imports};\ ${class-hunter.default-path-scanner-class-loader.supplier.additional-imports};\ org.burningwave.core.classes.PathScannerClassLoader; class-hunter.default-path-scanner-class-loader.supplier.name=\ org.burningwave.core.classes.DefaultPathScannerClassLoaderRetrieverForClassHunter class-hunter.new-isolated-path-scanner-class-loader.search-config.check-file-option=\ ${hunters.default-search-config.check-file-option} class-path-helper.class-path-hunter.search-config.check-file-option=\ ${hunters.default-search-config.check-file-option} class-hunter.default-path-scanner-class-loader=\ (Supplier<PathScannerClassLoader>)() -> ((ComponentSupplier)parameter[0]).getPathScannerClassLoader() class-path-hunter.default-path-scanner-class-loader=\ (Supplier<PathScannerClassLoader>)() -> ((ComponentSupplier)parameter[0]).getPathScannerClassLoader() #This variable is empty by default and can be valorized by developer and it is #included by 'class-path-hunter.default-path-scanner-class-loader.supplier.imports' property class-path-hunter.default-path-scanner-class-loader.supplier.additional-imports= class-path-hunter.default-path-scanner-class-loader.supplier.imports=\ ${code-executor.common.imports};\ ${class-path-hunter.default-path-scanner-class-loader.supplier.additional-imports};\ org.burningwave.core.classes.PathScannerClassLoader; class-path-hunter.default-path-scanner-class-loader.supplier.name=\ org.burningwave.core.classes.DefaultPathScannerClassLoaderRetrieverForClassPathHunter class-path-hunter.new-isolated-path-scanner-class-loader.search-config.check-file-option=\ ${hunters.default-search-config.check-file-option} #This variable is empty by default and can be valorized by developer and it is #included by 'code-executor.common.import' property code-executor.common.additional-imports= code-executor.common.imports=\ static org.burningwave.core.assembler.StaticComponentContainer.BackgroundExecutor;\ ${code-executor.common.additional-imports};\ org.burningwave.core.assembler.ComponentSupplier;\ java.util.function.Function;\ org.burningwave.core.io.FileSystemItem;\ org.burningwave.core.io.PathHelper;\ org.burningwave.core.concurrent.QueuedTasksExecutor$ProducerTask;\ org.burningwave.core.concurrent.QueuedTasksExecutor$Task;\ java.util.function.Supplier; component-container.after-init.operations.imports=\ ${code-executor.common.imports};\ ${component-container.after-init.operations.additional-imports};\ org.burningwave.core.classes.SearchResult; component-container.after-init.operations.executor.name=\ org.burningwave.core.assembler.AfterInitOperations hunters.default-search-config.check-file-option=\ ${path-scanner-class-loader.search-config.check-file-option} path-scanner-class-loader.parent=\ Thread.currentThread().getContextClassLoader() #This variable is empty by default and can be valorized by developer and it is #included by 'path-scanner-class-loader.parent.supplier.imports' property path-scanner-class-loader.parent.supplier.additional-imports=\ path-scanner-class-loader.parent.supplier.imports=\ ${code-executor.common.imports};\ ${path-scanner-class-loader.parent.supplier.additional-imports}; path-scanner-class-loader.parent.supplier.name=\ org.burningwave.core.classes.ParentClassLoaderRetrieverForPathScannerClassLoader #other possible values are: checkFileName, checkFileName|checkFileSignature, checkFileName&checkFileSignature path-scanner-class-loader.search-config.check-file-option=checkFileName #This variable is empty by default and can be valorized by developer and it is #included by 'paths.class-factory.default-class-loader.class-repositories' property paths.class-factory.default-class-loader.additional-class-repositories= #this variable indicates all the paths from which the classes #must be taken if during the definition of the compiled classes #on classloader there will be classes not found paths.class-factory.default-class-loader.class-repositories=\ ${paths.java-memory-compiler.class-paths};\ ${paths.java-memory-compiler.class-repositories};\ ${paths.class-factory.default-class-loader.additional-class-repositories} paths.hunters.default-search-config.paths=\ ${paths.main-class-paths};\ ${paths.main-class-paths.extension};\ ${paths.main-class-repositories}; #This variable is empty by default and can be valorized by developer and it is #included by 'paths.java-memory-compiler.class-paths' property paths.java-memory-compiler.additional-class-paths= paths.java-memory-compiler.black-listed-class-paths=\ //${paths.main-class-paths}/..//children:.*?surefirebooter\d{0,}\.jar; #this variable indicates all the class paths used by the JavaMemoryCompiler #component for compiling paths.java-memory-compiler.class-paths=\ ${paths.main-class-paths};\ ${paths.main-class-paths.extension};\ ${paths.java-memory-compiler.additional-class-paths} #This variable is empty by default and can be valorized by developer. and it is #included by 'paths.java-memory-compiler.class-repositories' property paths.java-memory-compiler.additional-class-repositories= #All paths inserted here will be analyzed by JavaMemoryCompiler component in case #of compilation failure to search for class paths of all classes imported by sources paths.java-memory-compiler.class-repositories=\ ${paths.main-class-repositories};\ ${paths.java-memory-compiler.additional-class-repositories}; paths.main-class-paths=\ ${system.properties:java.class.path} paths.main-class-paths.extension=\ //${system.properties:java.home}/lib//children:.*?\.jar;\ //${system.properties:java.home}/lib/ext//children:.*?\.jar;\ //${system.properties:java.home}/../lib//children:.*?\.jar; paths.main-class-repositories=\ //${system.properties:java.home}/jmods//children:.*?\.jmod; #mandatory if more burningwave.properties file are in the class paths priority-of-this-configuration=0
If in your custom burningwave.properties file one of this default properties is not found, the relative default value here in the box above is assumed.
If you create a component container instance through method ComponentContainer.create(String relativeConfigFileName), you can specify the file name of your properties file and you can locate it everywhere in your classpath project but remember to use a relative path in this case, i.e.: if you name your file “custom-config-file.properties” and put it in package “org.burningwave” you must create the component container as follow:
ComponentContainer.create("org/burningwave/custom-config-file.properties")
BackgroundExecutor
ClassFactory
ClassHunter
- In depth look to and configuration guide
- USE CASE: how to retrieve all classes of the classpath
- USE CASE: how to retrieve all classes that implement one or more interfaces
- USE CASE: finding all classes that extend a base class
- USE CASE: how to find all classes in a package
- USE CASE: Finding all classes for module name (Java 9 and later)
- USE CASE: finding all annotated classes
- USE CASE: how to scan classes for specific annotations and collect their values
- USE CASE: how to search for all classes with a constructor that takes a specific type as first parameter and with at least 2 methods that begin for a given string
- USE CASE: how to search for all classes with methods whose name begins for a given string and that takes a specific type as its first parameter
- USE CASE: finding all classes that have at least 2 protected fields
ClassPathHunter
CodeExecutor
FileSystemItem
FunctionalInterfaceFactory
IterableObjectHelper
JavaMemoryCompiler
PropertyAccessor
UnitSourceGenerator