NPE when initilizing Controller inside Controller

52 views
Skip to first unread message

Jonathan Tinsman

unread,
Jul 22, 2015, 10:51:50 PM7/22/15
to DataFX
I like the DataFX idea and I am in the process of moving my half-developed project from pure JavaFx 8 to using DataFX.

I am not using a Flow like all the tutorials show, but rather have a main pane, with buttons on the left and an AnchorPane on the right. The buttons will change the pane content on the right and invoke the proper controller.

In my main application I am doing:
    @Override
   
public void start(Stage stage) throws Exception {
        instance
= this;
       
new Flow(FXMLDocumentController.class).startInStage(stage);
   
}

Inside my FXMLDocumentController (which is the main controller that contains the buttons) I have:
@ViewController("/fxml/FXMLDocument.fxml")
public class FXMLDocumentController implements Initializable {
   
private Logger log = Logger.getLogger(FXMLDocumentController.class.getCanonicalName());

   
@ActionTrigger("view-contracts")
   
private Button contractsButton;
   
@ViewNode
   
@ActionTrigger("view-reports")
   
private Button reportsButton;
   
...
   
@FXML
   
private AnchorPane domainView;

   
// DataFX Controllers/Views
   
private ViewContext<ReportsController> reportsContext;
   
private ViewContext<ListContractsController> listContractsContext;
   
...

   
@Override
   
public void initialize(URL url, ResourceBundle rb) {
   
}

   
@PostConstruct
   
public void init() {
        contractsButton
.setDisable(true);
        reportsButton
.setDisable(true);
       
...

       
try {
           
ViewFactory factory = ViewFactory.getInstance();
           
// Create the Controllers
            reportsContext
= factory.createByController(ReportsController.class);
            listContractsContext
= factory.createByController(ListContractsController.class);
           
...
       
} catch (FxmlLoadException ex) {
            log
.log(Level.SEVERE, null, ex);
       
}
   
}

   
@ActionMethod("view-reports")
   
private void clickReportsButton() {
        setView
(reportsContext);
        reportsContext
.getController().reset();
   
}

   
@ActionMethod("view-contracts")
   
public void clickContractButton() {
        setView
(listContractsContext);
        listContractsContext
.getController().reset();
   
}
   
...

   
/**
     * Set the view to the side pane.
     * @param context the ViewContext that contains the desired view
     */

   
private void setView(ViewContext context) {
        domainView
.getChildren().add(0, context.getRootNode());
       
if (domainView.getChildren().size() > 1) {
            domainView
.getChildren().remove(1, domainView.getChildren().size());
       
}
   
}
}

Everything worked fine when only the main controller had the @ActionTrigger and @ActionMethod while the sub-controllers only to have @ViewController and the elements with @ViewNode (with the exception of the TreeTableView and the AnchorPanes which still needed @FXML) but no actions, relying on the @FXML and definition in the fxml

The problem arose when I added the @ActionTrigger and @ActionMethod to the ReportsController and ListContractsController. I get a NullPointerException when loading the controller

Caused by: java.lang.NullPointerException
    at io
.datafx.controller.flow.context.FXMLActionResourceConsumer.consumeResource(FXMLActionResourceConsumer.java:39)
    at io
.datafx.controller.flow.context.FXMLActionResourceConsumer.consumeResource(FXMLActionResourceConsumer.java:35)
    at io
.datafx.controller.context.ContextResolver.injectResources(ContextResolver.java:70)
    at io
.datafx.controller.ViewFactory.createByController(ViewFactory.java:185)
   
... 26 more

This references the following method where the context has no registered objects so the getRegisteredObject(ViewFlowContext.class) is null.
public class FXMLActionResourceConsumer implements ControllerResourceConsumer<ActionTrigger, Object>  {

   
@Override
   
public void consumeResource(ActionTrigger annotation, Object resource, ViewContext<?> context) {
       
FlowActionHandler actionHandler = context.getRegisteredObject(ViewFlowContext.class).getRegisteredObject(FlowActionHandler.class);
       
if (resource != null) {
           
if(resource instanceof MenuItem) {
                actionHandler
.attachEventHandler((MenuItem) resource, annotation.value());
           
} else if(resource instanceof Node){
                actionHandler
.attachEventHandler((Node) resource, annotation.value());
           
}
       
}
   
}
   
...
}

What am I doing incorrectly?


Reply all
Reply to author
Forward
0 new messages