Repository: apache/incubator-seata-go

Issue:
Feature: HttpServiceTaskState Support
Saga is a distributed transaction processing mode used to ensure consistency in distributed systems.The state machine mode of saga implemented in seata java, it`s needs to be support in seata go.

Each node of the state machine is declared as a state, and the state machine process is composed of different types of nodes.The `ServiceTaskState` represents an executable node. Historically, we have supported `GrpcServiceTaskState`. http calls are also frequent, We need to implement the http state type support http call, need consider `tls`, `http multiple versions`, etc.

@see ：pkg/saga/statemachine/statelang/state/task_state.go

Discussion:
@wt-better: There has been one history implementation, corresponding to the branch: feature/saga, but the details need to be completed. you can develop on this branch.@Code-Fight: pls assign to me

Solution patch:
diff --git a/pkg/client/config.go b/pkg/client/config.go
index bd84852..c4fce0f 100644
--- a/pkg/client/config.go
+++ b/pkg/client/config.go
@@ -20,6 +20,7 @@ package client
 import (
 	"flag"
 	"fmt"
+	"github.com/seata/seata-go/pkg/saga"
 	"io/ioutil"
 	"os"
 	"path/filepath"
@@ -84,6 +85,8 @@ type Config struct {
 	TransportConfig   remoteConfig.TransportConfig `yaml:"transport" json:"transport" koanf:"transport"`
 	ServiceConfig     discovery.ServiceConfig      `yaml:"service" json:"service" koanf:"service"`
 	RegistryConfig    discovery.RegistryConfig     `yaml:"registry" json:"registry" koanf:"registry"`
+
+	SagaConfig saga.Config `yaml:"saga" json:"saga" koanf:"saga"`
 }
 
 func (c *Config) RegisterFlags(f *flag.FlagSet) {
@@ -102,6 +105,7 @@ func (c *Config) RegisterFlags(f *flag.FlagSet) {
 	c.TransportConfig.RegisterFlagsWithPrefix("transport", f)
 	c.RegistryConfig.RegisterFlagsWithPrefix("registry", f)
 	c.ServiceConfig.RegisterFlagsWithPrefix("service", f)
+	c.SagaConfig.RegisterFlagsWithPrefix("saga", f)
 }
 
 type loaderConf struct {
diff --git a/pkg/saga/config.go b/pkg/saga/config.go
new file mode 100644
index 0000000..dd72bc6
--- /dev/null
+++ b/pkg/saga/config.go
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package saga
+
+import (
+	"flag"
+
+	"github.com/seata/seata-go/pkg/saga/statemachine"
+)
+
+type Config struct {
+	StateMachine *statemachine.StateMachineObject `yaml:"state-machine" json:"state-machine" koanf:"state-machine"`
+}
+
+func (cfg *Config) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) {
+	if cfg.StateMachine != nil {
+		cfg.StateMachine.RegisterFlagsWithPrefix(prefix+".state-machine", f)
+	}
+}
diff --git a/pkg/saga/statemachine/constant/constant.go b/pkg/saga/statemachine/constant/constant.go
index a089e7d..72af09e 100644
--- a/pkg/saga/statemachine/constant/constant.go
+++ b/pkg/saga/statemachine/constant/constant.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package constant
 
 const (
diff --git a/pkg/saga/statemachine/engine/core/bussiness_processor.go b/pkg/saga/statemachine/engine/core/bussiness_processor.go
index 6b0a2bb..38846df 100644
--- a/pkg/saga/statemachine/engine/core/bussiness_processor.go
+++ b/pkg/saga/statemachine/engine/core/bussiness_processor.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/compensation_holder.go b/pkg/saga/statemachine/engine/core/compensation_holder.go
index 562cb02..c22fb1f 100644
--- a/pkg/saga/statemachine/engine/core/compensation_holder.go
+++ b/pkg/saga/statemachine/engine/core/compensation_holder.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/default_statemachine_config.go b/pkg/saga/statemachine/engine/core/default_statemachine_config.go
index c769269..fa2ef15 100644
--- a/pkg/saga/statemachine/engine/core/default_statemachine_config.go
+++ b/pkg/saga/statemachine/engine/core/default_statemachine_config.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/engine_utils.go b/pkg/saga/statemachine/engine/core/engine_utils.go
index e1dcd4d..63eb799 100644
--- a/pkg/saga/statemachine/engine/core/engine_utils.go
+++ b/pkg/saga/statemachine/engine/core/engine_utils.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/event.go b/pkg/saga/statemachine/engine/core/event.go
index 4f7c18b..871c0ce 100644
--- a/pkg/saga/statemachine/engine/core/event.go
+++ b/pkg/saga/statemachine/engine/core/event.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 type Event interface {
diff --git a/pkg/saga/statemachine/engine/core/event_bus.go b/pkg/saga/statemachine/engine/core/event_bus.go
index 47d617d..e793419 100644
--- a/pkg/saga/statemachine/engine/core/event_bus.go
+++ b/pkg/saga/statemachine/engine/core/event_bus.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/event_consumer.go b/pkg/saga/statemachine/engine/core/event_consumer.go
index 1df21bd..25f8762 100644
--- a/pkg/saga/statemachine/engine/core/event_consumer.go
+++ b/pkg/saga/statemachine/engine/core/event_consumer.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/event_publisher.go b/pkg/saga/statemachine/engine/core/event_publisher.go
index 9ad8694..447dee3 100644
--- a/pkg/saga/statemachine/engine/core/event_publisher.go
+++ b/pkg/saga/statemachine/engine/core/event_publisher.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import "context"
diff --git a/pkg/saga/statemachine/engine/core/instruction.go b/pkg/saga/statemachine/engine/core/instruction.go
index ed81fc9..4b8f9d3 100644
--- a/pkg/saga/statemachine/engine/core/instruction.go
+++ b/pkg/saga/statemachine/engine/core/instruction.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/loop_context_holder.go b/pkg/saga/statemachine/engine/core/loop_context_holder.go
index b1f69fe..242e455 100644
--- a/pkg/saga/statemachine/engine/core/loop_context_holder.go
+++ b/pkg/saga/statemachine/engine/core/loop_context_holder.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/loop_task_utils.go b/pkg/saga/statemachine/engine/core/loop_task_utils.go
index d56ac7f..18a3bec 100644
--- a/pkg/saga/statemachine/engine/core/loop_task_utils.go
+++ b/pkg/saga/statemachine/engine/core/loop_task_utils.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/parameter_utils.go b/pkg/saga/statemachine/engine/core/parameter_utils.go
index 680167c..56336b7 100644
--- a/pkg/saga/statemachine/engine/core/parameter_utils.go
+++ b/pkg/saga/statemachine/engine/core/parameter_utils.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/process_context.go b/pkg/saga/statemachine/engine/core/process_context.go
index 9da5c3e..163ea64 100644
--- a/pkg/saga/statemachine/engine/core/process_context.go
+++ b/pkg/saga/statemachine/engine/core/process_context.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/process_controller.go b/pkg/saga/statemachine/engine/core/process_controller.go
index 2f45aeb..4c987db 100644
--- a/pkg/saga/statemachine/engine/core/process_controller.go
+++ b/pkg/saga/statemachine/engine/core/process_controller.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/process_ctrl_statemachine_engine.go b/pkg/saga/statemachine/engine/core/process_ctrl_statemachine_engine.go
index 426ec65..1b59123 100644
--- a/pkg/saga/statemachine/engine/core/process_ctrl_statemachine_engine.go
+++ b/pkg/saga/statemachine/engine/core/process_ctrl_statemachine_engine.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/process_router.go b/pkg/saga/statemachine/engine/core/process_router.go
index 5d7e599..1875cb1 100644
--- a/pkg/saga/statemachine/engine/core/process_router.go
+++ b/pkg/saga/statemachine/engine/core/process_router.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/process_state.go b/pkg/saga/statemachine/engine/core/process_state.go
index 3dc0692..66dee8f 100644
--- a/pkg/saga/statemachine/engine/core/process_state.go
+++ b/pkg/saga/statemachine/engine/core/process_state.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/state_router.go b/pkg/saga/statemachine/engine/core/state_router.go
index 185984e..73dd02e 100644
--- a/pkg/saga/statemachine/engine/core/state_router.go
+++ b/pkg/saga/statemachine/engine/core/state_router.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/statemachine_config.go b/pkg/saga/statemachine/engine/core/statemachine_config.go
index 9c77b73..e3f9da2 100644
--- a/pkg/saga/statemachine/engine/core/statemachine_config.go
+++ b/pkg/saga/statemachine/engine/core/statemachine_config.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/statemachine_engine.go b/pkg/saga/statemachine/engine/core/statemachine_engine.go
index c18d91c..75cdb1a 100644
--- a/pkg/saga/statemachine/engine/core/statemachine_engine.go
+++ b/pkg/saga/statemachine/engine/core/statemachine_engine.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/statemachine_store.go b/pkg/saga/statemachine/engine/core/statemachine_store.go
index 7a76333..f47065d 100644
--- a/pkg/saga/statemachine/engine/core/statemachine_store.go
+++ b/pkg/saga/statemachine/engine/core/statemachine_store.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/status_decision.go b/pkg/saga/statemachine/engine/core/status_decision.go
index e95a631..6fd596f 100644
--- a/pkg/saga/statemachine/engine/core/status_decision.go
+++ b/pkg/saga/statemachine/engine/core/status_decision.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/core/utils.go b/pkg/saga/statemachine/engine/core/utils.go
index 8300c0e..49f03e0 100644
--- a/pkg/saga/statemachine/engine/core/utils.go
+++ b/pkg/saga/statemachine/engine/core/utils.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/exception/exception.go b/pkg/saga/statemachine/engine/exception/exception.go
index f5c5823..ea7c078 100644
--- a/pkg/saga/statemachine/engine/exception/exception.go
+++ b/pkg/saga/statemachine/engine/exception/exception.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package exception
 
 import "github.com/seata/seata-go/pkg/util/errors"
diff --git a/pkg/saga/statemachine/engine/expr/expression.go b/pkg/saga/statemachine/engine/expr/expression.go
index 767c49d..00441d1 100644
--- a/pkg/saga/statemachine/engine/expr/expression.go
+++ b/pkg/saga/statemachine/engine/expr/expression.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package expr
 
 import (
diff --git a/pkg/saga/statemachine/engine/invoker/func_invoker.go b/pkg/saga/statemachine/engine/invoker/func_invoker.go
index 085decb..3131c52 100644
--- a/pkg/saga/statemachine/engine/invoker/func_invoker.go
+++ b/pkg/saga/statemachine/engine/invoker/func_invoker.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package invoker
 
 import (
diff --git a/pkg/saga/statemachine/engine/invoker/grpc_invoker.go b/pkg/saga/statemachine/engine/invoker/grpc_invoker.go
index e83e798..afdc7ef 100644
--- a/pkg/saga/statemachine/engine/invoker/grpc_invoker.go
+++ b/pkg/saga/statemachine/engine/invoker/grpc_invoker.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package invoker
 
 import (
diff --git a/pkg/saga/statemachine/engine/invoker/http_invoker.go b/pkg/saga/statemachine/engine/invoker/http_invoker.go
new file mode 100644
index 0000000..c23531a
--- /dev/null
+++ b/pkg/saga/statemachine/engine/invoker/http_invoker.go
@@ -0,0 +1,220 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package invoker
+
+import (
+	"bytes"
+	"context"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"io"
+	"net/http"
+	"reflect"
+	"strings"
+	"sync"
+	"time"
+
+	"github.com/seata/seata-go/pkg/saga/statemachine/statelang/state"
+	"github.com/seata/seata-go/pkg/util/log"
+)
+
+const errHttpCode = 400
+
+type HTTPInvoker struct {
+	clientsMapLock sync.Mutex
+	clients        map[string]HTTPClient
+}
+
+func NewHTTPInvoker() *HTTPInvoker {
+	return &HTTPInvoker{
+		clients: make(map[string]HTTPClient),
+	}
+}
+
+func (h *HTTPInvoker) RegisterClient(serviceName string, client HTTPClient) {
+	h.clientsMapLock.Lock()
+	defer h.clientsMapLock.Unlock()
+	h.clients[serviceName] = client
+}
+
+func (h *HTTPInvoker) GetClient(serviceName string) HTTPClient {
+	h.clientsMapLock.Lock()
+	defer h.clientsMapLock.Unlock()
+	return h.clients[serviceName]
+}
+
+func (h *HTTPInvoker) Invoke(ctx context.Context, input []any, service state.ServiceTaskState) (output []reflect.Value, err error) {
+	serviceTaskStateImpl := service.(*state.ServiceTaskStateImpl)
+	client := h.GetClient(serviceTaskStateImpl.ServiceName())
+	if client == nil {
+		return nil, fmt.Errorf("no http client %s for service task state", serviceTaskStateImpl.ServiceName())
+	}
+
+	if serviceTaskStateImpl.IsAsync() {
+		go func() {
+			_, err := client.Call(ctx, serviceTaskStateImpl, input)
+			if err != nil {
+				log.Errorf("invoke Service[%s].%s failed, err is %s", serviceTaskStateImpl.ServiceName(),
+					serviceTaskStateImpl.ServiceMethod(), err)
+			}
+		}()
+		return nil, nil
+	}
+
+	return client.Call(ctx, serviceTaskStateImpl, input)
+}
+
+func (h *HTTPInvoker) Close(ctx context.Context) error {
+	return nil
+}
+
+type HTTPClient interface {
+	Call(ctx context.Context, serviceTaskStateImpl *state.ServiceTaskStateImpl, input []any) ([]reflect.Value, error)
+}
+
+type HTTPClientImpl struct {
+	serviceName string
+	baseURL     string
+	client      *http.Client
+}
+
+func NewHTTPClient(serviceName string, baseURL string, client *http.Client) *HTTPClientImpl {
+	if client == nil {
+		client = &http.Client{
+			Timeout: time.Second * 30,
+		}
+	}
+	return &HTTPClientImpl{
+		serviceName: serviceName,
+		baseURL:     baseURL,
+		client:      client,
+	}
+}
+
+func (h *HTTPClientImpl) Call(ctx context.Context, serviceTaskStateImpl *state.ServiceTaskStateImpl, input []any) ([]reflect.Value, error) {
+	retryCountMap := make(map[state.Retry]int)
+	for {
+		res, err, shouldRetry := func() (res []reflect.Value, resErr error, shouldRetry bool) {
+			defer func() {
+				if r := recover(); r != nil {
+					errStr := fmt.Sprintf("%v", r)
+					retry := h.matchRetry(serviceTaskStateImpl, errStr)
+					resErr = errors.New(errStr)
+					if retry != nil {
+						shouldRetry = h.needRetry(serviceTaskStateImpl, retryCountMap, retry, resErr)
+					}
+				}
+			}()
+
+			reqBody, err := json.Marshal(input)
+			if err != nil {
+				return nil, err, false
+			}
+
+			req, err := http.NewRequestWithContext(ctx,
+				serviceTaskStateImpl.ServiceMethod(),
+				h.baseURL+serviceTaskStateImpl.Name(),
+				bytes.NewBuffer(reqBody))
+			if err != nil {
+				return nil, err, false
+			}
+
+			req.Header.Set("Content-Type", "application/json")
+
+			resp, err := h.client.Do(req)
+			if err != nil {
+				retry := h.matchRetry(serviceTaskStateImpl, err.Error())
+				if retry != nil {
+					return nil, err, h.needRetry(serviceTaskStateImpl, retryCountMap, retry, err)
+				}
+				return nil, err, false
+			}
+			defer resp.Body.Close()
+
+			body, err := io.ReadAll(resp.Body)
+			if err != nil {
+				return nil, err, false
+			}
+
+			if resp.StatusCode >= errHttpCode {
+				errStr := fmt.Sprintf("HTTP error: %d - %s", resp.StatusCode, string(body))
+				retry := h.matchRetry(serviceTaskStateImpl, errStr)
+				if retry != nil {
+					return nil, errors.New(errStr), h.needRetry(serviceTaskStateImpl, retryCountMap, retry, err)
+				}
+				return nil, errors.New(errStr), false
+			}
+
+			return []reflect.Value{
+				reflect.ValueOf(string(body)),
+				reflect.Zero(reflect.TypeOf((*error)(nil)).Elem()),
+			}, nil, false
+		}()
+
+		if !shouldRetry {
+			if err != nil {
+				return nil, fmt.Errorf("invoke Service[%s] failed, not satisfy retry config, the last err is %s",
+					serviceTaskStateImpl.ServiceName(), err)
+			}
+			return res, nil
+		}
+	}
+}
+
+func (h *HTTPClientImpl) matchRetry(impl *state.ServiceTaskStateImpl, str string) state.Retry {
+	if impl.Retry() != nil {
+		for _, retry := range impl.Retry() {
+			if retry.Exceptions() != nil {
+				for _, exception := range retry.Exceptions() {
+					if strings.Contains(str, exception) {
+						return retry
+					}
+				}
+			}
+		}
+	}
+	return nil
+}
+
+func (h *HTTPClientImpl) needRetry(impl *state.ServiceTaskStateImpl, countMap map[state.Retry]int, retry state.Retry, err error) bool {
+	attempt, exist := countMap[retry]
+	if !exist {
+		countMap[retry] = 0
+	}
+
+	if attempt >= retry.MaxAttempt() {
+		return false
+	}
+
+	intervalSecond := retry.IntervalSecond()
+	backoffRate := retry.BackoffRate()
+	var currentInterval int64
+	if attempt == 0 {
+		currentInterval = int64(intervalSecond * 1000)
+	} else {
+		currentInterval = int64(intervalSecond * backoffRate * float64(attempt) * 1000)
+	}
+
+	log.Warnf("invoke service[%s.%s] failed, will retry after %s millis, current retry count: %s, current err: %s",
+		impl.ServiceName(), impl.ServiceMethod(), currentInterval, attempt, err)
+
+	time.Sleep(time.Duration(currentInterval) * time.Millisecond)
+	countMap[retry] = attempt + 1
+	return true
+}
diff --git a/pkg/saga/statemachine/engine/invoker/invoker.go b/pkg/saga/statemachine/engine/invoker/invoker.go
index e1dd5dc..e0cb85f 100644
--- a/pkg/saga/statemachine/engine/invoker/invoker.go
+++ b/pkg/saga/statemachine/engine/invoker/invoker.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package invoker
 
 import (
diff --git a/pkg/saga/statemachine/engine/sequence/sequence.go b/pkg/saga/statemachine/engine/sequence/sequence.go
index 1a7fdae..57cb19c 100644
--- a/pkg/saga/statemachine/engine/sequence/sequence.go
+++ b/pkg/saga/statemachine/engine/sequence/sequence.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package sequence
 
 type SeqGenerator interface {
diff --git a/pkg/saga/statemachine/engine/sequence/snowflake.go b/pkg/saga/statemachine/engine/sequence/snowflake.go
index f5622b0..6f64edb 100644
--- a/pkg/saga/statemachine/engine/sequence/snowflake.go
+++ b/pkg/saga/statemachine/engine/sequence/snowflake.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package sequence
 
 import (
diff --git a/pkg/saga/statemachine/engine/sequence/uuid.go b/pkg/saga/statemachine/engine/sequence/uuid.go
index f3060dc..6dfb0c8 100644
--- a/pkg/saga/statemachine/engine/sequence/uuid.go
+++ b/pkg/saga/statemachine/engine/sequence/uuid.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package sequence
 
 import "github.com/google/uuid"
diff --git a/pkg/saga/statemachine/engine/serializer/serializer.go b/pkg/saga/statemachine/engine/serializer/serializer.go
index 4d668ef..3a3ddf0 100644
--- a/pkg/saga/statemachine/engine/serializer/serializer.go
+++ b/pkg/saga/statemachine/engine/serializer/serializer.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package serializer
 
 import (
diff --git a/pkg/saga/statemachine/process_ctrl/handlers/service_task_state_handler.go b/pkg/saga/statemachine/process_ctrl/handlers/service_task_state_handler.go
index 28d60d0..f2a7aff 100644
--- a/pkg/saga/statemachine/process_ctrl/handlers/service_task_state_handler.go
+++ b/pkg/saga/statemachine/process_ctrl/handlers/service_task_state_handler.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package handlers
 
 import (
diff --git a/pkg/saga/statemachine/process_ctrl/process/process_type.go b/pkg/saga/statemachine/process_ctrl/process/process_type.go
index b1a8e03..c67c806 100644
--- a/pkg/saga/statemachine/process_ctrl/process/process_type.go
+++ b/pkg/saga/statemachine/process_ctrl/process/process_type.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package process
 
 type ProcessType string
diff --git a/pkg/saga/statemachine/statelang/parser/choice_state_json_parser.go b/pkg/saga/statemachine/statelang/parser/choice_state_json_parser.go
index 9b4d51c..0910854 100644
--- a/pkg/saga/statemachine/statelang/parser/choice_state_json_parser.go
+++ b/pkg/saga/statemachine/statelang/parser/choice_state_json_parser.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package parser
 
 import (
diff --git a/pkg/saga/statemachine/statelang/parser/compensation_trigger_state_parser.go b/pkg/saga/statemachine/statelang/parser/compensation_trigger_state_parser.go
index d41a6d2..3131da9 100644
--- a/pkg/saga/statemachine/statelang/parser/compensation_trigger_state_parser.go
+++ b/pkg/saga/statemachine/statelang/parser/compensation_trigger_state_parser.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package parser
 
 import (
diff --git a/pkg/saga/statemachine/statelang/parser/end_state_parser.go b/pkg/saga/statemachine/statelang/parser/end_state_parser.go
index 823ee8d..8baa03a 100644
--- a/pkg/saga/statemachine/statelang/parser/end_state_parser.go
+++ b/pkg/saga/statemachine/statelang/parser/end_state_parser.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package parser
 
 import (
diff --git a/pkg/saga/statemachine/statelang/parser/statemachine_config_parser.go b/pkg/saga/statemachine/statelang/parser/statemachine_config_parser.go
new file mode 100644
index 0000000..a33bbde
--- /dev/null
+++ b/pkg/saga/statemachine/statelang/parser/statemachine_config_parser.go
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package parser
+
+import (
+	"bytes"
+	"fmt"
+	"github.com/seata/seata-go/pkg/saga/statemachine"
+	"io"
+	"os"
+
+	"github.com/knadh/koanf"
+	"github.com/knadh/koanf/parsers/json"
+	"github.com/knadh/koanf/parsers/yaml"
+	"github.com/knadh/koanf/providers/rawbytes"
+)
+
+// ConfigParser is a general configuration parser interface, used to agree on the implementation of different types of parsers
+type ConfigParser interface {
+	Parse(configContent []byte) (*statemachine.StateMachineObject, error)
+}
+
+type JSONConfigParser struct{}
+
+func NewJSONConfigParser() *JSONConfigParser {
+	return &JSONConfigParser{}
+}
+
+func (p *JSONConfigParser) Parse(configContent []byte) (*statemachine.StateMachineObject, error) {
+	if configContent == nil || len(configContent) == 0 {
+		return nil, fmt.Errorf("empty JSON config content")
+	}
+
+	k := koanf.New(".")
+	if err := k.Load(rawbytes.Provider(configContent), json.Parser()); err != nil {
+		return nil, fmt.Errorf("failed to parse JSON config content: %w", err)
+	}
+
+	var stateMachineObject statemachine.StateMachineObject
+	if err := k.Unmarshal("", &stateMachineObject); err != nil {
+		return nil, fmt.Errorf("failed to unmarshal JSON config to struct: %w", err)
+	}
+
+	return &stateMachineObject, nil
+}
+
+type YAMLConfigParser struct{}
+
+func NewYAMLConfigParser() *YAMLConfigParser {
+	return &YAMLConfigParser{}
+}
+
+func (p *YAMLConfigParser) Parse(configContent []byte) (*statemachine.StateMachineObject, error) {
+	if configContent == nil || len(configContent) == 0 {
+		return nil, fmt.Errorf("empty YAML config content")
+	}
+
+	k := koanf.New(".")
+	if err := k.Load(rawbytes.Provider(configContent), yaml.Parser()); err != nil {
+		return nil, fmt.Errorf("failed to parse YAML config content: %w", err)
+	}
+
+	var stateMachineObject statemachine.StateMachineObject
+	if err := k.Unmarshal("", &stateMachineObject); err != nil {
+		return nil, fmt.Errorf("failed to unmarshal YAML config to struct: %w", err)
+	}
+
+	return &stateMachineObject, nil
+}
+
+type StateMachineConfigParser struct{}
+
+func NewStateMachineConfigParser() *StateMachineConfigParser {
+	return &StateMachineConfigParser{}
+}
+
+func (p *StateMachineConfigParser) CheckConfigFile(filePath string) error {
+	_, err := os.Stat(filePath)
+	if os.IsNotExist(err) {
+		return fmt.Errorf("config file %s does not exist: %w", filePath, err)
+	}
+	if err != nil {
+		return fmt.Errorf("failed to access config file %s: %w", filePath, err)
+	}
+	return nil
+}
+
+func (p *StateMachineConfigParser) ReadConfigFile(configFilePath string) ([]byte, error) {
+	file, _ := os.Open(configFilePath)
+	defer func(file *os.File) {
+		_ = file.Close()
+	}(file)
+
+	var buf bytes.Buffer
+	_, err := io.Copy(&buf, file)
+	if err != nil {
+		return nil, fmt.Errorf("failed to read config file %s: %w", configFilePath, err)
+	}
+
+	return buf.Bytes(), nil
+}
+
+func (p *StateMachineConfigParser) getParser(content []byte) (ConfigParser, error) {
+	k := koanf.New(".")
+	if err := k.Load(rawbytes.Provider(content), json.Parser()); err == nil {
+		return NewJSONConfigParser(), nil
+	}
+
+	k = koanf.New(".")
+	if err := k.Load(rawbytes.Provider(content), yaml.Parser()); err == nil {
+		return NewYAMLConfigParser(), nil
+	}
+
+	return nil, fmt.Errorf("unsupported config file format")
+}
+
+func (p *StateMachineConfigParser) Parse(content []byte) (*statemachine.StateMachineObject, error) {
+	parser, err := p.getParser(content)
+	if err != nil {
+		return nil, err
+	}
+
+	return parser.Parse(content)
+}
diff --git a/pkg/saga/statemachine/statelang/parser/statemachine_json_parser.go b/pkg/saga/statemachine/statelang/parser/statemachine_json_parser.go
index 4bcfdcb..37ceaae 100644
--- a/pkg/saga/statemachine/statelang/parser/statemachine_json_parser.go
+++ b/pkg/saga/statemachine/statelang/parser/statemachine_json_parser.go
@@ -1,7 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package parser
 
 import (
-	"encoding/json"
 	"github.com/pkg/errors"
 	"github.com/seata/seata-go/pkg/saga/statemachine/constant"
 	"github.com/seata/seata-go/pkg/saga/statemachine/statelang"
@@ -23,9 +39,7 @@ func (stateMachineParser JSONStateMachineParser) GetType() string {
 }
 
 func (stateMachineParser JSONStateMachineParser) Parse(content string) (statelang.StateMachine, error) {
-	var stateMachineJsonObject StateMachineJsonObject
-
-	err := json.Unmarshal([]byte(content), &stateMachineJsonObject)
+	stateMachineJsonObject, err := NewStateMachineConfigParser().Parse([]byte(content))
 	if err != nil {
 		return nil, err
 	}
@@ -92,14 +106,13 @@ func (stateMachineParser JSONStateMachineParser) Parse(content string) (statelan
 }
 
 func (stateMachineParser JSONStateMachineParser) setForCompensation(stateValue statelang.State, stateMachine *statelang.StateMachineImpl) {
-	switch stateValue.Type() {
-	case stateValue.Type():
+	if stateValue.Type() == constant.StateTypeServiceTask {
 		serviceTaskStateImpl, ok := stateValue.(*state.ServiceTaskStateImpl)
 		if ok {
 			if serviceTaskStateImpl.CompensateState() != "" {
 				compState := stateMachine.States()[serviceTaskStateImpl.CompensateState()]
 				if stateMachineParser.isTaskState(compState.Type()) {
-					compStateImpl, ok := compState.(state.ServiceTaskStateImpl)
+					compStateImpl, ok := compState.(*state.ServiceTaskStateImpl)
 					if ok {
 						compStateImpl.SetForCompensation(true)
 					}
@@ -115,16 +128,3 @@ func (stateMachineParser JSONStateMachineParser) isTaskState(stateType string) b
 	}
 	return false
 }
-
-type StateMachineJsonObject struct {
-	Name                        string                 `json:"Name"`
-	Comment                     string                 `json:"Comment"`
-	Version                     string                 `json:"Version"`
-	StartState                  string                 `json:"StartState"`
-	RecoverStrategy             string                 `json:"RecoverStrategy"`
-	Persist                     bool                   `json:"IsPersist"`
-	RetryPersistModeUpdate      bool                   `json:"IsRetryPersistModeUpdate"`
-	CompensatePersistModeUpdate bool                   `json:"IsCompensatePersistModeUpdate"`
-	Type                        string                 `json:"Type"`
-	States                      map[string]interface{} `json:"States"`
-}
diff --git a/pkg/saga/statemachine/statelang/parser/statemachine_parser.go b/pkg/saga/statemachine/statelang/parser/statemachine_parser.go
index 690ad27..883d28e 100644
--- a/pkg/saga/statemachine/statelang/parser/statemachine_parser.go
+++ b/pkg/saga/statemachine/statelang/parser/statemachine_parser.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package parser
 
 import (
@@ -148,18 +165,23 @@ func (b BaseStateParser) GetIntOrDefault(stateName string, stateMap map[string]i
 		return defaultValue, nil
 	}
 
-	// just use float64 to convert, json reader will read all number as float64
-	valueAsFloat64, ok := value.(float64)
-	if !ok {
+	// use float64 conversion when the configuration file is json, and use int conversion when the configuration file is yaml
+	valueAsFloat64, okToFloat64 := value.(float64)
+	valueAsInt, okToInt := value.(int)
+	if !okToFloat64 && !okToInt {
 		return defaultValue, errors.New("State [" + stateName + "] " + key + " illegal, required int")
 	}
 
-	floatStr := strconv.FormatFloat(valueAsFloat64, 'f', -1, 64)
-	if strings.Contains(floatStr, ".") {
-		return defaultValue, errors.New("State [" + stateName + "] " + key + " illegal, required int")
+	if okToFloat64 {
+		floatStr := strconv.FormatFloat(valueAsFloat64, 'f', -1, 64)
+		if strings.Contains(floatStr, ".") {
+			return defaultValue, errors.New("State [" + stateName + "] " + key + " illegal, required int")
+		}
+
+		return int(valueAsFloat64), nil
 	}
 
-	return int(valueAsFloat64), nil
+	return valueAsInt, nil
 }
 
 func (b BaseStateParser) GetFloat64OrDefault(stateName string, stateMap map[string]interface{}, key string, defaultValue float64) (float64, error) {
@@ -169,11 +191,17 @@ func (b BaseStateParser) GetFloat64OrDefault(stateName string, stateMap map[stri
 		return defaultValue, nil
 	}
 
-	valueAsFloat64, ok := value.(float64)
-	if !ok {
+	// use float64 conversion when the configuration file is json, and use int conversion when the configuration file is yaml
+	valueAsFloat64, okToFloat64 := value.(float64)
+	valueAsInt, okToInt := value.(int)
+	if !okToFloat64 && !okToInt {
 		return defaultValue, errors.New("State [" + stateName + "] " + key + " illegal, required float64")
 	}
-	return valueAsFloat64, nil
+
+	if okToFloat64 {
+		return valueAsFloat64, nil
+	}
+	return float64(valueAsInt), nil
 }
 
 type StateParserFactory interface {
diff --git a/pkg/saga/statemachine/statelang/parser/sub_state_machine_parser.go b/pkg/saga/statemachine/statelang/parser/sub_state_machine_parser.go
index 4de6e5d..5938e5e 100644
--- a/pkg/saga/statemachine/statelang/parser/sub_state_machine_parser.go
+++ b/pkg/saga/statemachine/statelang/parser/sub_state_machine_parser.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package parser
 
 import (
diff --git a/pkg/saga/statemachine/statelang/parser/task_state_json_parser.go b/pkg/saga/statemachine/statelang/parser/task_state_json_parser.go
index 8dcfff5..3c9bff0 100644
--- a/pkg/saga/statemachine/statelang/parser/task_state_json_parser.go
+++ b/pkg/saga/statemachine/statelang/parser/task_state_json_parser.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package parser
 
 import (
@@ -242,7 +259,7 @@ func (s ServiceTaskStateParser) Parse(stateName string, stateMap map[string]inte
 		return nil, err
 	}
 
-	serviceName, err := s.GetString(stateName, stateMap, "serviceName")
+	serviceName, err := s.GetString(stateName, stateMap, "ServiceName")
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/saga/statemachine/statelang/state.go b/pkg/saga/statemachine/statelang/state.go
index 29ac672..f53449c 100644
--- a/pkg/saga/statemachine/statelang/state.go
+++ b/pkg/saga/statemachine/statelang/state.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package statelang
 
 type State interface {
diff --git a/pkg/saga/statemachine/statelang/state/choice_state.go b/pkg/saga/statemachine/statelang/state/choice_state.go
index c3f4827..2226404 100644
--- a/pkg/saga/statemachine/statelang/state/choice_state.go
+++ b/pkg/saga/statemachine/statelang/state/choice_state.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package state
 
 import "github.com/seata/seata-go/pkg/saga/statemachine/statelang"
diff --git a/pkg/saga/statemachine/statelang/state/compensation_trigger_state.go b/pkg/saga/statemachine/statelang/state/compensation_trigger_state.go
index cac7142..922b380 100644
--- a/pkg/saga/statemachine/statelang/state/compensation_trigger_state.go
+++ b/pkg/saga/statemachine/statelang/state/compensation_trigger_state.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package state
 
 import (
diff --git a/pkg/saga/statemachine/statelang/state/end_state.go b/pkg/saga/statemachine/statelang/state/end_state.go
index 099e2e0..3e1c203 100644
--- a/pkg/saga/statemachine/statelang/state/end_state.go
+++ b/pkg/saga/statemachine/statelang/state/end_state.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package state
 
 import (
diff --git a/pkg/saga/statemachine/statelang/state/loop_start_state.go b/pkg/saga/statemachine/statelang/state/loop_start_state.go
index e059431..91d604a 100644
--- a/pkg/saga/statemachine/statelang/state/loop_start_state.go
+++ b/pkg/saga/statemachine/statelang/state/loop_start_state.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package state
 
 import (
diff --git a/pkg/saga/statemachine/statelang/state/sub_state_machine.go b/pkg/saga/statemachine/statelang/state/sub_state_machine.go
index 78683a0..e18fc0e 100644
--- a/pkg/saga/statemachine/statelang/state/sub_state_machine.go
+++ b/pkg/saga/statemachine/statelang/state/sub_state_machine.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package state
 
 import (
diff --git a/pkg/saga/statemachine/statelang/state/task_state.go b/pkg/saga/statemachine/statelang/state/task_state.go
index bc9880a..a258a28 100644
--- a/pkg/saga/statemachine/statelang/state/task_state.go
+++ b/pkg/saga/statemachine/statelang/state/task_state.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package state
 
 import (
diff --git a/pkg/saga/statemachine/statelang/state_instance.go b/pkg/saga/statemachine/statelang/state_instance.go
index e77da05..5248d03 100644
--- a/pkg/saga/statemachine/statelang/state_instance.go
+++ b/pkg/saga/statemachine/statelang/state_instance.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package statelang
 
 import "time"
diff --git a/pkg/saga/statemachine/statelang/statemachine.go b/pkg/saga/statemachine/statelang/statemachine.go
index 8b13f8d..0e7dfff 100644
--- a/pkg/saga/statemachine/statelang/statemachine.go
+++ b/pkg/saga/statemachine/statelang/statemachine.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package statelang
 
 import (
diff --git a/pkg/saga/statemachine/statelang/statemachine_instance.go b/pkg/saga/statemachine/statelang/statemachine_instance.go
index 9da71ee..b794e10 100644
--- a/pkg/saga/statemachine/statelang/statemachine_instance.go
+++ b/pkg/saga/statemachine/statelang/statemachine_instance.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package statelang
 
 import (
diff --git a/pkg/saga/statemachine/statemachine.go b/pkg/saga/statemachine/statemachine.go
new file mode 100644
index 0000000..087f212
--- /dev/null
+++ b/pkg/saga/statemachine/statemachine.go
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package statemachine
+
+import (
+	"flag"
+)
+
+type StateMachineObject struct {
+	Name                        string                 `json:"Name" yaml:"Name"`
+	Comment                     string                 `json:"Comment" yaml:"Comment"`
+	Version                     string                 `json:"Version" yaml:"Version"`
+	StartState                  string                 `json:"StartState" yaml:"StartState"`
+	RecoverStrategy             string                 `json:"RecoverStrategy" yaml:"RecoverStrategy"`
+	Persist                     bool                   `json:"IsPersist" yaml:"IsPersist"`
+	RetryPersistModeUpdate      bool                   `json:"IsRetryPersistModeUpdate" yaml:"IsRetryPersistModeUpdate"`
+	CompensatePersistModeUpdate bool                   `json:"IsCompensatePersistModeUpdate" yaml:"IsCompensatePersistModeUpdate"`
+	Type                        string                 `json:"Type" yaml:"Type"`
+	States                      map[string]interface{} `json:"States" yaml:"States"`
+}
+
+func (smo *StateMachineObject) RegisterFlagsWithPrefix(prefix string, f *flag.FlagSet) {
+	f.StringVar(&smo.Name, prefix+".name", "", "State machine name.")
+	f.StringVar(&smo.Comment, prefix+".comment", "", "State machine comment.")
+	f.StringVar(&smo.Version, prefix+".version", "1.0", "State machine version.")
+	f.StringVar(&smo.StartState, prefix+".start-state", "", "State machine start state.")
+	f.StringVar(&smo.RecoverStrategy, prefix+".recover-strategy", "", "State machine recovery strategy.")
+	f.BoolVar(&smo.Persist, prefix+".persist", false, "Whether to persist state machine.")
+	f.BoolVar(&smo.RetryPersistModeUpdate, prefix+".retry-persist-mode-update", false, "Whether to use update mode for retry persistence.")
+	f.BoolVar(&smo.CompensatePersistModeUpdate, prefix+".compensate-persist-mode-update", false, "Whether to use update mode for compensate persistence.")
+	f.StringVar(&smo.Type, prefix+".type", "", "State machine type.")
+}
diff --git a/pkg/saga/statemachine/store/db/db.go b/pkg/saga/statemachine/store/db/db.go
index 39d62e9..aba2c66 100644
--- a/pkg/saga/statemachine/store/db/db.go
+++ b/pkg/saga/statemachine/store/db/db.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package db
 
 import (
diff --git a/pkg/saga/statemachine/store/db/statelang.go b/pkg/saga/statemachine/store/db/statelang.go
index e49bf96..f0c25e3 100644
--- a/pkg/saga/statemachine/store/db/statelang.go
+++ b/pkg/saga/statemachine/store/db/statelang.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package db
 
 import (
diff --git a/pkg/saga/statemachine/store/db/statelog.go b/pkg/saga/statemachine/store/db/statelog.go
index 23c3b55..ba60c61 100644
--- a/pkg/saga/statemachine/store/db/statelog.go
+++ b/pkg/saga/statemachine/store/db/statelog.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package db
 
 import (
diff --git a/pkg/saga/statemachine/store/repository/state_machine_repository.go b/pkg/saga/statemachine/store/repository/state_machine_repository.go
index 8a62cc4..ea37171 100644
--- a/pkg/saga/statemachine/store/repository/state_machine_repository.go
+++ b/pkg/saga/statemachine/store/repository/state_machine_repository.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package repository
 
 import (
diff --git a/pkg/util/reflectx/unmarkshaler.go b/pkg/util/reflectx/unmarkshaler.go
index 73acb27..a507a3a 100644
--- a/pkg/util/reflectx/unmarkshaler.go
+++ b/pkg/util/reflectx/unmarkshaler.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package reflectx
 
 import (



Test patch:
diff --git a/pkg/saga/statemachine/engine/core/statemachine_engine_test.go b/pkg/saga/statemachine/engine/core/statemachine_engine_test.go
index e87eb9c..8af2cdf 100644
--- a/pkg/saga/statemachine/engine/core/statemachine_engine_test.go
+++ b/pkg/saga/statemachine/engine/core/statemachine_engine_test.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package core
 
 import (
diff --git a/pkg/saga/statemachine/engine/invoker/func_invoker_test.go b/pkg/saga/statemachine/engine/invoker/func_invoker_test.go
index e800fdc..9a97427 100644
--- a/pkg/saga/statemachine/engine/invoker/func_invoker_test.go
+++ b/pkg/saga/statemachine/engine/invoker/func_invoker_test.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package invoker
 
 import (
diff --git a/pkg/saga/statemachine/engine/invoker/grpc_invoker_test.go b/pkg/saga/statemachine/engine/invoker/grpc_invoker_test.go
index 09d6745..4beb0d1 100644
--- a/pkg/saga/statemachine/engine/invoker/grpc_invoker_test.go
+++ b/pkg/saga/statemachine/engine/invoker/grpc_invoker_test.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package invoker
 
 import (
diff --git a/pkg/saga/statemachine/engine/invoker/http_invoker_test.go b/pkg/saga/statemachine/engine/invoker/http_invoker_test.go
new file mode 100644
index 0000000..062aac0
--- /dev/null
+++ b/pkg/saga/statemachine/engine/invoker/http_invoker_test.go
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package invoker
+
+import (
+	"context"
+	"encoding/json"
+	"net/http"
+	"net/http/httptest"
+	"testing"
+	"time"
+
+	"github.com/seata/seata-go/pkg/saga/statemachine/statelang/state"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestHTTPInvokerInvokeSucceedWithOutRetry(t *testing.T) {
+	// create test server
+	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		var input []interface{}
+		err := json.NewDecoder(r.Body).Decode(&input)
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusBadRequest)
+			return
+		}
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte(input[0].(string)))
+	}))
+	defer server.Close()
+
+	// create HTTP Invoker
+	invoker := NewHTTPInvoker()
+	client := NewHTTPClient("test", server.URL+"/", &http.Client{})
+	invoker.RegisterClient("test", client)
+
+	// invoke
+	ctx := context.Background()
+	values, err := invoker.Invoke(ctx, []any{"hello"}, newHTTPServiceTaskState())
+
+	// verify
+	assert.NoError(t, err)
+	assert.NotNil(t, values)
+	assert.Equal(t, "hello", values[0].Interface())
+}
+
+func TestHTTPInvokerInvokeWithRetry(t *testing.T) {
+	attemptCount := 0
+	// create test server
+	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		attemptCount++
+		if attemptCount < 2 {
+			w.WriteHeader(http.StatusInternalServerError)
+			w.Write([]byte("fail"))
+			return
+		}
+		var input []interface{}
+		json.NewDecoder(r.Body).Decode(&input)
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte(input[0].(string)))
+	}))
+	defer server.Close()
+
+	// create HTTP Invoker
+	invoker := NewHTTPInvoker()
+	client := NewHTTPClient("test", server.URL+"/", &http.Client{})
+	invoker.RegisterClient("test", client)
+
+	// invoker
+	ctx := context.Background()
+	values, err := invoker.Invoke(ctx, []any{"hello"}, newHTTPServiceTaskStateWithRetry())
+
+	// verify
+	assert.NoError(t, err)
+	assert.NotNil(t, values)
+	assert.Equal(t, "hello", values[0].Interface())
+	assert.Equal(t, 2, attemptCount)
+}
+
+func TestHTTPInvokerInvokeFailedInRetry(t *testing.T) {
+	// create test server
+	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		w.WriteHeader(http.StatusInternalServerError)
+		w.Write([]byte("fail"))
+	}))
+	defer server.Close()
+
+	// create HTTP Invoker
+	invoker := NewHTTPInvoker()
+	client := NewHTTPClient("test", server.URL+"/", &http.Client{})
+	invoker.RegisterClient("test", client)
+
+	// invoker
+	ctx := context.Background()
+	_, err := invoker.Invoke(ctx, []any{"hello"}, newHTTPServiceTaskStateWithRetry())
+
+	// verify
+	assert.Error(t, err)
+}
+
+func TestHTTPInvokerAsyncInvoke(t *testing.T) {
+	called := false
+	// create test server
+	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+		called = true
+		w.WriteHeader(http.StatusOK)
+		w.Write([]byte("success"))
+	}))
+	defer server.Close()
+
+	// create HTTP Invoker
+	invoker := NewHTTPInvoker()
+	client := NewHTTPClient("test", server.URL+"/", &http.Client{})
+	invoker.RegisterClient("test", client)
+
+	// async invoke
+	ctx := context.Background()
+	taskState := newHTTPServiceTaskStateWithAsync()
+	_, err := invoker.Invoke(ctx, []any{"hello"}, taskState)
+
+	// verify
+	assert.NoError(t, err)
+	time.Sleep(100 * time.Millisecond)
+	assert.True(t, called)
+}
+
+func newHTTPServiceTaskState() state.ServiceTaskState {
+	serviceTaskStateImpl := state.NewServiceTaskStateImpl()
+	serviceTaskStateImpl.SetName("test")
+	serviceTaskStateImpl.SetIsAsync(false)
+	serviceTaskStateImpl.SetServiceName("test")
+	serviceTaskStateImpl.SetServiceType("HTTP")
+	serviceTaskStateImpl.SetServiceMethod("POST")
+	return serviceTaskStateImpl
+}
+
+func newHTTPServiceTaskStateWithAsync() state.ServiceTaskState {
+	serviceTaskStateImpl := state.NewServiceTaskStateImpl()
+	serviceTaskStateImpl.SetName("test")
+	serviceTaskStateImpl.SetIsAsync(true)
+	serviceTaskStateImpl.SetServiceName("test")
+	serviceTaskStateImpl.SetServiceType("HTTP")
+	serviceTaskStateImpl.SetServiceMethod("POST")
+	return serviceTaskStateImpl
+}
+
+func newHTTPServiceTaskStateWithRetry() state.ServiceTaskState {
+	serviceTaskStateImpl := state.NewServiceTaskStateImpl()
+	serviceTaskStateImpl.SetName("test")
+	serviceTaskStateImpl.SetIsAsync(false)
+	serviceTaskStateImpl.SetServiceName("test")
+	serviceTaskStateImpl.SetServiceType("HTTP")
+	serviceTaskStateImpl.SetServiceMethod("POST")
+
+	retryImpl := &state.RetryImpl{}
+	retryImpl.SetExceptions([]string{"fail"})
+	retryImpl.SetIntervalSecond(1)
+	retryImpl.SetMaxAttempt(3)
+	retryImpl.SetBackoffRate(0.9)
+	serviceTaskStateImpl.SetRetry([]state.Retry{retryImpl})
+	return serviceTaskStateImpl
+}
diff --git a/pkg/saga/statemachine/engine/sequence/snowflake_test.go b/pkg/saga/statemachine/engine/sequence/snowflake_test.go
index 451f478..9c6a96a 100644
--- a/pkg/saga/statemachine/engine/sequence/snowflake_test.go
+++ b/pkg/saga/statemachine/engine/sequence/snowflake_test.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package sequence
 
 import (
diff --git a/pkg/saga/statemachine/engine/serializer/serializer_test.go b/pkg/saga/statemachine/engine/serializer/serializer_test.go
index 9dba88a..eb16336 100644
--- a/pkg/saga/statemachine/engine/serializer/serializer_test.go
+++ b/pkg/saga/statemachine/engine/serializer/serializer_test.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package serializer
 
 import (
diff --git a/pkg/saga/statemachine/statelang/parser/statemachine_config_parser_test.go b/pkg/saga/statemachine/statelang/parser/statemachine_config_parser_test.go
new file mode 100644
index 0000000..e634fc2
--- /dev/null
+++ b/pkg/saga/statemachine/statelang/parser/statemachine_config_parser_test.go
@@ -0,0 +1,882 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package parser
+
+import (
+	"github.com/seata/seata-go/pkg/saga/statemachine"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestStateMachineConfigParser_Parse(t *testing.T) {
+	parser := NewStateMachineConfigParser()
+
+	tests := []struct {
+		name           string
+		configFilePath string
+		expectedObject *statemachine.StateMachineObject
+	}{
+		{
+			name:           "JSON Simple 1",
+			configFilePath: "../../../../../testdata/saga/statelang/simple_statelang_with_choice.json",
+			expectedObject: GetStateMachineObject1("json"),
+		},
+		{
+			name:           "JSON Simple 2",
+			configFilePath: "../../../../../testdata/saga/statelang/simple_statemachine.json",
+			expectedObject: GetStateMachineObject2("json"),
+		},
+		{
+			name:           "JSON Simple 3",
+			configFilePath: "../../../../../testdata/saga/statelang/state_machine_new_designer.json",
+			expectedObject: GetStateMachineObject3("json"),
+		},
+		{
+			name:           "YAML Simple 1",
+			configFilePath: "../../../../../testdata/saga/statelang/simple_statelang_with_choice.yaml",
+			expectedObject: GetStateMachineObject1("yaml"),
+		},
+		{
+			name:           "YAML Simple 2",
+			configFilePath: "../../../../../testdata/saga/statelang/simple_statemachine.yaml",
+			expectedObject: GetStateMachineObject2("yaml"),
+		},
+		{
+			name:           "YAML Simple 3",
+			configFilePath: "../../../../../testdata/saga/statelang/state_machine_new_designer.yaml",
+			expectedObject: GetStateMachineObject3("yaml"),
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			content, err := parser.ReadConfigFile(tt.configFilePath)
+			if err != nil {
+				t.Error("parse fail: " + err.Error())
+			}
+			object, err := parser.Parse(content)
+			if err != nil {
+				t.Error("parse fail: " + err.Error())
+			}
+			assert.Equal(t, tt.expectedObject, object)
+		})
+	}
+}
+
+func GetStateMachineObject1(format string) *statemachine.StateMachineObject {
+	switch format {
+	case "json":
+	case "yaml":
+	}
+
+	return &statemachine.StateMachineObject{
+		Name:       "simpleChoiceTestStateMachine",
+		Comment:    "带条件分支的测试状态机定义",
+		StartState: "FirstState",
+		Version:    "0.0.1",
+		States: map[string]interface{}{
+			"FirstState": map[string]interface{}{
+				"Type":          "ServiceTask",
+				"ServiceName":   "demoService",
+				"ServiceMethod": "foo",
+				"Next":          "ChoiceState",
+			},
+			"ChoiceState": map[string]interface{}{
+				"Type": "Choice",
+				"Choices": []interface{}{
+					map[string]interface{}{
+						"Expression": "[a] == 1",
+						"Next":       "SecondState",
+					},
+					map[string]interface{}{
+						"Expression": "[a] == 2",
+						"Next":       "ThirdState",
+					},
+				},
+				"Default": "SecondState",
+			},
+			"SecondState": map[string]interface{}{
+				"Type":          "ServiceTask",
+				"ServiceName":   "demoService",
+				"ServiceMethod": "bar",
+			},
+			"ThirdState": map[string]interface{}{
+				"Type":          "ServiceTask",
+				"ServiceName":   "demoService",
+				"ServiceMethod": "foo",
+			},
+		},
+	}
+}
+
+func GetStateMachineObject2(format string) *statemachine.StateMachineObject {
+	var retryMap map[string]interface{}
+
+	switch format {
+	case "json":
+		retryMap = map[string]interface{}{
+			"Exceptions": []interface{}{
+				"java.lang.Exception",
+			},
+			"IntervalSeconds": float64(2),
+			"MaxAttempts":     float64(3),
+			"BackoffRate":     1.5,
+		}
+	case "yaml":
+		retryMap = map[string]interface{}{
+			"Exceptions": []interface{}{
+				"java.lang.Exception",
+			},
+			"IntervalSeconds": 2,
+			"MaxAttempts":     3,
+			"BackoffRate":     1.5,
+		}
+	}
+
+	return &statemachine.StateMachineObject{
+		Name:       "simpleTestStateMachine",
+		Comment:    "测试状态机定义",
+		StartState: "FirstState",
+		Version:    "0.0.1",
+		States: map[string]interface{}{
+			"FirstState": map[string]interface{}{
+				"Type":          "ServiceTask",
+				"ServiceName":   "is.seata.saga.DemoService",
+				"ServiceMethod": "foo",
+				"IsPersist":     false,
+				"Next":          "ScriptState",
+			},
+			"ScriptState": map[string]interface{}{
+				"Type":          "ScriptTask",
+				"ScriptType":    "groovy",
+				"ScriptContent": "return 'hello ' + inputA",
+				"Input": []interface{}{
+					map[string]interface{}{
+						"inputA": "$.data1",
+					},
+				},
+				"Output": map[string]interface{}{
+					"scriptStateResult": "$.#root",
+				},
+				"Next": "ChoiceState",
+			},
+			"ChoiceState": map[string]interface{}{
+				"Type": "Choice",
+				"Choices": []interface{}{
+					map[string]interface{}{
+						"Expression": "foo == 1",
+						"Next":       "FirstMatchState",
+					},
+					map[string]interface{}{
+						"Expression": "foo == 2",
+						"Next":       "SecondMatchState",
+					},
+				},
+				"Default": "FailState",
+			},
+			"FirstMatchState": map[string]interface{}{
+				"Type":            "ServiceTask",
+				"ServiceName":     "is.seata.saga.DemoService",
+				"ServiceMethod":   "bar",
+				"CompensateState": "CompensateFirst",
+				"Status": map[string]interface{}{
+					"return.code == 'S'":              "SU",
+					"return.code == 'F'":              "FA",
+					"$exception{java.lang.Throwable}": "UN",
+				},
+				"Input": []interface{}{
+					map[string]interface{}{
+						"inputA1": "$.data1",
+						"inputA2": map[string]interface{}{
+							"a": "$.data2.a",
+						},
+					},
+					map[string]interface{}{
+						"inputB": "$.header",
+					},
+				},
+				"Output": map[string]interface{}{
+					"firstMatchStateResult": "$.#root",
+				},
+				"Retry": []interface{}{
+					retryMap,
+				},
+				"Catch": []interface{}{
+					map[string]interface{}{
+						"Exceptions": []interface{}{
+							"java.lang.Exception",
+						},
+						"Next": "CompensationTrigger",
+					},
+				},
+				"Next": "SuccessState",
+			},
+			"CompensateFirst": map[string]interface{}{
+				"Type":              "ServiceTask",
+				"ServiceName":       "is.seata.saga.DemoService",
+				"ServiceMethod":     "compensateBar",
+				"IsForCompensation": true,
+				"IsForUpdate":       true,
+				"Input": []interface{}{
+					map[string]interface{}{
+						"input": "$.data",
+					},
+				},
+				"Output": map[string]interface{}{
+					"firstMatchStateResult": "$.#root",
+				},
+				"Status": map[string]interface{}{
+					"return.code == 'S'":              "SU",
+					"return.code == 'F'":              "FA",
+					"$exception{java.lang.Throwable}": "UN",
+				},
+			},
+			"CompensationTrigger": map[string]interface{}{
+				"Type": "CompensationTrigger",
+				"Next": "CompensateEndState",
+			},
+			"CompensateEndState": map[string]interface{}{
+				"Type":      "Fail",
+				"ErrorCode": "StateCompensated",
+				"Message":   "State Compensated!",
+			},
+			"SecondMatchState": map[string]interface{}{
+				"Type":             "SubStateMachine",
+				"StateMachineName": "simpleTestSubStateMachine",
+				"Input": []interface{}{
+					map[string]interface{}{
+						"input": "$.data",
+					},
+					map[string]interface{}{
+						"header": "$.header",
+					},
+				},
+				"Output": map[string]interface{}{
+					"firstMatchStateResult": "$.#root",
+				},
+				"Next": "SuccessState",
+			},
+			"FailState": map[string]interface{}{
+				"Type":      "Fail",
+				"ErrorCode": "DefaultStateError",
+				"Message":   "No Matches!",
+			},
+			"SuccessState": map[string]interface{}{
+				"Type": "Succeed",
+			},
+		},
+	}
+}
+
+func GetStateMachineObject3(format string) *statemachine.StateMachineObject {
+	var (
+		boundsMap1 map[string]interface{}
+		boundsMap2 map[string]interface{}
+		boundsMap3 map[string]interface{}
+		boundsMap4 map[string]interface{}
+		boundsMap5 map[string]interface{}
+		boundsMap6 map[string]interface{}
+		boundsMap7 map[string]interface{}
+		boundsMap8 map[string]interface{}
+		boundsMap9 map[string]interface{}
+
+		waypoints1 []interface{}
+		waypoints2 []interface{}
+		waypoints3 []interface{}
+		waypoints4 []interface{}
+		waypoints5 []interface{}
+		waypoints6 []interface{}
+		waypoints7 []interface{}
+	)
+
+	switch format {
+	case "json":
+		boundsMap1 = map[string]interface{}{
+			"x":      float64(300),
+			"y":      float64(178),
+			"width":  float64(100),
+			"height": float64(80),
+		}
+		boundsMap2 = map[string]interface{}{
+			"x":      float64(455),
+			"y":      float64(193),
+			"width":  float64(50),
+			"height": float64(50),
+		}
+		boundsMap3 = map[string]interface{}{
+			"x":      float64(300),
+			"y":      float64(310),
+			"width":  float64(100),
+			"height": float64(80),
+		}
+		boundsMap4 = map[string]interface{}{
+			"x":      float64(550),
+			"y":      float64(178),
+			"width":  float64(100),
+			"height": float64(80),
+		}
+		boundsMap5 = map[string]interface{}{
+			"x":      float64(550),
+			"y":      float64(310),
+			"width":  float64(100),
+			"height": float64(80),
+		}
+		boundsMap6 = map[string]interface{}{
+			"x":      float64(632),
+			"y":      float64(372),
+			"width":  float64(36),
+			"height": float64(36),
+		}
+		boundsMap7 = map[string]interface{}{
+			"x":      float64(722),
+			"y":      float64(200),
+			"width":  float64(36),
+			"height": float64(36),
+		}
+		boundsMap8 = map[string]interface{}{
+			"x":      float64(722),
+			"y":      float64(372),
+			"width":  float64(36),
+			"height": float64(36),
+		}
+		boundsMap9 = map[string]interface{}{
+			"x":      float64(812),
+			"y":      float64(372),
+			"width":  float64(36),
+			"height": float64(36),
+		}
+
+		waypoints1 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(400),
+					"y": float64(218),
+				},
+				"x": float64(400),
+				"y": float64(218),
+			},
+			map[string]interface{}{"x": float64(435), "y": float64(218)},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(455),
+					"y": float64(218),
+				},
+				"x": float64(455),
+				"y": float64(218),
+			},
+		}
+		waypoints2 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(505),
+					"y": float64(218),
+				},
+				"x": float64(505),
+				"y": float64(218),
+			},
+			map[string]interface{}{"x": float64(530), "y": float64(218)},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(550),
+					"y": float64(218),
+				},
+				"x": float64(550),
+				"y": float64(218),
+			},
+		}
+		waypoints3 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(480),
+					"y": float64(243),
+				},
+				"x": float64(480),
+				"y": float64(243),
+			},
+			map[string]interface{}{"x": float64(600), "y": float64(290)},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(600),
+					"y": float64(310),
+				},
+				"x": float64(600),
+				"y": float64(310),
+			},
+		}
+		waypoints4 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(650),
+					"y": float64(218),
+				},
+				"x": float64(650),
+				"y": float64(218),
+			},
+			map[string]interface{}{"x": float64(702), "y": float64(218)},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(722),
+					"y": float64(218),
+				},
+				"x": float64(722),
+				"y": float64(218),
+			},
+		}
+		waypoints5 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(668),
+					"y": float64(390),
+				},
+				"x": float64(668),
+				"y": float64(390),
+			},
+			map[string]interface{}{"x": float64(702), "y": float64(390)},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(722),
+					"y": float64(390),
+				},
+				"x": float64(722),
+				"y": float64(390),
+			},
+		}
+		waypoints6 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(600),
+					"y": float64(310),
+				},
+				"x": float64(600),
+				"y": float64(310),
+			},
+			map[string]interface{}{"x": float64(740), "y": float64(256)},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(740),
+					"y": float64(236),
+				},
+				"x": float64(740),
+				"y": float64(236),
+			},
+		}
+		waypoints7 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(758),
+					"y": float64(390),
+				},
+				"x": float64(758),
+				"y": float64(390),
+			},
+			map[string]interface{}{"x": float64(792), "y": float64(390)},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": float64(812),
+					"y": float64(390),
+				},
+				"x": float64(812),
+				"y": float64(390),
+			},
+		}
+
+	case "yaml":
+		boundsMap1 = map[string]interface{}{
+			"x":      300,
+			"y":      178,
+			"width":  100,
+			"height": 80,
+		}
+		boundsMap2 = map[string]interface{}{
+			"x":      455,
+			"y":      193,
+			"width":  50,
+			"height": 50,
+		}
+		boundsMap3 = map[string]interface{}{
+			"x":      300,
+			"y":      310,
+			"width":  100,
+			"height": 80,
+		}
+		boundsMap4 = map[string]interface{}{
+			"x":      550,
+			"y":      178,
+			"width":  100,
+			"height": 80,
+		}
+		boundsMap5 = map[string]interface{}{
+			"x":      550,
+			"y":      310,
+			"width":  100,
+			"height": 80,
+		}
+		boundsMap6 = map[string]interface{}{
+			"x":      632,
+			"y":      372,
+			"width":  36,
+			"height": 36,
+		}
+		boundsMap7 = map[string]interface{}{
+			"x":      722,
+			"y":      200,
+			"width":  36,
+			"height": 36,
+		}
+		boundsMap8 = map[string]interface{}{
+			"x":      722,
+			"y":      372,
+			"width":  36,
+			"height": 36,
+		}
+		boundsMap9 = map[string]interface{}{
+			"x":      812,
+			"y":      372,
+			"width":  36,
+			"height": 36,
+		}
+
+		waypoints1 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 400,
+					"y": 218,
+				},
+				"x": 400,
+				"y": 218,
+			},
+			map[string]interface{}{"x": 435, "y": 218},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 455,
+					"y": 218,
+				},
+				"x": 455,
+				"y": 218,
+			},
+		}
+		waypoints2 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 505,
+					"y": 218,
+				},
+				"x": 505,
+				"y": 218,
+			},
+			map[string]interface{}{"x": 530, "y": 218},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 550,
+					"y": 218,
+				},
+				"x": 550,
+				"y": 218,
+			},
+		}
+		waypoints3 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 480,
+					"y": 243,
+				},
+				"x": 480,
+				"y": 243,
+			},
+			map[string]interface{}{"x": 600, "y": 290},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 600,
+					"y": 310,
+				},
+				"x": 600,
+				"y": 310,
+			},
+		}
+		waypoints4 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 650,
+					"y": 218,
+				},
+				"x": 650,
+				"y": 218,
+			},
+			map[string]interface{}{"x": 702, "y": 218},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 722,
+					"y": 218,
+				},
+				"x": 722,
+				"y": 218,
+			},
+		}
+		waypoints5 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 668,
+					"y": 390,
+				},
+				"x": 668,
+				"y": 390,
+			},
+			map[string]interface{}{"x": 702, "y": 390},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 722,
+					"y": 390,
+				},
+				"x": 722,
+				"y": 390,
+			},
+		}
+		waypoints6 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 600,
+					"y": 310,
+				},
+				"x": 600,
+				"y": 310,
+			},
+			map[string]interface{}{"x": 740, "y": 256},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 740,
+					"y": 236,
+				},
+				"x": 740,
+				"y": 236,
+			},
+		}
+		waypoints7 = []interface{}{
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 758,
+					"y": 390,
+				},
+				"x": 758,
+				"y": 390,
+			},
+			map[string]interface{}{"x": 792, "y": 390},
+			map[string]interface{}{
+				"original": map[string]interface{}{
+					"x": 812,
+					"y": 390,
+				},
+				"x": 812,
+				"y": 390,
+			},
+		}
+	}
+
+	return &statemachine.StateMachineObject{
+		Name:                        "StateMachineNewDesigner",
+		Comment:                     "This state machine is modeled by designer tools.",
+		Version:                     "0.0.1",
+		StartState:                  "ServiceTask-a9h2o51",
+		RecoverStrategy:             "",
+		Persist:                     false,
+		RetryPersistModeUpdate:      false,
+		CompensatePersistModeUpdate: false,
+		Type:                        "",
+		States: map[string]interface{}{
+			"ServiceTask-a9h2o51": map[string]interface{}{
+				"style": map[string]interface{}{
+					"bounds": boundsMap1,
+				},
+				"Name":              "ServiceTask-a9h2o51",
+				"IsForCompensation": false,
+				"Input":             []interface{}{map[string]interface{}{}},
+				"Output":            map[string]interface{}{},
+				"Status":            map[string]interface{}{},
+				"Retry":             []interface{}{},
+				"ServiceName":       "",
+				"ServiceMethod":     "",
+				"Type":              "ServiceTask",
+				"Next":              "Choice-4ajl8nt",
+				"edge": map[string]interface{}{
+					"Choice-4ajl8nt": map[string]interface{}{
+						"style": map[string]interface{}{
+							"waypoints": waypoints1,
+							"source":    "ServiceTask-a9h2o51",
+							"target":    "Choice-4ajl8nt",
+						},
+						"Type": "Transition",
+					},
+				},
+				"CompensateState": "CompensateFirstState",
+			},
+			"Choice-4ajl8nt": map[string]interface{}{
+				"style": map[string]interface{}{
+					"bounds": boundsMap2,
+				},
+				"Name": "Choice-4ajl8nt",
+				"Type": "Choice",
+				"Choices": []interface{}{
+					map[string]interface{}{
+						"Expression": "",
+						"Next":       "SubStateMachine-cauj9uy",
+					},
+					map[string]interface{}{
+						"Expression": "",
+						"Next":       "ServiceTask-vdij28l",
+					},
+				},
+				"Default": "SubStateMachine-cauj9uy",
+				"edge": map[string]interface{}{
+					"SubStateMachine-cauj9uy": map[string]interface{}{
+						"style": map[string]interface{}{
+							"waypoints": waypoints2,
+							"source":    "Choice-4ajl8nt",
+							"target":    "SubStateMachine-cauj9uy",
+						},
+						"Type": "ChoiceEntry",
+					},
+					"ServiceTask-vdij28l": map[string]interface{}{
+						"style": map[string]interface{}{
+							"waypoints": waypoints3,
+							"source":    "Choice-4ajl8nt",
+							"target":    "ServiceTask-vdij28l",
+						},
+						"Type": "ChoiceEntry",
+					},
+				},
+			},
+			"CompensateFirstState": map[string]interface{}{
+				"style": map[string]interface{}{
+					"bounds": boundsMap3,
+				},
+				"Name":              "CompensateFirstState",
+				"IsForCompensation": true,
+				"Input":             []interface{}{map[string]interface{}{}},
+				"Output":            map[string]interface{}{},
+				"Status":            map[string]interface{}{},
+				"Retry":             []interface{}{},
+				"ServiceName":       "",
+				"ServiceMethod":     "",
+				"Type":              "ServiceTask",
+			},
+			"SubStateMachine-cauj9uy": map[string]interface{}{
+				"style": map[string]interface{}{
+					"bounds": boundsMap4,
+				},
+				"Name":              "SubStateMachine-cauj9uy",
+				"IsForCompensation": false,
+				"Input":             []interface{}{map[string]interface{}{}},
+				"Output":            map[string]interface{}{},
+				"Status":            map[string]interface{}{},
+				"Retry":             []interface{}{},
+				"StateMachineName":  "",
+				"Type":              "SubStateMachine",
+				"Next":              "Succeed-5x3z98u",
+				"edge": map[string]interface{}{
+					"Succeed-5x3z98u": map[string]interface{}{
+						"style": map[string]interface{}{
+							"waypoints": waypoints4,
+							"source":    "SubStateMachine-cauj9uy",
+							"target":    "Succeed-5x3z98u",
+						},
+						"Type": "Transition",
+					},
+				},
+			},
+			"ServiceTask-vdij28l": map[string]interface{}{
+				"style": map[string]interface{}{
+					"bounds": boundsMap5,
+				},
+				"Name":              "ServiceTask-vdij28l",
+				"IsForCompensation": false,
+				"Input":             []interface{}{map[string]interface{}{}},
+				"Output":            map[string]interface{}{},
+				"Status":            map[string]interface{}{},
+				"Retry":             []interface{}{},
+				"ServiceName":       "",
+				"ServiceMethod":     "",
+				"Catch": []interface{}{
+					map[string]interface{}{
+						"Exceptions": []interface{}{},
+						"Next":       "CompensationTrigger-uldp2ou",
+					},
+				},
+				"Type": "ServiceTask",
+				"catch": map[string]interface{}{
+					"style": map[string]interface{}{
+						"bounds": boundsMap6,
+					},
+					"edge": map[string]interface{}{
+						"CompensationTrigger-uldp2ou": map[string]interface{}{
+							"style": map[string]interface{}{
+								"waypoints": waypoints5,
+								"source":    "ServiceTask-vdij28l",
+								"target":    "CompensationTrigger-uldp2ou",
+							},
+							"Type": "ExceptionMatch",
+						},
+					},
+				},
+				"Next": "Succeed-5x3z98u",
+				"edge": map[string]interface{}{
+					"Succeed-5x3z98u": map[string]interface{}{
+						"style": map[string]interface{}{
+							"waypoints": waypoints6,
+							"source":    "ServiceTask-vdij28l",
+							"target":    "Succeed-5x3z98u",
+						},
+						"Type": "Transition",
+					},
+				},
+			},
+			"Succeed-5x3z98u": map[string]interface{}{
+				"style": map[string]interface{}{
+					"bounds": boundsMap7,
+				},
+				"Name": "Succeed-5x3z98u",
+				"Type": "Succeed",
+			},
+			"CompensationTrigger-uldp2ou": map[string]interface{}{
+				"style": map[string]interface{}{
+					"bounds": boundsMap8,
+				},
+				"Name": "CompensationTrigger-uldp2ou",
+				"Type": "CompensationTrigger",
+				"Next": "Fail-9roxcv5",
+				"edge": map[string]interface{}{
+					"Fail-9roxcv5": map[string]interface{}{
+						"style": map[string]interface{}{
+							"waypoints": waypoints7,
+							"source":    "CompensationTrigger-uldp2ou",
+							"target":    "Fail-9roxcv5",
+						},
+						"Type": "Transition",
+					},
+				},
+			},
+			"Fail-9roxcv5": map[string]interface{}{
+				"style": map[string]interface{}{
+					"bounds": boundsMap9,
+				},
+				"Name":      "Fail-9roxcv5",
+				"ErrorCode": "",
+				"Message":   "",
+				"Type":      "Fail",
+			},
+		},
+	}
+}
diff --git a/pkg/saga/statemachine/statelang/parser/statemachine_json_parser_test.go b/pkg/saga/statemachine/statelang/parser/statemachine_json_parser_test.go
index 0028309..2150875 100644
--- a/pkg/saga/statemachine/statelang/parser/statemachine_json_parser_test.go
+++ b/pkg/saga/statemachine/statelang/parser/statemachine_json_parser_test.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package parser
 
 import (
@@ -5,41 +22,106 @@ import (
 	"testing"
 )
 
-func TestParseChoice(t *testing.T) {
-	filePath := "../../../../../testdata/saga/statelang/simple_statelang_with_choice.json"
-	fileContent, err := os.ReadFile(filePath)
+func readFileContent(filePath string) (string, error) {
+	content, err := os.ReadFile(filePath)
 	if err != nil {
-		t.Error("parse fail: " + err.Error())
-		return
+		return "", err
 	}
-	_, err = NewJSONStateMachineParser().Parse(string(fileContent))
-	if err != nil {
-		t.Error("parse fail: " + err.Error())
+	return string(content), nil
+}
+
+func TestParseChoice(t *testing.T) {
+	parser := NewJSONStateMachineParser()
+
+	tests := []struct {
+		name           string
+		configFilePath string
+	}{
+		{
+			name:           "JSON Simple: StateLang With Choice",
+			configFilePath: "../../../../../testdata/saga/statelang/simple_statelang_with_choice.json",
+		},
+		{
+			name:           "YAML Simple: StateLang With Choice",
+			configFilePath: "../../../../../testdata/saga/statelang/simple_statelang_with_choice.yaml",
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			content, err := readFileContent(tt.configFilePath)
+			if err != nil {
+				t.Error("read file fail: " + err.Error())
+				return
+			}
+			_, err = parser.Parse(content)
+			if err != nil {
+				t.Error("parse fail: " + err.Error())
+			}
+		})
 	}
 }
 
 func TestParseServiceTaskForSimpleStateMachine(t *testing.T) {
-	filePath := "../../../../../testdata/saga/statelang/simple_statemachine.json"
-	fileContent, err := os.ReadFile(filePath)
-	if err != nil {
-		t.Error("parse fail: " + err.Error())
-		return
+	parser := NewJSONStateMachineParser()
+
+	tests := []struct {
+		name           string
+		configFilePath string
+	}{
+		{
+			name:           "JSON Simple: StateMachine",
+			configFilePath: "../../../../../testdata/saga/statelang/simple_statemachine.json",
+		},
+		{
+			name:           "YAML Simple: StateMachine",
+			configFilePath: "../../../../../testdata/saga/statelang/simple_statemachine.yaml",
+		},
 	}
-	_, err = NewJSONStateMachineParser().Parse(string(fileContent))
-	if err != nil {
-		t.Error("parse fail: " + err.Error())
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			content, err := readFileContent(tt.configFilePath)
+			if err != nil {
+				t.Error("read file fail: " + err.Error())
+				return
+			}
+			_, err = parser.Parse(content)
+			if err != nil {
+				t.Error("parse fail: " + err.Error())
+			}
+		})
 	}
 }
 
 func TestParseServiceTaskForNewDesigner(t *testing.T) {
-	filePath := "../../../../../testdata/saga/statelang/state_machine_new_designer.json"
-	fileContent, err := os.ReadFile(filePath)
-	if err != nil {
-		t.Error("parse fail: " + err.Error())
-		return
+	parser := NewJSONStateMachineParser()
+
+	tests := []struct {
+		name           string
+		configFilePath string
+	}{
+		{
+			name:           "JSON Simple: StateMachine New Designer",
+			configFilePath: "../../../../../testdata/saga/statelang/state_machine_new_designer.json",
+		},
+		{
+			name:           "YAML Simple: StateMachine New Designer",
+			configFilePath: "../../../../../testdata/saga/statelang/state_machine_new_designer.yaml",
+		},
 	}
-	_, err = NewJSONStateMachineParser().Parse(string(fileContent))
-	if err != nil {
-		t.Error("parse fail: " + err.Error())
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			content, err := readFileContent(tt.configFilePath)
+			if err != nil {
+				t.Error("read file fail: " + err.Error())
+				return
+			}
+			_, err = parser.Parse(content)
+			if err != nil {
+				t.Error("parse fail: " + err.Error())
+			}
+		})
 	}
 }
diff --git a/pkg/saga/statemachine/store/db/db_test.go b/pkg/saga/statemachine/store/db/db_test.go
index a5e3edc..e80f704 100644
--- a/pkg/saga/statemachine/store/db/db_test.go
+++ b/pkg/saga/statemachine/store/db/db_test.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package db
 
 import (
diff --git a/pkg/saga/statemachine/store/db/statelang_test.go b/pkg/saga/statemachine/store/db/statelang_test.go
index 87f868d..4b870c1 100644
--- a/pkg/saga/statemachine/store/db/statelang_test.go
+++ b/pkg/saga/statemachine/store/db/statelang_test.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package db
 
 import (
diff --git a/pkg/saga/statemachine/store/db/statelog_test.go b/pkg/saga/statemachine/store/db/statelog_test.go
index 4376747..fb15b8c 100644
--- a/pkg/saga/statemachine/store/db/statelog_test.go
+++ b/pkg/saga/statemachine/store/db/statelog_test.go
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package db
 
 import (
diff --git a/testdata/saga/statelang/simple_statelang_with_choice.yaml b/testdata/saga/statelang/simple_statelang_with_choice.yaml
new file mode 100644
index 0000000..32fa403
--- /dev/null
+++ b/testdata/saga/statelang/simple_statelang_with_choice.yaml
@@ -0,0 +1,26 @@
+Name: simpleChoiceTestStateMachine
+Comment: 带条件分支的测试状态机定义
+StartState: FirstState
+Version: 0.0.1
+States:
+  FirstState:
+    Type: ServiceTask
+    ServiceName: demoService
+    ServiceMethod: foo
+    Next: ChoiceState
+  ChoiceState:
+    Type: Choice
+    Choices:
+      - Expression: "[a] == 1"
+        Next: SecondState
+      - Expression: "[a] == 2"
+        Next: ThirdState
+    Default: SecondState
+  SecondState:
+    Type: ServiceTask
+    ServiceName: demoService
+    ServiceMethod: bar
+  ThirdState:
+    Type: ServiceTask
+    ServiceName: demoService
+    ServiceMethod: foo
\ No newline at end of file
diff --git a/testdata/saga/statelang/simple_statemachine.yaml b/testdata/saga/statelang/simple_statemachine.yaml
new file mode 100644
index 0000000..a5da6c0
--- /dev/null
+++ b/testdata/saga/statelang/simple_statemachine.yaml
@@ -0,0 +1,90 @@
+Name: simpleTestStateMachine
+Comment: 测试状态机定义
+StartState: FirstState
+Version: 0.0.1
+States:
+  FirstState:
+    Type: ServiceTask
+    ServiceName: is.seata.saga.DemoService
+    ServiceMethod: foo
+    IsPersist: false
+    Next: ScriptState
+  ScriptState:
+    Type: ScriptTask
+    ScriptType: groovy
+    ScriptContent: return 'hello ' + inputA
+    Input:
+      - inputA: $.data1
+    Output:
+      scriptStateResult: '$.#root'
+    Next: ChoiceState
+  ChoiceState:
+    Type: Choice
+    Choices:
+      - Expression: foo == 1
+        Next: FirstMatchState
+      - Expression: foo == 2
+        Next: SecondMatchState
+    Default: FailState
+  FirstMatchState:
+    Type: ServiceTask
+    ServiceName: is.seata.saga.DemoService
+    ServiceMethod: bar
+    CompensateState: CompensateFirst
+    Status:
+      return.code == 'S': SU
+      return.code == 'F': FA
+      '$exception{java.lang.Throwable}': UN
+    Input:
+      - inputA1: $.data1
+        inputA2:
+          a: $.data2.a
+      - inputB: $.header
+    Output:
+      firstMatchStateResult: '$.#root'
+    Retry:
+      - Exceptions: [java.lang.Exception]
+        IntervalSeconds: 2
+        MaxAttempts: 3
+        BackoffRate: 1.5
+    Catch:
+      - Exceptions:
+          - java.lang.Exception
+        Next: CompensationTrigger
+    Next: SuccessState
+  CompensateFirst:
+    Type: ServiceTask
+    ServiceName: is.seata.saga.DemoService
+    ServiceMethod: compensateBar
+    IsForCompensation: true
+    IsForUpdate: true
+    Input:
+      - input: $.data
+    Output:
+      firstMatchStateResult: '$.#root'
+    Status:
+      return.code == 'S': SU
+      return.code == 'F': FA
+      '$exception{java.lang.Throwable}': UN
+  CompensationTrigger:
+    Type: CompensationTrigger
+    Next: CompensateEndState
+  CompensateEndState:
+    Type: Fail
+    ErrorCode: StateCompensated
+    Message: State Compensated!
+  SecondMatchState:
+    Type: SubStateMachine
+    StateMachineName: simpleTestSubStateMachine
+    Input:
+      - input: $.data
+      - header: $.header
+    Output:
+      firstMatchStateResult: '$.#root'
+    Next: SuccessState
+  FailState:
+    Type: Fail
+    ErrorCode: DefaultStateError
+    Message: No Matches!
+  SuccessState:
+    Type: Succeed
diff --git a/testdata/saga/statelang/state_machine_new_designer.yaml b/testdata/saga/statelang/state_machine_new_designer.yaml
new file mode 100644
index 0000000..d646ab0
--- /dev/null
+++ b/testdata/saga/statelang/state_machine_new_designer.yaml
@@ -0,0 +1,286 @@
+Name: StateMachineNewDesigner
+Comment: This state machine is modeled by designer tools.
+Version: 0.0.1
+style:
+  bounds:
+    x: 200
+    y: 200
+    width: 36
+    height: 36
+States:
+  ServiceTask-a9h2o51:
+    style:
+      bounds:
+        x: 300
+        y: 178
+        width: 100
+        height: 80
+    Name: ServiceTask-a9h2o51
+    IsForCompensation: false
+    Input:
+      - {}
+    Output: {}
+    Status: {}
+    Retry: []
+    ServiceName: ""
+    ServiceMethod: ""
+    Type: ServiceTask
+    Next: Choice-4ajl8nt
+    edge:
+      Choice-4ajl8nt:
+        style:
+          waypoints:
+            - original:
+                x: 400
+                y: 218
+              x: 400
+              y: 218
+            - x: 435
+              y: 218
+            - original:
+                x: 455
+                y: 218
+              x: 455
+              y: 218
+          source: ServiceTask-a9h2o51
+          target: Choice-4ajl8nt
+        Type: Transition
+    CompensateState: CompensateFirstState
+  Choice-4ajl8nt:
+    style:
+      bounds:
+        x: 455
+        y: 193
+        width: 50
+        height: 50
+    Name: Choice-4ajl8nt
+    Type: Choice
+    Choices:
+      - Expression: ""
+        Next: SubStateMachine-cauj9uy
+      - Expression: ""
+        Next: ServiceTask-vdij28l
+    Default: SubStateMachine-cauj9uy
+    edge:
+      SubStateMachine-cauj9uy:
+        style:
+          waypoints:
+            - original:
+                x: 505
+                y: 218
+              x: 505
+              y: 218
+            - x: 530
+              y: 218
+            - original:
+                x: 550
+                y: 218
+              x: 550
+              y: 218
+          source: Choice-4ajl8nt
+          target: SubStateMachine-cauj9uy
+        Type: ChoiceEntry
+      ServiceTask-vdij28l:
+        style:
+          waypoints:
+            - original:
+                x: 480
+                y: 243
+              x: 480
+              y: 243
+            - x: 600
+              y: 290
+            - original:
+                x: 600
+                y: 310
+              x: 600
+              y: 310
+          source: Choice-4ajl8nt
+          target: ServiceTask-vdij28l
+        Type: ChoiceEntry
+  CompensateFirstState:
+    style:
+      bounds:
+        x: 300
+        y: 310
+        width: 100
+        height: 80
+    Name: CompensateFirstState
+    IsForCompensation: true
+    Input:
+      - {}
+    Output: {}
+    Status: {}
+    Retry: []
+    ServiceName: ""
+    ServiceMethod: ""
+    Type: ServiceTask
+  SubStateMachine-cauj9uy:
+    style:
+      bounds:
+        x: 550
+        y: 178
+        width: 100
+        height: 80
+    Name: SubStateMachine-cauj9uy
+    IsForCompensation: false
+    Input:
+      - {}
+    Output: {}
+    Status: {}
+    Retry: []
+    StateMachineName: ""
+    Type: SubStateMachine
+    Next: Succeed-5x3z98u
+    edge:
+      Succeed-5x3z98u:
+        style:
+          waypoints:
+            - original:
+                x: 650
+                y: 218
+              x: 650
+              y: 218
+            - x: 702
+              y: 218
+            - original:
+                x: 722
+                y: 218
+              x: 722
+              y: 218
+          source: SubStateMachine-cauj9uy
+          target: Succeed-5x3z98u
+        Type: Transition
+  ServiceTask-vdij28l:
+    style:
+      bounds:
+        x: 550
+        y: 310
+        width: 100
+        height: 80
+    Name: ServiceTask-vdij28l
+    IsForCompensation: false
+    Input:
+      - {}
+    Output: {}
+    Status: {}
+    Retry: []
+    ServiceName: ""
+    ServiceMethod: ""
+    Catch:
+      - Exceptions: []
+        Next: CompensationTrigger-uldp2ou
+    Type: ServiceTask
+    catch:
+      style:
+        bounds:
+          x: 632
+          y: 372
+          width: 36
+          height: 36
+      edge:
+        CompensationTrigger-uldp2ou:
+          style:
+            waypoints:
+              - original:
+                  x: 668
+                  y: 390
+                x: 668
+                y: 390
+              - x: 702
+                y: 390
+              - original:
+                  x: 722
+                  y: 390
+                x: 722
+                y: 390
+            source: ServiceTask-vdij28l
+            target: CompensationTrigger-uldp2ou
+          Type: ExceptionMatch
+    Next: Succeed-5x3z98u
+    edge:
+      Succeed-5x3z98u:
+        style:
+          waypoints:
+            - original:
+                x: 600
+                y: 310
+              x: 600
+              y: 310
+            - x: 740
+              y: 256
+            - original:
+                x: 740
+                y: 236
+              x: 740
+              y: 236
+          source: ServiceTask-vdij28l
+          target: Succeed-5x3z98u
+        Type: Transition
+  Succeed-5x3z98u:
+    style:
+      bounds:
+        x: 722
+        y: 200
+        width: 36
+        height: 36
+    Name: Succeed-5x3z98u
+    Type: Succeed
+  CompensationTrigger-uldp2ou:
+    style:
+      bounds:
+        x: 722
+        y: 372
+        width: 36
+        height: 36
+    Name: CompensationTrigger-uldp2ou
+    Type: CompensationTrigger
+    Next: Fail-9roxcv5
+    edge:
+      Fail-9roxcv5:
+        style:
+          waypoints:
+            - original:
+                x: 758
+                y: 390
+              x: 758
+              y: 390
+            - x: 792
+              y: 390
+            - original:
+                x: 812
+                y: 390
+              x: 812
+              y: 390
+          source: CompensationTrigger-uldp2ou
+          target: Fail-9roxcv5
+        Type: Transition
+  Fail-9roxcv5:
+    style:
+      bounds:
+        x: 812
+        y: 372
+        width: 36
+        height: 36
+    Name: Fail-9roxcv5
+    ErrorCode: ""
+    Message: ""
+    Type: Fail
+StartState: ServiceTask-a9h2o51
+edge:
+  style:
+    waypoints:
+      - original:
+          x: 236
+          y: 218
+        x: 236
+        y: 218
+      - x: 280
+        y: 218
+      - original:
+          x: 300
+          y: 218
+        x: 300
+        y: 218
+    target: ServiceTask-a9h2o51
+  Type: Transition
\ No newline at end of file