Reader

How should ViewModels and Services communicate in a JavaFX + Spring Boot MVVM application?

| Software Engineering Stack Exchange | Default

I'm building a JavaFX + Spring Boot application using the MVVM pattern.

Problem

I have two ViewModels:

  • SharedLoginViewModel: Manages the workflow state (e.g., login process, step transitions).

  • TokenCreationViewModel: Manages token creation logic (e.g., form validation, token generation).

The SharedLoginViewModel advances the workflow based on state changes. However, TokenCreationViewModel needs to notify SharedLoginViewModel to advance the workflow after successful token creation.

This creates a circular dependency:

SharedLoginViewModel injects TokenCreationViewModel (or vice versa).

This causes Spring Boot to throw:

creating bean with name 'sharedLoginViewModel': Requested bean is currently in creation: Is there an unresolvable circular reference?

What I’ve Tried

1. Direct injection

  • Causes the circular dependency.

2. Spring Events

  • TokenCreationViewModel publishes an event.

  • SharedLoginViewModel listens and advances the workflow.

This decouples them but feels overkill for simple workflow steps.

3. Custom Interface (LoginNavigationService)

Defined:

public interface LoginNavigationService {
    
 void advanceStep();
    
 void cancel();

}
  • SharedLoginViewModel implements this interface.

  • TokenCreationViewModel injects LoginNavigationService instead of directly referencing SharedLoginViewModel.

This works but feels awkward. I'm unsure if this is good practice.

What I Want

A clean way to decouple these ViewModels.

Avoid circular dependencies while allowing TokenCreationViewModel to advance the workflow after successful token creation.

Code Snippets

SharedLoginViewModel:

@Component
public class SharedLoginViewModel implements LoginNavigationService {

    @Override
    public void advanceStep() {
        // Advance the workflow
    }

    @Override
    public void cancel() {
        // Cancel the workflow
    }
}

TokenCreationViewModel:

@Component
public class TokenCreationViewModel {
    private final LoginNavigationService navigationService;
    @Autowired
    public TokenCreationViewModel(LoginNavigationService navigationService) {
        this.navigationService = navigationService;
    }
    public void handleTokenCreated() {
        navigationService.advanceStep();
    }
}

Question

Is the LoginNavigationService approach a good practice for decoupling ViewModels?

Is there a better way to avoid circular dependencies between ViewModels in JavaFX + Spring Boot MVVM?

Any guidance appreciated!