arrow-left

All pages
gitbookPowered by GitBook
1 of 8

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Tasks

A task is like a ”secondary action” assigned to an endpoint. The primary action is the <success> and <error> action described in Types of Endpoints. The "secondary" action may contain zero or many tasks, that will be executed once the primary action has been completed successfully.

circle-info

Task vs Primary Action

The task does some action, but the response body of the task is not part of the response to the client's request. The response to the request might be a simple "status 200", while the request had triggered the execution of a task which did have a response body.

With a task you can

  • send a request to any API =>

  • send emails with attachments =>

Each <task> is a set of commands embedded into an endpoint-definition in the endpoints.xml:

hashtag
Parallel or Subsequent Execution of Tasks

Offer-Ready uses multiple cores, if available. If not specified otherwise, tasks are executed in parallel and will be finished in an arbitrary order. In order to determine a distinctive order of tasks, read .

hashtag
Intermediate Values

If a task requires the output from a second task as an output, you may use .

HttpRequest Task
Email Task
Parallel or Subsequent Execution of Tasks
Intermediate Values
<endpoint name="foo">
    <success>...</success>
    <error>...</error>
    <!-- zero or many tasks -->
    <task class="...">
       ...
    </task>
    <task class="...">
       ...
    </task>
</endpoint>

Email Task

To send an email from OpenEndpoints you need to

  1. Configure your email server

  2. Create an email task

hashtag
Configure Email Server

To send email from your application the file "email-sending-configuration.xml" must be present under application.

The file has the root element <email-sending-configuration> and have the following sets of sub-elements.

  • If no username and password are set, TLS will not be used

  • extra headers are written into every email sent via SMTP, for example authorization headers for a commercial email sending service

Any of the fields (apart from the header names) may use ${foo} parameters.

hashtag
Alternative Set-Up:

An alternative option is to configure an MX address for the DNS lookup.

hashtag
Create Email Task

The task <task class="endpoints.task.EmailTask"> sends an email. It has the following sub-elements configuring it:

• <from> is mandatory (variables are expanded)

• <to> is mandatory (variables are expanded). There may be multiple <to> elements. Each <to> sends a separate email, to just this recipient. Per <to>, only one recipient address is allowed

• <subject> is mandatory (variables are expanded)

• <body-transformation name="a-transformation"/> is mandatory, and can appear multiple times. This references a transformation (see below). All the different results are placed into a ”multipart/alternative” email part. It would be normal for one referenced transformation to produce HTML and the other plain text.

• <attachment-static filename="path/foo.pdf"> takes the foo.pdf file out of the static directory and includes it as an attachment in the email. Variables are not allowed in the filename attribute.

• <attachment-transformation name="a-transformation" filename="invoice-${invoice-number}.pdf"/>. For each of the elements, the transformation is executed, and the resulting bytes are attached as a file to the sent email. The name of the file is specified in the filename attribute, variables are expanded.

• <attachment-ooxml-parameter-expansion source="foo.docx" filename="invoice-${invoice-number}.pdf"/> will read in the file “foo.docx” from the “ooxml-responses” directory under the Endpoint's configuration and replace any ${foo} variables in the document's body, and deliver it. Only DOCX is supported; DOC is not supported. The name of the file is specified in the filename attribute, parameters like ${foo} are expanded.

• <attachments-from-request-file-uploads/>. This includes as attachments all file uploads that have been uploaded to this request. Any attachment may (optionally) have attributes such as if="${foo}" equals="bar".

hashtag
Embedding Images

If the body has a content type like text/html; charset=utf-8 then it may include tags such as <img src="cid:foo/bar.jpg">. The tag is most commonly an <img> but can be any tag.

The system then searches in the static directory for any file with that path. The file is included with the image, as a “related” multi-part part, meaning the file is available to the HTML document when its rendered in the email client.

<email-sending-configuration>
    <server>hostname-to-connect-to</server>
    <!--optional-->
    <port>xxxx</port>
    <!--optional-->
    <username>xxxx</username>
    <password>xxxx</password>
    <!--optional: zero or many -->
    <header name='foo'>some-value</header>
</email-sending-configuration>
<email-sending-configuration>
    <mx-address>an address for MX DNS lookup.</mx-address>
</email-sending-configuration>
<task class="endpoints.task.EmailTask">
    <from>me@my-email.com</from>
    <to>${client-email}</to>
    <subject>Message from OpenEndpoints</subject>
    <!-- one or many; "many" will create an multipart/alternative email part -->
    <body-transformation name="a-transformation-generating-text-or-html"/>
    <!-- zero or many -->
    <attachment-static filename="path-to-file-in-static"/>
    <!-- zero or many -->
    <attachment-transformation name="a-transformation" filename="invoice-${invoice-number}.pdf"/>
    <!-- zero or many -->
    <attachment-ooxml-parameter-expansion source="foo.docx" filename="invoice-${invoice-number}.pdf"/>
    <!-- zero or one -->
    <attachments-from-request-file-uploads/>
</task>

Request Log Task

You can add custom key/value pairs to your request-log.

For example, if you want to add the "country" submitted in your contact workflow to your request log, you simply create a parameter ${country} and add this task to your endpoint:

<task class="endpoints.task.RequestLogExpressionCaptureTask" key="Country" value="${county}" />

If an endpoint is forwarding the request to another endpoint, then the initial "parent" endpoint will remain the only entry in the log. However, you can add key/value pairs to this "parent" log entry in each subsequent step.

Create Shortlink Task

Some email programs may have issues with long links. Links to endpoints (containing all parameters) may get long, so this can become a problem.

The “Short Link To Endpoint” feature allows shorter links to endpoints (including all parameters) to be created. This is analogous to Forwarding Between Endpoints, with the exception that rather than the destination endpoint getting executed immediately, a link is created to the processing of that endpoint.

The task creates a short-link in the database with a random code. The resulting full link, including the code and also including the base URL of the current installation of Endpoints.

The short link looks like this: [base-url]/shortlink/RANDOMCODE.

The generated link is written to an output intermediate variable. The concept of intermediate valriables is described here: Intermediate Values.

The shortlink will be auto-deleted in the database after the time specified in expires-in-minutes. For example, if you put expires-in-minutes="1440" then the link will be available for 1 day. After that time the link will not work any longer.

Use a syntax like the following to create a short link to an endpoint in the variable ${foo}. (You can choose any other variable name, of course).

The variable ${foo} can then be used as an input-intermediate-value in a subsequent task.

For example, you can send an email containing ${foo} in the email-body. The xslt (to create the email-body) would look like this:

<task id="create-link"
      class="endpoints.task.CreateShortLinkToEndpointTask"
      destination-endpoint-name="test"
      output-intermediate-value="foo"
      expires-in-minutes="1440"/>
<a>
  <xsl:attribute name="href" select="transformation-input/parameters/intermediate-value[@name eq 'foo']/@value"/>
  <xsl:text>Short Link</xsl:text>
</a>

Parallel or Subsequent Execution of Tasks

Offer-Ready uses multiple cores, if available. If not specified otherwise, tasks are executed in parallel and will be finished in an arbitrary order.

Paralell execution of primary action and tasks

Note that - as a default - the primary task (data transformation) and all tasks are executed in parallel.

Therefore if one HTTP request depends on another previous one having completed first, that will not work without declaring this dependency.

You may optionally assign an id attribute to the task element:

<task class="endpoints.task.HttpRequestTask" id="foo">
  ...
</task>

You may insert an element <after task-id="..."/> into any task that needs to be executed after foo…

Note that on using the software will automatically determine the order of execution such that intermediate outputs are created before they are required as inputs. Intermediate values and “after” elements can be used in parallel.

<task class="endpoints.task.HttpRequestTask">
    <after task-id="foo"/>
    ...
</task>
Intermediate Values

Conditional Tasks

Any task can be made conditional, that means the task will only be executed if some parameter value matches a condition.

The current set of operators supported are:

  • if="..." equals="..."

  • if="..." notequals="..."

  • if="..." isempty="true"

  • if="..." hasmultiple="true"

  • if="..." gt="..."

  • if="..." ge="..."

  • if="..." lt="..."

  • if="..." le="..."

Note the syntax of the if condition: Either side can use parameter placeholder.

If the parameter has a value like foo||bar i.e. created as a result of a request such as ?param=foo&param=bar, then the equals=".." will check if any of the values match, and notequals=".." will check that none of the values match the value.

For the gt, ge, lt, le operators the comparison values will be treated as numbers (decimal). If either side are empty or not parseable as a number, the comparison is false.

The right hand side of isempty and hasmultiple can be true or false.

<task class="..." if="${foo}" equals="true">
    ...
<task>

HttpRequest Task

OpenEndpoints supports any kind of HTTP request to other systems. You can call and fetch data from

  • REST Api

  • SOAP interface

  • simple URL that returns content

Examples:

  • fetch data from any CRM or ERP system (as long as it offers a REST or SOAP API that can be called from the internet)

  • upload generated files to a CRM or an archive

  • fetch the next available invoice-number from your accounting system, generate an invoice and send it as an email

circle-info

Task vs Data-Source

Interaction with external APIs is available for both, loading data for the purpose of a data-source transformation (see ), or for the execution of a task - which is content of this section. Technically both types of application are very similar, but there are some differences:

  • A task can have a "condition" based on a parameter value. While a request as part of a data source will always be triggered (on using the data source), a task may be triggered only if a certain condition applies.

hashtag
Basic Syntax

This task performs an HTTP request, checks the response is a 2xx OK, and ignores the response body.

Redirects are not followed.

The attribute ignore-if-error="true" may be present on the <task> element to indicate that if an error occurs (e.g. server not found, non-2xx response, etc.) this error is ignored. By default, the error aborts the processing of the endpoint.

hashtag
Request Body

đź’ˇThe beauty of <OpenEndpoints/> shows in the solution of the optional request body, which can be json or xml. There are several different options how-to build the content for the request-body.

hashtag
XML-Request Body with Inline Contents

The request body is expressed as xml within the <xml-body> tag. Endpoint parameters are expanded.

Uploaded content encoded in base64 can be filled into any tag of the request body. This requires 2 actions:

  • Add attribute upload-files="true" to <xml-from-url>

  • Add to any element of your request body attributes upload-field-name="foo" encoding="base64"

The uploaded content will expand into that xml element.

circle-exclamation

base64 encoded content only

The expansion of uploaded content works for base 64 encoded content only!

It is also possible to send generated content within a request body:

  • Add attribute expand-transformations="true" to <xml-from-url>

  • Add to any element of your request body attributes xslt-transformation="foo" encoding="base64"

iAdding that attribute to the element indicates that the transformation with that name should be executed (for example, generate a PDF file), and the contents of the resulting file should be placed in this tag. The encoding is always base64, no other encodings are supported.

hashtag
XML-Request Body from Transformation

The request body is generated by XSLT. This leaves maximum flexibility to build different content of the request body depending on endpoint parameter values!

Note that this is a transformation within a transformation. The XSLT takes a <parameters> as its input document; This XSLT does not have access to the results of any other data sources. The reason is, that data sources cannot use data produced by another data source.

  • The XSLT file is taken from the http-xslt directory.

  • The transformation-input to apply that XSLT has <parameters> as its root tag.

The optional attribute upload-files="true" and expand-transformations="true" may be present as above.

hashtag
JSON-Request Body with Inline Contents

The request body is expressed as json within the <json-body> tag. Endpoint parameters are expanded.

Endpoint parameters are expanded within the string context of JSON, that is to say that no concern about escaping is necessary.

Options for expanding base 64 content from file upload or generated content is not available for JSON.

hashtag
JSON-Request Body from Transformation

The request body is generated by XSLT. That requires that the result of the transformation is valid JSON.

Note that this is a transformation within a transformation. The XSLT takes a <parameters> as its input document; This XSLT does not have access to the results of any other data sources. The reason is, that data sources cannot use data produced by another data source.

  • The XSLT file is taken from the http-xslt directory.

  • The transformation-input to apply that XSLT has <parameters> as its root tag.

Options for expanding base 64 content from file upload or generated content is not available for JSON.

validate the existence of an address by calling an external validation service

  • The response body of a task can be parsed to generate values that do not come from the user's request, instead they come from that task. Such "intermediate values" can be used like parameters in subsequent tasks.

  • Load Data from any REST-API
    <task class="endpoints.task.HttpRequestTask">
        <!-- mandatory -->
        <url>http://www.google.com/foo/${variable}</url>
        <!-- optional, default GET -->
        <method name="POST"/>
        <!-- zero or more - provided method is GET -->
        <get-parameter name="foo">${variable}</get-parameter>
        <!-- zero or more - provided method is POST -->
        <post-parameter name="foo">${variable}</post-parameter>
        <!-- zero or more -->
        <request-header name="foo">${variable}</request-header>
        <!-- optional -->
        <basic-access-authentication username="${variable}" password="${variable}"/>
        <!-- either one <xml-body>, or <json-body>, or neither -->
        <json-body>...</json-body>
    </task>
    <xml-from-url ignore-if-error="true">...</xml-from-url>
    <task class="endpoints.task.HttpRequestTask">
         ...
        <xml-body>
            <your-tag>${parameter}</your-tag>
        </xml-body>
        ...
    </task>
    <task class="endpoints.task.HttpRequestTask">
        ...
        <xml-body xslt-file="foo.xslt"/>
        ...
    </task>
    <parameters>
        <parameter name="foo" value="abc"/>
        <parameter name="long" employees="def"/>
        ...
    </parameters>
    <parameters>
        <parameter name="foo" value="abc"/>
        <parameter name="long" employees="def"/>
        ...
    </parameters>
    <task class="endpoints.task.HttpRequestTask">
        ...
        <json-body xslt-file="foo.xslt"/>
        ...
    </task>
    <parameters>
        <parameter name="foo" value="abc"/>
        <parameter name="long" employees="def"/>
        ...
    </parameters>

    Intermediate Values

    In addition to parameters there are Intermediate Values . These are like parameters, but they do not come from the user’s request, instead they come from other tasks.

    For example, imagine a CRM which requires 2 separate calls to

    1. fetch the next available id to insert a new customerinsert a new customer, with that id (from irst request) as a mandatory parameter

    2. insert a new customer, with that id (from irst request) as a mandatory parameter

    In this case the first <task> will fetch the id, and make it available as an input to the second task. This is an “intermediate value”.

    • Intermediate values can be referenced as ${value} just like normal parameters.

    • Intermediate values may not have the same name as a parameter declared in “endpoints.xml”. (If intermediate values could have the same names, then ${value} could be ambiguous.)

    • Tasks must explicitly specify which intermediate values they output and which they input. Any task may accept any input intermediate value, however, the output of an intermediate value is task-specific. (For example, HTTP Tasks parse the response, but there is no useful way for an email task to output a variable.)

    For example:

    To produce an <output-intermediate-value> from a response-body, one of the following syntaxes must be used:

    The former requires that the result of the response be XML, the latter that it be JSON. No attempt is made to convert the response between XML and JSON. The regex attribute is optional.

    hashtag
    Using Intermediate Values in data-source-xslt

    ssIn case you want to use the intermediate value within a regular data-source-xslt, then you need to declare it within the <success> tags:

    A task which outputs intermediate values may not be optional (with if and equals attributes). That is because the output variables will be used by other tasks, therefore the task must always run.

    <success>
        <input-intermediate-value name="name-of-intermediate-variable"/>
            <response-transformation name="name-of-transformer"/>
    </success>
    <task class="endpoints.task.HttpRequestTask">
        ...
        <output-intermediate-value name="invoice-number"/>
    </task>
    
    <task class="endpoints.task.HttpRequestTask">
        <input-intermediate-value name="invoice-number"/>
        ...
    </task>
    <task class="endpoints.task.HttpRequestTask">
        ...
        <output-intermediate-value
            name="invoice-number"
            xpath="/foo/bar"
            regex=" d+"/>
    </task>
    
    <task class="endpoints.task.HttpRequestTask">
        ...
        <output-intermediate-value
            name="invoice-number"
            jsonpath="$.invoiceNumbers[:1].value"
            regex=" d+"/>
    </task>