I am building a simple application with JavaFX + Afterburner.fx.
When running mvn clean javafx:run
, I get this error:
File: recipelistpresenter.fxml not found, attempting with camel case
Cannot load file RecipeListPresenter.fxml
Stopping initialization phase...
Exception in Application start method
java.lang.reflect.InvocationTargetException
...
I doubled checked and my RecipeListPresenter.fxml is in the target/:
-rw-rw-r-- 1 amaury amaury 291 janv. 11 21:23 RecipeListPresenter.fxml
Here is my Main.java:
package com.example.eatti;
import com.airhacks.afterburner.injection.Injector;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import com.example.eatti.view.recipe.RecipeListPresenter;
public class Main extends Application {
@Override
public void start(Stage stage) {
RecipeListPresenter recipeListPresenter = new RecipeListPresenter();
Scene scene = new Scene(recipeListPresenter.getView());
stage.setTitle("Recipe Manager");
stage.setScene(scene);
stage.show();
}
@Override
public void stop() throws Exception {
Injector.forgetAll(); // Cleanup Afterburner.fx injections
}
public static void main(String[] args) {
launch(args);
}
}
I also have a FXMLView.java:
package com.example.eatti.view;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FXMLView {
private static final Logger log = LoggerFactory.getLogger(FXMLView.class);
public static void load(String fxmlPath, Stage stage) {
try {
log.debug("Loading FXML from path: {}", fxmlPath);
FXMLLoader loader = new FXMLLoader(FXMLView.class.getResource(fxmlPath));
Parent root = loader.load();
log.debug("FXML successfully loaded: {}", fxmlPath);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
} catch (Exception e) {
log.error("Error loading FXML file: {}", fxmlPath, e);
throw new RuntimeException(e);
}
}
}
And here is the RecipeListPresenter.java:
package com.example.eatti.view.recipe;
import javax.inject.Inject;
import com.airhacks.afterburner.views.FXMLView;
import com.example.eatti.model.entity.Recipe;
import com.example.eatti.service.RecipeService;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
import javafx.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.UUID;
public class RecipeListPresenter extends FXMLView {
private static final Logger log = LoggerFactory.getLogger(RecipeListPresenter.class);
@Inject
private RecipeService recipeService;
@FXML
private ListView<Pair<UUID, String>> recipeListView;
@FXML
public void initialize() {
loadRecipes();
setupListView();
}
private void loadRecipes() {
List<Recipe> recipes = recipeService.findAllRecipes();
for (Recipe recipe : recipes) {
Pair<UUID, String> recipeItem = new Pair<>(recipe.getId(), recipe.getName());
recipeListView.getItems().add(recipeItem);
}
}
private void setupListView() {
recipeListView.setCellFactory(param -> new ListCell<Pair<UUID, String>>() {
@Override
protected void updateItem(Pair<UUID, String> item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText(null);
} else {
setText(item.getValue());
}
}
});
recipeListView.setOnMouseClicked(event -> {
if (event.getClickCount() == 2) {
handleRecipeDoubleClick(event);
}
});
}
private void handleRecipeDoubleClick(MouseEvent event) {
if (event.getClickCount() == 2) {
Pair<UUID, String> selectedRecipe = recipeListView.getSelectionModel().getSelectedItem();
if (selectedRecipe != null) {
UUID selectedRecipeId = selectedRecipe.getKey();
Recipe recipe = recipeService.findRecipeById(selectedRecipeId);
if (recipe != null) {
openRecipeDetails(recipe);
}
}
}
}
private void openRecipeDetails(Recipe recipe) {
log.debug("Opening recipe: {}", recipe.getName());
Stage stage = new Stage();
RecipeDetailsPresenter recipeDetailsPresenter = new RecipeDetailsPresenter();
recipeDetailsPresenter.setRecipe(recipe);
stage.setScene(new Scene(recipeDetailsPresenter.getView()));
stage.show();
}
}
Directory structure:
src/main/
├── java
│ └── com
│ └── example
│ └── eatti
│ ├── controller
│ ├── Main.java
│ ├── model
│ │ ├── entity
│ │ │ ├── Ingredient.java
│ │ │ ├── RecipeIngredient.java
│ │ │ ├── Recipe.java
│ │ │ ├── RecipeUnit.java
│ │ │ └── Unit.java
│ │ └── repository
│ │ ├── IngredientRepository.java
│ │ ├── RecipeIngredientRepository.java
│ │ ├── RecipeRepository.java
│ │ ├── RecipeUnitRepository.java
│ │ └── UnitRepository.java
│ ├── service
│ │ └── RecipeService.java
│ ├── util
│ │ └── HibernateUtil.java
│ └── view
│ ├── FXMLView.java
│ └── recipe
│ ├── RecipeDetailsPresenter.java
│ ├── RecipeFormPresenter.java
│ └── RecipeListPresenter.java
└── resources
├── application.properties
├── com
│ └── example
│ └── eatti
│ └── fxml
│ ├── recipe-details.fxml
│ ├── recipe-form.fxml
│ └── RecipeListPresenter.fxml
└── hibernate.cfg.xml
18 directories, 22 files
I get the idea that the file is not loaded from the right place, but I have no clue on how to:
As @trashgod noted it, I had to place the .fxml in:
resources/com/example/eatti/view/recipe/*.fxml
So it replicates: src/com/example/eatti/view/recipe/*.java