How to customize auto-configured beans
This page explains how to customize or replace the beans that the Spring Boot Starter creates automatically.
How auto-configuration works
The Spring Boot Starter uses @ConditionalOnMissingBean annotations on all auto-configured beans. This means your custom beans take precedence over the defaults. If you define a bean of the same type, the auto-configuration skips creating its version.
How to override a bean
Define a bean of the same type in your configuration class:
@Configuration
public class MyWhatIfConfiguration {
@Bean
public IUniqueIdGenerator customIdGenerator() {
return new MyCustomIdGenerator();
}
}
The starter detects your bean and skips creating the default IncrementalUniqueIdGenerator.
Common customization scenarios
Custom ID generator
The default ID generator uses an incremental counter starting from the epoch second. To use a different strategy:
@Bean
public IUniqueIdGenerator uuidBasedIdGenerator() {
return () -> UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE;
}
Custom security manager
To implement custom authorization logic, provide your own IDatabaseSimulationsSecurityManager:
@Bean
public IDatabaseSimulationsSecurityManager customSecurityManager(
ISimulationPersistenceManager persistenceManager,
IBranchPermissionsManager branchPermissionsManager) {
return new MyCustomSecurityManager(persistenceManager, branchPermissionsManager);
}
When you provide a custom security manager, set the security type to custom in your configuration:
atoti:
what-if:
security:
type: custom
See How are user permissions managed for details on implementing custom security managers.
Custom workflow
To modify how simulations are created, executed, or deleted:
@Bean
public IDatabaseSimulationsWorkflow customWorkflow(
DatabaseSimulationEngine engine,
ISimulationPersistenceManager persistenceManager,
IDatabaseSimulationsSecurityManager securityManager,
IDatabaseService databaseService,
IUniqueIdGenerator idGenerator) {
return new MyCustomWorkflow(engine, persistenceManager, securityManager, databaseService, idGenerator);
}
Custom distributed database service
When running in distributed mode, you can provide a custom implementation:
@Bean
public IDatabaseService distributedDatabaseService(
IDistributedQueryResultsMerger resultsMerger,
Supplier<Set<String>> addressSupplier,
Supplier<AAuthenticator> authenticator) {
return new MyCustomDistributedDatabaseService(resultsMerger, addressSupplier, authenticator);
}
Set the configuration to not create the default distributed service:
atoti:
what-if:
distribution:
enabled: true
create-distributed-service: false
Custom SessionFactory
To customize the Hibernate SessionFactory beyond what persistence properties provide (such as adding interceptors or event listeners):
@Bean(destroyMethod = "close")
public SessionFactory whatIfSessionFactory(IWhatIfPersistenceProperties persistence) {
var configuration = new org.hibernate.cfg.Configuration();
var props = new Properties();
props.putAll(persistence.getPersistence());
// Add custom configuration
props.setProperty("hibernate.cache.use_second_level_cache", "true");
configuration.addProperties(props);
configuration.addAnnotatedClass(DatabaseSimulationJPA.class);
// Add custom interceptors or event listeners
configuration.setInterceptor(new MyCustomInterceptor());
return configuration.buildSessionFactory();
}
The destroyMethod = "close" attribute ensures the SessionFactory closes properly when the application shuts down. When you override the SessionFactory, the default ISimulationPersistenceManager automatically uses your custom instance.
Bean dependencies
When customizing beans, be aware of their dependencies. The auto-configuration wires beans together in this order:
DatabaseSimulationEngineandIUniqueIdGenerator(no dependencies)SessionFactory(requiresIWhatIfPersistenceProperties)ISimulationPersistenceManager(requiresSessionFactory)IDatabaseSimulationsSecurityManager(may require persistence manager)IDatabaseSimulationsWorkflow(requires engine, persistence manager, security manager, database service, ID generator)DatabaseSimulationsRestService(requires workflow, persistence manager, database service)
If you override a bean that others depend on, ensure your implementation is compatible.
Verifying your customizations
To verify which beans are active, enable debug logging:
logging:
level:
com.activeviam.tools.whatif.configuration: DEBUG
Or inspect the application context at runtime:
@Autowired
private ApplicationContext context;
public void checkBeans() {
IUniqueIdGenerator generator = context.getBean(IUniqueIdGenerator.class);
System.out.println("ID Generator: " + generator.getClass().getName());
}