Architectural overview and configuration

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 assumedHere an example of a burningwave.static.properties file.

Dynamic component container

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")

Here an example of a burningwave.properties file.

Flexible

It’s possible to search classes by every criteria that your imagination can make by using lambda expressions

Optimized

Scan engine is highly optimized using direct allocated ByteBuffers to avoid heap saturation

Open

Burningwave core is an advanced free and open source Java library