Routing¶
Spring JavaFX Boot features a Spring MVC-inspired routing system that cleanly separates route configuration from FXML view controllers. If you've worked with Spring MVC or Angular, the patterns will feel familiar.
Architecture Overview¶
The routing system mirrors Spring MVC's request handling model, adapted for a desktop UI:
| Spring MVC | Spring JavaFX Boot | Role |
|---|---|---|
DispatcherServlet |
FxRouter |
Central dispatcher — orchestrates navigation |
RequestMappingHandlerMapping |
FxRouteRegistry |
Scans and registers routes at startup |
@RestController |
@FxRoutes |
Route configuration class (singleton) |
@GetMapping |
@FxMapping |
Maps a method to a route path |
Model |
FxModel |
Carries data from handler to view |
ViewResolver |
ViewResolver |
Resolves view name to FXML template |
Defining Routes¶
Routes are defined in classes annotated with @FxRoutes. Each method annotated with @FxMapping maps a path to a view:
@FxRoutes
public class AppRoutes {
@FxMapping("/")
public String layout(FxModel model) {
return "layout"; // resolves to /templates/layout.fxml
}
@FxMapping(value = "/main", parent = "/", title = "page.title.main")
public String main(FxModel model) {
model.put("greeting", "Hello!");
return "main"; // resolves to /templates/main.fxml
}
@FxMapping(value = "/second", parent = "/", title = "page.title.second")
public String second(FxModel model) {
return "second";
}
}
Return type
@FxMapping methods must return a String (the view name). They can accept FxModel or Map<String, Object> as parameters.
Navigating¶
Inject FxRouter into any Spring-managed bean and call navigateTo():
@Controller
@Scope("prototype")
@RequiredArgsConstructor
public class MainController {
private final FxRouter router;
@FXML
private void onGoToSecond() {
router.navigateTo("/second");
}
}
Passing Parameters¶
Pass data to the target view via a parameter map:
Parameters are added to the FxModel and injected into the target controller's @ModelAttribute fields:
@Controller
@Scope("prototype")
public class DetailsController {
@ModelAttribute
private Integer itemId;
@ModelAttribute
private String mode;
@FXML
private void initialize() {
// itemId = 42, mode = "edit"
}
}
View Resolution¶
ViewResolver maps logical view names to FXML templates using a configurable prefix and suffix:
Configure in application.properties:
Route Logging¶
Routes are logged at startup so you can verify the route table:
Mapped "/" → AppRoutes.layout()
Mapped "/main" → AppRoutes.main() [parent: /]
Mapped "/second" → AppRoutes.second() [parent: /]
Mapped "/demo/window" → AppRoutes.demoWindow()
Mapped "/demo/modal" → AppRoutes.demoModal()
Registered 5 FxMapping route(s)
Navigation Lifecycle¶
When router.navigateTo("/main") is called:
FxRouteRegistryresolves"/main"and findsparent = "/"- The router builds the ancestor chain:
["/", "/main"] - For each level in the chain, starting from the root:
- If the parent
"/"is already active — reuse its cached layout - If not — invoke the
@FxMappinghandler, load the FXML, cache asActiveRoute
- If the parent
- The handler is invoked — it populates
FxModeland returns a view name ViewResolverresolves the view name to an FXML template path- The FXML is loaded with Spring's
ApplicationContextas the controller factory @ModelAttributefields are injected into the controller from the model- The optional
onModelReady(FxModel)hook is called (if defined on the controller) @FXML initialize()runs — all model data is available- The child view is placed into the parent's
@RouterOutlet
Reloading¶
Call router.reload() to force a full reload of the current route and all its parents. This is useful after a locale change: