2017-12-31 9 views
0

Ich habe einen javafx Controller bekam, die wie folgtmit guice mit JavaFX und Hibernate

public class DictionaryFxController implements Initializable { 

    @Inject 
    private QueryTemplate queryTemplate; 

    @SuppressWarnings("unchecked") 
    @Override 
    public void initialize(URL location, ResourceBundle resources) { 
     .... 
     queryTemplate.insert(langs); 
     .... 
    } 
} 

sieht My application Klasse sieht wie folgt aus

public class Main extends Application { 

    public static void main(String[] args) throws Exception { 
     launch(args); 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     Injector injector = Guice.createInjector(new ApplicationModule()); 
     Scene scene = null; 
     FXMLLoader loader = new FXMLLoader(); 
     try { 
      Parent root = loader.load(getClass().getResourceAsStream("/dictionary.fxml")); 
      loader.setControllerFactory(injector::getInstance); 
      scene = new Scene(root); 
     } catch (IOException e) { 
      throw new IllegalStateException(e); 
     } 

     primaryStage.setTitle("Dictionary"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

} 

Meine Klasse, die Hibernate Sitzung bietet sieht wie folgt aus

@Singleton 
public class HibernateController { 
    private SessionFactory sessionFactory; 

    public HibernateController() { 
     sessionFactory = new Configuration() 
       .configure() 
       .buildSessionFactory(); 
    } 

    public Session openSession() { 
     return sessionFactory.openSession(); 
    } 

    @PreDestroy 
    private void close() { 
     sessionFactory.close(); 
     StandardServiceRegistryBuilder.destroy(sessionFactory.getSessionFactoryOptions().getServiceRegistry()); 
    } 
} 

Ich verdrahte diese Klasse in template, die ich Abfragen peform verwenden, um

public class QueryTemplate { 
    private HibernateController hibernateController; 

    @Inject 
    public QueryTemplate(HibernateController controller) { 
     this.hibernateController = controller; 
    } 

    public <T> void insert(List<T> objects) { 
     try (Session session = hibernateController.openSession()) { 
      Transaction tx = session.beginTransaction(); 

      // generalize 
      objects.forEach(session::save); 

      tx.commit(); 
     } 
    } 
} 

ich diese Klasse im Modul gebunden

public class ApplicationModule extends AbstractModule { 
    @Override 
    protected void configure() { 
     bind(QueryTemplate.class); 
    } 
} 

Aber wenn ich die Anwendung zu starten, schlägt es auf der Linie

queryTemplate.insert(langs); 

weil queryTemplate ist Null. Was ist das Problem?

Antwort

2

Sie setzen die Controller-Fabrik nach Laden der FXML; Der Controller wurde bereits an diesem Punkt erstellt. Da der FXMLLoader den Standardmechanismus zum Erstellen des Controllers verwendet - d. H. Einfach den Standardkonstruktor des Controllers aufruft - wird der Controller nicht von Guice verwaltet und seine injizierten Felder werden nicht initialisiert.

Sie können das Problem einfach beheben, indem Sie die Reihenfolge der Zeilen mit loader.setControllerFactory(...) und loader.load(...) umkehren.

Nebenbei ist es besser, den Speicherort eines FXMLLoader als die Methode load(InputStream) zu verwenden. Wenn Sie die Methode verwenden, die eine Stream nimmt, wird der Speicherort nicht festgelegt und Standortauflösung wird nicht ordnungsgemäß in Ihrer FXML-Datei funktionieren.

So ersetzen

FXMLLoader loader = new FXMLLoader(); 
    try { 
     Parent root = loader.load(getClass().getResourceAsStream("/dictionary.fxml")); 
     loader.setControllerFactory(injector::getInstance); 
     scene = new Scene(root); 
    } catch (IOException e) { 
     throw new IllegalStateException(e); 
    } 

mit

FXMLLoader loader = new FXMLLoader(); 
    loader.setLocation(getClass().getResource("/dictionary.fxml")); 
    loader.setControllerFactory(injector::getInstance); 
    try { 
     Parent root = loader.load(); 
     scene = new Scene(root); 
    } catch (IOException e) { 
     throw new IllegalStateException(e); 
    } 

Sie die ersten beiden Zeilen in die einzelnen Zeile

FXMLLoader loader = new FXMLLoader(getClass().getResource("/dictionary.fxml")); 

, wenn Sie es vorziehen, kombinieren.