0

I want to open a JDialog from the Main-GUI with a JTable in it. To display data in this JTable I have a TableModel called "PvsTTableModel"..

The exception gets thrown when trying to set the tablemodel "model" in the class"KPI_PvsT" (the second code - text in this question), although it should get autowired.

The Dialog is called "KPI_PvsT", which gets called when someone clicks on the menuItem "itemPvsT".

There are more objects in the Main-GUI which all work properly (they are able to create JDialogs with the TableModels successfully - I have already compared those to mine).

I cannot find anything which gets created by the "new"-keyword which can also be a problem as described here. Everything is annotated with "@Component" and "@Autowiring".

This is my table-model:

@Component
public class PvsTTableModel extends AbstractTableModel {

    @Autowired
    private TicketRepository ticketRepository;

    @Autowired
    private ResidentRepository residentRepository;

    @Autowired
    private ResidentSchichtRespository residentSchichtRepository;

    @Autowired
    private SchichtRepository schichtRepository;

    private final String[] HEADER = {"Stunde", "Anzahl Mitarbeiter", "Anzahl offene Tickets"};

    private Map<Integer, Integer> numberOfResidents = new HashMap<>();
    private Map<Integer, Integer> numberOfOpenTickets = new HashMap<>();

    @Override
public int getRowCount() {
    return numberOfOpenTickets.size();
}

@Override
public int getColumnCount() {
    return HEADER.length;
}

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
    switch(columnIndex){
        case 0: return rowIndex;
        case 1: return this.numberOfResidents.get(rowIndex);
        case 2: return this.numberOfOpenTickets.get(rowIndex);
    }

    return null;
}

This is the JDialog:

@Component
public class KPI_PvsT extends JDialog {
    private JPanel contentPane;
    private JButton buttonCancel;
    private JTable table;
    private JTextField tfDatum;
    private JButton btOk;

    @Autowired
    private PvsTTableModel model;

    public KPI_PvsT() {
        setContentPane(contentPane);
        setModal(true);

        buttonCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onCancel();
            }
        });

        // call onCancel() when cross is clicked
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                onCancel();
            }
        });

        // call onCancel() on ESCAPE
        contentPane.registerKeyboardAction(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                onCancel();
            }
        }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);

        table.setModel(model);

        btOk.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String s = tfDatum.getText();
                LocalDate date = null;
                try{
                    date = LocalDate.parse(s, dtfLocalDate);
                }catch(Exception ex){
                    JOptionPane.showMessageDialog(null, "Bitte geben Sie das Datum im richtigen Format ein!");
                }

                if(date != null){
                    model.fillMaps(date);
                }
            }
        });
    }

    private void onOK() {
        // add your code here
        dispose();
    }

    private void onCancel() {
        // add your code here if necessary
        dispose();
    }

    public void init()
    {
        this.pack();
        this.setVisible(true);
    }
}

This is the GUI where the JDialog gets called:

@Component
public class MainGUI extends JFrame{

@Autowired
private KPI_PvsT kpi_pvsT;

private JMenu menuHotline = new JMenu();
private JMenuItem itemPvsT = new JMenuItem();
public MainGUI() {
        addListeners();
}

private void addListeners()
{
    itemPvsT.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                kpi_pvsT.init();

            }
        });
}
public void starte(){

 menuHotline.setText("Hotline");
 itemPvsT.setText("Berechne Gegenüberstellung von Ticket und Personal");

}
}

error-stacktrace

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'KPI_PvsT' defined in file [D:\HTBLA_Kaindorf\5AHIF\Diplomarbeit\Projekt\chantal_master\chantal\out\production\classes\com\chantal\gui\KPI_PvsT.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.chantal.gui.KPI_PvsT]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: Cannot set a null TableModel
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1155) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:134) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
    at com.chantal.ChantalApplication.main(ChantalApplication.java:22) [classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_161]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_161]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_161]
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-1.5.9.RELEASE.jar:1.5.9.RELEASE]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.chantal.gui.KPI_PvsT]: Constructor threw exception; nested exception is java.lang.IllegalArgumentException: Cannot set a null TableModel
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:154) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1147) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    ... 21 common frames omitted
Caused by: java.lang.IllegalArgumentException: Cannot set a null TableModel
    at javax.swing.JTable.setModel(JTable.java:3678) ~[na:1.8.0_161]
    at com.chantal.gui.KPI_PvsT.<init>(KPI_PvsT.java:49) ~[classes/:na]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_161]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_161]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_161]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_161]
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
    ... 23 common frames omitted
watchme
  • 720
  • 1
  • 9
  • 25

1 Answers1

3

As pointed-out by @kdowbecki, you are using the autowired value "model" in your constructor, but the autowired values are set AFTER object is instantiated so at construction time it's still null. What you should probably do is set the @Autowired annotation to your constructor and have your model as a constructor paramerer.

//NOT Autowired
private PvsTTableModel model;

@Autowired
public KPI_PvsT(PvsTTableModel model) {
    this.model = model;
    [...]
}

FYI, constuctor autowiring is the Spring recommended way of doing injection now and in very recent versions of Spring, the @Autowired on constructor is not even required anymore so classes can be fully agnostic of DI.

Simon Berthiaume
  • 643
  • 4
  • 11
  • Now I have transfered the .setModel(model) into the init() method (which gets called in the Main_GUI). So it gets called after the constructor - thank you! – watchme Mar 04 '18 at 14:16
  • IMO, if the model class is a hard requirement for KPI_PvsT to work properly, it should be a constructor argument. It makes dependencies much clearer and helps testability. – Simon Berthiaume Mar 04 '18 at 14:26
  • But in order to call the constructor I have to create the object with new, right? – watchme Mar 04 '18 at 14:40
  • If you add the @Autowired to the constructor, Spring will inject the dependency at the constructor level, you won't have to provide it explicitly no. Here is the [Spring doc](https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-spring-beans-and-dependency-injection.html). – Simon Berthiaume Mar 04 '18 at 14:45
  • thanks! When I create the JDialog-class, there is a main method in it. Can I replace the main-method with an init-method created by my own? You can see what I mean in my question (I posted the whole JDialog-code) – watchme Mar 04 '18 at 15:42
  • Because it works - and that way, I can easily hand over some attributes which cannot be injected (because they have to be the same object in both classes (Main-GUI and JDialog)) – watchme Mar 04 '18 at 15:44
  • I'm not sure I understand your question this time. What do you mean by "cannot be injected (because they have to be the same object in both classes"? Spring beans are, by default, singletons so if you create a bean, then inject it in two classes, they will be the same object in both. – Simon Berthiaume Mar 04 '18 at 15:53
  • So I cannot use a TableModel for different GUIs? Because if there is just one instance - I would change the data for 2 GUIs, wouldn't I? – watchme Mar 04 '18 at 16:00
  • Yes, but if you would like a new instance to be created for each bean using that bean, then you can set the bean's scope to [prototype](https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch04s04.html#beans-factory-scopes-prototype). – Simon Berthiaume Mar 04 '18 at 16:07
  • ok wow thanks, I should begin to use these documentation more often. – watchme Mar 04 '18 at 16:09
  • I don't use the doc that often, I just have a tendency to support my claims with references (old school habits I guess) :P. – Simon Berthiaume Mar 04 '18 at 16:11
  • Keep that tendency! ;-) – watchme Mar 04 '18 at 16:19