Skip to content

Commit d3734a5

Browse files
authored
Resolve workflow identifier for CDI proxied beans (#199)
Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
1 parent a283812 commit d3734a5

File tree

11 files changed

+155
-29
lines changed

11 files changed

+155
-29
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.quarkiverse.flow.deployment.test.metrics;
2+
3+
import java.util.Map;
4+
5+
import jakarta.inject.Inject;
6+
import jakarta.ws.rs.POST;
7+
import jakarta.ws.rs.Path;
8+
9+
@Path("/simple-resource")
10+
public class SimpleResource {
11+
12+
@Inject
13+
SimpleFlow flow;
14+
15+
@POST
16+
public void start() {
17+
flow.instance(Map.of("message", "hello"))
18+
.start()
19+
.join();
20+
}
21+
}

core/integration-tests/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@
1919
<groupId>io.quarkus</groupId>
2020
<artifactId>quarkus-rest-jackson</artifactId>
2121
</dependency>
22+
<dependency>
23+
<groupId>io.quarkus</groupId>
24+
<artifactId>quarkus-hibernate-orm-panache</artifactId>
25+
</dependency>
26+
<dependency>
27+
<groupId>io.quarkus</groupId>
28+
<artifactId>quarkus-jdbc-h2</artifactId>
29+
</dependency>
2230
<dependency>
2331
<groupId>io.quarkiverse.flow</groupId>
2432
<artifactId>quarkus-flow</artifactId>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.quarkiverse.flow.it;
2+
3+
import jakarta.inject.Inject;
4+
import jakarta.ws.rs.POST;
5+
import jakarta.ws.rs.Path;
6+
import jakarta.ws.rs.Produces;
7+
8+
import io.serverlessworkflow.impl.WorkflowModel;
9+
10+
@Path("/proposals")
11+
public class ProposalResource {
12+
13+
@Inject
14+
SaveProposalWorkflow workflow;
15+
16+
@POST
17+
@Produces("text/plain")
18+
public String proposal() {
19+
WorkflowModel model = workflow.instance().start().join();
20+
return "Proposal created with ID: " + model.asNumber().orElseThrow().longValue();
21+
}
22+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package io.quarkiverse.flow.it;
2+
3+
import static io.serverlessworkflow.fluent.func.dsl.FuncDSL.function;
4+
5+
import jakarta.enterprise.context.ApplicationScoped;
6+
import jakarta.persistence.Entity;
7+
import jakarta.transaction.Transactional;
8+
9+
import io.quarkiverse.flow.Flow;
10+
import io.quarkus.hibernate.orm.panache.PanacheEntity;
11+
import io.serverlessworkflow.api.types.Workflow;
12+
import io.serverlessworkflow.fluent.func.FuncWorkflowBuilder;
13+
14+
@ApplicationScoped
15+
public class SaveProposalWorkflow extends Flow {
16+
17+
@Override
18+
public Workflow descriptor() {
19+
return FuncWorkflowBuilder.workflow("saveProposalWorkflow")
20+
.tasks(function("doSave", this::save, String.class).outputAs(o -> (Long) o))
21+
.build();
22+
}
23+
24+
@Transactional
25+
public Long save(String proposal) {
26+
Proposal p = new Proposal(proposal);
27+
p.persist();
28+
return p.id;
29+
}
30+
31+
@Entity
32+
static class Proposal extends PanacheEntity {
33+
34+
private String proposal;
35+
36+
protected Proposal() {
37+
}
38+
39+
public Proposal(String proposal) {
40+
this.proposal = proposal;
41+
}
42+
43+
public String getProposal() {
44+
return proposal;
45+
}
46+
}
47+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.quarkiverse.flow.it;
2+
3+
import org.hamcrest.Matchers;
4+
import org.junit.jupiter.api.Test;
5+
6+
import io.quarkus.test.junit.QuarkusTest;
7+
import io.restassured.RestAssured;
8+
9+
@QuarkusTest
10+
class ProposalResourceTest {
11+
12+
@Test
13+
void should_resolve_workflow_identifier_when_the_workflow_bean_is_a_proxy() {
14+
RestAssured.given()
15+
.accept("text/plain")
16+
.post("/proposals")
17+
.then()
18+
.body(Matchers.containsString("Proposal created with ID: 1"))
19+
.extract()
20+
.body()
21+
.asString();
22+
}
23+
24+
}

core/runtime/src/main/java/io/quarkiverse/flow/Flowable.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package io.quarkiverse.flow;
22

3+
import io.quarkus.arc.ClientProxy;
4+
import io.quarkus.arc.InterceptionProxySubclass;
5+
import io.quarkus.arc.Subclass;
36
import io.serverlessworkflow.api.types.Workflow;
47
import io.serverlessworkflow.impl.WorkflowDefinitionId;
58

@@ -18,7 +21,15 @@ default WorkflowDefinitionId id() {
1821
}
1922

2023
default String identifier() {
21-
return this.getClass().getName();
24+
if (this instanceof ClientProxy proxy) {
25+
return proxy.getClass().getSuperclass().getName();
26+
} else if (this instanceof InterceptionProxySubclass proxy) {
27+
return proxy.getClass().getSuperclass().getName();
28+
} else if (this instanceof Subclass subclass) {
29+
return subclass.getClass().getSuperclass().getName();
30+
} else {
31+
return this.getClass().getName();
32+
}
2233
}
2334

2435
}

examples/agentic-http/src/main/java/org/acme/agentic/InvestmentAnalystAgent.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ public interface InvestmentAnalystAgent {
4040
/**
4141
* Analyze the prompt and produce an investment memo.
4242
*
43-
* @param memoryId Conversation / workflow memory id (provided by Quarkus Flow).
44-
* @param prompt Ticker, objective, horizon and raw market-data JSON.
43+
* @param memoryId
44+
* Conversation / workflow memory id (provided by Quarkus Flow).
45+
* @param prompt
46+
* Ticker, objective, horizon and raw market-data JSON.
4547
*/
4648
@UserMessage("""
4749
Ticker: {prompt.ticker}
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
package org.acme;
22

33
import static io.serverlessworkflow.fluent.func.FuncWorkflowBuilder.workflow;
4-
import static io.serverlessworkflow.fluent.func.dsl.FuncDSL.function;
54
import static io.serverlessworkflow.fluent.func.dsl.FuncDSL.set;
65

76
import io.quarkiverse.flow.Flow;
87
import io.serverlessworkflow.api.types.Workflow;
9-
import io.serverlessworkflow.fluent.func.dsl.FuncDSL;
108
import jakarta.enterprise.context.ApplicationScoped;
119

1210
@ApplicationScoped
1311
public class SimpleWorkflow extends Flow {
1412

1513
@Override
1614
public Workflow descriptor() {
17-
return workflow("simple-workflow", "quarkus.flow")
18-
.tasks(set("{ message: \"Ana Sara\" }")).build();
15+
return workflow("simple-workflow", "quarkus.flow").tasks(set("{ message: \"Ana Sara\" }")).build();
1916
}
2017
}

examples/micrometer-prometheus/src/main/java/org/acme/TryWorkflowsResource.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ public Uni<Message> simple() throws InterruptedException {
5656

5757
instance.resume();
5858

59-
return Uni.createFrom().completionStage(start.toCompletableFuture())
60-
.onItem()
59+
return Uni.createFrom().completionStage(start.toCompletableFuture()).onItem()
6160
.transform(workflowModel -> workflowModel.as(Message.class).orElseThrow());
6261
}
6362

examples/petstore-openapi/src/test/java/org/acme/http/PetstoreFlowIT.java

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22

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

5+
import io.quarkus.test.common.QuarkusTestResource;
56
import io.quarkus.test.junit.QuarkusTest;
67
import jakarta.inject.Inject;
78
import java.util.Map;
8-
99
import org.junit.jupiter.api.Test;
10-
import io.quarkus.test.common.QuarkusTestResource;
1110

1211
@QuarkusTest
1312
@QuarkusTestResource(PetstoreMockResource.class)
@@ -28,12 +27,8 @@ void petstoreWorkflowShouldReturnPetDetails() throws Exception {
2827
// Very lightweight sanity checks – we mainly care that the flow ran end-to-end
2928
assertThat(pet).isNotNull();
3029
assertThat(pet).isNotEmpty();
31-
assertThat(((Number) pet.get("id")).intValue())
32-
.as("pet id from mocked response")
33-
.isEqualTo(123);
34-
assertThat((String) pet.get("name"))
35-
.as("pet name from mocked response")
36-
.isEqualTo("Mocked Pet");
30+
assertThat(((Number) pet.get("id")).intValue()).as("pet id from mocked response").isEqualTo(123);
31+
assertThat((String) pet.get("name")).as("pet name from mocked response").isEqualTo("Mocked Pet");
3732

3833
}
3934
}

0 commit comments

Comments
 (0)