简体   繁体   中英

InvocationTargetException in FXMLLoader in SpringFramework Project

Hello StackOverflowers,

I am working on a Ticket Sales Program using (among others) the Spring Framework. I am getting a very interesting InvocationTargetException which is caused by a NullpointerException. When I checked with the Debugger (IDE IntelliJ) however, the line at which the Nullpointer is thrown, there is nothing null.

BasketController (Controller for the Shopping Basket):

package ticketline.client.gui.controller;

import ticketline.client.util.SpringFxmlLoader;
import ticketline.dto.*;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.URL;
import java.util.*;

/**
 * Created by Sebastian on 11.05.2015.
 */
@Component
public class BasketController implements Initializable {

    private static final Logger LOGGER = LoggerFactory.getLogger(BasketController.class);

    @Autowired
    private SpringFxmlLoader springFxmlLoader;

    private HashMap<ShowDto, List<ReceiptEntryDto>> showsMap;

    private List<ReceiptEntryDto> receiptEntryDtos;

    /**
     * {@inheritDoc}
     */
    @Override
    public void initialize(URL url, ResourceBundle resBundle) {
        initNewBasket();
    }

    /**
     * Resets all fields, call if process was cancelled and after basket elements were purchased.
     */
     private void initNewBasket() {
        receiptEntryDtos = new ArrayList<>();
        showsMap = new HashMap<>();
     }

    /**
     * Checks if there is a version of this ShowDto in the ShoppingBasket and gives back that element if present,
     * else returns the parameter
     *
     * @param showDto
     * @return the parameter if not in basket, else the version with lists of chosen tickets
     */
    public Boolean showInBasket(ShowDto showDto) {

        for (ShowDto s : showsMap.keySet()) {
            if (s.getId().equals(showDto.getId())) {
                return true;
            }
        }
        return false;
    }

    /**
     * Gets all TicketIdentiferDtos in Basket of a certain Show
     *
     * @param showDto of which to get all TicketIdentifiers
     * @return list of all TicketIdentifiers
     */
    public List<TicketIdentifierDto> getTicketIdentifiersToShow(ShowDto showDto) {
        List<TicketIdentifierDto> toReturn = new ArrayList<>();

        // Next Line throws NullPointerException, no Objects are null though
        for (ReceiptEntryDto r : showsMap.get(showDto)) {
            toReturn.add(r.getTicketIdentifier());
        }
        return toReturn;
    }

    /**
     * Gets the Show to the specified Ticket
     *
     * @param ticket ticket for which to get the Show
     * @return the ShowDto of the ticket
     */
    private ShowDto getShowByTicket(TicketDto ticket) {

        for (ShowDto show : showsMap.keySet()) {
            for (ReceiptEntryDto re : showsMap.get(show)) {
                if (re.getTicketIdentifier().getTicket().getId().equals(ticket.getId())) {
                    return show;
                }
            }
        }
        return null;
    }
}

ShowTabController:

package ticketline.client.gui.controller;

import ticketline.client.util.SpringFxmlLoader;
import ticketline.dto.ShowDto;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.URL;
import java.util.Date;
import java.util.List;

/**
 * Created by Sebastian on 08.05.2015.
 */
@Component
public class ShowTabController implements Initializable {

    private static final Logger LOGGER = LoggerFactory.getLogger(ShowTabController.class);

    private ObservableList<ShowDto> showData = FXCollections.observableArrayList();

    @Autowired
    private SpringFxmlLoader springFxmlLoader;

    @Autowired
    private SeatingChartController seatingChartController;

    @Autowired
    private BasketController basketController;    

    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }

    /**
     * Handle the event in which the Buy / Reserve Button was pressed
     */
    @FXML
    private void handlePurchase(MouseEvent event) {

        if (event.getClickCount() == 2) {

            if (tableShows.getSelectionModel().getSelectedIndex() >= 0) {
                SpringFxmlLoader.LoadWrapper wrapper = springFxmlLoader.loadAndWrap("/gui/fxml/seatingChartDialog.fxml");
                ShowDto selected = tableShows.getSelectionModel().getSelectedItem();

                Stage seatChartStage = new Stage();
                seatChartStage.setScene(new Scene((Parent) wrapper.getLoadedObject()));
                seatChartStage.setResizable(false);
                seatChartStage.initModality(Modality.APPLICATION_MODAL);
                seatChartStage.initOwner(tableShows.getScene().getWindow());
                seatChartStage.setTitle(BundleManager.getBundle().getString("chart.title"));
                seatChartStage.getIcons().add(new Image(LoginController.class.getResourceAsStream("/image/ticketlineLogo.png")));

                if (basketController.showInBasket(selected)) {

                    // This Call brings us to the basketController
                    seatingChartController.setupSeatingChart(selected, basketController.getTicketIdentifiersToShow(selected));
                } else {
                    seatingChartController.setupSeatingChart(selected, null);
        }
    }
}

In ShowTabController there is a TableView containing ShowDtos, in the handlePurchase Method I call the SeatingChart Dialog (another scene where free/taken/reserved Seats are drawn). But first I check if currently there are any Tickets to the chosen Show in the Shopping Basket and if, I send them to the SeatingChart so they can be drawn as chosen.

In 99% this logic works perfectly well, but now we managed to create that 1% Bug where it suddenly does not work anymore, the Process:

Tickets are chosen for Reservation in SeatingChart

  • Tickets are sent to BasketController
  • In BasketController Tickets are sent to the Database and saved
  • Reserved Tickets are loaded from Database (in a different Tab)
  • Some of these are chosen and sent to the Shopping Basket again (to buy them for real)
  • If I call change the Tickets from the BasketElementController (representing one Purchase) the SeatingChart opens up perfectly (BasketController.getTicketIdentifiersToShow is called during this)
  • If I call change the Tickets using the ShowTabController.handlePurchase Method however, I get the following Exception:

Exception

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1770)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1653)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    [..more lines..]
    at com.sun.glass.ui.win.WinApplication$$Lambda$38/1786955566.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1765)
    ... 35 more
Caused by: java.lang.NullPointerException
    at ticketline.client.gui.controller.BasketController.getTicketIdentifiersToShow(BasketController.java:338)
    at ticketline.client.gui.controller.ShowTabController.handlePurchase(ShowTabController.java:252)
    ... 45 more

However, when I use the Debugger to check everything in the BasketController, none of the variables are null, showsMap has valid Key and valid Values that should not throw a NullpointerException.

EDIT: It is shown that they are != null in Debugger, LogStatement shows however, that showsMap.get(showDto) == null, even though showsMap.values() != null and there is only one key.

Can this be in some way be caused by the DependencyInjection on the Controller classes? That an Injected Object can suddenly turn null? Some help and hints would be greatly appreciated.

PS: I tried my best to keep the Code samples as small as possible while still showing the relevant Places.

One should realize that the Hash in HashMap actually means something. It seems the ShowDto were really different Objects because one was loaded again from the Database and thus the hash was not the same resulting in the NullpointerException. Simpler solution would be to simply implement the Object.hashCode method in ShowDto.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM