Skip to content

ModuleContainer requires List<ModuleProvider>, but DynamiaBaseConfiguration's emptyModuleProvider() fallback never registers for a minimal app #102

Description

@marioserrano09

Problem

Every project scaffolded by dynamia new with a Java/Kotlin/Groovy backend fails to start
(contextLoads test fails, spring-boot:run fails the same way) with:

UnsatisfiedDependencyException: Error creating bean with name 'moduleContainer':
Unsatisfied dependency expressed through field '_providers':
No qualifying bean of type 'java.util.List<tools.dynamia.navigation.ModuleProvider>' available:
expected at least 1 bean which qualifies as autowire candidate.

ModuleContainer (platform/core/navigation/.../ModuleContainer.java) has @Autowired private transient List<ModuleProvider> _providers; (required=true, no default). A minimal app using only
tools.dynamia.app + tools.dynamia.domain.jpa (no other business modules) has zero ModuleProvider
beans of its own, so this is expected to be covered by the fallback in DynamiaBaseConfiguration
(platform/app/.../DynamiaBaseConfiguration.java):

@Bean
@ConditionalOnMissingBean(ModuleProvider.class)
public ModuleProvider emptyModuleProvider() {
    return () -> new Module(StringUtils.randomString(), "No modules registered");
}

This fallback is not actually kicking in

Reproduced against the published tools.dynamia:tools.dynamia.app:26.4.1 jar (same version
pinned in cli.properties/the templates), not a stale artifact:

  • javap -v on the jar confirms emptyModuleProvider() is present, public, correctly annotated
    with @Bean and @ConditionalOnMissingBean(ModuleProvider.class) — bytecode is fine.
  • git merge-base --is-ancestor confirms the commit that introduced it (d8ed4f41, "feat: add empty
    ModuleProvider bean for improved module handling") is an ancestor of the 26.4.1 tag, so it should
    be included in what's published.
  • Yet running the app with --debug (Spring Boot's ConditionEvaluationReport), DynamiaBaseConfiguration#emptyModuleProvider
    never appears in the report at all — not in "Positive matches", not in "Negative matches". Its
    sibling @ConditionalOnMissingBean methods in the exact same class (defaultSearchService,
    messageService, templateEngine, defaultSearchProvider, noOpCrudService, reportCompiler)
    all show up correctly (matched or not). Only emptyModuleProvider is silently absent from condition
    evaluation entirely, which points to the bean method never being reached by
    ConfigurationClassParser/ConfigurationClassBeanDefinitionReader, not to the condition itself
    evaluating false. Root cause of why it's skipped is still open — ideas not yet ruled out:
    eager type-resolution during infrastructure bean processing locking the ModuleProvider type before
    DynamiaBaseConfiguration's own @Bean methods finish registering, or something specific to how
    @Import(RestApiNavigationConfiguration.class) (a plain, non-@Configuration class also imported by
    DynamiaBaseConfiguration) interacts with bean method registration order.

Workaround confirmed

Explicitly declaring a ModuleProvider bean in the app (e.g. in the @SpringBootApplication class)
fixes it immediately — List<ModuleProvider> injection is additive, so this doesn't conflict with the
framework's fallback or with real modules added later. Applied as a permanent, documented default in
dynamiatools/template-backend-java (commit 98bd757) and will be mirrored in
template-backend-kotlin/template-backend-groovy.

To reproduce

git clone --depth=1 https://github.com/dynamiatools/template-backend-java
cd template-backend-java
git checkout 0c4fc76   # commit before the workaround was added
./mvnw clean verify    # fails: contextLoads

Suggested next step

Someone familiar with DynamiaBaseConfiguration's @Import/@ComponentScan setup and Spring's
ConfigurationClassParser internals should check whether emptyModuleProvider()'s bean method is
even being visited during configuration class parsing (e.g. temporarily add a System.out inside the
method body, or increase to TRACE logging for org.springframework.context.annotation and
org.springframework.boot.autoconfigure.condition) to pin down exactly where it's being dropped, then
decide whether the fix belongs in DynamiaBaseConfiguration itself or in how EnableDynamiaToolsApi
composes its imports.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions