From a3789ba1be46cea8ccaf9a5927302d2f29414d2a Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 6 Nov 2023 22:37:47 +0000
Subject: [PATCH 1/4] Bump org.apache.maven.plugins:maven-javadoc-plugin from
 3.6.0 to 3.6.2

Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.6.0 to 3.6.2.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.6.0...maven-javadoc-plugin-3.6.2)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 multitenancy-spring-boot-starter/pom.xml | 2 +-
 pom.xml                                  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/multitenancy-spring-boot-starter/pom.xml b/multitenancy-spring-boot-starter/pom.xml
index 06e4246..79671ec 100644
--- a/multitenancy-spring-boot-starter/pom.xml
+++ b/multitenancy-spring-boot-starter/pom.xml
@@ -52,7 +52,7 @@
         <maven-deploy.version>3.1.1</maven-deploy.version>
         <maven-gpg.version>3.1.0</maven-gpg.version>
         <maven-install.version>3.1.1</maven-install.version>
-        <maven-javadoc.version>3.6.0</maven-javadoc.version>
+        <maven-javadoc.version>3.6.2</maven-javadoc.version>
         <maven-resources.version>3.3.1</maven-resources.version>
     </properties>
 
diff --git a/pom.xml b/pom.xml
index 4dc3ec8..5cecd01 100644
--- a/pom.xml
+++ b/pom.xml
@@ -77,7 +77,7 @@
         <maven-gpg.version>3.1.0</maven-gpg.version>
         <maven-install.version>3.1.1</maven-install.version>
         <maven-jar.version>3.3.0</maven-jar.version>
-        <maven-javadoc.version>3.6.0</maven-javadoc.version>
+        <maven-javadoc.version>3.6.2</maven-javadoc.version>
         <maven-release.version>3.0.1</maven-release.version>
         <maven-source.version>3.3.0</maven-source.version>
         <maven-surefire.version>3.1.2</maven-surefire.version>

From 764142932c8e1eb90fa3a0fb011dc879b289288a Mon Sep 17 00:00:00 2001
From: Stefan <91stefan@gmail.com>
Date: Wed, 15 Nov 2023 13:43:35 +0100
Subject: [PATCH 2/4] Start Axon Server Tenant components before using them

---
 README.md                                     | 31 ++++++++
 ...ltiTenancyAxonServerAutoConfiguration.java | 74 +++++++++++--------
 2 files changed, 74 insertions(+), 31 deletions(-)

diff --git a/README.md b/README.md
index 3ec5b65..4a9d234 100644
--- a/README.md
+++ b/README.md
@@ -160,6 +160,37 @@ public void retryDLQ(@RequestParam String tenant, @RequestParam String processin
 
 Only JPA Dead letter queue and In-Memory queues are supported.
 
+#### Deadline manager
+
+As of now, there is no plan to support deadline manager out of the box.
+None of deadline manager implementation support multi-tenancy.
+See Event scheduler section as alternative.
+
+#### Event scheduler
+
+You can use event scheduler to schedule events for specific tenant.
+To do so, you need to inject `EventScheduler` and use it to schedule events.
+
+    @Autowired
+    private EventScheduler eventScheduler;
+
+    @EventHandler
+    public void eventHandler(Event event) {
+        ScheduledToken token = eventScheduler.schedule(Instant.now().plusDays(10), event);
+        //example of cancelation
+        eventScheduler.cancelSchedule(token);
+    }
+
+If you use scheduler from any message handler, it will automatically pick up tenant from message metadata, you dont need to specify it.
+If you wish to use scheduler outside of message handlers, you need to wrap execution into tenant transaction where you specify tenant.
+
+            new TenantWrappedTransactionManager(
+                    TenantDescriptor.tenantWithId(tenantName))
+                    .executeInTransaction(() ->
+                        eventScheduler.cancelSchedule(token)
+                    );
+
+
 ### Supported multi-tenant components
 
 Currently, supported multi-tenants components are as follows:
diff --git a/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/MultiTenancyAxonServerAutoConfiguration.java b/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/MultiTenancyAxonServerAutoConfiguration.java
index 69fd9e9..6bbfa20 100644
--- a/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/MultiTenancyAxonServerAutoConfiguration.java
+++ b/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/MultiTenancyAxonServerAutoConfiguration.java
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *    http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -108,17 +108,21 @@ public TenantCommandSegmentFactory tenantAxonServerCommandSegmentFactory(
             AxonServerConfiguration axonServerConfig,
             AxonServerConnectionManager connectionManager
     ) {
-        return tenantDescriptor -> AxonServerCommandBus.builder()
-                                                       .localSegment(localSegment)
-                                                       .serializer(messageSerializer)
-                                                       .routingStrategy(routingStrategy)
-                                                       .priorityCalculator(priorityCalculator)
-                                                       .loadFactorProvider(loadFactorProvider)
-                                                       .targetContextResolver(targetContextResolver)
-                                                       .axonServerConnectionManager(connectionManager)
-                                                       .configuration(axonServerConfig)
-                                                       .defaultContext(tenantDescriptor.tenantId())
-                                                       .build();
+        return tenantDescriptor -> {
+            AxonServerCommandBus commandBus = AxonServerCommandBus.builder()
+                                                             .localSegment(localSegment)
+                                                             .serializer(messageSerializer)
+                                                             .routingStrategy(routingStrategy)
+                                                             .priorityCalculator(priorityCalculator)
+                                                             .loadFactorProvider(loadFactorProvider)
+                                                             .targetContextResolver(targetContextResolver)
+                                                             .axonServerConnectionManager(connectionManager)
+                                                             .configuration(axonServerConfig)
+                                                             .defaultContext(tenantDescriptor.tenantId())
+                                                             .build();
+            commandBus.start();
+            return commandBus;
+        };
     }
 
 
@@ -152,20 +156,23 @@ public TenantQuerySegmentFactory tenantAxonServerQuerySegmentFactory(
                     new CorrelationDataInterceptor<>(config.correlationDataProviders())
             );
 
-            return AxonServerQueryBus.builder()
-                                     .axonServerConnectionManager(axonServerConnectionManager)
-                                     .configuration(axonServerConfig)
-                                     .localSegment(simpleQueryBus)
-                                     .updateEmitter(
-                                             ((MultiTenantQueryUpdateEmitter) multiTenantQueryUpdateEmitter)
-                                                     .getTenant(tenantDescriptor)
-                                     )
-                                     .messageSerializer(messageSerializer)
-                                     .genericSerializer(genericSerializer)
-                                     .priorityCalculator(priorityCalculator)
-                                     .targetContextResolver(targetContextResolver)
-                                     .defaultContext(tenantDescriptor.tenantId())
-                                     .build();
+            AxonServerQueryBus queryBus = AxonServerQueryBus.builder()
+                                                         .axonServerConnectionManager(axonServerConnectionManager)
+                                                         .configuration(axonServerConfig)
+                                                         .localSegment(simpleQueryBus)
+                                                         .updateEmitter(
+                                                                 ((MultiTenantQueryUpdateEmitter) multiTenantQueryUpdateEmitter)
+                                                                         .getTenant(tenantDescriptor)
+                                                         )
+                                                         .messageSerializer(messageSerializer)
+                                                         .genericSerializer(genericSerializer)
+                                                         .priorityCalculator(priorityCalculator)
+                                                         .targetContextResolver(targetContextResolver)
+                                                         .defaultContext(tenantDescriptor.tenantId())
+                                                         .build();
+
+            queryBus.start();
+            return queryBus;
         };
     }
 
@@ -214,11 +221,15 @@ public TenantEventSchedulerSegmentFactory tenantEventSchedulerSegmentFactory(
             AxonServerConnectionManager axonServerConnectionManager,
             Serializer serializer
     ) {
-        return tenant -> AxonServerEventScheduler.builder()
-                                                 .connectionManager(axonServerConnectionManager)
-                                                 .eventSerializer(serializer)
-                                                 .defaultContext(tenant.tenantId())
-                                                 .build();
+        return tenant -> {
+            AxonServerEventScheduler eventScheduler = AxonServerEventScheduler.builder()
+                                                                     .connectionManager(axonServerConnectionManager)
+                                                                     .eventSerializer(serializer)
+                                                                     .defaultContext(tenant.tenantId())
+                                                                     .build();
+            eventScheduler.start();
+            return eventScheduler;
+        };
     }
 
     @Bean
@@ -233,6 +244,7 @@ public EventProcessorInfoConfiguration processorInfoConfiguration(
                     c.getComponent(AxonServerConfiguration.class)
             );
             tenantProvider.subscribe(controlService);
+            controlService.start();
             return controlService;
         });
     }

From f9a55b68b9f3922d16edf5c61fc0e20cb13bafde Mon Sep 17 00:00:00 2001
From: Stefan <91stefan@gmail.com>
Date: Wed, 22 Nov 2023 09:57:28 +0100
Subject: [PATCH 3/4] add a comment about tenant segment creation, and a
 shutdown hook in tenant provided

---
 .../autoconfig/AxonServerTenantProvider.java             | 9 ++++++++-
 .../scheduling/TenantEventSchedulerSegmentFactory.java   | 3 ++-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/AxonServerTenantProvider.java b/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/AxonServerTenantProvider.java
index 76bfd36..ccce48a 100644
--- a/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/AxonServerTenantProvider.java
+++ b/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/AxonServerTenantProvider.java
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *    http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -215,5 +215,12 @@ public Registration subscribe(MultiTenantAwareComponent bus) {
     @Override
     public void registerLifecycleHandlers(@Nonnull LifecycleRegistry lifecycle) {
         lifecycle.onStart(Phase.INSTRUCTION_COMPONENTS + 10, this::start);
+        lifecycle.onShutdown(Phase.INSTRUCTION_COMPONENTS + 10, this::shutdown);
+    }
+
+    private void shutdown() {
+        registrationMap.forEach((tenant, registrationList) -> {
+            registrationList.forEach(Registration::cancel);
+        });
     }
 }
diff --git a/multitenancy/src/main/java/org/axonframework/extensions/multitenancy/components/scheduling/TenantEventSchedulerSegmentFactory.java b/multitenancy/src/main/java/org/axonframework/extensions/multitenancy/components/scheduling/TenantEventSchedulerSegmentFactory.java
index e7f856a..25042b0 100644
--- a/multitenancy/src/main/java/org/axonframework/extensions/multitenancy/components/scheduling/TenantEventSchedulerSegmentFactory.java
+++ b/multitenancy/src/main/java/org/axonframework/extensions/multitenancy/components/scheduling/TenantEventSchedulerSegmentFactory.java
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *    http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -22,6 +22,7 @@
 
 /**
  * Factory for creating {@link EventScheduler} segments for a given {@link TenantDescriptor}.
+ * After a segment is created, it may be started automatically by the factory.
  *
  * @author Stefan Dragisic
  * @since 4.9.0

From 7e6dd156a8a4e8c95eadd56a6dc6e14cba6dc50a Mon Sep 17 00:00:00 2001
From: Stefan <91stefan@gmail.com>
Date: Wed, 22 Nov 2023 10:26:29 +0100
Subject: [PATCH 4/4] The get invocation of the eventProcessorControlService
 variable is retrieving the MultiTenantEventProcessorControlService from a
 Component. Due to this, its lifecycle methods should be invoked.

---
 .../autoconfig/MultiTenancyAxonServerAutoConfiguration.java      | 1 -
 1 file changed, 1 deletion(-)

diff --git a/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/MultiTenancyAxonServerAutoConfiguration.java b/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/MultiTenancyAxonServerAutoConfiguration.java
index 6bbfa20..0de496f 100644
--- a/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/MultiTenancyAxonServerAutoConfiguration.java
+++ b/multitenancy-spring-boot-autoconfigure/src/main/java/org/axonframework/extensions/multitenancy/autoconfig/MultiTenancyAxonServerAutoConfiguration.java
@@ -244,7 +244,6 @@ public EventProcessorInfoConfiguration processorInfoConfiguration(
                     c.getComponent(AxonServerConfiguration.class)
             );
             tenantProvider.subscribe(controlService);
-            controlService.start();
             return controlService;
         });
     }