Skip to content

Commit

Permalink
[WIP] relates to C2-2197: setup the command serialization with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Senic committed Nov 28, 2022
1 parent d777930 commit 111027e
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.stargate.sgv3.docsapi.api.configuration;

import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import io.quarkus.jackson.ObjectMapperCustomizer;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.Produces;
import javax.inject.Singleton;

/** Configures the {@link ObjectMapper} instance that going to be injectable and used in the app. */
public class ObjectMapperConfiguration {

/** Replaces the CDI producer for ObjectMapper built into Quarkus. */
@Singleton
@Produces
ObjectMapper objectMapper(Instance<ObjectMapperCustomizer> customizers) {
ObjectMapper mapper = createMapper();

// apply all ObjectMapperCustomizer beans (incl. Quarkus)
for (ObjectMapperCustomizer customizer : customizers) {
customizer.customize(mapper);
}

return mapper;
}

private ObjectMapper createMapper() {
// enabled:
// case insensitive enums, so "before" will match to "BEFORE" in an enum
return JsonMapper.builder().enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.stargate.sgv3.docsapi.api.model.command;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.stargate.sgv3.docsapi.api.model.command.impl.InsertOneCommand;

/**
* POJO object (data no behavior) that represents a syntactically and grammatically valid command as
* defined in the API spec.
*
* <p>The behavior about *how* to run a Command is in the {@link CommandResolver}.
*
* <p>Commands <b>should not</b> include JSON other than for documents we want to insert. They
* should represent a translate of the API request into an internal representation. e.g. this
* insulates from tweaking JSON on the wire protocol, we would only need to modify how we create the
* command and nothing else.
*
* <p>These may be created from parsing the incoming message and could also be created
* programmatically for internal and testing purposes.
*
* <p>Each command should validate itself using the javax.validation framework.
*/
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.WRAPPER_OBJECT,
property = "commandName")
@JsonSubTypes({
@JsonSubTypes.Type(value = InsertOneCommand.class),
})
@JsonIgnoreProperties({"commandName"})
public interface Command {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package io.stargate.sgv3.docsapi.api.model.command;

/** Base for any commands that modify, such as insert, delete, update, etc. */
public interface ModifyCommand extends Command {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package io.stargate.sgv3.docsapi.api.model.command;

public interface ReadCommand {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.stargate.sgv3.docsapi.api.model.command.impl;

import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.databind.JsonNode;
import io.stargate.sgv3.docsapi.api.model.command.Command;
import io.stargate.sgv3.docsapi.api.model.command.ModifyCommand;
import javax.validation.constraints.NotNull;
import org.eclipse.microprofile.openapi.annotations.media.Schema;

/**
* Representation of the insertOne API {@link Command}.
*
* @param document The document to insert.
*/
@Schema(description = "Command that inserts a single JSON document.")
@JsonTypeName("insertOne")
public record InsertOneCommand(
@NotNull @Schema(description = "JSON document to insert.") JsonNode document)
implements ModifyCommand {}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package io.stargate.sgv3.docsapi.api.v3;

import io.smallrye.mutiny.Uni;
import io.stargate.sgv3.docsapi.api.model.command.Command;
import io.stargate.sgv3.docsapi.config.constants.OpenApiConstants;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
Expand All @@ -19,7 +22,7 @@ public class CollectionResource {
public static final String BASE_PATH = "/v3/{database}/{collection}";

@POST
public Uni<RestResponse<?>> postCommand() {
public Uni<RestResponse<?>> postCommand(@NotNull @Valid Command command) {
return Uni.createFrom().item(RestResponse.ok());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.stargate.sgv3.docsapi.api.configuration;

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

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.junit.TestProfile;
import io.stargate.sgv2.common.testprofiles.NoGlobalResourcesTestProfile;
import io.stargate.sgv3.docsapi.api.model.command.Command;
import io.stargate.sgv3.docsapi.api.model.command.impl.InsertOneCommand;
import javax.inject.Inject;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

@QuarkusTest
@TestProfile(NoGlobalResourcesTestProfile.Impl.class)
class ObjectMapperConfigurationTest {

@Inject ObjectMapper objectMapper;

@Nested
class InsertOne {

@Test
public void happyPath() throws Exception {
String json =
"""
{
"insertOne": {
"document": {
"some": {
"data": true
}
}
}
}
""";

Command result = objectMapper.readValue(json, Command.class);

assertThat(result)
.isInstanceOfSatisfying(
InsertOneCommand.class,
insertOne -> {
JsonNode document = insertOne.document();
assertThat(document).isNotNull();
assertThat(document.required("some").required("data").asBoolean()).isTrue();
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,24 @@ public static void enableLog() {
}

@Nested
class PostCommand {
class InsertOne {

@Test
public void happyPath() {
public void emptyDocument() {
String json =
"""
{
"insertOne": {
"document": {
}
}
}
""";

given()
.header(HttpConstants.AUTHENTICATION_TOKEN_HEADER_NAME, getAuthToken())
.contentType(ContentType.JSON)
.body(json)
.when()
.post(CollectionResource.BASE_PATH, "database", "collection")
.then()
Expand Down
5 changes: 5 additions & 0 deletions src/test/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# by default ignore bridge for data store props in tests

stargate:
data-store:
ignore-bridge: true

0 comments on commit 111027e

Please sign in to comment.