All features supporting the SysML v2 BETA specification are currently ALPHA and subject to change. The final SysML 2.0.0 specification is expected to be officially adopted in the second half of 2025. While there have been many questions during the finalization, we believe this implementation provides enough value for early adopters to start preparing to create and execute models using the new specification. We will be expanding support for the specification through finalization, into SysML v2.1, and beyond. There are a small number of remaining issues related to execution scheduled for revision in SysMLv2.1. We will be expanding and clarifying support for SysML v2.x throughout the upcoming language revision process. Consult the What's New and Modeling with SysML v2 pages for more information about what is currently supported.
Delegate Module Providers
A DelegateModuleProvider
registers a delegate module with Behavior Execution Engine via a Service Provider Interface
(SPI) proxy. This occurs at the start of a Behavior Execution Engine simulation.
You need to include the SPI file in the resulting JAR to load the delegate module prior to running a simulation. To create and include an SPI
file, open your project directory that contains the source directory (usually src) and the build.gradle file. From
there, create a simple text file in the \resources\META-INF\services\ directory named
com.agi.mbse.sysml2.spi.DelegateModuleProvider.
That file should contain the fully qualified canonical name of your DelegateModuleProvider
for the delegate module.
For the example in Figure 1, the name is
com.agi.mbse.tutorial.tortoisevshare.TortoiseVsHareDelegateModuleProvider
and you can find this SPI file
in the sample code provided as a reference in your Behavior Execution Engine installation.
Let's take a look at the contents of TortoiseVsHareDelegateModuleProvider
in Figure 1:
package com.agi.mbse.tutorial.tortoisevshare;
import com.agi.mbse.sysml2.api.delegation.*;
import com.agi.mbse.sysml2.spi.DelegateModuleProvider;
import java.util.UUID;
public class TortoiseVsHareDelegateModuleProvider implements DelegateModuleProvider {
public static final String rootPackageName = "TortoiseVsHare Part 2";
@Override
public DelegateModule provideDelegateModule() {
return new DelegateModule() {
@Override
public DelegateIdentity getIdentity() {
return new DelegateIdentity(
UUID.fromString("d547ca5c-3fb7-11f0-ac13-325096b39f47"),
"TortoiseVsHare Part 2 Module",
"The delegate module for the Tortoise vs Hare part 2 sample."
);
}
@Override
public void registerDelegate(CustomCodeRegistry codeRegistry) {
codeRegistry.registerInstanceDataFor(rootPackageName + "::Racer", RacerDataHistory.class, context -> {
return new RacerDataHistory();
});
codeRegistry.delegateScalarValueForFeature(rootPackageName + "::Racer::distanceCovered", new DistanceCoveredAccessor());
codeRegistry.delegateExecutionOfAction(rootPackageName + "::Racer::startRacing", context -> {
RacerCode.startRacing(context);
return DelegationResult.NoAdditionalEvents.INSTANCE;
});
codeRegistry.delegateExecutionOfAction(rootPackageName + "::Racer::stopRacing", context -> {
RacerCode.stopRacing(context);
return DelegationResult.NoAdditionalEvents.INSTANCE;
});
codeRegistry.delegateExecutionOfAction(rootPackageName + "::Hare::startNapping", context -> {
HareCode.startNapping(context);
return DelegationResult.NoAdditionalEvents.INSTANCE;
});
codeRegistry.delegateExecutionOfAction(rootPackageName + "::Hare::stopNapping", context -> {
HareCode.stopNapping(context);
return DelegationResult.NoAdditionalEvents.INSTANCE;
});
}
};
}
}
Figure 1: The tutorial Tortoise and Hare part 2's delegate module provider
The only method you must implement for a DelegateModuleProvider
is
provideDelegateModule()
, which returns a DelegateModule
. A DelegateModule
is the plugin point for registering delegates in the system for a simulation.
The DelegateModule
has a few different methods that you can override. There are only two that are required for
Behavior Execution Engine to use it. The first method is the getIdentity()
method, which returns a
DelegateIdentity
. This identity is used when specifying delegate modules in the
model configuration file. Make sure that the UUID that you specify is unique and not
reused for any other delegate module. The other required method is the
registerDelegate(CustomCodeRegistry codeRegistry)
method, which provides a
CustomCodeRegistry
to make calls to the engine during the pre-simulation initialization of the delegate module.
Registering dependencies
If you want to use other delegate modules as dependencies for your delegate module, you can provide an implementation of the
getDependencies()
method from the DelegateModule
interface, which returns a
list of each DelegateDependency
. A DelegateDependency
is a data structure that takes in
an UUID identifier for the required delegate modules.
Behavior Execution Engine will attempt to load dependencies before dependants but will throw an exception if there are any circular dependencies or if a dependency could not be found.
Behavior Execution Engine includes a STK delegate module for loading the JNI libraries into the classpath. To use it in your delegate module, you
can specify its UUID bc8b4be5-975f-4084-8fdf-507fc21dfa23
as a dependency. Below is an example delegate module
provider that connects to STK.
If you are copying another delegate module, ensure you change the UUID to denote a distinct module.
@Override
public DelegateModule provideDelegateModule() {
return new DelegateModule() {
private IAgStkObjectRoot mStkRoot = null;
@Override
public List<DelegateDependency> getDependencies() {
return List.of(
// This is the UUID for the delegate module: 'com.agi.mbse.stk.StkDelegateModule'.
// By specifying that as a dependency, the JNI setup of STK will be completed before the load of this module.
new DelegateDependency(UUID.fromString("bc8b4be5-975f-4084-8fdf-507fc21dfa23"))
);
}
@Override
public DelegateIdentity getIdentity() {
return new DelegateIdentity(
UUID.fromString("3c0096fc-72f7-4e62-8504-48dc7bd0d03f"),
"MyStkDelegateModule",
"This is a simple delegate module using stk."
);
}
@Override
public void initialize(SimulationContext context) {
// Attempt to grab a window of STK if open.
try {
context.getContextLogger().info("Attaching to STK Desktop.");
mStkRoot = AgStkUi.getStkUiInstance().getIAgStkObjectRoot();
} catch (Exception ex) {
context.getContextLogger().info("An open instance of STK was not found.");
throw ex;
}
}
@Override
public void registerDelegate(CustomCodeRegistry codeRegistry) {
/* Registration code */
}
};
}
Figure 2: Example delegate module provider template for a delegate module using STK.