Griffon "error injecting constructor" while trying to call loadFromFXML

1.7k Views Asked by At

I have a series of popups where I edit or view specific objects. I use these popups for editing various objects that are handled by and ORM (ORMLite), what I am trying to achieve is to have a generic/abstract class that implements similar behaviours through encapsulating methods. As I don't want to have the same FXML for all of the popup dialogs what I came up with was to create a "template" FXML, load it through loadFXML() function provided by Griffon and store it in a Node object to be the root of the created Scene at the Abstract Class. I am familiar with dependency injection, but I am not aware of the AST of the framework so my Abstract class is able to call loadFromFXML() within the Abstract class I created.

I post my code here:

Concrete class implementing the abstract ViewPopUp class I created:

    @ArtifactProviderFor(GriffonView.class)
    public class VerConductoresView extends AbstractViewPopUp<ObservablePlanilla> {
    private VerConductoresController controller;
    private ConductoresModel model;

    VerConductoresView() {
        super(ObservablePlanilla.class, Conductor.class);
        nodeM = new GridPane();
        super.setController(controller);
    }


    @Override
    public void initUI() {
        Stage stage = (Stage) getApplication()
            .createApplicationContainer(Collections.<String,Object>emptyMap());
        stage.setTitle(getApplication().getConfiguration().getAsString("application.title"));
        stage.setScene(init());
        stage.sizeToScene();
        getApplication().getWindowManager().attach("ver-conductores", stage);
    }
}

Abstract view PopUp I created:

public abstract class AbstractViewPopUp<T> extends AbstractJavaFXGriffonView {
    protected Class klazz;
    protected Class<T> klazz2;
    protected Scene viewScene;
    protected ViewControllerPopUp viewController;
    protected TableView tableView;
    protected GridPane gridPane;
    protected String[] ignoredNames;
    protected String[] columnNames;
    protected IModel<T> viewModel;
    protected Node nodeM;

    @MVCMember
    public void setController(ViewControllerPopUp controller) {
        this.viewController = controller;
    }


    AbstractViewPopUp(Class<T> k1, Class k2, Node node){
        klazz = k2;
        klazz2 = k1;
        nodeM = node;
        nodeM = loadFromFXML("com.softgan.viewPopUp");
        nodeM = node;
    }

    AbstractViewPopUp(Class<T> k1, Class k2){
        klazz = k2;
        klazz2 = k1;
        nodeM = loadFromFXML("com.softgan.viewPopUp");
    }

    protected Scene init() {
        Scene scene = new Scene(new Group());

        if (nodeM instanceof Parent) {
            scene.setRoot((Parent) nodeM);
        } else {
            ((Group) scene.getRoot()).getChildren().addAll(nodeM);
        }

        connectActions(nodeM, viewController);
        connectMessageSource(nodeM);
        return scene;
    }
}

I want to load the FXML through the Abstract class and then store it so the concrete class can access the loaded FXML so I am able to manipulate its contents, adding labels and textfields dynamically. The problem seems to be that loadFromFXML is throwing a NullPointerException as it is not able to resolve the FXML file from the resources. I already tried to use an AST transformation to make it resources aware, but it seems to not be a valid approach as Guice is not able to resolve, I think, the ResourceHandler.

EDIT

This is the Stacktrace I am getting:

[griffon-pool-1-thread-2] WARN org.codehaus.griffon.runtime.core.controller.AbstractActionManager - An exception occurred when executing com.softgan.ConductoresController.view
griffon.exceptions.InstanceMethodInvocationException: An error occurred while invoking instance method com.softgan.ConductoresController.view()
    at griffon.util.GriffonClassUtils.invokeExactInstanceMethod(GriffonClassUtils.java:3186)
Caused by: griffon.exceptions.GriffonException: An error occurred while executing a task inside the UI thread
    at com.softgan.ConductoresController.view(ConductoresController.java:122)
    at griffon.util.MethodUtils.invokeExactMethod(MethodUtils.java:407)
    at griffon.util.MethodUtils.invokeExactMethod(MethodUtils.java:356)
    at griffon.util.GriffonClassUtils.invokeExactInstanceMethod(GriffonClassUtils.java:3182)
Caused by: java.util.concurrent.ExecutionException: griffon.exceptions.InstanceNotFoundException: Could not find an instance of type com.softgan.VerConductoresView
    ... 4 more
Caused by: griffon.exceptions.InstanceNotFoundException: Could not find an instance of type com.softgan.VerConductoresView
Caused by: com.google.inject.ProvisionException: Unable to provision, see the following errors:

1) Error injecting constructor, java.lang.NullPointerException
  at com.softgan.VerConductoresView.<init>(VerConductoresView.java:31)
  while locating com.softgan.VerConductoresView

1 error
    at com.google.inject.internal.InternalProvisionException.toProvisionException(InternalProvisionException.java:226)
    at com.google.inject.internal.InjectorImpl$1.get(InjectorImpl.java:1053)
    at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1086)
Caused by: java.lang.NullPointerException
    at com.softgan.AbstractViewPopUp.<init>(AbstractViewPopUp.java:72)
    at com.softgan.VerConductoresView.<init>(VerConductoresView.java:31)
    at com.softgan.VerConductoresView$$FastClassByGuice$$d0c2bde8.newInstance(<generated>)
    at com.google.inject.internal.DefaultConstructionProxyFactory$FastClassProxy.newInstance(DefaultConstructionProxyFactory.java:89)
    at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:114)
    at com.google.inject.internal.ConstructorInjector.access$000(ConstructorInjector.java:32)
    at com.google.inject.internal.ConstructorInjector$1.call(ConstructorInjector.java:98)
    at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:112)
    at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:120)
    at com.google.inject.internal.ProvisionListenerStackCallback.provision(ProvisionListenerStackCallback.java:66)
    at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:93)
    at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:306)
    at com.google.inject.internal.InjectorImpl$1.get(InjectorImpl.java:1050)
    ... 1 more
[griffon-pool-1-thread-2] ERROR griffon.core.GriffonExceptionHandler - Uncaught Exception. Stacktrace was sanitized. Set System property 'griffon.full.stacktrace' to 'true' for full report.
griffon.exceptions.InstanceMethodInvocationException: An error occurred while invoking instance method com.softgan.ConductoresController.view()
    at griffon.util.GriffonClassUtils.invokeExactInstanceMethod(GriffonClassUtils.java:3186)
Caused by: griffon.exceptions.GriffonException: An error occurred while executing a task inside the UI thread
    at com.softgan.ConductoresController.view(ConductoresController.java:122)
    at griffon.util.MethodUtils.invokeExactMethod(MethodUtils.java:407)
    at griffon.util.MethodUtils.invokeExactMethod(MethodUtils.java:356)
    at griffon.util.GriffonClassUtils.invokeExactInstanceMethod(GriffonClassUtils.java:3182)
Caused by: java.util.concurrent.ExecutionException: griffon.exceptions.InstanceNotFoundException: Could not find an instance of type com.softgan.VerConductoresView
    ... 4 more
Caused by: griffon.exceptions.InstanceNotFoundException: Could not find an instance of type com.softgan.VerConductoresView
Caused by: com.google.inject.ProvisionException: Unable to provision, see the following errors:

1) Error injecting constructor, java.lang.NullPointerException
  at com.softgan.VerConductoresView.<init>(VerConductoresView.java:31)
  while locating com.softgan.VerConductoresView

1 error
    at com.google.inject.internal.InternalProvisionException.toProvisionException(InternalProvisionException.java:226)
    at com.google.inject.internal.InjectorImpl$1.get(InjectorImpl.java:1053)
    at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1086)
Caused by: java.lang.NullPointerException
    at com.softgan.AbstractViewPopUp.<init>(AbstractViewPopUp.java:72)
    at com.softgan.VerConductoresView.<init>(VerConductoresView.java:31)
    at com.softgan.VerConductoresView$$FastClassByGuice$$d0c2bde8.newInstance(<generated>)
    at com.google.inject.internal.DefaultConstructionProxyFactory$FastClassProxy.newInstance(DefaultConstructionProxyFactory.java:89)
    at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:114)
    at com.google.inject.internal.ConstructorInjector.access$000(ConstructorInjector.java:32)
    at com.google.inject.internal.ConstructorInjector$1.call(ConstructorInjector.java:98)
    at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:112)
    at com.google.inject.internal.ProvisionListenerStackCallback$Provision.provision(ProvisionListenerStackCallback.java:120)
    at com.google.inject.internal.ProvisionListenerStackCallback.provision(ProvisionListenerStackCallback.java:66)
    at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:93)
    at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:306)
    at com.google.inject.internal.InjectorImpl$1.get(InjectorImpl.java:1050)
    ... 1 more

UPDATE

I already found what the problem was. The constructor was not aware of the loadFromFXML method as in the constructor of the view the UI has not been loaded yet. What I did was simply put the loadFromFXML() inside the init() method of the Abstract Class and call it directly from the Concrete View Class. I found out this by calling the loadFromFXML from the initUI method, which is where the UI can be accessed.

1

There are 1 best solutions below

3
Andres Almiray On

AST transformations only apply if you're compiling Groovy code, which may not be what you're doing. The loadFromFXML() method expects a resource to be available on the classpath by matching the given argument using the following value transformation

arg.replaceAll('.', '/') + ".fxml"

This means your code resolves "com.softgan.viewPopUp" to "com/softgan/viewPopUp.fxml". Does that file exist in src/main/resources or griffon-app/resources?