我在Masstransit中定义了以下状态机:
public class OrderStateMachine : MassTransitStateMachine<OrderState>
{
public OrderStateMachine()
{
InstanceState(x => x.Status);
Event(() => OrderCreated, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode).SelectId(ctx => NewId.NextGuid()));
//How should I select an id for these events?
Event(() => OrderProvisioned, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode));
Event(() => OrderInvoiced, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode));
State(() => Created);
State(() => Finished);
CompositeEvent(() => OrderFinished, order => order.CompositeStatus, OrderProvisioned, OrderInvoiced);
Initially(
When(OrderCreated)
.Then(context => Console.WriteLine("Order created"))
.TransitionTo(Created));
During(Created,
When(OrderFinished)
.Then(context => Console.WriteLine("Order finished"))
.TransitionTo(Finished)
.Finalize());
}
public State Created { get; set; }
public State Finished { get; set; }
public Event<OrderCreated> OrderCreated { get; set; }
public Event<OrderProvisioned> OrderProvisioned { get; set; }
public Event<OrderInvoiced> OrderInvoiced { get; set; }
public Event OrderFinished { get; set; }
}
public class OrderState : SagaStateMachineInstance
{
public Guid CorrelationId { get; set; }
public string OrderCode { get; set; }
public string Status { get; set; }
public CompositeEventStatus CompositeStatus { get; set; }
}
public class OrderCreated
{
public string OrderCode { get; set; }
public OrderCreated(string orderCode)
{
OrderCode = orderCode;
}
}
public class OrderInvoiced
{
public string OrderCode { get; set; }
public OrderInvoiced(string orderCode)
{
OrderCode = orderCode;
}
}
public class OrderProvisioned
{
public string OrderCode { get; set; }
public OrderProvisioned(string orderCode)
{
OrderCode = orderCode;
}
}
如何将OrderProvisoned和OrderInvoiced事件关联到与初始OrderCreated事件相同的OrderState实例,而不在我的事件中发送Guids并仅使用ordercode属性来关联它们? 如果我运行这个例子,如果发送了OrderProvisioned和OrderInvoiced,我永远不会得到OrderFinished事件,但是如果我将Guids添加到事件中并根据Guid将它们关联起来,它就会被正确执行。
答案 0 :(得分:2)
我解决了它,显然你必须在statemachine实例上显式设置自定义correlationid,我希望masstransit能为我做到这一点。 所以这是初始状态的改编代码:
import static javafx.scene.layout.Region.USE_PREF_SIZE;
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Separator;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
*
* @author Naoghuman
*/
public class ExtendedComponentsMCVE extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
ExtendedTextField extendedTextField = new ExtendedTextField();
// OnlyAnchorPane oap = new OnlyAnchorPane(extendedTextField);
// Scene scene = new Scene(oap, 800, 600);
TabAnchorPane tap = new TabAnchorPane(extendedTextField);
Scene scene = new Scene(tap, 800, 600);
primaryStage.setTitle("Demo Extended Components");
primaryStage.setScene(scene);
primaryStage.show();
}
// ExtendedTextField #######################################################
class ExtendedTextField extends HBox {
private BooleanProperty configureCheckBoxProperty;
private BooleanProperty configureLeftLabelProperty;
private BooleanProperty configureTopLabelProperty;
private CheckBox cbReadOnly;
private Label lLeft;
private Label lTop;
private TextField tfText;
private VBox vBox;
private String lastUserInput = ""; // NOI18N
ExtendedTextField() {
super();
this.init();
}
private void init() {
// vbox
super.setAlignment(Pos.BOTTOM_LEFT);
super.setStyle("-fx-background-color: lightgreen;");
// left label
configureLeftLabelProperty = new SimpleBooleanProperty(Boolean.TRUE);
lLeft = new Label("<left>"); // NOI18N
lLeft.setMaxHeight(USE_PREF_SIZE);
lLeft.setMinHeight(USE_PREF_SIZE);
lLeft.visibleProperty().bind(configureLeftLabelProperty);
lLeft.managedProperty().bind(configureLeftLabelProperty);
super.getChildren().add(lLeft);
// checkbox
configureCheckBoxProperty = new SimpleBooleanProperty(Boolean.TRUE);
cbReadOnly = new CheckBox();
cbReadOnly.setMaxHeight(USE_PREF_SIZE);
cbReadOnly.setMinHeight(USE_PREF_SIZE);
cbReadOnly.visibleProperty().bind(configureCheckBoxProperty);
cbReadOnly.managedProperty().bind(configureCheckBoxProperty);
super.getChildren().add(cbReadOnly);
// vbox
vBox = new VBox();
HBox.setHgrow(vBox, Priority.ALWAYS);
// top label
configureTopLabelProperty = new SimpleBooleanProperty(Boolean.TRUE);
lTop = new Label("<top>"); // NOI18N
lTop.visibleProperty().bind(configureTopLabelProperty);
lTop.managedProperty().bind(configureTopLabelProperty);
vBox.getChildren().add(lTop);
// textfield
tfText = new TextField(lastUserInput);
tfText.disableProperty().bind(cbReadOnly.selectedProperty().not());
lLeft.prefHeightProperty().bind(tfText.heightProperty());
cbReadOnly.prefHeightProperty().bind(tfText.heightProperty());
vBox.getChildren().add(tfText);
super.getChildren().add(vBox);
}
public void setCheckBoxSelected(Boolean selected) {
cbReadOnly.setSelected(selected);
if (selected) {
tfText.setText(lastUserInput);
}
else {
lastUserInput = tfText.getText();
tfText.setText(null);
}
}
public void setCheckBoxVisibleManaged(Boolean visible) {
configureCheckBoxProperty.setValue(visible);
}
public void setLeftLabelVisibleManaged(boolean selected) {
configureLeftLabelProperty.setValue(selected);
}
public void setTopLabelVisibleManaged(boolean selected) {
configureTopLabelProperty.setValue(selected);
}
}
// ExtendedTextField #######################################################
// OnlyAnchorPane ##########################################################
class OnlyAnchorPane extends AnchorPane {
OnlyAnchorPane(ExtendedTextField extendedTextField) {
super();
super.setStyle("-fx-background-color: BLANCHEDALMOND;");
// hbox
HBox hbox = new HBox();
hbox.setStyle("-fx-background-color: KHAKI;");
hbox.setSpacing(7.0d);
hbox.setPrefWidth(Double.MAX_VALUE);
// extendedTextField
VBox vbox = new VBox();
vbox.getChildren().add(extendedTextField);
HBox.setHgrow(vbox, Priority.ALWAYS);
hbox.getChildren().add(vbox);
// menu
MenuVBox menu = new MenuVBox(extendedTextField);
hbox.getChildren().add(menu);
AnchorPane.setBottomAnchor(hbox, 14d);
AnchorPane.setLeftAnchor(hbox, 14d);
AnchorPane.setTopAnchor(hbox, 14d);
AnchorPane.setRightAnchor(hbox, 14d);
super.getChildren().add(hbox);
}
}
// OnlyAnchorPane ##########################################################
// TabAnchorPane ###########################################################
class TabAnchorPane extends AnchorPane {
TabAnchorPane(ExtendedTextField extendedTextField) {
super();
super.setStyle("-fx-background-color: BLANCHEDALMOND;");
// tabpane
TabPane tp = new TabPane();
// tab
Tab t = new Tab("TextField");
t.setClosable(false);
tp.getTabs().add(t);
// hbox
HBox hbox = new HBox();
hbox.setStyle("-fx-background-color: KHAKI;");
hbox.setSpacing(7.0d);
hbox.setPrefWidth(Double.MAX_VALUE);
// extendedTextField
VBox vbox = new VBox();
vbox.getChildren().add(extendedTextField);
HBox.setHgrow(vbox, Priority.ALWAYS);
hbox.getChildren().add(vbox);
// menu
MenuVBox menu = new MenuVBox(extendedTextField);
hbox.getChildren().add(menu);
t.setContent(hbox);
AnchorPane.setBottomAnchor(tp, 14d);
AnchorPane.setLeftAnchor(tp, 14d);
AnchorPane.setTopAnchor(tp, 14d);
AnchorPane.setRightAnchor(tp, 14d);
super.getChildren().add(tp);
}
}
// TabAnchorPane ###########################################################
// MenuVBox ################################################################
class MenuVBox extends VBox {
MenuVBox(ExtendedTextField extendedTextField) {
super();
super.setStyle("-fx-background-color: HONEYDEW;");
super.setSpacing(7.0d);
super.setMaxWidth(200.0d);
super.setMinWidth(200.0d);
super.setPrefWidth(200.0d);
// show top label
CheckBox cb1 = new CheckBox("Show top label");
cb1.setSelected(true);
cb1.setOnAction((ActionEvent event) -> {
extendedTextField.setTopLabelVisibleManaged(cb1.isSelected());
});
super.getChildren().add(cb1);
// show left label
CheckBox cb2 = new CheckBox("Show left label");
cb2.setSelected(true);
cb2.setOnAction((ActionEvent event) -> {
extendedTextField.setLeftLabelVisibleManaged(cb2.isSelected());
});
super.getChildren().add(cb2);
// seperator
super.getChildren().add(new Separator());
// select checkbox
CheckBox cb3 = new CheckBox("Select checkbox");
cb3.setSelected(false);
cb3.setOnAction((ActionEvent event) -> {
extendedTextField.setCheckBoxSelected(cb3.isSelected());
});
super.getChildren().add(cb3);
// show checkbox
CheckBox cb4 = new CheckBox("Show checkbox");
cb4.setSelected(true);
cb4.setOnAction((ActionEvent event) -> {
extendedTextField.setCheckBoxVisibleManaged(cb4.isSelected());
});
super.getChildren().add(cb4);
}
}
// MenuVBox ################################################################
}
同样使用一个传奇工厂,但我认为你可以放弃选择逻辑,因为传奇工厂否决了这个,但我得到了一个例外。
Initially(
When(OrderCreated)
.Then(context => context.Instance.OrderCode = context.Data.OrderCode)
.Then(context => Console.WriteLine("Order created"))
.TransitionTo(Created));
答案 1 :(得分:1)
是否存在可用于查看此行为是否无效的单元测试损坏?从上面编辑的代码中,这似乎是我期望它如何相关 - 使用OrderCode。这就是购物车示例的工作原理。
只有启动状态机的事件才需要SelectId()函数,因为这是分配CorrelationId的地方。如果它没有被其他事件使用,则无需选择&#34;因为Query(orderCode)会进行相关。
以下是购物车示例在示例中的工作原理: https://github.com/MassTransit/Sample-ShoppingWeb/blob/master/src/CartTracking/ShoppingCartStateMachine.cs#L15
在上面的示例中:
Event(() => OrderCreated, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode).SelectId(ctx => NewId.NextGuid()));
Event(() => OrderProvisioned, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode));
Event(() => OrderInvoiced, x => x.CorrelateBy(order => order.OrderCode, ctx => ctx.Message.OrderCode));
这正是我配置它的方式,看起来你正走在正确的轨道上。