Skip to content

Commit

Permalink
Merge pull request #55 from camunda-community-hub/feature/tx-handling
Browse files Browse the repository at this point in the history
Feature/tx handling
  • Loading branch information
stephanpelikan authored Jul 31, 2024
2 parents eb2ffab + 195d677 commit 1dd57b9
Show file tree
Hide file tree
Showing 14 changed files with 1,031 additions and 200 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<artifactId>camunda8-adapter</artifactId>

<name>VanillaBP SPI adapter for Camunda 8.x</name>
<version>1.3.1-SNAPSHOT</version>
<version>1.4.0-SNAPSHOT</version>
<packaging>pom</packaging>

<properties>
Expand Down
40 changes: 38 additions & 2 deletions spring-boot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,51 @@ Since Camunda 8 is an external system to your services one has to deal with even
1. Camunda 8 is not reachable / cannot process the confirmation of a completed task
1. The task to be completed was cancelled meanwhile e.g. due to boundary events

If there is an exception in your business code and you have to roll back the transaction then Camunda's task retry-mechanism should retry as configured. Additionally, the `TaskException` is used for expected business errors handled by BPMN error boundary events which must not cause a rollback. To achieve both one should mark the service bean like this:
In order to activate this behavior one has to mark methods accessing VanillaBP-APIs as `@Transactional`, either by
using the method-level annotation:

```java
@Service
@WorkflowService(workflowAggregateClass = Ride.class)
@Transactional(noRollbackFor = TaskException.class)
public class TaxiRide {
@Autowired
private ProcessService<Ride> processService;
@Transactional
public void receivePayment(...) {
...
processService.startWorkflow(ride);
...
}
@Transactional
@WorkflowTask
public void chargeCreditCard(final Ride ride) {
...
}
@Transactional
public void paymentReceived(final Ride ride) {
...
processService.correlateMessage(ride, 'PaymentReceived');
...
}
}
```

or the class-level annotation:

```java
@Service
@WorkflowService(workflowAggregateClass = Ride.class)
@Transactional
public class TaxiRide {
...
}
```

If there is an exception in your business code and you have to roll back the transaction then Camunda's task retry-mechanism should retry as configured. Additionally, the `TaskException` is used for expected business errors handled by BPMN error boundary events which must not cause a rollback. This is handled by the adapter, one does not need to take care about it.

## Workflow aggregate serialization

On using C7 one can use workflow aggregates having relations and calculated values:
Expand Down
15 changes: 10 additions & 5 deletions spring-boot/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
<parent>
<groupId>org.camunda.community.vanillabp</groupId>
<artifactId>camunda8-adapter</artifactId>
<version>1.3.1-SNAPSHOT</version>
<version>1.4.0-SNAPSHOT</version>
</parent>

<artifactId>camunda8-spring-boot-adapter</artifactId>
<name>VanillaBP SPI adapter for Camunda 8.x for Spring Boot</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.zeebe.version>8.3.4.2</spring.zeebe.version>
<spring.zeebe.version>8.5.4</spring.zeebe.version>
</properties>

<build>
Expand All @@ -38,14 +38,19 @@
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>io.camunda</groupId>
<artifactId>spring-zeebe-starter</artifactId>
<groupId>io.camunda.spring</groupId>
<artifactId>spring-boot-starter-camunda</artifactId>
<version>${spring.zeebe.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.23</version>
<version>6.1.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>3.2.5</version><!-- see pom of spring-client-root -->
</dependency>
<dependency>
<groupId>jakarta.persistence</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package io.vanillabp.camunda8;

import io.camunda.zeebe.spring.client.CamundaAutoConfiguration;
import io.camunda.zeebe.spring.client.jobhandling.DefaultCommandExceptionHandlingStrategy;
import io.vanillabp.camunda8.deployment.Camunda8DeploymentAdapter;
import io.vanillabp.camunda8.deployment.DeploymentRepository;
import io.vanillabp.camunda8.deployment.DeploymentResourceRepository;
import io.vanillabp.camunda8.deployment.DeploymentService;
import io.vanillabp.camunda8.service.Camunda8ProcessService;
import io.vanillabp.camunda8.service.Camunda8TransactionAspect;
import io.vanillabp.camunda8.service.Camunda8TransactionProcessor;
import io.vanillabp.camunda8.wiring.Camunda8Connectable.Type;
import io.vanillabp.camunda8.wiring.Camunda8TaskHandler;
import io.vanillabp.camunda8.wiring.Camunda8TaskWiring;
Expand All @@ -17,6 +18,8 @@
import io.vanillabp.springboot.adapter.VanillaBpProperties;
import io.vanillabp.springboot.parameters.MethodParameter;
import jakarta.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopProxyUtils;
Expand All @@ -29,13 +32,13 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.data.repository.CrudRepository;

import java.lang.reflect.Method;
import java.util.List;

@AutoConfigurationPackage(basePackageClasses = Camunda8AdapterConfiguration.class)
@AutoConfigureBefore(CamundaAutoConfiguration.class)
@EnableConfigurationProperties(Camunda8VanillaBpProperties.class)
Expand All @@ -57,9 +60,6 @@ public class Camunda8AdapterConfiguration extends AdapterConfigurationBase<Camun
@Autowired
private ApplicationContext applicationContext;

@Autowired
private DefaultCommandExceptionHandlingStrategy commandExceptionHandlingStrategy;

@Autowired
private DeploymentRepository deploymentRepository;

Expand All @@ -69,6 +69,9 @@ public class Camunda8AdapterConfiguration extends AdapterConfigurationBase<Camun
@Autowired
private Camunda8VanillaBpProperties camunda8Properties;

@Autowired
private ApplicationEventPublisher eventPublisher;

@PostConstruct
public void init() {

Expand All @@ -77,6 +80,14 @@ public void init() {

}

@Bean
@Order(Ordered.LOWEST_PRECEDENCE)
public Camunda8TransactionAspect camunda8TransactionAspect() {

return new Camunda8TransactionAspect(eventPublisher);

}

@Override
public String getAdapterId() {

Expand Down Expand Up @@ -148,7 +159,6 @@ public Camunda8TaskHandler camunda8TaskHandler(

return new Camunda8TaskHandler(
taskType,
commandExceptionHandlingStrategy,
repository,
bean,
method,
Expand All @@ -166,8 +176,9 @@ public <DE> Camunda8ProcessService<?> newProcessServiceImplementation(

final var result = new Camunda8ProcessService<DE>(
camunda8Properties,
eventPublisher,
workflowAggregateRepository,
workflowAggregate -> springDataUtil.getId(workflowAggregate),
springDataUtil::getId,
workflowAggregateClass);

putConnectableService(workflowAggregateClass, result);
Expand All @@ -185,4 +196,31 @@ public SpringBeanUtil vanillabpSpringBeanUtil(

}

/*
* https://www.tirasa.net/en/blog/dynamic-spring-s-transactional-2020-edition
*/
/*
@Bean
public static BeanFactoryPostProcessor camunda8TransactionInterceptorInjector() {
return beanFactory -> {
String[] names = beanFactory.getBeanNamesForType(TransactionInterceptor.class);
for (String name : names) {
BeanDefinition bd = beanFactory.getBeanDefinition(name);
bd.setBeanClassName(Camunda8TransactionInterceptor.class.getName());
bd.setFactoryBeanName(null);
bd.setFactoryMethodName(null);
}
};
}
*/

@Bean
public Camunda8TransactionProcessor camunda8TransactionProcessor() {

return new Camunda8TransactionProcessor();

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public String getTenantId(
if (!configuration.isUseTenants()) {
return null;
}
if (StringUtils.hasText(configuration.getTenant())) {
return configuration.getTenant();
if (StringUtils.hasText(configuration.getTenantId())) {
return configuration.getTenantId();
}
return workflowModuleId;

Expand Down Expand Up @@ -101,7 +101,7 @@ public static class AdapterConfiguration extends WorkerProperties {

private boolean useTenants = true;

private String tenant;
private String tenantId;

public boolean isUseTenants() {
return useTenants;
Expand All @@ -111,12 +111,12 @@ public void setUseTenants(boolean useTenants) {
this.useTenants = useTenants;
}

public String getTenant() {
return tenant;
public String getTenantId() {
return tenantId;
}

public void setTenant(String tenant) {
this.tenant = tenant;
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}

}
Expand Down
Loading

0 comments on commit 1dd57b9

Please sign in to comment.