Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions camel/camel-slack/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?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>
<parent>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-camel-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<artifactId>camel-slack</artifactId>
<name>Quarkus Flow :: Camel :: Slack</name>
<properties>
<!-- Must be aligned with Slack client okhttp -->
<version.com.squareup.okhttp3.v4>4.12.0</version.com.squareup.okhttp3.v4>
</properties>

<dependencies>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-slack</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-camel</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
<version>${version.com.squareup.okhttp3.v4}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.quarkiverse.flow.camel.slack;

import io.quarkiverse.flow.camel.CamelConnector;

public final class FlowCamelSlackDSL {

private FlowCamelSlackDSL() {
}

public static <T, R> CamelConnector<T, R> slack(String channel, String webHookUrlConfigKey) {
return new SlackCamelConnector<>(channel, webHookUrlConfigKey);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.quarkiverse.flow.camel.slack;

import io.quarkiverse.flow.camel.AbstractCamelInvoker;
import io.quarkiverse.flow.camel.CamelConnector;

public class SlackCamelConnector<T, R> extends AbstractCamelInvoker implements CamelConnector<T, R> {

private final String channel;
private final String webHookUrlConfigKey;

public SlackCamelConnector(String channel, String webHookUrlConfigKey) {
this.channel = channel;
this.webHookUrlConfigKey = webHookUrlConfigKey;
}

@SuppressWarnings("unchecked")
@Override
public R apply(T t) {
return (R) this.invoke(t);
}

@Override
protected String configureEndpoint() {
return "slack:#" + channel + "?webhookUrl={{" + webHookUrlConfigKey + "}}";
}

@Override
public String connectorName() {
return "slack";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package io.quarkiverse.flow.camel.slack;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.jetbrains.annotations.NotNull;

import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
import okhttp3.mockwebserver.Dispatcher;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;

public class MockSlackServer implements QuarkusTestResourceLifecycleManager {

private static MockWebServer server;

static MockWebServer getServer() {
return server;
}

@Override
public Map<String, String> start() {
server = new MockWebServer();

server.setDispatcher(new Dispatcher() {
@Override
public @NotNull MockResponse dispatch(@NotNull RecordedRequest request) {
if ("/slack-webhook".equals(request.getPath())) {
return new MockResponse()
.setResponseCode(200)
.setBody("ok")
.addHeader("Content-Type", "text/plain");
}
return new MockResponse().setResponseCode(404);
}
});

Map<String, String> props = new HashMap<>();
// This becomes: http://localhost:<port>/slack-webhook
props.put("slack.webhook.team1", server.url("/slack-webhook").toString());
return props;
}

@Override
public void stop() {
if (server != null) {
try {
server.shutdown();
} catch (IOException e) {
// ignore
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.quarkiverse.flow.camel.slack;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import java.io.IOException;

import org.junit.jupiter.api.Test;

import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest;
import okhttp3.mockwebserver.RecordedRequest;

@QuarkusTest
@QuarkusTestResource(MockSlackServer.class)
class SlackCamelConnectorTest {

@Test
void shouldPostMessageToMockSlackWebhook() throws InterruptedException, IOException {
SlackCamelConnector<String, String> connector = new SlackCamelConnector<>("alerts", "slack.webhook.team1");

String result = connector.apply("hello from quarkus-flow");

// Camel returns the same response
assertEquals("hello from quarkus-flow", result);

RecordedRequest recordedRequest = MockSlackServer.getServer().takeRequest();
assertNotNull(recordedRequest);
assertEquals("POST", recordedRequest.getMethod());
assertEquals("/slack-webhook", recordedRequest.getPath());

String body = recordedRequest.getBody().readUtf8();
// Just make sure our text went through
org.assertj.core.api.Assertions.assertThat(body)
.contains("hello from quarkus-flow");
}

@Test
void connectorNameShouldBeSlack() {
SlackCamelConnector<Void, Void> connector = new SlackCamelConnector<>("alerts", "slack.webhook.team1");

assertEquals("slack", connector.connectorName());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.quarkiverse.flow.camel.slack;

import static io.quarkiverse.flow.camel.FlowCamelDSL.camel;
import static io.quarkiverse.flow.camel.slack.FlowCamelSlackDSL.slack;
import static io.serverlessworkflow.fluent.func.FuncWorkflowBuilder.workflow;
import static io.serverlessworkflow.fluent.func.dsl.FuncDSL.set;

import jakarta.enterprise.context.ApplicationScoped;

import io.quarkiverse.flow.Flow;
import io.serverlessworkflow.api.types.Workflow;

@ApplicationScoped
public class SlackNotificationWorkflow extends Flow {

@Override
public Workflow descriptor() {
return workflow()
.tasks(set("${ \"Hello \" + .name }"),
camel(slack("alerts", "slack.webhook.team1"), String.class))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.quarkiverse.flow.camel.slack;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.IOException;
import java.util.Map;

import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;

import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest;
import okhttp3.mockwebserver.RecordedRequest;

@QuarkusTest
@QuarkusTestResource(MockSlackServer.class)
class SlackNotificationWorkflowTest {

@Inject
SlackNotificationWorkflow workflow;

@Test
void shouldSendSlackNotificationFromWorkflow() throws InterruptedException, IOException {
final String response = workflow.instance(Map.of("name", "Elisa"))
.start()
.join()
.asText()
.orElseThrow();

assertThat(response).isNotEmpty();
assertThat(response).isEqualTo("Hello Elisa");

RecordedRequest recordedRequest = MockSlackServer.getServer().takeRequest();
assertThat(recordedRequest.getMethod()).isEqualTo("POST");
assertThat(recordedRequest.getPath()).isEqualTo("/slack-webhook");

String body = recordedRequest.getBody().readUtf8();
assertThat(body).contains("Hello Elisa");
assertThat(body).contains("#alerts");
}
}
54 changes: 54 additions & 0 deletions camel/deployment/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?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>
<parent>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-camel-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<name>Quarkus Flow :: Camel :: Deployment</name>
<artifactId>quarkus-flow-camel-deployment</artifactId>

<dependencies>
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-camel</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-deployment</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-core-deployment</artifactId>
</dependency>
</dependencies>


<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.quarkiverse.flow.camel.deployment;

import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.FeatureBuildItem;

public class FlowCamelProcessor {

private static final String FEATURE = "flow-camel";

@BuildStep
FeatureBuildItem feature() {
return new FeatureBuildItem(FEATURE);
}

}
38 changes: 38 additions & 0 deletions camel/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?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>
<parent>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>

<name>Quarkus Flow :: Camel :: Parent</name>
<artifactId>quarkus-flow-camel-parent</artifactId>
<packaging>pom</packaging>

<properties>
<version.org.apache.camel.quarkus>3.30.0</version.org.apache.camel.quarkus>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-bom</artifactId>
<version>${version.org.apache.camel.quarkus}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<modules>
<module>deployment</module>
<module>runtime</module>
<module>camel-slack</module>
</modules>

</project>
Loading
Loading