Search code examples
javajavafxfxmlafterburner.fx

Afterburner.fx - File: *.fxml not found


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:

  1. Check the loading location,
  2. Change it to fit with my needs

Solution

  • 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