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.classes.PropertyAccessor ByFieldOrByMethodPropertyAccessor;
public static final org.burningwave.core.classes.PropertyAccessor ByMethodOrByFieldPropertyAccessor;
public static final org.burningwave.core.jvm.LowLevelObjectsHandler.ByteBufferDelegate ByteBufferDelegate;
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 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 org.burningwave.core.jvm.JVMInfo JVMInfo;
public static final org.burningwave.core.jvm.LowLevelObjectsHandler LowLevelObjectsHandler;
public static final org.burningwave.core.ManagedLogger.Repository ManagedLoggersRepository;
public static final org.burningwave.core.classes.Members Members;
public static final org.burningwave.core.classes.Methods Methods;
public static final org.burningwave.core.Strings.Paths Paths;
public static final org.burningwave.core.io.Resources Resources;
public static final org.burningwave.core.io.Streams Streams;
public static final org.burningwave.core.classes.SourceCodeHandler SourceCodeHandler;
public static final org.burningwave.core.Strings Strings;
public static final org.burningwave.core.Throwables Throwables;

… That can be used within your application, simply adding a static import to your compilation unit, i.e.:

package org.burningwave.core.examples.staticcomponents;

import static org.burningwave.core.assembler.StaticComponentContainer.Classes;
import static org.burningwave.core.assembler.StaticComponentContainer.ManagedLoggersRepository;

public class UseOfStaticComponentsExample {
    
    public void yourMethod(){
        ManagedLoggersRepository.logInfo(UseOfStaticComponentsExample.class, Classes.getId(this));
    }

}

Configuration

The configuration of this type of container is done via burningwave.static.properties file or via burningwave.static.default.properties file: the library searches for the first file and if it does not find it, then it searches for the second file and if neither this one is found then the library sets the default configuration programmatically. The default configuration loaded programmatically if no configuration file is found is the following:

#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
static-component-container.clear-temporary-folder-on-init=true
static-component-container.hide-banner-on-init=false
streams.default-buffer-size=1024
streams.default-byte-buffer-allocation-mode=ByteBuffer::allocateDirect

If in your custom burningwave.static.properties or burningwave.static.default.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 with all configurable properties:

#other possible values are: autodetect, org.burningwave.core.SimpleManagedLoggerRepository
managed-logger.repository=org.burningwave.core.SLF4JManagedLoggerRepository
#to increase performance set it to false
managed-logger.repository.enabled=true
managed-logger.repository.logging.debug.disabled-for=\
    org.burningwave.core.io.FileSystemItem;\
    org.burningwave.core.classes.PathMemoryClassLoader;\
    org.burningwave.core.classes.MemoryClassLoader;
streams.default-buffer-size=0.5Kb
#other possible value is ByteBuffer::allocate
streams.default-byte-buffer-allocation-mode=ByteBuffer::allocateDirect
static-component-container.clear-temporary-folder-on-init=true
static-component-container.hide-banner-on-init=false

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 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 org.burningwave.core.iterable.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 classpath project. The default configuration automatically loaded if no configuration file is found is the following:

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()
class-factory.default-class-loader.imports=\
    #This variable is empty by default and could be valorized by developer
    ${class-factory.default-class-loader.additional-imports};\
    org.burningwave.core.assembler.ComponentSupplier;\
    java.util.function.Function;\
    org.burningwave.core.io.FileSystemItem;\
    org.burningwave.core.classes.PathScannerClassLoader;\
    java.util.function.Supplier;
class-factory.default-class-loader.name=\
    org.burningwave.core.classes.DefaultClassLoaderRetrieverForClassFactory
class-hunter.default-path-scanner-class-loader=\
    (Supplier<PathScannerClassLoader>)() -> ((ComponentSupplier)parameter[0]).getPathScannerClassLoader()
class-hunter.default-path-scanner-class-loader.imports=\
    #This variable is empty by default and could be valorized by developer
    ${class-hunter.default-path-scanner-class-loader.additional-imports};\
    org.burningwave.core.assembler.ComponentSupplier;\
    org.burningwave.core.io.FileSystemItem;\
    org.burningwave.core.classes.PathScannerClassLoader;\
    java.util.function.Supplier;
class-hunter.default-path-scanner-class-loader.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}
hunters.default-search-config.check-file-option=\
    ${path-scanner-class-loader.search-config.check-file-option}
hunters.path-loading-lock=forPath
java-memory-compiler.class-path-hunter.search-config.check-file-option=\
    ${hunters.default-search-config.check-file-option}
path-scanner-class-loader.parent=\
    Thread.currentThread().getContextClassLoader()
path-scanner-class-loader.parent.imports=\
    ${path-scanner-class-loader.parent.additional-imports};\
    org.burningwave.core.assembler.ComponentSupplier;\
    org.burningwave.core.io.FileSystemItem;\
    org.burningwave.core.classes.PathScannerClassLoader;\
    java.util.function.Supplier;
path-scanner-class-loader.parent.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 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-repositories};\
    ${paths.class-factory.default-class-loader.additional-class-repositories};
paths.hunters.default-search-config.paths=${main-class-paths};
#this variable indicates all the paths from which the classes 
#must be taken if during the compilation there will be classes
#not found
paths.java-memory-compiler.class-repositories=\
    ${main-class-paths};\
    ${paths.java-memory-compiler.additional-main-class-paths};\
    ${paths.main-class-paths.extension};\
    #This variable is empty by default and could be valorized by developer
    ${paths.java-memory-compiler.additional-class-repositories};
paths.java-memory-compiler.main-class-paths=\
    ${main-class-paths};\
    #This variable is empty by default and could be valorized by developer
    ${paths.java-memory-compiler.additional-main-class-paths};
paths.main-class-paths=${system.properties:java.class.path}
paths.main-class-paths.extension=\
    //${system.properties:java.home}/lib//children:.*?\.jar|.*?\.jmod;\
    //${system.properties:java.home}/lib/ext//children:.*?\.jar|.*?\.jmod;\
    //${system.properties:java.home}/jmods//children:.*?\.jar|.*?\.jmod;

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 with all configurable properties :

class-factory.byte-code-hunter.search-config.check-file-option=\
    checkFileName&checkFileSignature
class-factory.default-class-loader.parent=Thread.currentThread().getContextClassLoader()
class-factory.default-class-loader=PathScannerClassLoader.create(\
    ${class-factory.default-class-loader.parent},\
    ((ComponentSupplier)parameter[0]).getPathHelper(),\
    FileSystemItem.Criteria.forClassTypeFiles(\
        FileSystemItem.CheckingOption.FOR_NAME\
    )\
)
class-factory.default-class-loader.imports=\
    ${class-factory.default-class-loader.additional-imports};\
    org.burningwave.core.assembler.ComponentSupplier;\
    java.util.function.Function;\
    org.burningwave.core.io.FileSystemItem;\
    org.burningwave.core.classes.PathScannerClassLoader;\
    java.util.function.Supplier;
class-factory.default-class-loader.name=\
    org.burningwave.core.classes.DefaultClassLoaderRetrieverForClassFactory
class-hunter.default-path-scanner-class-loader=\
    (Supplier<PathScannerClassLoader>)() -> ((ComponentSupplier)parameter[0]).getPathScannerClassLoader()
class-hunter.default-path-scanner-class-loader.imports=\
    ${class-hunter.default-path-scanner-class-loader.additional-imports};\
    org.burningwave.core.assembler.ComponentSupplier;\
    org.burningwave.core.io.FileSystemItem;\
    org.burningwave.core.classes.PathScannerClassLoader;\
    java.util.function.Supplier;
class-hunter.default-path-scanner-class-loader.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}
hunters.default-search-config.check-file-option=\
    ${path-scanner-class-loader.search-config.check-file-option}
hunters.path-loading-lock=forPath
java-memory-compiler.class-path-hunter.search-config.check-file-option=\
    ${hunters.default-search-config.check-file-option}
path-scanner-class-loader.parent=\
    Thread.currentThread().getContextClassLoader()
path-scanner-class-loader.parent.imports=\
    ${path-scanner-class-loader.parent.additional-imports};\
    org.burningwave.core.assembler.ComponentSupplier;\
    org.burningwave.core.io.FileSystemItem;\
    org.burningwave.core.classes.PathScannerClassLoader;\
    java.util.function.Supplier;
path-scanner-class-loader.parent.name=\
    org.burningwave.core.classes.ParentClassLoaderRetrieverForPathScannerClassLoader
path-scanner-class-loader.search-config.check-file-option=checkFileName
paths.class-factory.default-class-loader.class-repositories=\
    ${paths.java-memory-compiler.class-repositories};\
    ${paths.class-factory.default-class-loader.additional-class-repositories};
paths.hunters.default-search-config.paths=${main-class-paths};
paths.java-memory-compiler.class-repositories=\
    ${main-class-paths};\
    ${paths.java-memory-compiler.additional-main-class-paths};\
    ${paths.main-class-paths.extension};\
    ${paths.java-memory-compiler.additional-class-repositories};
paths.java-memory-compiler.main-class-paths=\
    ${main-class-paths};\
    ${paths.java-memory-compiler.additional-main-class-paths};
paths.main-class-paths=${system.properties:java.class.path}
paths.main-class-paths.extension=\
    //${system.properties:java.home}/lib//children:.*?\.jar|.*?\.jmod;\
    //${system.properties:java.home}/lib/ext//children:.*?\.jar|.*?\.jmod;\
    //${system.properties:java.home}/jmods//children:.*?\.jar|.*?\.jmod;
paths.java-memory-compiler.additional-main-class-paths=C:/some paths 1;C:/some paths 2;
paths.java-memory-compiler.additional-class-repositories=C:/some paths 3;C:/some paths 4;
paths.class-factory.default-class-loader.additional-class-repositories=C:/some paths 5;C:/some paths 6;