Core starter providing fundamental building blocks for Spring Boot applications with auto-configuration support, logging, and YAML parsing
—
Comprehensive logging infrastructure with structured logging support and application failure analysis capabilities.
Core logging system abstraction and management.
/**
* Common abstraction over logging systems
*/
public abstract class LoggingSystem {
/**
* System property used to override the system type
*/
public static final String SYSTEM_PROPERTY = LoggingSystem.class.getName();
/**
* Get the logging system for the given class loader
* @param classLoader the class loader or null to use the default
* @return the logging system
*/
public static LoggingSystem get(ClassLoader classLoader);
/**
* Detect and return the logging system in use
* @param classLoader the class loader or null to use the default
* @return the logging system or NONE if not detected
*/
public static LoggingSystem getLoggingSystem(ClassLoader classLoader);
/**
* Called before the logging system is initialized
*/
public abstract void beforeInitialize();
/**
* Fully initialize the logging system
* @param initializationContext the initialization context
* @param configLocation the config location or null if default
* @param logFile the log file or null if none
*/
public abstract void initialize(LoggingInitializationContext initializationContext,
String configLocation, LogFile logFile);
/**
* Clean up the logging system. The default implementation does nothing
*/
public abstract void cleanUp();
/**
* Returns a Runnable that can handle shutdown of this logging system when the JVM exits
* @return the shutdown handler or null
*/
public Runnable getShutdownHandler();
/**
* Set the log level for the specified logger
* @param loggerName the name of the logger to set
* @param level the log level
*/
public abstract void setLogLevel(String loggerName, LogLevel level);
/**
* Return the configurations that were applied when the logging system was initialized
* @return the configurations or an empty list
*/
public List<LoggingSystemProperty> getLoggingSystemProperties();
}
/**
* Logging levels supported by a LoggingSystem
*/
public enum LogLevel {
TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF
}
/**
* A reference to a log file
*/
public class LogFile {
/**
* The name of the Spring property that contains the name of the log file
*/
public static final String FILE_NAME_PROPERTY = "logging.file.name";
/**
* The name of the Spring property that contains the directory where log files are written
*/
public static final String FILE_PATH_PROPERTY = "logging.file.path";
/**
* Create a new LogFile instance
* @param file the file reference (may be null)
* @param path the file path reference (may be null)
*/
public LogFile(String file, String path);
/**
* Get a LogFile from the given Spring Environment
* @param propertyResolver property resolver used to obtain the logging properties
* @return a LogFile instance or null if the Environment contains no log file configuration
*/
public static LogFile get(PropertyResolver propertyResolver);
/**
* Return the log file that will be written (this may not exist)
* @return the file or null if none
*/
public String toString();
}
/**
* Context passed to the LoggingSystem during initialization
*/
public class LoggingInitializationContext {
/**
* Create a new LoggingInitializationContext instance
* @param environment the Spring environment
*/
public LoggingInitializationContext(ConfigurableEnvironment environment);
/**
* Return the Spring environment that should be used for initialization
* @return the environment
*/
public ConfigurableEnvironment getEnvironment();
}Support for structured logging formats and formatters.
/**
* A formatter for structured log events
*/
@FunctionalInterface
public interface StructuredLogFormatter<E> {
/**
* Format the given log event
* @param event the log event to format
* @return the formatted log event
*/
String format(E event);
}
/**
* Common structured log formats
*/
public enum CommonStructuredLogFormat implements StructuredLogFormatter<ILoggingEvent> {
/**
* Elastic Common Schema format
*/
ECS {
@Override
public String format(ILoggingEvent event) {
return new EcsJsonFormatter().format(event);
}
},
/**
* Logstash JSON format
*/
LOGSTASH {
@Override
public String format(ILoggingEvent event) {
return new LogstashJsonFormatter().format(event);
}
};
/**
* Get the StructuredLogFormatter for the given format name
* @param format the format name
* @return the formatter or null if not found
*/
public static StructuredLogFormatter<ILoggingEvent> of(String format);
}
/**
* Factory for creating StructuredLogFormatter instances
*/
public interface StructuredLogFormatterFactory<E> {
/**
* Create a StructuredLogFormatter
* @param format the format string
* @return the formatter
*/
StructuredLogFormatter<E> createFormatter(String format);
}System for analyzing application startup failures and providing helpful diagnostics.
/**
* Interface used to analyze failures and provide diagnostic information that can be displayed to the user
*/
@FunctionalInterface
public interface FailureAnalyzer {
/**
* Returns an analysis of the given failure, or null if no analysis was possible
* @param failure the failure
* @return the analysis or null
*/
FailureAnalysis analyze(Throwable failure);
}
/**
* Abstract base class for most FailureAnalyzer implementations
*/
public abstract class AbstractFailureAnalyzer<T extends Throwable> implements FailureAnalyzer {
@Override
public FailureAnalysis analyze(Throwable failure);
/**
* Returns an analysis of the given root failure, or null if no analysis was possible
* @param rootFailure the root failure passed to the analyzer
* @param cause the actual found cause
* @return the analysis or null
*/
protected abstract FailureAnalysis analyze(Throwable rootFailure, T cause);
/**
* Return the cause of the specified type that is at the root of the failure, or null if none is found
* @param failure the source failure
* @return the cause or null
*/
@SuppressWarnings("unchecked")
protected final T findCause(Throwable failure);
}
/**
* The result of analyzing a failure
*/
public class FailureAnalysis {
private final String description;
private final String action;
private final Throwable cause;
/**
* Creates a new FailureAnalysis with the given description and action
* @param description the description
* @param action the action
* @param cause the cause
*/
public FailureAnalysis(String description, String action, Throwable cause);
/**
* Returns a description of the failure
* @return the description
*/
public String getDescription();
/**
* Returns the action that the user should take to address the failure
* @return the action
*/
public String getAction();
/**
* Returns the cause of the failure
* @return the cause
*/
public Throwable getCause();
}
/**
* Reports FailureAnalysis instances to the user
*/
@FunctionalInterface
public interface FailureAnalysisReporter {
/**
* Report the specified failure analysis to the user
* @param analysis the analysis
*/
void report(FailureAnalysis analysis);
}Usage Examples:
// Custom failure analyzer
@Component
public class DatabaseConnectionFailureAnalyzer extends AbstractFailureAnalyzer<SQLException> {
@Override
protected FailureAnalysis analyze(Throwable rootFailure, SQLException cause) {
return new FailureAnalysis(
"Failed to connect to the database: " + cause.getMessage(),
"Check your database connection settings in application.properties",
cause
);
}
}
// Custom logging configuration
@Configuration
public class LoggingConfig {
@Bean
public LoggingSystemProperty customLoggingProperty() {
return LoggingSystemProperty.of("logging.custom.enabled", "true");
}
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
LoggingSystem loggingSystem = LoggingSystem.get(getClass().getClassLoader());
loggingSystem.setLogLevel("com.example", LogLevel.DEBUG);
}
}Support for exposing build and version information.
/**
* Provide build-related information such as group and artifact
*/
@ConfigurationProperties("spring.info.build")
public class BuildProperties extends InfoProperties {
/**
* Create an instance with the specified entries
* @param entries the entries
*/
public BuildProperties(Properties entries);
/**
* Get the application group
* @return the group or null
*/
public String getGroup();
/**
* Get the application artifact
* @return the artifact or null
*/
public String getArtifact();
/**
* Get the application name
* @return the name or null
*/
public String getName();
/**
* Get the application version
* @return the version or null
*/
public String getVersion();
/**
* Get the timestamp of when the application was built
* @return the build time or null
*/
public Instant getTime();
}
/**
* Provide Git-related information
*/
@ConfigurationProperties("spring.info.git")
public class GitProperties extends InfoProperties {
/**
* Create an instance with the specified entries
* @param entries the entries
*/
public GitProperties(Properties entries);
/**
* Get the name of the branch
* @return the branch or null
*/
public String getBranch();
/**
* Get the commit id
* @return the commit id or null
*/
public String getCommitId();
/**
* Get the abbreviated commit id
* @return the short commit id or null
*/
public String getShortCommitId();
/**
* Get the commit time
* @return the commit time or null
*/
public Instant getCommitTime();
}
/**
* Base class for configuration properties that provide application information
*/
public abstract class InfoProperties implements Iterable<InfoProperties.Entry> {
private final Properties entries;
/**
* Create an instance with the specified entries
* @param entries the entries
*/
public InfoProperties(Properties entries);
/**
* Return the value of the specified property or null if the property is not set
* @param key the key of the property
* @return the property value or null
*/
public String get(String key);
/**
* Return the value of the specified property as an Instant or null if the property is not set or cannot be converted
* @param key the key of the property
* @return the property value or null
*/
public Instant getInstant(String key);
@Override
public Iterator<Entry> iterator();
/**
* A key/value pair entry from the info
*/
public static final class Entry {
private final String key;
private final String value;
/**
* Create a new Entry instance
* @param key the entry key
* @param value the entry value
*/
public Entry(String key, String value);
/**
* Return the key of the entry
* @return the key
*/
public String getKey();
/**
* Return the value of the entry
* @return the value
*/
public String getValue();
}
}Event-driven logging configuration and lifecycle management.
/**
* ApplicationListener that configures the LoggingSystem
*/
public class LoggingApplicationListener implements GenericApplicationListener, Ordered {
/**
* Create a new LoggingApplicationListener instance
*/
public LoggingApplicationListener();
@Override
public void onApplicationEvent(ApplicationEvent event);
@Override
public boolean supportsEventType(ResolvableType resolvableType);
@Override
public int getOrder();
/**
* Set if initialization arguments should be parsed for debug and trace options
* @param parseArgs if arguments should be parsed
*/
public void setParseArgs(boolean parseArgs);
/**
* Set a custom logging system
* @param loggingSystem the logging system
*/
public void setLoggingSystem(LoggingSystem loggingSystem);
}
/**
* ClearTrigger that can be used to clear caches once the application context loads
*/
public class ClearCachesApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event);
}Usage Examples:
// Build information configuration
@Configuration
public class InfoConfig {
@Bean
@ConditionalOnResource(resources = "META-INF/build-info.properties")
public BuildProperties buildProperties() throws IOException {
Properties properties = new Properties();
try (InputStream inputStream = getClass().getResourceAsStream("/META-INF/build-info.properties")) {
if (inputStream != null) {
properties.load(inputStream);
}
}
return new BuildProperties(properties);
}
@Bean
@ConditionalOnResource(resources = "git.properties")
public GitProperties gitProperties() throws IOException {
Properties properties = new Properties();
try (InputStream inputStream = getClass().getResourceAsStream("/git.properties")) {
if (inputStream != null) {
properties.load(inputStream);
}
}
return new GitProperties(properties);
}
}
// Using build and git information
@RestController
public class InfoController {
private final BuildProperties buildProperties;
private final GitProperties gitProperties;
public InfoController(BuildProperties buildProperties, GitProperties gitProperties) {
this.buildProperties = buildProperties;
this.gitProperties = gitProperties;
}
@GetMapping("/info")
public Map<String, Object> info() {
Map<String, Object> info = new HashMap<>();
if (buildProperties != null) {
info.put("app", Map.of(
"name", buildProperties.getName(),
"version", buildProperties.getVersion(),
"buildTime", buildProperties.getTime()
));
}
if (gitProperties != null) {
info.put("git", Map.of(
"branch", gitProperties.getBranch(),
"commit", gitProperties.getShortCommitId(),
"commitTime", gitProperties.getCommitTime()
));
}
return info;
}
}
// Structured logging configuration
@Configuration
public class StructuredLoggingConfig {
@Bean
@ConditionalOnProperty(name = "logging.structured.format", havingValue = "ecs")
public StructuredLogFormatter<ILoggingEvent> ecsFormatter() {
return CommonStructuredLogFormat.ECS;
}
@Bean
@ConditionalOnProperty(name = "logging.structured.format", havingValue = "logstash")
public StructuredLogFormatter<ILoggingEvent> logstashFormatter() {
return CommonStructuredLogFormat.LOGSTASH;
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework-boot--spring-boot-starter