Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

When developing an application with Saga Library embedded, and connecting to the ElasticSearch manage by the Saga Server

Note

This tutorial assumes, the :

  • The reader ability to create a project with Maven Framework support
  • The data Saga will use is manage through the Saga's user interface

Step-by-step guide

  • Configure pom.xml
  • Main class
  • Settings loading

    Table of Contents
    maxLevel3
    minLevel3
    outlinetrue

    Configure pom.xml

    In the pom.xml of the project, a basic example of the minimum configuration can be found below. But elementary section of this configuration is the dependencies section, where we need two main libraries.

    saga-library

    The core library of Saga, this dependency includes the Engine, Stages, Tag Manager, Pipeline Manager and Resource Manager which are all the parts necessary to use Saga in any application.

    saga-elastic-

    library

    provider

    This dependency will grant us access to ElasticSearch as a provider for Saga, which means our Stages and Managers will be able to fetch the data directly from this providerThe core library of Saga, this dependency includes the Engine, Stages, Tag Manager, Pipeline Manager and Resource Manager which are all the parts necessary to use Saga in any application.

    Info

    More indexers providers will be available in the future, but to use Saga full functionality we recommend the use of the saga-elastic-indexerprovider.

    Other important configuration to notice is the use of Java 11, for the compilation of the code and the encoding UTF-8, as you can see in the lines 36-38

    Code Block
    collapse
    languagexml
    themeRDark
    firstline0
    titlepom.xml
    linenumberstruetrue
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.accenture.saga</groupId>
        <artifactId>saga-howto</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <saga.version>1.0.0</saga.version>
        </properties>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                    <executions>
                        <execution>
                            <id>compile</id>
                            <phase>compile</phase>
                            <goals>
                                <goal>compile</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>testCompile</id>
                            <phase>test-compile</phase>
                            <goals>
                                <goal>testCompile</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <source>11</source>
                        <target>11</target>
                        <encoding>${project.build.sourceEncoding}</encoding>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>3.1.0</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <mainClass>com.accenture.saga.server.SagaServer</mainClass>
                            </manifest>
                        </archive>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                        <appendAssemblyId>false</appendAssemblyId>
                    </configuration>
                    <executions>
                        <execution>
                            <id>make-assembly</id> <!-- this is used for inheritance merges -->
                            <phase>package</phase> <!-- bind to the packaging phase -->
                            <goals>
                                <goal>single</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    
        <dependencies>
            <dependency>
                <groupId>com.accenture.saga</groupId>
                <artifactId>saga-library</artifactId>
                <version>${saga.version}</version>
                <scope>compile</scope>
            </dependency>
    
            <dependency>
                <groupId>com.accenture.saga</groupId>
                <artifactId>saga-elastic-indexer<provider</artifactId>
                <version>${saga.version}</version>
                <scope>compile</scope>
            </dependency>
        </dependencies>
    </project>
    Main Class

    Setting Up The Configuration

    For starters, we will create a main class, which will hold a SagaEngine, ResourceManager, TagManager and PipelineManager.

    Code Block
    languagejava
    themeRDark
    linenumberstrue
    package com.accenture.saga;
    
    import com.accenture.saga.engine.PipelineManager;
    import com.accenture.saga.engine.SagaEngine;
    import com.accenture.saga.resourcemgr.ResourceManager;
    import com.accenture.saga.tags.TagManager;
    
    public class Main {
    
        SagaEngine engine;
        ResourceManager resourceManager;
        TagManager tagManager;
        PipelineManager pipelineManager;
    
        /**
         * Constructor
         public*/
       static voidpublic mainMain(String[] args) {
            
        }
    }
        
        }
        
        public static void main(String[] args) {
            Main _instance = new Main();
        }
    }
    


    First we start by creating an configuring the ResourceManager, and adding a provider to it, but this configuration will be hard-coded,  so we need to add SagaJsonFactory class, which allow us to create SagaJson objects (the standard document of Saga) from text, files or readers.

    The configuration we are going to use for the provider is the following

    Saga_json
    "name": "saga-provider",
    "type": "Elastic",
    "scheme": "http",
    "hostname": "localhost",
    "port": 9200,
    "timestamp": "updatedAt",
    "exclude": [
      "updatedAt",
      "createdAt"
    ]

    Each field from the top, starting with the common

    • Parameter
      summaryThe name we are going to use for the provider. It doesn't which name you use, but our take is "saga-provider"
      namename
      requiredtrue
    • Parameter
      summaryIndicates the type of provider we are using, in this case since we are using saga-elastic-provider, it's type would be "Elastic"
      nametype
      requiredtrue

    from here on, all the properties are specific to saga-elastic-indexer

    • Parameter
      summarySchema for the url to Elasticsearch
      defaulthttp
      nameshema
    • Parameter
      summaryName of the hosting server
      defaultlocalhost
      namehostname
    • Parameter
      summaryPort of ElasticSearch
      default9200
      name9200
      typeinteger
    • Parameter
      summaryName of the field reflecting any change done to the data
      defaultupdatedAt
      nametimestamp
    • Parameter
      summaryName of the fields omitted (when possible) from the response of ElasticSearch
      nameexclude
      typestring array

    Our code should look this this

    Code Block
    languagejava
    themeRDark
    linenumberstrue
    public Main() {
    
        resourceManager = new ResourceManager();
    
        resourceManager.registerProvider(
            SagaJsonFactory.getInstance(
                "{"
                + "\"name\":\"saga-provider\","
                + "\"type\":\"FileSystem\","
                + "\"baseDir\":\"testdata\""
                + "}"
            )
        );
    }
    

    Next we proceed with the configuration of the TagManager below the ResourceManager, once again we will hard-code the configuration for this one

    Saga_json
    "resource": "saga-provider:saga_tags"

    In the configuration above, saga-provider is representing the provider we add to the ResourceManager in the previous configuration, then the colon (:) indicates the division between the provider and the actual resource; since we are using a saga-elastic-provider, the resources will be indexes names, and since were are connecting to a Saga index, created by the Saga server, all the indexes will be a combination between the solution's name (usually will be saga), and underscore (_) and the type of data the index holds, in this case tags, forming the name saga_tags 

    The code should look now like this

    Code Block
    languagejava
    themeRDark
    linenumberstrue
    public Main() {
    
        resourceManager = new ResourceManager();
    
        resourceManager.registerProvider(
                SagaJsonFactory.getInstance(
                        "{"
                                + "\"name\":\"saga-provider\","
                                + "\"type\":\"FileSystem\","
                                + "\"baseDir\":\"testdata\""
                                + "}"
                )
        );
    
        tagManager = new TagManager(resourceManager, SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_tags\"}"));
    }
    

    As you can see the TagManager, receives as a parameter the ResourceManager, which grant us access to the resource saga-provider:saga_tags.

    In the same way, we proceed to configure the PipelinesManager using the following configuration

    Saga_json
    "resource": "saga-provider:saga_pipelines"

    Once again, saga-provider, does reference to the provider added in the ResourceManager, and saga_pipelines is a combination between the name of the solution's name and the type of data, in this case pipelines.

    Code Block
    languagejava
    themeRDark
    linenumberstrue
    public Main() {
    
        resourceManager = new ResourceManager();
    
        resourceManager.registerProvider(
                SagaJsonFactory.getInstance(
                        "{"
                                + "\"name\":\"saga-provider\","
                                + "\"type\":\"FileSystem\","
                                + "\"baseDir\":\"testdata\""
                                + "}"
                )
        );
    
        tagManager = new TagManager(resourceManager, SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_tags\"}"));
    
        pipelineManager = new PipelineManager(resourceManager,  SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_pipelines\"}"));
    }
    

    Configuring the Engine

    So one we are at the fun part, once we got the Resource, Tag and Pipeline Manager all set up, we assign the ResourceManager and the TagManager to the Engine

    Code Block
    languagejava
    themeRDark
    linenumberstrue
    public Main() {
    
        resourceManager = new ResourceManager();
    
        resourceManager.registerProvider(
                SagaJsonFactory.getInstance(
                        "{"
                                + "\"name\":\"saga-provider\","
                                + "\"type\":\"FileSystem\","
                                + "\"baseDir\":\"testdata\""
                                + "}"
                )
        );
    
        tagManager = new TagManager(resourceManager, SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_tags\"}"));
    
        pipelineManager = new PipelineManager(resourceManager,  SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_pipelines\"}"));
    
        engine = new SagaEngine();
    
        engine.setResourceManager(resourceManager);
        engine.setTagManager(tagManager);
    }
    

    Working With The Pipeline Manager

    From here we got 2 options, first option is letting the PipelineManager build the pipeline for us, using a set of tags (that we will provide); the second option is to manually provide a complete pipeline configuration to the PipelineManager

    Pros & Cons

    Automatic Pipeline

    Manual Pipeline

    Pros

    • Uses configuration set up through Saga's UI

    • Loads only the necessary from the resource (tags, stages, ...)

    • Builds pipeline based on tag dependency

    • Can generate multiple and different pipelines

    • Each Recognizer can have a base pipeline as dependency

    Pros

    • Complete control over the flow of the data

    Cons

    • Pipelines not always the most efficient (...yet)

    • Each base pipeline must be configure manually (... for the moment)

    Cons

    • Configuration of every stage must be done manually

    • Relies strongly in the knowledge of the user for each possible stage configuration

    • Lack of flexibly when changing to another pipeline

    Tie

    • Needs a stage of type TextBlockReader configure manually

    Tie

    • Needs a stage of type TextBlockReader configure manually

    Since the first one is the most flexible and the one that makes use of the configuration in ElasticSearch, we will use that one.

    Request A Pipeline

    Before asking the PipelineManager for a pipeline, we need to provide a stage of type TextBlockReader, at the moment we only have one stage of that type, the SimpleReaderStage, which requires a splitRegex in the configuration, as a SagaJson object. So let's add that to the code shall we.

    Code Block
    languagejava
    themeRDark
    linenumberstrue
    public Main() {
    
        resourceManager = new ResourceManager();
    
        resourceManager.registerProvider(
                SagaJsonFactory.getInstance(
                        "{"
                                + "\"name\":\"saga-provider\","
                                + "\"type\":\"FileSystem\","
                                + "\"baseDir\":\"testdata\""
                                + "}"
                )
        );
    
        tagManager = new TagManager(resourceManager, SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_tags\"}"));
    
        pipelineManager = new PipelineManager(resourceManager,  SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_pipelines\"}"));
    
        //The Fun Part
    
        engine = new SagaEngine();
    
        engine.setResourceManager(resourceManager);
        engine.setTagManager(tagManager);
    
    
        SimpleReaderStage simpleReaderStage = new SimpleReaderStage(engine, SagaJsonFactory.getInstance("{ \"splitRegex\": \"[\\r|\\n]+\"}"));
    }
    

    The splitRegex is the way the SimpleReader know when to split the text for processing, with the regex [\r\n]+ we are indicating the character signaling a break line; also note the SimpleReaderStage receives the engine as the first parameter.

    Tip

    The regex [\r\n]+, is the standard for mostly all the text you will be processing




    Content by Label
    showLabelsfalse
    max5
    spacessaga12new
    showSpacefalse
    sortmodified
    reversetrue
    typepage
    cqllabel in ("embedded","saga","library","app") and type = "page" and space = "saga12new"
    labelssaga library app embedded

    When developing an application with Saga Library embedded, and connecting to the ElasticSearch manage by the Saga Server

    Note

    This tutorial assumes:

    • The reader ability to create a project with Maven Framework support
    • The data Saga will use is manage through the Saga's user interface

    Step-by-step guide

    Table of Contents
    maxLevel3
    minLevel3
    outlinetrue

    Configure pom.xml

    In the pom.xml of the project, a basic example of the minimum configuration can be found below. But elementary section of this configuration is the dependencies section, where we need two main libraries.

    saga-library

    The core library of Saga, this dependency includes the Engine, Stages, Tag Manager, Pipeline Manager and Resource Manager which are all the parts necessary to use Saga in any application.

    saga-elastic-provider

    This dependency will grant us access to ElasticSearch as a provider for Saga, which means our Stages and Managers will be able to fetch the data directly from this provider

    Info

    More providers will be available in the future, but to use Saga full functionality we recommend the use of the saga-elastic-provider.

    Other important configuration to notice is the use of Java 11, for the compilation of the code and the encoding UTF-8, as you can see in the lines 36-38

    Code Block
    languagexml
    themeRDark
    firstline0
    titlepom.xml
    linenumberstrue
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.accenture.saga</groupId>
        <artifactId>saga-howto</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <saga.version>1.0.0</saga.version>
        </properties>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                    <executions>
                        <execution>
                            <id>compile</id>
                            <phase>compile</phase>
                            <goals>
                                <goal>compile</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>testCompile</id>
                            <phase>test-compile</phase>
                            <goals>
                                <goal>testCompile</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <source>11</source>
                        <target>11</target>
                        <encoding>${project.build.sourceEncoding}</encoding>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-assembly-plugin</artifactId>
                    <version>3.1.0</version>
                    <configuration>
                        <archive>
                            <manifest>
                                <mainClass>com.accenture.saga.server.SagaServer</mainClass>
                            </manifest>
                        </archive>
                        <descriptorRefs>
                            <descriptorRef>jar-with-dependencies</descriptorRef>
                        </descriptorRefs>
                        <appendAssemblyId>false</appendAssemblyId>
                    </configuration>
                    <executions>
                        <execution>
                            <id>make-assembly</id> <!-- this is used for inheritance merges -->
                            <phase>package</phase> <!-- bind to the packaging phase -->
                            <goals>
                                <goal>single</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    
        <dependencies>
            <dependency>
                <groupId>com.accenture.saga</groupId>
                <artifactId>saga-library</artifactId>
                <version>${saga.version}</version>
                <scope>compile</scope>
            </dependency>
    
            <dependency>
                <groupId>com.accenture.saga</groupId>
                <artifactId>saga-elastic-provider</artifactId>
                <version>${saga.version}</version>
                <scope>compile</scope>
            </dependency>
        </dependencies>
    </project>

    Setting Up The Configuration

    For starters, we will create a main class, which will hold a SagaEngine, ResourceManager, TagManager and PipelineManager.

    Code Block
    languagejava
    themeRDark
    linenumberstrue
    package com.accenture.saga;
    
    import com.accenture.saga.engine.PipelineManager;
    import com.accenture.saga.engine.SagaEngine;
    import com.accenture.saga.resourcemgr.ResourceManager;
    import com.accenture.saga.tags.TagManager;
    
    public class Main {
    
        SagaEngine engine;
        ResourceManager resourceManager;
        TagManager tagManager;
        PipelineManager pipelineManager;
    
        /**
         * Constructor
         */
        public Main() {
            
            
        }
        
        public static void main(String[] args) {
            Main _instance = new Main();
        }
    }
    


    First we start by creating an configuring the ResourceManager, and adding a provider to it, but this configuration will be hard-coded,  so we need to add SagaJsonFactory class, which allow us to create SagaJson objects (the standard document of Saga) from text, files or readers.

    The configuration we are going to use for the provider is the following

    Saga_json
    "name": "saga-provider",
    "type": "Elastic",
    "scheme": "http",
    "hostname": "localhost",
    "port": 9200,
    "timestamp": "updatedAt",
    "exclude": [
      "updatedAt",
      "createdAt"
    ]

    Each field from the top, starting with the common

    • Parameter
      summaryThe name we are going to use for the provider. It doesn't which name you use, but our take is "saga-provider"
      namename
      requiredtrue
    • Parameter
      summaryIndicates the type of provider we are using, in this case since we are using saga-elastic-provider, it's type would be "Elastic"
      nametype
      requiredtrue

    from here on, all the properties are specific to saga-elastic-indexer

    • Parameter
      summarySchema for the url to Elasticsearch
      defaulthttp
      nameshema
    • Parameter
      summaryName of the hosting server
      defaultlocalhost
      namehostname
    • Parameter
      summaryPort of ElasticSearch
      default9200
      name9200
      typeinteger
    • Parameter
      summaryName of the field reflecting any change done to the data
      defaultupdatedAt
      nametimestamp
    • Parameter
      summaryName of the fields omitted (when possible) from the response of ElasticSearch
      nameexclude
      typestring array

    Our code should look this this

    Code Block
    languagejava
    themeRDark
    linenumberstrue
    public Main() {
    
        resourceManager = new ResourceManager();
    
        resourceManager.registerProvider(
            SagaJsonFactory.getInstance(
                "{"
                + "\"name\":\"saga-provider\","
                + "\"type\":\"FileSystem\","
                + "\"baseDir\":\"testdata\""
                + "}"
            )
        );
    }
    

    Next we proceed with the configuration of the TagManager below the ResourceManager, once again we will hard-code the configuration for this one

    Saga_json
    "resource": "saga-provider:saga_tags"

    In the configuration above, saga-provider is representing the provider we add to the ResourceManager in the previous configuration, then the colon (:) indicates the division between the provider and the actual resource; since we are using a saga-elastic-provider, the resources will be indexes names, and since were are connecting to a Saga index, created by the Saga server, all the indexes will be a combination between the solution's name (usually will be saga), and underscore (_) and the type of data the index holds, in this case tags, forming the name saga_tags 

    The code should look now like this

    Code Block
    languagejava
    themeRDark
    linenumberstrue
    public Main() {
    
        resourceManager = new ResourceManager();
    
        resourceManager.registerProvider(
                SagaJsonFactory.getInstance(
                        "{"
                                + "\"name\":\"saga-provider\","
                                + "\"type\":\"FileSystem\","
                                + "\"baseDir\":\"testdata\""
                                + "}"
                )
        );
    
        tagManager = new TagManager(resourceManager, SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_tags\"}"));
    }
    

    As you can see the TagManager, receives as a parameter the ResourceManager, which grant us access to the resource saga-provider:saga_tags.

    In the same way, we proceed to configure the PipelinesManager using the following configuration

    Saga_json
    "resource": "saga-provider:saga_pipelines"

    Once again, saga-provider, does reference to the provider added in the ResourceManager, and saga_pipelines is a combination between the name of the solution's name and the type of data, in this case pipelines.

    Code Block
    languagejava
    themeRDark
    linenumberstrue
    public Main() {
    
        resourceManager = new ResourceManager();
    
        resourceManager.registerProvider(
                SagaJsonFactory.getInstance(
                        "{"
                                + "\"name\":\"saga-provider\","
                                + "\"type\":\"FileSystem\","
                                + "\"baseDir\":\"testdata\""
                                + "}"
                )
        );
    
        tagManager = new TagManager(resourceManager, SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_tags\"}"));
    
        pipelineManager = new PipelineManager(resourceManager,  SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_pipelines\"}"));
    }
    

    Configuring the Engine

    So one we are at the fun part, once we got the Resource, Tag and Pipeline Manager all set up, we assign the ResourceManager and the TagManager to the Engine

    Code Block
    languagejava
    themeRDark
    linenumberstrue
    public Main() {
    
        resourceManager = new ResourceManager();
    
        resourceManager.registerProvider(
                SagaJsonFactory.getInstance(
                        "{"
                                + "\"name\":\"saga-provider\","
                                + "\"type\":\"FileSystem\","
                                + "\"baseDir\":\"testdata\""
                                + "}"
                )
        );
    
        tagManager = new TagManager(resourceManager, SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_tags\"}"));
    
        pipelineManager = new PipelineManager(resourceManager,  SagaJsonFactory.getInstance("{ \"resource\": \"saga-provider:saga_pipelines\"}"));
    
        //The Fun Part
    
        engine = new SagaEngine();
    
        engine.setResourceManager(resourceManager);
        engine.setTagManager(tagManager);
    }
    

    Working With The Pipeline Manager

    From here we got 2 options, first option is letting the PipelineManager build the pipeline for us, using a set of tags (that we will provide); the second option is to manually provide a complete pipeline configuration to the PipelineManager

    Pros & Cons

    Automatic Pipeline

    Manual Pipeline

    Pros

    • Uses configuration set up through Saga's UI

    • Loads only the necessary from the resource (tags, stages, ...)

    • Builds pipeline based on tag dependency

    • Can generate multiple and different pipelines

    • Each Recognizer can have a base pipeline as dependency

    Pros

    • Complete control over the flow of the data

    Cons

    • Pipelines not always the most efficient (...yet)

    • Each base pipeline must be configure manually (... for the moment)

    Cons

    • Configuration of every stage must be done manually

    • Relies strongly in the knowledge of the user for each possible stage configuration

    • Lack of flexibly when changing to another pipeline

    Tie

    • Needs a stage of type TextBlockReader configure manually

    Tie

    • Needs a stage of type TextBlockReader configure manually

    Since the first one is the most flexible and the one that makes use of the configuration in ElasticSearch, we will use that one.

    Request A Pipeline

    Before asking the PipelineManager for a pipeline, we need to provide a stage of type TextBlockReader, at the moment we only have one stage of that type, the SimpleReaderStage, which requires a 

    splitRegex


    Related articles

    Content by Label
    showLabelsfalse
    max5
    spacessaga12new
    showSpacefalse
    sortmodified
    reversetrue
    typepage
    cqllabel in ("embedded","saga","library","app") and type = "page" and space = "saga12new"
    labelssaga library app embedded

    Related articles

    Content by Label
    showLabelsfalse
    max5
    spacessaga12new
    showSpacefalse
    sortmodified
    reversetrue
    typepage
    cqllabel in ("embedded","saga","library","app") and type = "page" and space = "saga12new"
    labelssaga library app embedded