NullPointerException w uruchomionym wątku

0

Hej, próbuje pobrać cały inbox z poczty ( za pomocą javamail ) i wyrzucić to do TableView. Wszystko jest ok, maile się pobierają, mogę je wypisać - wszystkie zostają dodane do tabeli ale... tylko kiedy nie próbuje tego zrobić za pomocą wątku ( nie chce czekać aż aplikacja pobierze wszystkie maile - więc odpalam od razu i w trakcie dane pobiera odpalony wątek )

Do rzeczy:

 //.... cośtam
   @Override
    public void initialize(URL url, ResourceBundle rb) {
        
        setEnemyEvent();
        dataSet();
        Thread t = new Thread(new MessageLoop());
        t.start(); //teraz nie działa ale kiedy poczekam do wykonania tego wątku czyli zrobie np:
        //przykładowo
        t.join(); //to wszystko jest ok, ale muszę czekać dopóki maile się nie pobiorą 
        //koniec

    }
    //static nested class for "loop"
    private static class MessageLoop implements Runnable {
        public void run() {
            try {
               EmailConnetion con = new EmailConnetion();
               MainModel MainModel = new MainModel();
                   for(int i=0;i<con.message.length;i++){
                    try{
                        MainModel.Item item = MainModel.new Item();
                        item.name.setValue(i+""+con.message[i].getFrom()[0].toString());
                        item.qty.setValue(con.message[i].getSentDate().toString());
                        item.title.setValue(con.message[i].getSubject().toString());
                      //...................................
                        data.add(item); // kompilator prowadzi mnie do tej linii    
                    //...................................
                    }catch(AddressException e){
                        System.out.println("Error : " + "AddressException:"+i);
                    }catch(NullPointerException ex){
                        System.out.println("Error : " + "NullPointerException:"+i);
                    }
               }
           } catch (NoSuchProviderException ex) {
               Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
           } catch (MessagingException ex) {
               Logger.getLogger(SimpleController.class.getName()).log(Level.SEVERE, null, ex);
           }
        }
    }
    }

Ma ktoś pomysł dlaczego po uruchomieni ( bez join() - czyli bez czekania ) - wywala NullPointerException ? Robi to w różnych miejscach, czasem przy 10 wiadomości, czasem 16, czasem 30 - ale potem wali nullami do końca.

Byłbym wdzięczny za wszystkie propozycje jak to naprawić.

EDIT:: Jakby ktoś miał podobny problem to zapraszam: http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm

0

A pole data jest zainicjowana?

0

Zamień może

}catch(NullPointerException ex){
      System.out.println("Error : " + "NullPointerException:"+i);
}

na

}catch(NullPointerException ex){
      System.out.println("Error : " + "NullPointerException:"+i);
      System.out.println("data: "+data);
      System.out.println("item: "+item);
}
0

Jak dla mnie, starasz się pobrać tytuł, czas i nadawcę z wiadomości, które niekoniecznie są już pobrane. Trzeba by pogrzebać w bibliotece i sprawdzić, jak ona działa. Jeśli pobiera całą wiadomość, tworzy obiekt i dodaje do EmailConnetion().message, to to nie to. Jeśli jednak tworzy obiekty, a później je wypełnia, to być może dlatego nie możesz nic pobrać.

Mam jeszcze drugi strzał - message jest tablicą statyczną, więc istnieje ogromne prawdopodobieństwo, że biblioteka czyta sobie ilość maili, tworzy tablicę o takim rozmiarze, a następnie ją wypełnia. Problem polega na tym, że starasz się ją czytać, zanim zostanie wypełniona.

Jak to naprawić? Cóż... nie mam pojęcia:). Możesz łapać NullPointer, czekać sekundę i wznawiać pętlę.

0

Niestety pudła. Problem rozwiązany. W artykule który podałem w EDIT można znaleźć rozwiązanie. Ale jeżeli już robiło się takie zainteresowanie wątkiem.
W skrócie: nie używaj zwykłych wątków przy aktywnej scenie. Prosta zasada używaj runLater albo runAndWait. W tym przypadku używam runLater:

Tak wygląda rozwiązanie:

Platform.runLater(new Runnable() {
  @Override public void run() {
    data.add(item);
  }
});

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.