diff --git a/pom.xml b/pom.xml
index edca9801b..a4ad2c39d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -24,6 +24,7 @@
4.1.52.Final
2.6.0-SNAPSHOT
1.15.1
+ 1.0.6.RELEASE
spring.data.elasticsearch
@@ -256,6 +257,14 @@
test
+
+ io.projectreactor.tools
+ blockhound-junit-platform
+ ${blockhound-junit}
+ test
+
+
+
+
org.skyscreamer
@@ -448,9 +457,7 @@
-
ci
-
@@ -473,9 +480,26 @@
-
+
+ jdk13+
+
+
+ [13,)
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ -XX:+AllowRedefinitionToAddDeleteMethods
+
+
+
+
+
diff --git a/src/test/java/org/springframework/data/elasticsearch/blockhound/BlockHoundIntegrationCustomizer.java b/src/test/java/org/springframework/data/elasticsearch/blockhound/BlockHoundIntegrationCustomizer.java
new file mode 100644
index 000000000..89a8c6900
--- /dev/null
+++ b/src/test/java/org/springframework/data/elasticsearch/blockhound/BlockHoundIntegrationCustomizer.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 the original author or 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
+ *
+ * https://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 org.springframework.data.elasticsearch.blockhound;
+
+import reactor.blockhound.BlockHound;
+import reactor.blockhound.integration.BlockHoundIntegration;
+
+import org.elasticsearch.Build;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.springframework.data.elasticsearch.support.VersionInfo;
+
+/**
+ * @author Peter-Josef Meisch
+ */
+public class BlockHoundIntegrationCustomizer implements BlockHoundIntegration {
+ @Override
+ public void applyTo(BlockHound.Builder builder) {
+ // Elasticsearch classes reading from the classpath on initialization, needed for parsing Elasticsearch responses
+ builder.allowBlockingCallsInside(XContentBuilder.class.getName(), "")
+ .allowBlockingCallsInside(Build.class.getName(), "");
+
+ // Spring Data Elasticsearch classes reading from the classpath
+ builder.allowBlockingCallsInside(VersionInfo.class.getName(), "logVersions");
+ }
+}
diff --git a/src/test/java/org/springframework/data/elasticsearch/blockhound/BlockHoundTests.java b/src/test/java/org/springframework/data/elasticsearch/blockhound/BlockHoundTests.java
new file mode 100644
index 000000000..4bd0392b1
--- /dev/null
+++ b/src/test/java/org/springframework/data/elasticsearch/blockhound/BlockHoundTests.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 the original author or 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
+ *
+ * https://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 org.springframework.data.elasticsearch.blockhound;
+
+import static org.assertj.core.api.Assertions.*;
+
+import reactor.blockhound.BlockingOperationError;
+import reactor.core.publisher.Mono;
+
+import java.time.Duration;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+/**
+ * @author Peter-Josef Meisch
+ */
+public class BlockHoundTests {
+
+ @Test // #1822
+ @DisplayName("should fail if BlockHound is not installed")
+ void shouldFailIfBlockHoundIsNotInstalled() {
+
+ assertThatThrownBy(() -> {
+ Mono.delay(Duration.ofMillis(1)).doOnNext(it -> {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }).block(); // should throw an exception about Thread.sleep
+ }).hasCauseInstanceOf(BlockingOperationError.class);
+ }
+}
diff --git a/src/test/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilderIntegrationTests.java b/src/test/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilderIntegrationTests.java
new file mode 100644
index 000000000..c163aefef
--- /dev/null
+++ b/src/test/java/org/springframework/data/elasticsearch/core/index/ReactiveMappingBuilderIntegrationTests.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2021 the original author or 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
+ *
+ * https://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 org.springframework.data.elasticsearch.core.index;
+
+import static org.springframework.data.elasticsearch.annotations.FieldType.*;
+
+import java.time.Instant;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.elasticsearch.annotations.DateFormat;
+import org.springframework.data.elasticsearch.annotations.Document;
+import org.springframework.data.elasticsearch.annotations.Field;
+import org.springframework.data.elasticsearch.annotations.Mapping;
+import org.springframework.data.elasticsearch.core.ReactiveElasticsearchOperations;
+import org.springframework.data.elasticsearch.core.ReactiveIndexOperations;
+import org.springframework.data.elasticsearch.junit.jupiter.ReactiveElasticsearchRestTemplateConfiguration;
+import org.springframework.data.elasticsearch.junit.jupiter.SpringIntegrationTest;
+import org.springframework.lang.Nullable;
+import org.springframework.test.context.ContextConfiguration;
+
+/**
+ * @author Peter-Josef Meisch
+ */
+@SpringIntegrationTest
+@ContextConfiguration(classes = { ReactiveElasticsearchRestTemplateConfiguration.class })
+public class ReactiveMappingBuilderIntegrationTests {
+
+ @Autowired private ReactiveElasticsearchOperations operations;
+
+ @Test // #1822
+ @DisplayName("should write runtime fields")
+ void shouldWriteRuntimeFields() {
+
+ ReactiveIndexOperations indexOps = operations.indexOps(RuntimeFieldEntity.class);
+
+ indexOps.create().block();
+ indexOps.putMapping().block();
+ indexOps.delete().block();
+ }
+
+ // region entities
+ @Document(indexName = "runtime-fields")
+ @Mapping(runtimeFieldsPath = "/mappings/runtime-fields.json")
+ private static class RuntimeFieldEntity {
+ @Id @Nullable private String id;
+ @Field(type = Date, format = DateFormat.epoch_millis, name = "@timestamp") @Nullable private Instant timestamp;
+ }
+ // endregion
+}
diff --git a/src/test/resources/META-INF/services/reactor.blockhound.integration.BlockHoundIntegration b/src/test/resources/META-INF/services/reactor.blockhound.integration.BlockHoundIntegration
new file mode 100644
index 000000000..1cd5f8f92
--- /dev/null
+++ b/src/test/resources/META-INF/services/reactor.blockhound.integration.BlockHoundIntegration
@@ -0,0 +1 @@
+org.springframework.data.elasticsearch.blockhound.BlockHoundIntegrationCustomizer