Skip to content
Open
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
129 changes: 129 additions & 0 deletions dapr-spring/dapr-spring-boot-4-autoconfigure/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?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.dapr.spring</groupId>
<artifactId>dapr-spring-parent</artifactId>
<version>1.18.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>dapr-spring-boot-4-autoconfigure</artifactId>
<name>dapr-spring-boot-4-autoconfigure</name>
<description>Dapr Spring Boot 4.x Autoconfigure</description>
<packaging>jar</packaging>

<properties>
<springboot4.version>4.0.2</springboot4.version>
<!-- Override JUnit version to align with Spring Boot 4.0.2 -->
<junit-bom.version>6.0.2</junit-bom.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot4.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-jackson</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.dapr.spring</groupId>
<artifactId>dapr-spring-6-data</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.dapr</groupId>
<artifactId>dapr-sdk-actors</artifactId>
</dependency>
<dependency>
<groupId>io.dapr.spring</groupId>
<artifactId>dapr-spring-messaging</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.dapr.spring</groupId>
<artifactId>dapr-spring-workflows</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.dapr.spring</groupId>
<artifactId>dapr-spring-boot-properties</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-keyvalue</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.dapr</groupId>
<artifactId>testcontainers-dapr</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
* Copyright 2024 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* 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
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/

package io.dapr.spring.boot4.autoconfigure.client;

import io.dapr.actors.client.ActorClient;
import io.dapr.actors.runtime.ActorRuntime;
import io.dapr.client.DaprClient;
import io.dapr.client.DaprClientBuilder;
import io.dapr.config.Properties;
import io.dapr.serializer.DaprObjectSerializer;
import io.dapr.spring.boot.properties.client.ClientPropertiesDaprConnectionDetails;
import io.dapr.spring.boot.properties.client.DaprClientProperties;
import io.dapr.spring.boot.properties.client.DaprConnectionDetails;
import io.dapr.workflows.client.DaprWorkflowClient;
import io.dapr.workflows.runtime.WorkflowRuntimeBuilder;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import java.util.HashMap;
import java.util.Map;

@AutoConfiguration
@ConditionalOnClass(DaprClient.class)
@EnableConfigurationProperties(DaprClientProperties.class)
public class DaprClientSB4AutoConfiguration {

@Bean
@ConditionalOnMissingBean(DaprConnectionDetails.class)
DaprConnectionDetails daprConnectionDetails(DaprClientProperties properties) {
return new ClientPropertiesDaprConnectionDetails(properties);
}

@Bean
@ConditionalOnMissingBean
DaprClientBuilder daprClientBuilder(DaprConnectionDetails daprConnectionDetails,
ObjectProvider<DaprObjectSerializer> serializerProvider) {
DaprClientBuilder builder = createDaprClientBuilder();

DaprObjectSerializer serializer = serializerProvider.getIfAvailable();
if (serializer != null) {
builder.withObjectSerializer(serializer);
builder.withStateSerializer(serializer);
}

String httpEndpoint = daprConnectionDetails.getHttpEndpoint();

if (httpEndpoint != null) {
builder.withPropertyOverride(Properties.HTTP_ENDPOINT, httpEndpoint);
}

String grpcEndpoint = daprConnectionDetails.getGrpcEndpoint();

if (grpcEndpoint != null) {
builder.withPropertyOverride(Properties.GRPC_ENDPOINT, grpcEndpoint);
}

Integer httpPort = daprConnectionDetails.getHttpPort();

if (httpPort != null) {
builder.withPropertyOverride(Properties.HTTP_PORT, String.valueOf(httpPort));
}

Integer grpcPort = daprConnectionDetails.getGrpcPort();

if (grpcPort != null) {
builder.withPropertyOverride(Properties.GRPC_PORT, String.valueOf(grpcPort));
}

String apiToken = daprConnectionDetails.getApiToken();
if (apiToken != null) {
builder.withPropertyOverride(Properties.API_TOKEN, apiToken);
}

return builder;
}

@Bean
@ConditionalOnMissingBean
DaprClient daprClient(DaprClientBuilder daprClientBuilder) {
return daprClientBuilder.build();
}

@Bean
@ConditionalOnMissingBean
DaprWorkflowClient daprWorkflowClient(DaprConnectionDetails daprConnectionDetails) {
Properties properties = createPropertiesFromConnectionDetails(daprConnectionDetails);
return new DaprWorkflowClient(properties);
}

@Bean
@ConditionalOnMissingBean
ActorClient daprActorClient(DaprConnectionDetails daprConnectionDetails) {
Properties properties = createPropertiesFromConnectionDetails(daprConnectionDetails);
return new ActorClient(properties);
}

@Bean
@ConditionalOnMissingBean
ActorRuntime daprActorRuntime(DaprConnectionDetails daprConnectionDetails) {
Properties properties = createPropertiesFromConnectionDetails(daprConnectionDetails);
return ActorRuntime.getInstance(properties);
}

@Bean
@ConditionalOnMissingBean
WorkflowRuntimeBuilder daprWorkflowRuntimeBuilder(DaprConnectionDetails daprConnectionDetails) {
Properties properties = createPropertiesFromConnectionDetails(daprConnectionDetails);

return new WorkflowRuntimeBuilder(properties);
}

/**
* We use this method in tests to override the default DaprClientBuilder.
*/
protected DaprClientBuilder createDaprClientBuilder() {
return new DaprClientBuilder();
}

/**
* Creates a Properties object from the DaprConnectionDetails.
*
* @param daprConnectionDetails the DaprConnectionDetails
* @return the Properties object
*/
protected Properties createPropertiesFromConnectionDetails(DaprConnectionDetails daprConnectionDetails) {
Map<String, String> propertyOverrides = new HashMap<>();
String httpEndpoint = daprConnectionDetails.getHttpEndpoint();

if (httpEndpoint != null) {
propertyOverrides.put(Properties.HTTP_ENDPOINT.getName(), httpEndpoint);
}

Integer httpPort = daprConnectionDetails.getHttpPort();

if (httpPort != null) {
propertyOverrides.put(Properties.HTTP_PORT.getName(), String.valueOf(httpPort));
}

String grpcEndpoint = daprConnectionDetails.getGrpcEndpoint();

if (grpcEndpoint != null) {
propertyOverrides.put(Properties.GRPC_ENDPOINT.getName(), grpcEndpoint);
}

Integer grpcPort = daprConnectionDetails.getGrpcPort();

if (grpcPort != null) {
propertyOverrides.put(Properties.GRPC_PORT.getName(), String.valueOf(grpcPort));
}

String apiToken = daprConnectionDetails.getApiToken();
if (apiToken != null) {
propertyOverrides.put(Properties.API_TOKEN.getName(), apiToken);
}

return new Properties(propertyOverrides);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2025 The Dapr Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* 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
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
limitations under the License.
*/

package io.dapr.spring.boot4.autoconfigure.client;

import io.dapr.serializer.DaprObjectSerializer;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import tools.jackson.databind.json.JsonMapper;

/**
* Auto-configuration that bridges Jackson 3's {@link JsonMapper} into a {@link DaprObjectSerializer}.
*
* <p>Activates only when Jackson 3 is on the classpath and no other {@link DaprObjectSerializer}
* bean has been defined. Runs after {@link JacksonAutoConfiguration} (which creates the
* {@link JsonMapper} bean) and before {@link DaprClientSB4AutoConfiguration} (which consumes it).
*/
@AutoConfiguration(after = JacksonAutoConfiguration.class, before = DaprClientSB4AutoConfiguration.class)
@ConditionalOnClass(JsonMapper.class)
public class DaprJackson3SB4AutoConfiguration {

@Bean
@ConditionalOnMissingBean(DaprObjectSerializer.class)
DaprObjectSerializer daprObjectSerializer(JsonMapper jsonMapper) {
return new Jackson3ObjectSerializer(jsonMapper);
}
}
Loading
Loading