Skip to content

Commit

Permalink
Add initial Spring Boot implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Spikhalskiy committed Jul 14, 2022
1 parent abb3cb1 commit 79def99
Show file tree
Hide file tree
Showing 33 changed files with 1,380 additions and 16 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ target
.gradle
/build
/*/build
/out
**/out
/lib
dummy
$buildDir
Expand Down
13 changes: 8 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,23 @@ ext {
// We have to use specific versions with platforms until Maven 4.0.0 is released
// See https://github.com/temporalio/sdk-java/issues/1033
//
// grpcVersion = '[1.34.0,)!!1.44.1'
// grpcVersion = '[1.34.0,)!!1.47.0'
// jacksonVersion = '[2.9.0,)!!2.13.1'
// micrometerVersion = '[1.0.0,)!!1.8.3'
// micrometerVersion = '[1.0.0,)!!1.9.2'
// springBootVersion = '[2.4.0,)!!2.7.1'
grpcVersion = '1.47.0'
jacksonVersion = '2.13.1'
micrometerVersion = '1.9.1'
micrometerVersion = '1.9.2'
springBootVersion = '2.7.1'

slf4jVersion = '[1.4.0,)!!1.7.36'
protoVersion = '[3.10.0,3.99)!!3.20.1'
annotationApiVersion = '1.3.2'
guavaVersion = '[10.0,)!!31.1-jre'
jsonPathVersion = '2.7.0'
tallyVersion = '[0.4.0,)!!0.11.1'

jsonPathVersion = '2.7.0'
gsonVersion = '[2.0,)!!2.9.0'
slf4jVersion = '[1.4.0,)!!1.7.36'

logbackVersion = '1.2.11'
mockitoVersion = '4.6.1'
Expand Down
2 changes: 2 additions & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ include 'temporal-testing'
include 'temporal-test-server'
include 'temporal-opentracing'
include 'temporal-kotlin'
include 'temporal-spring-boot-autoconfigure-alpha'
include 'temporal-spring-boot-starter-alpha'
4 changes: 1 addition & 3 deletions temporal-sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ dependencies {
api "com.fasterxml.jackson.core:jackson-databind"
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310"
implementation "com.fasterxml.jackson.datatype:jackson-datatype-jdk8"
if (!JavaVersion.current().isJava8()) {
implementation 'javax.annotation:javax.annotation-api:1.3.2'
}

// compileOnly and testImplementation because this dependency is needed only to work with json format of history
// which shouldn't be needed for any production usage of temporal-sdk.
// It's useful only for unit tests and debugging.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
* machines in case of child workflow task execution failure and contains an original unparsed
* Failure message with details from the attributes in the exception.
*
* <p>This class is needed to don't make Failure -> Exception conversion inside the state machines.
* So the state machine forms ChildWorkflowFailure without cause and parse the original Failure, so
* the outside code may join them together.
* <p>This class is needed to don't make Failure -&gt; Exception conversion inside the state
* machines. So the state machine forms ChildWorkflowFailure without cause and parse the original
* Failure, so the outside code may join them together.
*/
public class ChildWorkflowTaskFailedException extends RuntimeException {

Expand Down
4 changes: 2 additions & 2 deletions temporal-serviceclient/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ dependencies {
api "io.grpc:grpc-stub" //Part of WorkflowServiceStubs API
api "io.grpc:grpc-netty-shaded" //Part of WorkflowServiceStubs API, specifically SslContext
api "com.google.protobuf:protobuf-java-util:$protoVersion" //proto request and response objects are a part of this module's API
if (!JavaVersion.current().isJava8()) {
//needed for the generated grpc stubs
if (JavaVersion.current().isJava9Compatible()) {
//needed for the generated grpc stubs and is not a part of JDK since java 9
implementation "javax.annotation:javax.annotation-api:$annotationApiVersion"
}

Expand Down
30 changes: 30 additions & 0 deletions temporal-spring-boot-autoconfigure-alpha/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
description = '''Spring Boot AutoConfigure for Temporal Java SDK'''

dependencies {
api(platform("org.springframework.boot:spring-boot-dependencies:$springBootVersion"))

api project(':temporal-sdk')
compileOnly project(':temporal-testing')

implementation "org.springframework.boot:spring-boot"
implementation "org.springframework.boot:spring-boot-autoconfigure"

// this dependency is not mandatory for the module to work, but it provides a better IDE experience developing the module
// it's needed to auto-generate configuration metadata. See for more details:
// https://docs.spring.io/spring-boot/docs/2.4.0/reference/html/appendix-configuration-metadata.html#configuration-metadata-annotation-processor
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor:$springBootVersion"

testImplementation project(':temporal-testing')

testImplementation "org.mockito:mockito-core:${mockitoVersion}"
testImplementation group: 'ch.qos.logback', name: 'logback-classic', version: "${logbackVersion}"

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

tasks.test {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved.
*
* Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Modifications copyright (C) 2017 Uber Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this material 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.temporal.spring.boot;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface ActivityImpl {
String[] taskQueues();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved.
*
* Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Modifications copyright (C) 2017 Uber Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this material 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.temporal.spring.boot;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface WorkflowImpl {
String[] taskQueues();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved.
*
* Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Modifications copyright (C) 2017 Uber Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this material 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.temporal.spring.boot.autoconfigure;

import io.temporal.client.WorkflowClient;
import io.temporal.client.WorkflowClientOptions;
import io.temporal.serviceclient.WorkflowServiceStubs;
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
import io.temporal.spring.boot.autoconfigure.properties.ClientProperties;
import io.temporal.spring.boot.autoconfigure.properties.TemporalProperties;
import io.temporal.testing.TestWorkflowEnvironment;
import javax.annotation.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.support.BeanDefinitionValidationException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** Provides a client based on `spring.temporal.client` section */
@Configuration
@EnableConfigurationProperties(TemporalProperties.class)
@ConditionalOnClass(name = "io.temporal.client.WorkflowClient")
@ConditionalOnProperty(prefix = "spring.temporal", name = "client.target")
public class ClientAutoConfiguration {

@Bean(name = "temporalWorkflowClient")
@ConditionalOnMissingBean(name = "temporalWorkflowClient")
public WorkflowClient client(
TemporalProperties temporalProperties,
@Qualifier("temporalTestWorkflowEnvironment") @Autowired(required = false) @Nullable
TestWorkflowEnvironment testWorkflowEnvironment) {
ClientProperties clientProperties = temporalProperties.getClient();
WorkflowServiceStubs workflowServiceStubs;
switch (temporalProperties.getClient().getTarget().toLowerCase()) {
case ClientProperties.TARGET_IN_PROCESS_TEST_SERVER:
if (testWorkflowEnvironment == null) {
throw new BeanDefinitionValidationException(
"Test workflow environment is not available. "
+ "Please make sure that you have enabled the 'temporal-test' module "
+ "and configured `spring.temporal.testServer.enabled: true`.");
}
return testWorkflowEnvironment.getWorkflowClient();
case ClientProperties.TARGET_LOCAL_SERVICE:
workflowServiceStubs = WorkflowServiceStubs.newLocalServiceStubs();
break;
default:
WorkflowServiceStubsOptions.Builder stubsOptionsBuilder =
WorkflowServiceStubsOptions.newBuilder();

if (clientProperties.getTarget() != null) {
stubsOptionsBuilder.setTarget(clientProperties.getTarget());
}

workflowServiceStubs =
WorkflowServiceStubs.newServiceStubs(
stubsOptionsBuilder.validateAndBuildWithDefaults());
}

WorkflowClientOptions.Builder clientOptionsBuilder = WorkflowClientOptions.newBuilder();

if (clientProperties.getNamespace() != null) {
clientOptionsBuilder.setNamespace(clientProperties.getNamespace());
}

return WorkflowClient.newInstance(
workflowServiceStubs, clientOptionsBuilder.validateAndBuildWithDefaults());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved.
*
* Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Modifications copyright (C) 2017 Uber Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this material 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.temporal.spring.boot.autoconfigure;

import io.temporal.spring.boot.autoconfigure.properties.TemporalProperties;
import io.temporal.testing.TestWorkflowEnvironment;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/** Provides a client based on `spring.temporal.testServer` section */
@Configuration
@EnableConfigurationProperties(TemporalProperties.class)
@ConditionalOnClass(name = "io.temporal.testing.TestWorkflowEnvironment")
@ConditionalOnProperty(
prefix = "spring.temporal",
name = "testServer.enabled",
havingValue = "true")
public class TestServerAutoConfiguration {
@Bean(name = "temporalTestWorkflowEnvironment", destroyMethod = "close")
public TestWorkflowEnvironment testServer() {
return TestWorkflowEnvironment.newInstance();
}
}
Loading

0 comments on commit 79def99

Please sign in to comment.