I want to create a JavaFX application with OpenDolphin. In this application I want to open a new window that has an own FXMLController class and an own Presentation Model. When I open the dialog window for the first time everthing works fine. When I close the dialog window and try to reopen it the I get an IllegalArgumentException
Caused by: java.lang.IllegalArgumentException: There already is a PM with id
full stacktrace
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2605)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2583)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2445)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3218)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3179)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3152)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3128)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3108)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3101)
at com.ognios.qa.jotc.client.FXMLController.handleTestCaseAction(FXMLController.java:67)
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.GeneratedMethodAccessor1.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)
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)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Node.fireEvent(Node.java:8390)
at javafx.scene.control.Button.fire(Button.java:185)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
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)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3758)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3486)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2495)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:350)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$350(GlassViewEventHandler.java:385)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$$Lambda$200/19201760.get(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:404)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:384)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:927)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$48(GtkApplication.java:139)
at com.sun.glass.ui.gtk.GtkApplication$$Lambda$43/811004261.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: There already is a PM with id com.ognios.qa.jotc.shared.Constants.tcmodelId
at org.opendolphin.core.ModelStore.add(ModelStore.java:99)
at org.opendolphin.core.client.ClientModelStore.add(ClientModelStore.java:58)
at org.opendolphin.core.client.ClientModelStore$add.call(Unknown Source)
at org.opendolphin.core.client.ClientDolphin.presentationModel(ClientDolphin.groovy:76)
at org.opendolphin.core.client.ClientDolphin.presentationModel(ClientDolphin.groovy)
at com.ognios.qa.jotc.client.FXMLTestCaseDialogController.initialize(FXMLTestCaseDialogController.java:40)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2552)
... 68 more
How can I either reset the PM or reuse the previously initialized PM?
My (client) code
ApplicationStarter.java
public class ApplicationStarter {
public static void main(String args[]) {
ClientDolphin clientDolphin = new ClientDolphin();
clientDolphin.setClientModelStore(new ClientModelStore(clientDolphin));
ClientConnector connector = createConnector(clientDolphin);
connector.setUiThreadHandler(new JavaFXUiThreadHandler());
clientDolphin.setClientConnector(connector);
com.ognios.qa.jotc.client.Application.clientDolphin = clientDolphin;
Application.launch(com.ognios.qa.jotc.client.Application.class);
}
private static ClientConnector createConnector(ClientDolphin clientDolphin) {
//running real client server mode.
HttpClientConnector connector = new HttpClientConnector(clientDolphin, "http://localhost:8080/otc/tutorial/");
connector.setCodec(new JsonCodec());
return connector;
}
}
Application.java
public class Application extends javafx.application.Application {
static ClientDolphin clientDolphin;
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/fxml/Scene.fxml"));
clientDolphin.send(CMD_CREATE_PMS, new OnFinishedHandlerAdapter() {
@Override
public void onFinished(List<ClientPresentationModel> presentationModels) {
clientDolphin.send(CMD_INIT_DATA, new OnFinishedHandlerAdapter() {
@Override
public void onFinished(List<ClientPresentationModel> presentationModels) {
stage.show();
}
}
);
}
});
Scene scene = new Scene(root);
scene.getStylesheets().add("/styles/Styles.css");
stage.setTitle("JOTC");
stage.setScene(scene);
stage.show();
}
}
FXMLController.java // FXML Controller for main window
public class FXMLController implements Initializable {
private PresentationModel textAttributeModel;
@FXML
private void handleTestCaseAction(ActionEvent event) {
Parent root;
try {
root = FXMLLoader.load(getClass().getClassLoader().getResource("fxml/FXMLTestCase.fxml"));
Stage stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.setTitle("TestCase");
stage.setScene(new Scene(root, 600, 450));
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
private void setupBinding() {
/*
...
*/
}
@Override
public void initialize(URL url, ResourceBundle rb) {
//PM for controls in main window
textAttributeModel = Application.clientDolphin.presentationModel(PM_PERSON, new ClientAttribute(ATT_FIRSTNAME, ""));
setupBinding();
}
...
}
FXMLTestCaseDialogController.java //FXML Controller for dialog window
public class FXMLTestCaseDialogController implements Initializable {
private PresentationModel tcTextAttributeModel;
@FXML
private TextField tf_tcid;
@FXML
private TextField tf_tcname;
@Override
public void initialize(URL location, ResourceBundle resources) {
tcTextAttributeModel = Application.clientDolphin.presentationModel(PM_TC,
new ClientAttribute(ATT_TCID, ""),
new ClientAttribute(ATT_TCNAME, ""));
setupBinding();
}
private void setupBinding() {
JFXBinder.bind("text").of(tf_tcid).to(ATT_TCID).of(tcTextAttributeModel);
JFXBinder.bind("text").of(tf_tcname).to(ATT_TCNAME).of(tcTextAttributeModel);
}
@FXML
private void handleCancel(ActionEvent event) {
((Node) (event.getSource())).getScene().getWindow().hide();
}
@FXML
private void handleDeactivate(ActionEvent event) {
}
@FXML
private void handleResetStats(ActionEvent event) {
}
@FXML
private void handleDelete(ActionEvent event) {
}
@FXML
private void handleSave(ActionEvent event) {
Application.clientDolphin.send(CMD_SAVETC, new OnFinishedHandlerAdapter() {
@Override
public void onFinished(List<ClientPresentationModel> presentationModels) {
tcTextAttributeModel.getAt(ATT_TCID).rebase();
tcTextAttributeModel.getAt(ATT_TCNAME).rebase();
}
});
}
}
OpenDolphin Version: 0.11
one of the rules of OpenDolphin is that presentation models (PMs) have a unique ID. You cannot create a second PM with that same ID. There is no exception to this rule.
To create a new PM with that ID, you first have to delete the old one. You can use
dolphin.deletePresentationModel(model)
for that purpose.A second alternative is to not delete and recreate the PM but to re-use it if it is there:
This is a tiny bit more reuse efficient but in the first place, it allows to keep all listeners in place that may be attached to the attributes of this PM.
happy hacking!