> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How to customize auto-configured beans

> Guide for overriding default beans provided by the Spring Boot Starter.

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:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
@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:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
@Bean
public IUniqueIdGenerator uuidBasedIdGenerator() {
    return () -> UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE;
}
```

### Custom security manager

To implement custom authorization logic, provide your own `IDatabaseSimulationsSecurityManager`:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
@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:

```yaml theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
atoti:
  what-if:
    security:
      type: custom
```

See [How are user permissions managed](./dev-permissioning) for details on implementing custom security managers.

### Custom workflow

To modify how simulations are created, executed, or deleted:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
@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:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
@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:

```yaml theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
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):

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
@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:

1. `DatabaseSimulationEngine` and `IUniqueIdGenerator` (no dependencies)
2. `SessionFactory` (requires `IWhatIfPersistenceProperties`)
3. `ISimulationPersistenceManager` (requires `SessionFactory`)
4. `IDatabaseSimulationsSecurityManager` (may require persistence manager)
5. `IDatabaseSimulationsWorkflow` (requires engine, persistence manager, security manager, database service, ID generator)
6. `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:

```yaml theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
logging:
  level:
    com.activeviam.tools.whatif.configuration: DEBUG
```

Or inspect the application context at runtime:

```java theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
@Autowired
private ApplicationContext context;

public void checkBeans() {
    IUniqueIdGenerator generator = context.getBean(IUniqueIdGenerator.class);
    System.out.println("ID Generator: " + generator.getClass().getName());
}
```
