I'm using Persistence unit and Entity classes from Database, all in a JavaFx fxml Application, I succeeded importing all my tables as entities in my Model, the proble is that I get an exceptions and errors when I try to insert into an entity, here's my entire code
public class SampleController implements Initializable {
@PersistenceContext(unitName="RawdaPU")
private EntityManager em;
@FXML
private Label label;
@FXML
private void handleButtonAction(ActionEvent event)
{
Moyendidactique moyenDidactique = new Moyendidactique("1", "moyen1", "Type1");
em.persist(moyenDidactique);
em.close();
}
@Override
public void initialize(URL url, ResourceBundle rb)
{
// TODO
}
}
Here is the full errors I get when I press the button (when handleButtonAction is fired)
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1440)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
at javafx.event.Event.fireEvent(Event.java:171)
at javafx.scene.Node.fireEvent(Node.java:6863)
at javafx.scene.control.Button.fire(Button.java:179)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:193)
at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:336)
at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:329)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:64)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
at javafx.event.Event.fireEvent(Event.java:171)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3324)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3164)
at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3119)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1559)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2261)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:228)
at com.sun.glass.ui.View.handleMouseEvent(View.java:528)
at com.sun.glass.ui.View.notifyMouse(View.java:922)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.access$100(WinApplication.java:29)
at com.sun.glass.ui.win.WinApplication$2$1.run(WinApplication.java:67)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1435)
... 41 more
Caused by: java.lang.NullPointerException
at rawda.Controller.SampleController.handleButtonAction(SampleController.java:37)
... 46 more
I couldn't find an answer in the already existing similar questions, Can't know exactly what I'm missing, thanks in advance for helping.
Why you get a NullPointerException in your code
The @PersistenceContext annotation "Expresses a dependency on a container-managed EntityManager and its associated persistence context."
By default FXML controllers are not container-managed, which means they aren't going to set container-managed members such as those marked with the
@PersistenceContext
.You can use FXML controllers in a container-managed environment by defining a controller factory for your FXMLLoader (for example as the InjectionProvider is used to inject values into in the Afterburner.fx framework).
But really, you don't need to do that injection if you are just starting out with Java. The inversion of control stuff likely adds a bit too much magic until you are used to it.
Recommended JavaFX Integration Approach to Try for JPA Beginners
Instead, don't rely on the
@PersistenceContext
annotation. Get an entity manager directly from an entity manager factory reference. There is a good example of using an EntityManager outside a container managed environment in the java2s sample Create Query From Entity Manager.In your application provide a mechanism to get an entity manager:
In your controller, get an entity manager from the application and use it as needed.
On Closing and Entity Manager Lifetimes
Because your original example closed the entity manager after the persist statement, I moved the entity manager creation into the same method as the close method so that they are matched. The close means that the entity manager can't be used again, so you may as well create it in the same place that you close it - that way you can't reuse it somewhere else by mistake. Note that you don't need to do the close like that and can reuse the entity manager if you like, but for getting started with jpa, just doing it as in this example answer is likely fine and you can look into more complex entity manager reuse scenarios as you get more experience and confidence with the technology.
Concurrency Concerns
You also need to be aware of concurrency integrations of JPA usage in your application. Doing stuff such as the JPA calls directly in the button's action handler is not usually a great idea because the calls are blocking I/O that will halt the JavaFX application thread and freeze up your application UI for periods of time. Instead, it is best to make use of the JavaFX task and service concurrency utilities to handle JPA interaction similar to how the database work is abstracted from the UI thread in the JavaFX JDBC task sample.
For a small local database it is concurrency is likely not that much of a concern, so you could try your app first single threaded and if it works fine, great, but if it is freezing up then look into the concurrency utilities.
Next Steps
The above approach is really a quick getting started thing.
Once you understand this simple approach, you may want to look into the more structured design demonstrated in the afterburner.fx and airhacks-control frameworks or the (much more heavyweight) javafx/jpa/spring framework integration.