diff --git a/endpoints/citrus-http/pom.xml b/endpoints/citrus-http/pom.xml
index 7d12033e39..640190b243 100644
--- a/endpoints/citrus-http/pom.xml
+++ b/endpoints/citrus-http/pom.xml
@@ -65,6 +65,15 @@
provided
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
org.springframework
spring-core
diff --git a/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpServerActionBuilder.java b/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpServerActionBuilder.java
index ebe65dc94e..9d9c552ba1 100644
--- a/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpServerActionBuilder.java
+++ b/endpoints/citrus-http/src/main/java/org/citrusframework/http/actions/HttpServerActionBuilder.java
@@ -16,15 +16,21 @@
package org.citrusframework.http.actions;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.citrusframework.TestAction;
import org.citrusframework.TestActionBuilder;
import org.citrusframework.endpoint.Endpoint;
+import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.spi.ReferenceResolver;
import org.citrusframework.spi.ReferenceResolverAware;
import org.citrusframework.util.ObjectHelper;
import org.citrusframework.util.StringUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+
+import static com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT;
/**
* Action executes http server operations such as receiving requests and sending response messages.
@@ -34,6 +40,8 @@
*/
public class HttpServerActionBuilder implements TestActionBuilder.DelegatingTestActionBuilder, ReferenceResolverAware {
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper().enable(INDENT_OUTPUT);
+
/** Bean reference resolver */
private ReferenceResolver referenceResolver;
@@ -73,6 +81,32 @@ public HttpServerResponseActionBuilder respond(HttpStatus status) {
return new HttpServerSendActionBuilder().response(status);
}
+ /**
+ * Generic response builder for sending JSON response messages to client with response status 200 (OK).
+ *
+ * @return
+ */
+ public HttpServerResponseActionBuilder.HttpMessageBuilderSupport respondOkJson(String json) {
+ return new HttpServerSendActionBuilder()
+ .response(HttpStatus.OK)
+ .message()
+ .contentType(MediaType.APPLICATION_JSON_VALUE)
+ .body(json);
+ }
+
+ /**
+ * Generic response builder for sending JSON response messages to client with response status 200 (OK).
+ *
+ * @return
+ */
+ public HttpServerResponseActionBuilder.HttpMessageBuilderSupport respondOkJson(Object json) {
+ try {
+ return respondOkJson(OBJECT_MAPPER.writeValueAsString(json));
+ } catch (JsonProcessingException e) {
+ throw new CitrusRuntimeException("Failed to write JSON body as string!", e);
+ }
+ }
+
/**
* Receive Http requests as server.
*/
diff --git a/endpoints/citrus-http/src/test/java/org/citrusframework/http/actions/HttpServerActionBuilderTest.java b/endpoints/citrus-http/src/test/java/org/citrusframework/http/actions/HttpServerActionBuilderTest.java
new file mode 100644
index 0000000000..8a2b9aea44
--- /dev/null
+++ b/endpoints/citrus-http/src/test/java/org/citrusframework/http/actions/HttpServerActionBuilderTest.java
@@ -0,0 +1,55 @@
+package org.citrusframework.http.actions;
+
+import org.citrusframework.endpoint.Endpoint;
+import org.citrusframework.http.message.HttpMessage;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import static org.mockito.Mockito.mock;
+import static org.springframework.test.util.ReflectionTestUtils.getField;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertTrue;
+
+public class HttpServerActionBuilderTest {
+
+ private static final TestJsonObject JSON_OBJECT_REPRESENTATION = new TestJsonObject("value");
+ private static final String JSON_STRING_REPRESENTATION = """
+ {
+ "property" : "value"
+ }""";
+
+ private HttpServerActionBuilder fixture;
+
+ private static void verifyOkJsonResponse(HttpServerResponseActionBuilder.HttpMessageBuilderSupport httpMessageBuilderSupport) {
+ Object responseMessage = getField(httpMessageBuilderSupport, "httpMessage");
+ assertTrue(responseMessage instanceof HttpMessage);
+
+ HttpMessage httpMessage = (HttpMessage) responseMessage;
+
+ assertEquals(HttpStatus.OK, httpMessage.getStatusCode());
+ assertEquals(MediaType.APPLICATION_JSON_VALUE, httpMessage.getContentType());
+ assertEquals(JSON_STRING_REPRESENTATION, httpMessage.getPayload(String.class).replace("\r\n", "\n"));
+ }
+
+ @BeforeMethod
+ public void beforeMethodSetup() {
+ fixture = new HttpServerActionBuilder(mock(Endpoint.class));
+ }
+
+ @Test
+ public void sendOkJsonFromString() {
+ HttpServerResponseActionBuilder.HttpMessageBuilderSupport httpMessageBuilderSupport = fixture.respondOkJson(JSON_STRING_REPRESENTATION);
+ verifyOkJsonResponse(httpMessageBuilderSupport);
+ }
+
+ @Test
+ public void sendOkJsonFromObject() {
+ HttpServerResponseActionBuilder.HttpMessageBuilderSupport httpMessageBuilderSupport = fixture.respondOkJson(JSON_OBJECT_REPRESENTATION);
+ verifyOkJsonResponse(httpMessageBuilderSupport);
+ }
+
+ private record TestJsonObject(String property) {
+ }
+}