2

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

1 Answers1

1

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:

PresentationModel dialogPM = dolphin.findPresentationModelById(model.id);
if (dialogPM == null) {
     dialogPM = dolphin.presentationModel( ... )
}
dialogPM.reset() // if it has been used before, reset all values

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!

Dierk
  • 1,308
  • 7
  • 13