Handling Circular Dependencies with Delegate Wire-Up

Overview

SysML permits circular dependencies, and it can be very useful for two blocks to each have a reference to the other, but it can also cause instantiation problems in executable software. Fortunately, Behavior Execution Engine wires up the delegates in such a way that you can avoid these problems while retaining the usefulness of mutual references. In this section, you will use the delegate wire-up to safely establish the circular dependencies between the UAV, computer, and ground station delegates.

This section covers the following concept:

public GroundStationDelegate(@InjectByName("timeProvider") TimeProvider timeProvider,
        @OptionalInjectBySlot("flightPlanUploadDuration") TimeDuration flightPlanUploadDuration,
        @OptionalInjectBySlot("dataDownloadDuration") TimeDuration dataDownloadDuration,
        @OptionalInjectBySlot("referencePoint") SpatialPoint referencePoint) {
    uavProperty = new BasicProperty<>(timeProvider);
    flightPlanUploadDurationProperty = new BasicProperty<>(timeProvider, flightPlanUploadDuration);
    dataDownloadDurationProperty = new BasicProperty<>(timeProvider, dataDownloadDuration);
    referencePointProperty = new BasicProperty<>(timeProvider, referencePoint);
}

Figure A1: An independent delegate constructor

Prerequisites

Prerequisite Description
Behavior Execution Engine Installation You must have installed Behavior Execution Engine and have the prerequisites for developing delegates for Behavior Execution Engine.
Tutorial Project Start with the files from the Behavior Execution Engine installation: \documentation\tutorialFiles\03\DelegateCodeGeneration, and you will need to configure the delegate module for your environment.
Recommended Reading Before completing this section, you may want to read the following help topic:
  • The wire-up section of the delegate Properties and Operations topic

Instructions

Examine the circular dependencies

  1. Open the UAVMission.mdzip project from the previous section.
  2. Execute the simulation and observe that the simulation fails with the following exception:
    ERROR: com.agi.moxie.uml.engine.InstantiationCycleException
    This indicates that Behavior Execution Engine encountered a circular dependency while attempting to instantiate the Java delegates.
  3. In the System Definition (the BDD), notice the bidirectional relationships between the UAV and GroundStation blocks and between the UAV and Computer blocks. Each relationship represents two properties, one on each block that references the other block.
  4. In the UAVMissionDelegateModule\src\com\agi\moxie\tutorial\uavmission\structure\impl directory, open the UAVDelegate, GroundStationDelegate, and ComputerDelegate classes and notice that they expect each other as constructor parameters. This means that none of them can be instantiated until the others have been instantiated.

Remove the mutual recursion

After Behavior Execution Engine instantiates the Java delegates, it wires them up to their SysML instance specifications, setting the Java fields with the SysML property values. By setting the instance specification properties, you can establish the circular dependencies with this wire-up instead of trying to establish them in the constructors. This in turn allows Behavior Execution Engine to instantiate the delegates in the first place.

  1. In the Instance Specification Diagram, notice that the computer and groundStation properties on the uav instance specification, the uav property on the groundStation instance specification, and the uav property on the uav.computer instance specification are all set to the other instance specifications.
  2. In the GroundStationDelegate class, remove the uav parameter both from the constructor header and from the uavProperty initialization in the constructor body. The constructor should now look like the following:
    public GroundStationDelegate(@InjectByName("timeProvider") TimeProvider timeProvider,
            @OptionalInjectBySlot("flightPlanUploadDuration") TimeDuration flightPlanUploadDuration,
            @OptionalInjectBySlot("dataDownloadDuration") TimeDuration dataDownloadDuration,
            @OptionalInjectBySlot("referencePoint") SpatialPoint referencePoint) {
        uavProperty = new BasicProperty<>(timeProvider);
        flightPlanUploadDurationProperty = new BasicProperty<>(timeProvider, flightPlanUploadDuration);
        dataDownloadDurationProperty = new BasicProperty<>(timeProvider, dataDownloadDuration);
        referencePointProperty = new BasicProperty<>(timeProvider, referencePoint);
    }
    This will initialize the uavProperty value to null in the constructor, but Behavior Execution Engine will wire it up to the correct UAVDelegate instance before the simulation starts.
  3. In the ComputerDelegate class, again remove the uav parameter both from the constructor header and from the uavProperty initialization in the constructor body:
    public ComputerDelegate(@InjectByName("timeProvider") TimeProvider timeProvider,
            @OptionalInjectBySlot("powerSystem") PowerSystem powerSystem,
             ... ) {
        uavProperty = new BasicProperty<>(timeProvider);
         ...
    }
  4. Save your work and reinstall the delegate module.
  5. Execute the simulation again and observe that the simulation no longer throws a com.agi.moxie.uml.engine.InstantiationCycleException.

    The simulation still fails, but with a different exception now, which you will debug in the next section.

Next Section >