19. HTTP Bağlayıcıları (Dış Entegrasyonlar)

HTTP Bağlayıcı Merkezi (HTTP Connector Hub), BPMN iş akışlarının herhangi bir Hizmet Görevinden (Service Task) dış REST API'leri (Slack, Jira, GitHub vb.) çağırmasına izin verir — hem de Java kodu yazmadan.

Nasıl Çalışır

  1. Bir yönetici (admin), Yönetici → Bağlayıcılar (Admin → Connectors) bölümünde bir Bağlayıcı (Connector) yapılandırır (ad, URL, HTTP yöntemi, üstbilgiler (headers), gövde şablonu, zaman aşımı).
  2. Bir BPMN Hizmet Görevinde, httpConnector temsilcisini (delegate) kullanarak bağlayıcıya adına göre başvurursunuz.
  3. Çalışma zamanında (runtime) temsilci, URL, üstbilgiler ve gövdedeki herhangi bir ${processVariable} yer tutucusunu (placeholder) çözer, ardından HTTP çağrısını yapar.
  4. Sonuç değişkenleri otomatik olarak süreç örneğine (process instance) geri yazılır.

Sonuç Değişkenleri

Bir bağlayıcı tetiklendikten sonra, {connectorName}_{suffix} deseni altında üç değişken erişilebilir olur:

Değişken Örnek Açıklama
{name}_status Slack_PostMessage_status SUCCESS (HTTP 2xx) veya FAILED
{name}_httpCode Slack_PostMessage_httpCode HTTP durum kodu (örneğin 200), veya ağ hatasında 0
{name}_responseBody Slack_PostMessage_responseBody Ham yanıt gövdesi dizesi (Raw response body string)

Yumuşak hata tasarımı (Soft-fail design): Temsilci asla bir istisna (exception) fırlatmaz. Çağrı başarısız olursa, _status değeri FAILED olur ve süreç devam eder. Hata ayıklama (error handling) yapmanız gerekiyorsa _status değerine göre dallanmak için bir geçit (gateway) kullanın.


Temel Kullanım

Herhangi bir Hizmet Görevinde (Service Task), delegateExpression değerini ${httpConnector} olarak ayarlayın ve bağlayıcı adını bir alan olarak belirtin:

<serviceTask id="notifySlack" name="Notify Slack" flowable:delegateExpression="${httpConnector}">
    <extensionElements>
        <flowable:field name="connectorName" stringValue="Slack_PostMessage"/>
    </extensionElements>
</serviceTask>

İşte bu kadar. Slack_PostMessage adlı bağlayıcı veritabanından aranır, yer tutucular (placeholders) çözülür ve HTTP çağrısı yapılır.


Yer Tutucu Çözümleme (Placeholder Resolution)

Bağlayıcının URL, Üstbilgiler (Headers) veya Gövde Şablonundaki (Body Template) herhangi bir ${variableName} yer tutucusu, çalışma zamanında (runtime) süreç değişkenlerinden çözümlenir.

Örnek: Gövde şablonu şu olan bir bağlayıcı:

{"channel": "${slackChannel}", "text": "${message}"}

Çalışma zamanında slackChannel = "#alerts" ve message = "Approval needed" ise, temsilci şunları gönderir:

{"channel": "#alerts", "text": "Approval needed"}

Örnek 1: Bir Slack Bildirimi Gönderme

Bir form mesajı toplar, bir hizmet görevi Slack'i çağırır, ardından bir geçit (gateway) başarıyı (success) kontrol eder.

<!-- Step 1: User enters a message -->
<userTask id="composeMsg" name="Compose Message" flowable:assignee="${initiator}">
    <extensionElements>
        <activiti:formProperty id="slackChannel" name="Slack Channel" type="string"
                               required="true" default="#general"/>
        <activiti:formProperty id="message" name="Message" type="string" required="true">
            <activiti:value id="type" name="textarea"/>
        </activiti:formProperty>
    </extensionElements>
</userTask>

<sequenceFlow sourceRef="composeMsg" targetRef="callSlack"/>

<!-- Step 2: Call the Slack connector -->
<serviceTask id="callSlack" name="Send Slack Message"
             flowable:delegateExpression="${httpConnector}">
    <extensionElements>
        <flowable:field name="connectorName" stringValue="Slack_PostMessage"/>
    </extensionElements>
</serviceTask>

<sequenceFlow sourceRef="callSlack" targetRef="checkResult"/>

<!-- Step 3: Branch on result -->
<exclusiveGateway id="checkResult"/>

<sequenceFlow sourceRef="checkResult" targetRef="notifySuccess">
    <conditionExpression>${Slack_PostMessage_status == 'SUCCESS'}</conditionExpression>
</sequenceFlow>

<sequenceFlow sourceRef="checkResult" targetRef="handleFailure">
    <conditionExpression>${Slack_PostMessage_status == 'FAILED'}</conditionExpression>
</sequenceFlow>

Örnek 2: Süreç Başlangıcında Jira Görevi (Issue) Oluşturma

Bir iş akışı başladığında otomatik olarak bir Jira bileti (ticket) açın.

<startEvent id="start" flowable:initiator="initiator">
    <extensionElements>
        <activiti:formProperty id="projectKey" name="Jira Project" type="string"
                               required="true" default="WORK"/>
        <activiti:formProperty id="summary" name="Issue Summary" type="string" required="true"/>
    </extensionElements>
</startEvent>

<sequenceFlow sourceRef="start" targetRef="createJiraIssue"/>

<serviceTask id="createJiraIssue" name="Create Jira Issue"
             flowable:delegateExpression="${httpConnector}">
    <extensionElements>
        <flowable:field name="connectorName" stringValue="Jira_CreateIssue"/>
    </extensionElements>
</serviceTask>

<sequenceFlow sourceRef="createJiraIssue" targetRef="managerApproval"/>

Ön Koşul (Prerequisite): Jira_CreateIssue bağlayıcısının Authorization başlığı (header), Yönetici → Bağlayıcılar bölümünde Base64 ile kodlanmış (encoded) gerçek bir user:api_token kimlik bilgisi (credential) ile yapılandırılmış olmalıdır.


Örnek 3: Bağlayıcıları Zincirleme (Chaining Connectors)

İki harici sistemi sırayla çağırın. Burada, bir GitHub görevi (issue) oluşturulur ve ardından Slack'e bildirim gönderilir.

<!-- Call GitHub -->
<serviceTask id="createGhIssue" name="Create GitHub Issue"
             flowable:delegateExpression="${httpConnector}">
    <extensionElements>
        <flowable:field name="connectorName" stringValue="GitHub_CreateIssue"/>
    </extensionElements>
</serviceTask>

<sequenceFlow sourceRef="createGhIssue" targetRef="notifySlack"/>

<!-- Call Slack (uses variables from the same process) -->
<serviceTask id="notifySlack" name="Notify Team"
             flowable:delegateExpression="${httpConnector}">
    <extensionElements>
        <flowable:field name="connectorName" stringValue="Slack_PostMessage"/>
    </extensionElements>
</serviceTask>

Örnek 4: Genel Web Kancası (Generic Webhook)

Bir ön ayar (preset) kapsamına girmeyen herhangi bir REST uç noktası (endpoint) için Generic_Webhook bağlayıcısını kullanın. Hedef URL'yi bir süreç değişkeninde saklayarak URL'sini ve gövdesini geçersiz kılabilirsiniz... Aslında, yer tutucular (placeholders) bağlayıcı yapılandırmasının (config) kendi içinde olduğu için, daha basit yaklaşım Generic_Webhook'u kopyalayıp Yönetici → Bağlayıcılar aracılığıyla belirli bir statik URL ile yapılandırmaktır.

Alternatif olarak, Generic_Webhook ön ayarını (preset) kullanın ve yer tutucular aracılığıyla gövdeye dinamik veri koyun:

<!-- Store the payload in a script task first -->
<scriptTask id="buildPayload" name="Build Payload" scriptFormat="super-js">
  <script>
    var amount = execution.getVariable('amount');
    var requester = execution.getVariable('initiator');
    execution.setVariable('webhookPayload',
        '{"amount": ' + amount + ', "requester": "' + requester + '"}');
  </script>
</scriptTask>

<!-- Then fire the connector (body template uses ${webhookPayload}) -->
<serviceTask id="fireHook" flowable:delegateExpression="${httpConnector}">
    <extensionElements>
        <flowable:field name="connectorName" stringValue="Generic_Webhook"/>
    </extensionElements>
</serviceTask>

İpucu: Bir Script Görevinde (Script Task) oluşturulmuş tam biçimli (fully-formed) bir JSON dizesini enjekte etmek için Yönetici → Bağlayıcılar bölümündeki Generic_Webhook gövde şablonunu ${webhookPayload} (tek bir değişken) olarak yapılandırın.


Yönetici → Bağlayıcılar Başvurusu (Admin → Connectors Reference)

Alan Açıklama
Ad (Name) Benzersiz tanımlayıcı — BPMN connectorName alanındaki stringValue ile eşleşmelidir. Oluşturulduktan sonra değiştirilemez.
Açıklama (Description) Yönetici kullanıcı arayüzü (Admin UI) için insan tarafından okunabilir etiket.
Hedef URL (Target URL) Tam URL. ${variable} yer tutucularını destekler.
HTTP Yöntemi (HTTP Method) GET, POST, PUT, DELETE
Üstbilgiler (Headers) Düz (Flat) JSON nesnesi, ör. {"Authorization": "Bearer TOKEN"}. Değerler ${variable} yer tutucularını destekler.
Gövde Şablonu (Body Template) İstekle birlikte gönderilen JSON gövdesi. Dize (string) değerlerinin içinde ${variable} yer tutucularını destekler.
Zaman Aşımı (Timeout) Saniye cinsinden bağlantı (connection) + okuma (read) zaman aşımı (varsayılan: 10).
Aktif (Active) Etkin olmayan bağlayıcılar sessizce atlanır (_status = FAILED). Liste sayfasından açıp kapatabilirsiniz (toggle).

Ön Ayarlı Bağlayıcılar (Preset Connectors)

Sistem, ilk açılışta aşağıdaki bağlayıcıları (connectors) hazır olarak yükler (tümü aktiftir, kimlik bilgileri yapılandırılmalıdır):

Bağlayıcı Adı (Connector Name) Hizmet (Service) Yöntem (Method)
Generic_Webhook Herhangi bir REST uç noktası POST
Slack_PostMessage Slack Web API POST
Discord_Webhook Discord POST
Teams_Webhook Microsoft Teams POST
Telegram_SendMessage Telegram Bot API POST
Jira_CreateIssue Atlassian Jira POST
Linear_CreateIssue Linear POST
Trello_CreateCard Trello POST
GitHub_CreateIssue GitHub POST
GitLab_CreateIssue GitLab POST
HubSpot_CreateContact HubSpot CRM POST
PagerDuty_CreateIncident PagerDuty POST