Skip to content

Commit

Permalink
feat(multitenancy): Add web starter and autoconfiguration
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Vitale <[email protected]>
  • Loading branch information
ThomasVitale committed Jan 27, 2024
1 parent 4b92d6f commit 0a8e19c
Show file tree
Hide file tree
Showing 37 changed files with 894 additions and 155 deletions.
37 changes: 0 additions & 37 deletions arconia-core/.gitignore

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
*/
public final class MdcTenantContextEventListener implements TenantEventListener {

private static final String DEFAULT_TENANT_ID_KEY = "tenantId";
public static final String DEFAULT_TENANT_ID_KEY = "tenantId";

private final String tenantIdKey;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ public class ObservationTenantContextEventListener implements TenantEventListene
private final String tenantIdKey;

public ObservationTenantContextEventListener() {
this(DEFAULT_CARDINALITY, DEFAULT_TENANT_ID_KEY);
this(DEFAULT_TENANT_ID_KEY, DEFAULT_CARDINALITY);
}

public ObservationTenantContextEventListener(Cardinality cardinality, String tenantIdKey) {
Assert.notNull(cardinality, "cardinality cannot be null");
public ObservationTenantContextEventListener(String tenantIdKey, Cardinality cardinality) {
Assert.hasText(tenantIdKey, "tenantIdKey cannot be empty");
this.cardinality = cardinality;
Assert.notNull(cardinality, "cardinality cannot be null");
this.tenantIdKey = tenantIdKey;
this.cardinality = cardinality;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/
public final class FixedTenantResolver implements TenantResolver<Object> {

private static final String DEFAULT_FIXED_TENANT = "default";
public static final String DEFAULT_FIXED_TENANT = "default";

private final String fixedTenantName;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
*
* @author Thomas Vitale
*/
public class TenantRequiredException extends IllegalStateException {
public class TenantResolutionException extends IllegalStateException {

public TenantRequiredException() {
public TenantResolutionException() {
super("A tenant must be specified for the current operation");
}

public TenantRequiredException(String message) {
public TenantResolutionException(String message) {
super(message);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

/**
* Unit tests for {@link DefaultTenantKeyGenerator}.
*
* @author Thomas Vitale
*/
class DefaultTenantKeyGeneratorTests {

DefaultTenantKeyGenerator keyGenerator = new DefaultTenantKeyGenerator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

/**
* Unit tests for {@link TenantContextHolder}.
*
* @author Thomas Vitale
*/
class TenantContextHolderTests {

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

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

/**
* Unit tests for {@link HolderTenantContextEventListener}.
*
* @author Thomas Vitale
*/
class HolderTenantContextEventListenerTests {

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

/**
* Unit tests for {@link MdcTenantContextEventListener}.
*
* @author Thomas Vitale
*/
class MdcTenantContextEventListenerTests {

@Test
Expand Down Expand Up @@ -50,4 +55,4 @@ void whenCustomValueIsUsedAsKey() {
assertThat(MDC.get(tenantKey)).isNull();
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,32 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

/**
* Unit tests for {@link ObservationTenantContextEventListener}.
*
* @author Thomas Vitale
*/
class ObservationTenantContextEventListenerTests {

@Test
void whenNullCardinalityThenThrow() {
assertThatThrownBy(() -> new ObservationTenantContextEventListener(null, "tenant.id"))
assertThatThrownBy(() -> new ObservationTenantContextEventListener("tenant.id", null))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("cardinality cannot be null");
}

@Test
void whenEmptyTenantKeyThenThrow() {
assertThatThrownBy(
() -> new ObservationTenantContextEventListener(ObservationTenantContextEventListener.Cardinality.HIGH,
""))
assertThatThrownBy(() -> new ObservationTenantContextEventListener("",
ObservationTenantContextEventListener.Cardinality.HIGH))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("tenantIdKey cannot be empty");
}

@Test
void whenNullTenantKeyThenThrow() {
assertThatThrownBy(
() -> new ObservationTenantContextEventListener(ObservationTenantContextEventListener.Cardinality.HIGH,
null))
assertThatThrownBy(() -> new ObservationTenantContextEventListener(null,
ObservationTenantContextEventListener.Cardinality.HIGH))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("tenantIdKey cannot be empty");
}
Expand All @@ -54,8 +57,8 @@ void whenDefaultValueIsUsedAsKey() {
void whenCustomValueIsUsedAsKey() {
var tenantKey = "tenant.identifier";
var tenantId = "acme";
var listener = new ObservationTenantContextEventListener(
ObservationTenantContextEventListener.DEFAULT_CARDINALITY, tenantKey);
var listener = new ObservationTenantContextEventListener(tenantKey,
ObservationTenantContextEventListener.DEFAULT_CARDINALITY);
var observationContext = new Observation.Context();
var event = new TenantContextAttachedEvent(tenantId, this);
event.setObservationContext(observationContext);
Expand All @@ -69,8 +72,9 @@ void whenCustomValueIsUsedAsKey() {
@Test
void whenCustomCardinalityIsUsed() {
var tenantId = "acme";
var listener = new ObservationTenantContextEventListener(ObservationTenantContextEventListener.Cardinality.LOW,
ObservationTenantContextEventListener.DEFAULT_TENANT_ID_KEY);
var listener = new ObservationTenantContextEventListener(
ObservationTenantContextEventListener.DEFAULT_TENANT_ID_KEY,
ObservationTenantContextEventListener.Cardinality.LOW);
var observationContext = new Observation.Context();
var event = new TenantContextAttachedEvent(tenantId, this);
event.setObservationContext(observationContext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

/**
* Unit tests for {@link FixedTenantResolver}.
*
* @author Thomas Vitale
*/
class FixedTenantResolverTests {

@Test
Expand Down Expand Up @@ -35,4 +40,4 @@ void whenCustomValueIsUsedAsFixedTenant() {
assertThat(actualTenantId).isEqualTo(expectedTenantId);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

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

/**
* Unit tests for {@link DefaultTenantEventPublisher}.
*
* @author Thomas Vitale
*/
class DefaultTenantEventPublisherTests {

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

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

/**
* Unit tests for {@link TenantEvent}.
*
* @author Thomas Vitale
*/
class TenantEventTests {

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

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

/**
* Unit tests for {@link TenantNotFoundException}.
*
* @author Thomas Vitale
*/
class TenantNotFoundExceptionTests {

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@

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

class TenantRequiredExceptionTests {
/**
* Unit tests for {@link TenantResolutionException}.
*
* @author Thomas Vitale
*/
class TenantResolutionExceptionTests {

@Test
void whenDefaultMessage() {
var exception = new TenantRequiredException();
var exception = new TenantResolutionException();
assertThat(exception).hasMessageContaining("A tenant must be specified for the current operation");
}

@Test
void whenCustomMessage() {
var message = "Custom tenant exception message";
var exception = new TenantRequiredException(message);
var exception = new TenantResolutionException(message);
assertThat(exception).hasMessageContaining(message);
}

Expand Down
40 changes: 40 additions & 0 deletions arconia-spring-boot-autoconfigure/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
plugins {
id 'code-quality-conventions'
id 'java-conventions'
id 'sbom-conventions'
id 'release-conventions'
}

configurations {
compileOnly {
extendsFrom annotationProcessor
}
}

dependencies {
annotationProcessor 'org.springframework.boot:spring-boot-autoconfigure-processor'
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'

implementation 'org.springframework.boot:spring-boot-starter'

optional project(':arconia-core')
optional project(':arconia-web')

optional 'jakarta.servlet:jakarta.servlet-api'

optional 'org.springframework:spring-context'
optional 'org.springframework:spring-web'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

publishing {
publications {
mavenJava(MavenPublication) {
pom {
name = "Arconia Spring Boot Autoconfigure"
description = "Arconia Spring Boot Autoconfigure."
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.arconia.autoconfigure.core.multitenancy;

import org.springframework.boot.context.properties.ConfigurationProperties;

import io.arconia.core.multitenancy.context.resolvers.FixedTenantResolver;

/**
* Configuration properties for fixed tenant resolution.
*
* @author Thomas Vitale
*/
@ConfigurationProperties(prefix = FixedTenantResolutionProperties.CONFIG_PREFIX)
public class FixedTenantResolutionProperties {

public static final String CONFIG_PREFIX = "arconia.multitenancy.resolution.fixed";

/**
* Whether a fixed tenant resolution strategy should be used.
*/
private boolean enabled = false;

/**
* The name of the fixed tenant to use in each context.
*/
private String tenantId = FixedTenantResolver.DEFAULT_FIXED_TENANT;

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public String getTenantId() {
return tenantId;
}

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

}
Loading

0 comments on commit 0a8e19c

Please sign in to comment.