Skip to content
This repository has been archived by the owner on Aug 13, 2020. It is now read-only.

Commit

Permalink
Implement payload-only RestProcessor
Browse files Browse the repository at this point in the history
  • Loading branch information
ZeeshanGhalib committed Apr 22, 2016
1 parent 4dc8fa6 commit 5eeacff
Show file tree
Hide file tree
Showing 7 changed files with 255 additions and 19 deletions.
6 changes: 5 additions & 1 deletion adapters/rest-adapter-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
<artifactId>messaging-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>uk.gov.justice.services</groupId>
<artifactId>core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
Expand Down Expand Up @@ -54,7 +59,6 @@
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.0.16.Final</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

import org.slf4j.Logger;
import uk.gov.justice.services.adapter.rest.envelope.RestEnvelopeBuilderFactory;
import uk.gov.justice.services.common.converter.JsonObjectToStringConverter;
import uk.gov.justice.services.messaging.JsonEnvelope;
import uk.gov.justice.services.messaging.JsonObjectEnvelopeConverter;

import javax.inject.Inject;
import javax.enterprise.inject.Alternative;
import javax.json.JsonObject;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
Expand All @@ -28,18 +26,19 @@
* all the logic for building an envelope from the REST request, passing it to a consumer and building a suitable
* response. This allows testing of this logic independently from the automated generation code.
*/
@Alternative
public class RestProcessor {

private static final Logger LOGGER = getLogger(RestProcessor.class);

@Inject
RestEnvelopeBuilderFactory envelopeBuilderFactory;
private final RestEnvelopeBuilderFactory envelopeBuilderFactory;

@Inject
JsonObjectEnvelopeConverter jsonObjectEnvelopeConverter;
private final Function<JsonEnvelope, String> responsebodyGenerator;

@Inject
JsonObjectToStringConverter jsonObjectToStringConverter;
RestProcessor(RestEnvelopeBuilderFactory envelopeBuilderFactory, Function<JsonEnvelope, String> responsebodyGenerator) {
this.envelopeBuilderFactory = envelopeBuilderFactory;
this.responsebodyGenerator = responsebodyGenerator;
}

/**
* Process an incoming REST request by combining the payload, headers and path parameters into an envelope and
Expand Down Expand Up @@ -83,7 +82,7 @@ public Response processSynchronously(final Function<JsonEnvelope, JsonEnvelope>
} else if (result.payload() == NULL) {
return status(NOT_FOUND).build();
} else {
return status(OK).entity(jsonObjectToStringConverter.convert(jsonObjectEnvelopeConverter.fromEnvelope(result))).build();
return status(OK).entity(responsebodyGenerator.apply(result)).build();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package uk.gov.justice.services.adapter.rest;

import uk.gov.justice.services.adapter.rest.envelope.RestEnvelopeBuilderFactory;
import uk.gov.justice.services.common.converter.JsonObjectToStringConverter;
import uk.gov.justice.services.messaging.JsonObjectEnvelopeConverter;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.inject.Inject;

import static uk.gov.justice.services.core.annotation.Component.QUERY_API;
import static uk.gov.justice.services.core.annotation.Component.componentFrom;

/**
* Produces the correct implementation of RestProcessor depending on the Adapter's Component type.
*/
@ApplicationScoped
public class RestProcessorProducer {

@Inject
JsonObjectToStringConverter jsonObjectToStringConverter;

@Inject
JsonObjectEnvelopeConverter jsonObjectEnvelopeConverter;

@Inject
RestEnvelopeBuilderFactory envelopeBuilderFactory;

private RestProcessor defaultRestProcessor;

private RestProcessor payloadOnlyRestProcessor;

/**
* Produces the correct implementation of a {@link RestProcessor} depending on the
* Adapter annotation at the injection point.
*
* @param injectionPoint class where the {@link RestProcessor} is being injected
* @return the correct RestProcessor instance
* @throws IllegalStateException if the injection point does not have an Adapter annotation
*/
@Produces
public RestProcessor produceRestProcessor(final InjectionPoint injectionPoint) {
return componentFrom(injectionPoint) == QUERY_API ? payloadOnlyRestProcessor() : defaultRestProcessor();
}

private RestProcessor defaultRestProcessor() {
if (defaultRestProcessor == null) {
defaultRestProcessor = new RestProcessor(envelopeBuilderFactory, envelope -> jsonObjectToStringConverter.convert(jsonObjectEnvelopeConverter.fromEnvelope(envelope)));
}
return defaultRestProcessor;
}

private RestProcessor payloadOnlyRestProcessor() {
if (payloadOnlyRestProcessor == null) {
payloadOnlyRestProcessor = new RestProcessor(envelopeBuilderFactory, envelope -> envelope.payloadAsJsonObject().toString());
}
return payloadOnlyRestProcessor;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package uk.gov.justice.services.adapter.rest;

import com.jayway.jsonassert.JsonAssert;
import org.hamcrest.collection.IsCollectionWithSize;
import org.hamcrest.core.IsCollectionContaining;
import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
import org.jboss.resteasy.specimpl.ResteasyHttpHeaders;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import uk.gov.justice.services.adapter.rest.envelope.RestEnvelopeBuilderFactory;
import uk.gov.justice.services.common.converter.JsonObjectToStringConverter;
import uk.gov.justice.services.core.annotation.Adapter;
import uk.gov.justice.services.messaging.DefaultJsonEnvelope;
import uk.gov.justice.services.messaging.JsonEnvelope;
import uk.gov.justice.services.messaging.JsonObjectEnvelopeConverter;
import uk.gov.justice.services.messaging.JsonObjectMetadata;

import javax.enterprise.inject.spi.InjectionPoint;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import java.lang.reflect.Member;
import java.util.HashMap;
import java.util.function.Function;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import static uk.gov.justice.services.core.annotation.Component.QUERY_API;
import static uk.gov.justice.services.core.annotation.Component.QUERY_CONTROLLER;
import static uk.gov.justice.services.messaging.JsonObjectEnvelopeConverter.METADATA;
import static uk.gov.justice.services.messaging.JsonObjectEnvelopeConverter.RESULTS;
import static uk.gov.justice.services.messaging.JsonObjectMetadata.ID;
import static uk.gov.justice.services.messaging.JsonObjectMetadata.NAME;

@RunWith(MockitoJUnitRunner.class)
public class RestProcessorProducerTest {

private static final String ID_VALUE = "861c9430-7bc6-4bf0-b549-6534394b8d65";
private static final String NAME_VALUE = "test.command.do-something";
private static final String ARRAY_ITEM_1 = "Array Item 1";
private static final String ARRAY_ITEM_2 = "Array Item 2";
private static final HashMap<String, String> NOT_USED_PATH_PARAMS = new HashMap<>();
private static final String FIELD_NAME = "name";
private static final String FIELD_VALUE = "TEST NAME";

@Mock
private InjectionPoint queryApiInjectionPoint;

@Mock
private InjectionPoint queryControllerInjectionPoint;

@Mock
private Member queryApiMember;

@Mock
private Member queryControllerMember;

@Mock
private Function<JsonEnvelope, JsonEnvelope> function;

@Mock
private HttpHeaders httpHeaders;

@InjectMocks
private RestProcessorProducer restProcessorProducer;


@Before
public void setup() {

when(queryApiInjectionPoint.getMember()).thenReturn(queryApiMember);
when(queryControllerInjectionPoint.getMember()).thenReturn(queryControllerMember);

doReturn(QueryApiAdapter.class).when(queryApiMember).getDeclaringClass();
doReturn(QueryControllerAdapter.class).when(queryControllerMember).getDeclaringClass();

restProcessorProducer.envelopeBuilderFactory = new RestEnvelopeBuilderFactory();
restProcessorProducer.jsonObjectToStringConverter = new JsonObjectToStringConverter();
restProcessorProducer.jsonObjectEnvelopeConverter = new JsonObjectEnvelopeConverter();
}

@Test
public void shouldReturnPayloadOnlyRestProcessorForJsonArray() {
when(function.apply(any())).thenReturn(envelopeWithArrayPayload());

Response response = restProcessorProducer.produceRestProcessor(queryApiInjectionPoint)
.processSynchronously(function, headersWith("Accept", "application/vnd.somecontext.query.somequery+json"), NOT_USED_PATH_PARAMS);

assertThat(response, notNullValue());
JsonAssert.with(response.getEntity().toString())
.assertThat("$." + RESULTS, IsCollectionWithSize.hasSize(2))
.assertThat("$." + RESULTS, IsCollectionContaining.hasItems(ARRAY_ITEM_1, ARRAY_ITEM_2));
}

@Test
public void shouldReturnPayloadOnlyRestProcessorForJsonObject() {
when(function.apply(any())).thenReturn(envelopeWithJsonObjectPayload());

Response response = restProcessorProducer.produceRestProcessor(queryApiInjectionPoint)
.processSynchronously(function, headersWith("Accept", "application/vnd.somecontext.query.somequery+json"), NOT_USED_PATH_PARAMS);

assertThat(response, notNullValue());
JsonAssert.with(response.getEntity().toString())
.assertThat("$." + FIELD_NAME, equalTo(FIELD_VALUE));
}

@Test
public void shouldReturnDefaultRestProcessor() {
when(function.apply(any())).thenReturn(envelopeWithJsonObjectPayload());

Response response = restProcessorProducer.produceRestProcessor(queryControllerInjectionPoint)
.processSynchronously(function, headersWith("Accept", "application/vnd.somecontext.query.somequery+json"), NOT_USED_PATH_PARAMS);

assertThat(response, notNullValue());
JsonAssert.with(response.getEntity().toString())
.assertThat("$." + FIELD_NAME, equalTo(FIELD_VALUE))
.assertThat("$." + METADATA + "." + ID, equalTo(ID_VALUE))
.assertThat("$." + METADATA + "." + NAME, equalTo(NAME_VALUE));
}

private HttpHeaders headersWith(String headerName, String headerValue) {
MultivaluedMapImpl headersMap = new MultivaluedMapImpl();
headersMap.add(headerName, headerValue);
return new ResteasyHttpHeaders(headersMap);
}

private JsonEnvelope envelopeWithArrayPayload() {
JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();

JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
jsonArrayBuilder.add(ARRAY_ITEM_1);
jsonArrayBuilder.add(ARRAY_ITEM_2);

jsonObjectBuilder.add(RESULTS, jsonArrayBuilder.build());

return DefaultJsonEnvelope.envelopeFrom(JsonObjectMetadata.metadataFrom(metadata()), jsonObjectBuilder.build());
}

private JsonEnvelope envelopeWithJsonObjectPayload() {
JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
jsonObjectBuilder.add(FIELD_NAME, FIELD_VALUE);

return DefaultJsonEnvelope.envelopeFrom(JsonObjectMetadata.metadataFrom(metadata()), jsonObjectBuilder.build());
}

private JsonObject metadata() {
JsonObjectBuilder metadataBuilder = Json.createObjectBuilder();
metadataBuilder.add(ID, ID_VALUE);
metadataBuilder.add(NAME, NAME_VALUE);

return metadataBuilder.build();
}

@Adapter(QUERY_API)
private class QueryApiAdapter {

}

@Adapter(QUERY_CONTROLLER)
private class QueryControllerAdapter {

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import uk.gov.justice.services.adapter.rest.envelope.RestEnvelopeBuilderFactory;
import uk.gov.justice.services.common.converter.JsonObjectToStringConverter;
import uk.gov.justice.services.messaging.JsonEnvelope;
import uk.gov.justice.services.messaging.JsonObjectEnvelopeConverter;
import uk.gov.justice.services.messaging.JsonObjectMetadata;
import uk.gov.justice.services.messaging.Metadata;

Expand Down Expand Up @@ -65,10 +63,7 @@ public class RestProcessorTest {

@Before
public void setup() {
restProcessor = new RestProcessor();
restProcessor.envelopeBuilderFactory = new RestEnvelopeBuilderFactory();
restProcessor.jsonObjectEnvelopeConverter = new JsonObjectEnvelopeConverter();
restProcessor.jsonObjectToStringConverter = new JsonObjectToStringConverter();
restProcessor = new RestProcessor(new RestEnvelopeBuilderFactory(), envelope -> envelope.payload().toString());

metadata = JsonObjectMetadata.metadataFrom(Json.createObjectBuilder()
.add(ID, UUID.randomUUID().toString())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.junit.runner.RunWith;
import uk.gov.justice.api.QueryApiRestExampleApplication;
import uk.gov.justice.services.adapter.rest.RestProcessor;
import uk.gov.justice.services.adapter.rest.RestProcessorProducer;
import uk.gov.justice.services.adapter.rest.envelope.RestEnvelopeBuilderFactory;
import uk.gov.justice.services.adapters.test.utils.dispatcher.AsynchronousRecordingDispatcher;
import uk.gov.justice.services.adapters.test.utils.dispatcher.SynchronousRecordingDispatcher;
Expand Down Expand Up @@ -96,6 +97,7 @@ public Properties properties() {
@Module
@Classes(cdi = true, value = {
RestProcessor.class,
RestProcessorProducer.class,
RestEnvelopeBuilderFactory.class,
AsynchronousRecordingDispatcher.class,
SynchronousRecordingDispatcher.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
*/
public class JsonObjectEnvelopeConverter {

private static final String METADATA = "_metadata";
private static final String RESULTS = "results";
public static final String METADATA = "_metadata";
public static final String RESULTS = "results";

/**
* Converts a jsonObject into {@link JsonEnvelope}
Expand Down

0 comments on commit 5eeacff

Please sign in to comment.