WillemJiang closed pull request #258: [SCB-855]Support JDK7 in saga-format URL: https://github.com/apache/incubator-servicecomb-saga/pull/258
This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/saga-format/pom.xml b/saga-format/pom.xml index 79e6fadc..b69473b7 100644 --- a/saga-format/pom.xml +++ b/saga-format/pom.xml @@ -16,7 +16,8 @@ ~ limitations under the License. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>saga</artifactId> <groupId>org.apache.servicecomb.saga</groupId> @@ -71,4 +72,19 @@ </dependency> </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.1</version> + <configuration> + <encoding>UTF-8</encoding> + <source>1.7</source> + <target>1.7</target> + </configuration> + </plugin> + </plugins> + </build> + </project> diff --git a/saga-format/src/main/java/org/apache/servicecomb/saga/format/ChildrenExtractor.java b/saga-format/src/main/java/org/apache/servicecomb/saga/format/ChildrenExtractor.java index cfd3b1c4..58cb1eb1 100644 --- a/saga-format/src/main/java/org/apache/servicecomb/saga/format/ChildrenExtractor.java +++ b/saga-format/src/main/java/org/apache/servicecomb/saga/format/ChildrenExtractor.java @@ -21,6 +21,8 @@ import java.util.HashSet; import java.util.Set; +import com.fasterxml.jackson.databind.JsonNode; + import org.apache.servicecomb.saga.core.SagaException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -31,6 +33,7 @@ public class ChildrenExtractor implements FromJsonFormat<Set<String>> { private static final String SAGA_CHILDREN = "sagaChildren"; + private final ObjectMapper objectMapper = new ObjectMapper(); @Override @@ -46,8 +49,9 @@ Set<String> children = new HashSet<>(); if (value.has(SAGA_CHILDREN)) { - value.get(SAGA_CHILDREN) - .forEach(node -> children.add(node.textValue())); + for (JsonNode node : value.get(SAGA_CHILDREN)) { + children.add(node.textValue()); + } } return children; diff --git a/saga-format/src/main/java/org/apache/servicecomb/saga/format/JacksonRestOperation.java b/saga-format/src/main/java/org/apache/servicecomb/saga/format/JacksonRestOperation.java index 4d424517..10876faa 100644 --- a/saga-format/src/main/java/org/apache/servicecomb/saga/format/JacksonRestOperation.java +++ b/saga-format/src/main/java/org/apache/servicecomb/saga/format/JacksonRestOperation.java @@ -51,7 +51,12 @@ public SagaResponse send(String address) { @Override public SagaResponse send(String address, SagaResponse response) { Map<String, Map<String, String>> updated = new HashMap<>(params()); - updated.computeIfAbsent("form", (key) -> new HashMap<>()).put("response", response.body()); + // This is not thread safe + if (updated.get("form") == null) { + HashMap<String, String> formMap = new HashMap<>(); + formMap.put("response", response.body()); + updated.put("form", formMap); + } return transport.with( address, diff --git a/saga-format/src/main/java/org/apache/servicecomb/saga/format/JacksonSagaEventFormat.java b/saga-format/src/main/java/org/apache/servicecomb/saga/format/JacksonSagaEventFormat.java index 1b416aaf..8b365c67 100644 --- a/saga-format/src/main/java/org/apache/servicecomb/saga/format/JacksonSagaEventFormat.java +++ b/saga-format/src/main/java/org/apache/servicecomb/saga/format/JacksonSagaEventFormat.java @@ -20,7 +20,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; -import java.util.function.BiFunction; import org.apache.servicecomb.saga.core.FailedSagaRequestContext; import org.apache.servicecomb.saga.core.NoOpSagaRequest; @@ -40,12 +39,42 @@ public class JacksonSagaEventFormat implements SagaEventFormat { private final Map<String, BiFunction<String, String, SagaEvent>> eventFactories = new HashMap<String, BiFunction<String, String, SagaEvent>>() {{ - put(SagaStartedEvent.class.getSimpleName(), (sagaId, json) -> sagaStartedEvent(sagaId, json)); - put(TransactionStartedEvent.class.getSimpleName(), (sagaId, json) -> transactionStartedEvent(sagaId, json)); - put(TransactionEndedEvent.class.getSimpleName(), (sagaId, json) -> transactionEndedEvent(sagaId, json)); - put(TransactionAbortedEvent.class.getSimpleName(), (sagaId, json) -> transactionAbortedEvent(sagaId, json)); - put(TransactionCompensatedEvent.class.getSimpleName(), (sagaId, json) -> compensationEndedEvent(sagaId, json)); - put(SagaEndedEvent.class.getSimpleName(), (sagaId, json) -> sagaEndedEvent(sagaId)); + put(SagaStartedEvent.class.getSimpleName(), new BiFunction<String, String, SagaEvent>() { + @Override + public SagaEvent apply(String sagaId, String json) { + return sagaStartedEvent(sagaId, json); + } + }); + put(TransactionStartedEvent.class.getSimpleName(), new BiFunction<String, String, SagaEvent>() { + @Override + public SagaEvent apply(String sagaId, String json) { + return transactionStartedEvent(sagaId, json); + } + }); + put(TransactionEndedEvent.class.getSimpleName(), new BiFunction<String, String, SagaEvent>() { + @Override + public SagaEvent apply(String sagaId, String json) { + return transactionEndedEvent(sagaId, json); + } + }); + put(TransactionAbortedEvent.class.getSimpleName(), new BiFunction<String, String, SagaEvent>() { + @Override + public SagaEvent apply(String sagaId, String json) { + return transactionAbortedEvent(sagaId, json); + } + }); + put(TransactionCompensatedEvent.class.getSimpleName(), new BiFunction<String, String, SagaEvent>() { + @Override + public SagaEvent apply(String sagaId, String json) { + return compensationEndedEvent(sagaId, json); + } + }); + put(SagaEndedEvent.class.getSimpleName(), new BiFunction<String, String, SagaEvent>() { + @Override + public SagaEvent apply(String sagaId, String json) { + return sagaEndedEvent(sagaId); + } + }); }}; private final ObjectMapper objectMapper = new ObjectMapper(); @@ -111,4 +140,8 @@ private SagaEvent sagaEndedEvent(String sagaId) { private String cause(String sagaId, String json) { return "Failed to deserialize saga event of sage id: " + sagaId + " from json: " + json; } + + private interface BiFunction<T, U, R> { + R apply(T t, U u); + } } diff --git a/saga-format/src/main/java/org/apache/servicecomb/saga/format/JsonSagaDefinition.java b/saga-format/src/main/java/org/apache/servicecomb/saga/format/JsonSagaDefinition.java index 5293a130..0cf3bc6c 100644 --- a/saga-format/src/main/java/org/apache/servicecomb/saga/format/JsonSagaDefinition.java +++ b/saga-format/src/main/java/org/apache/servicecomb/saga/format/JsonSagaDefinition.java @@ -32,12 +32,13 @@ static final RecoveryPolicy backwardRecovery = new BackwardRecovery(); - private static final Map<String, RecoveryPolicy> policies = new HashMap<String, RecoveryPolicy>(){{ + private static final Map<String, RecoveryPolicy> policies = new HashMap<String, RecoveryPolicy>() {{ put(RecoveryPolicy.SAGA_BACKWARD_RECOVERY_POLICY, backwardRecovery); put(RecoveryPolicy.SAGA_FORWARD_RECOVERY_POLICY, new ForwardRecovery()); }}; private final JsonSagaRequest[] requests; + private final RecoveryPolicy policy; public JsonSagaDefinition( @@ -45,7 +46,7 @@ public JsonSagaDefinition( @JsonProperty("requests") JsonSagaRequest[] requests) { this.requests = requests; - this.policy = policies.getOrDefault(policy, backwardRecovery); + this.policy = null == policies.get(policy) ? backwardRecovery : policies.get(policy); } @Override diff --git a/saga-format/src/test/java/org/apache/servicecomb/saga/format/JacksonFromJsonFormatTest.java b/saga-format/src/test/java/org/apache/servicecomb/saga/format/JacksonFromJsonFormatTest.java index bbf7510f..f2ae7242 100644 --- a/saga-format/src/test/java/org/apache/servicecomb/saga/format/JacksonFromJsonFormatTest.java +++ b/saga-format/src/test/java/org/apache/servicecomb/saga/format/JacksonFromJsonFormatTest.java @@ -18,7 +18,6 @@ package org.apache.servicecomb.saga.format; import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify; -import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; import static org.hamcrest.Matchers.contains; import static org.hamcrest.core.Is.is; @@ -27,12 +26,7 @@ import static org.mockito.Mockito.when; import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; +import java.util.*; import org.apache.servicecomb.saga.core.Operation; import org.apache.servicecomb.saga.core.SagaException; @@ -158,6 +152,43 @@ private final TransportFactory transportFactory = Mockito.mock(TransportFactory.class); private final FromJsonFormat<SagaDefinition> format = new JacksonFromJsonFormat(transportFactory); + private final Map<String, Map<String, String>> EMPTY_MAP = Collections.<String, Map<String, String>>emptyMap(); + + private final Function<SagaRequest, String> getRequestId = new Function<SagaRequest, String>() { + @Override + public String apply(SagaRequest sagaRequest) { + return sagaRequest.id(); + } + }; + + private final Function<SagaRequest, String> getRequestServiceName = new Function<SagaRequest, String>() { + @Override + public String apply(SagaRequest sagaRequest) { + return sagaRequest.serviceName(); + } + }; + + private final Function<SagaRequest, String> getRequestType = new Function<SagaRequest, String>() { + @Override + public String apply(SagaRequest sagaRequest) { + return sagaRequest.type(); + } + }; + + private final Function<SagaRequest, Integer> getCompensationRetries = new Function<SagaRequest, Integer>() { + @Override + public Integer apply(SagaRequest sagaRequest) { + return sagaRequest.compensation().retries(); + } + }; + + private final Function<SagaRequest, String> getFallbackType = new Function<SagaRequest, String>() { + @Override + public String apply(SagaRequest sagaRequest) { + return sagaRequest.fallback().type(); + } + }; + @Before public void setUp() throws Exception { when(transportFactory.restTransport()).thenReturn(restTransport); @@ -166,23 +197,24 @@ public void setUp() throws Exception { .thenReturn(response11); when(restTransport.with("aaa", "/rest/as", "delete", singletonMap("query", singletonMap("bar", "as")))) .thenReturn(response12); - when(restTransport.with("aaa", "/rest/as", "put", emptyMap())) + when(restTransport.with("aaa", "/rest/as", "put", EMPTY_MAP)) .thenReturn(response13); when(restTransport - .with("bbb", "/rest/bs", "post", mapOf("query", singletonMap("foo", "bs"), "json", singletonMap("body", "{ \"bar\": \"bs\" }")))) + .with("bbb", "/rest/bs", "post", + mapOf("query", singletonMap("foo", "bs"), "json", singletonMap("body", "{ \"bar\": \"bs\" }")))) .thenReturn(response21); - when(restTransport.with("bbb", "/rest/bs", "delete", emptyMap())) + when(restTransport.with("bbb", "/rest/bs", "delete", EMPTY_MAP)) .thenReturn(response22); - when(restTransport.with("bbb", "/rest/bs", "put", emptyMap())) + when(restTransport.with("bbb", "/rest/bs", "put", EMPTY_MAP)) .thenReturn(response23); when(restTransport .with("ccc", "/rest/cs", "post", mapOf("query", singletonMap("foo", "cs"), "form", singletonMap("bar", "cs")))) .thenReturn(response31); - when(restTransport.with("ccc", "/rest/cs", "delete", emptyMap())) + when(restTransport.with("ccc", "/rest/cs", "delete", EMPTY_MAP)) .thenReturn(response32); - when(restTransport.with("ccc", "/rest/cs", "put", emptyMap())) + when(restTransport.with("ccc", "/rest/cs", "put", EMPTY_MAP)) .thenReturn(response33); } @@ -190,12 +222,12 @@ public void setUp() throws Exception { public void addTransportToDeserializedRequests() throws IOException { SagaRequest[] sagaRequests = format.fromJson(requests).requests(); - assertThat(collect(sagaRequests, SagaRequest::id), contains("request-aaa", "request-bbb", "request-ccc")); - assertThat(collect(sagaRequests, SagaRequest::serviceName), contains("aaa", "bbb", "ccc")); - assertThat(collect(sagaRequests, SagaRequest::type), Matchers + assertThat(collect(sagaRequests, getRequestId), contains("request-aaa", "request-bbb", "request-ccc")); + assertThat(collect(sagaRequests, getRequestServiceName), contains("aaa", "bbb", "ccc")); + assertThat(collect(sagaRequests, getRequestType), Matchers .contains(Operation.TYPE_REST, Operation.TYPE_REST, Operation.TYPE_REST)); - assertThat(collect(sagaRequests, (request) -> request.compensation().retries()), contains(3, 4, 5)); - assertThat(collect(sagaRequests, (request) -> request.fallback().type()), Matchers + assertThat(collect(sagaRequests, getCompensationRetries), contains(3, 4, 5)); + assertThat(collect(sagaRequests, getFallbackType), Matchers .contains(Operation.TYPE_REST, Operation.TYPE_REST, Operation.TYPE_REST)); SagaResponse response = sagaRequests[0].transaction().send("aaa"); @@ -226,7 +258,7 @@ public void addTransportToDeserializedRequests() throws IOException { response = sagaRequests[2].fallback().send("ccc"); assertThat(response, is(response33)); - assertArrayEquals(new String[]{"request-aaa", "request-bbb"}, sagaRequests[2].parents()); + assertArrayEquals(new String[] {"request-aaa", "request-bbb"}, sagaRequests[2].parents()); } @Test @@ -242,9 +274,11 @@ public void blowsUpWhenJsonIsInvalid() throws IOException { } private <T> Collection<T> collect(SagaRequest[] requests, Function<SagaRequest, T> mapper) { - return Arrays.stream(requests) - .map(mapper) - .collect(Collectors.toList()); + List<T> result = new LinkedList<T>(); + for (SagaRequest request : requests) { + result.add(mapper.apply(request)); + } + return result; } private Map<String, Map<String, String>> mapOf( @@ -258,4 +292,8 @@ public void blowsUpWhenJsonIsInvalid() throws IOException { map.put(key2, value2); return map; } + + private interface Function<T, R> { + R apply(T t); + } } diff --git a/saga-format/src/test/java/org/apache/servicecomb/saga/format/JacksonRestOperationTest.java b/saga-format/src/test/java/org/apache/servicecomb/saga/format/JacksonRestOperationTest.java index dc3274e1..9241289e 100644 --- a/saga-format/src/test/java/org/apache/servicecomb/saga/format/JacksonRestOperationTest.java +++ b/saga-format/src/test/java/org/apache/servicecomb/saga/format/JacksonRestOperationTest.java @@ -18,18 +18,19 @@ package org.apache.servicecomb.saga.format; import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify; -import static java.util.Collections.emptyMap; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.apache.servicecomb.saga.core.Operation; import org.apache.servicecomb.saga.core.SagaResponse; import org.apache.servicecomb.saga.transports.RestTransport; +import org.apache.servicecomb.saga.transports.TransportFactory; import org.hamcrest.core.Is; import org.junit.Before; import org.junit.Test; @@ -44,11 +45,13 @@ private final Map<String, Map<String, String>> params = new HashMap<>(); private final RestTransport transport = Mockito.mock(RestTransport.class); + private final TransportFactory transportFactory = Mockito.mock(TransportFactory.class); private final JacksonRestOperation restOperation = new JacksonRestOperation(path, method, params); @Before public void setUp() throws Exception { - restOperation.with(() -> transport); + when(transportFactory.restTransport()).thenReturn(transport); + restOperation.with(transportFactory); } @Test @@ -62,7 +65,9 @@ public void appendsResponseToForm() throws Exception { assertThat(response, Is.is(SagaResponse.EMPTY_RESPONSE)); Map<String, Map<String, String>> updatedParams = argumentCaptor.getValue(); - assertThat(updatedParams.getOrDefault("form", emptyMap()).get("response"), Is.is(Operation.SUCCESSFUL_SAGA_RESPONSE.body())); + assertThat(null == updatedParams.get("form") ? Collections.<String, String>emptyMap().get("response") + : updatedParams.get("form").get("response") + , Is.is(Operation.SUCCESSFUL_SAGA_RESPONSE.body())); assertThat(params.isEmpty(), is(true)); } } diff --git a/saga-format/src/test/java/org/apache/servicecomb/saga/format/JsonRestSagaRequestTest.java b/saga-format/src/test/java/org/apache/servicecomb/saga/format/JsonRestSagaRequestTest.java index c727ccbc..4ef870ce 100644 --- a/saga-format/src/test/java/org/apache/servicecomb/saga/format/JsonRestSagaRequestTest.java +++ b/saga-format/src/test/java/org/apache/servicecomb/saga/format/JsonRestSagaRequestTest.java @@ -29,6 +29,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.Map; + import org.apache.servicecomb.saga.transports.TransportFactory; import org.junit.Test; import org.mockito.Mockito; @@ -74,7 +76,11 @@ public void defaultToNopFallbackIfNotSpecified() { request.fallback().send(uniquify("blah")); - verify(restTransport, never()).with(anyString(), anyString(), anyString(), anyMap()); + verify(restTransport, never()).with(anyString(), anyString(), anyString(), anyStringMap()); + } + + private Map<String, Map<String, String>> anyStringMap() { + return anyMap(); } private JsonRestSagaRequest newSagaRequest( diff --git a/saga-format/src/test/java/org/apache/servicecomb/saga/format/SagaEventFormatTest.java b/saga-format/src/test/java/org/apache/servicecomb/saga/format/SagaEventFormatTest.java index 9bad69cb..fc509e46 100644 --- a/saga-format/src/test/java/org/apache/servicecomb/saga/format/SagaEventFormatTest.java +++ b/saga-format/src/test/java/org/apache/servicecomb/saga/format/SagaEventFormatTest.java @@ -28,6 +28,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.Collections; +import java.util.Map; + import org.apache.servicecomb.saga.core.JacksonToJsonFormat; import org.apache.servicecomb.saga.core.SagaRequest; import org.apache.servicecomb.saga.core.SagaRequestImpl; @@ -59,13 +62,14 @@ public class SagaEventFormatTest { private final String sagaId = Randomness.uniquify("sagaId"); + private final Map<String, Map<String, String>> EMPTY_MAP = Collections.<String, Map<String, String>>emptyMap(); private final SagaRequest request = new SagaRequestImpl( sagaId, Randomness.uniquify("serviceName"), TYPE_REST, new JacksonRestTransaction("/rest/xxx", "POST", singletonMap("query", singletonMap("foo", "xxx"))), new JacksonRestCompensation("/rest/xxx", "DELETE", singletonMap("query", singletonMap("bar", "xxx"))), - new JacksonRestFallback(TYPE_REST, "/rest/xxx", "PUT", emptyMap()) + new JacksonRestFallback(TYPE_REST, "/rest/xxx", "PUT", EMPTY_MAP) ); private final RestTransport restTransport = Mockito.mock(RestTransport.class); @@ -140,7 +144,7 @@ public void compensationEndedEventCanBeSerializedAndDeserialized() throws JsonPr assertThat(((TransactionCompensatedEvent) sagaEvent).response(), eqToResponse(response)); } - private static Matcher<SagaRequest> eqToRequest(SagaRequest expected) { + private static Matcher<SagaRequest> eqToRequest(final SagaRequest expected) { return new TypeSafeMatcher<SagaRequest>() { @Override protected boolean matchesSafely(SagaRequest request) { @@ -162,7 +166,7 @@ public void describeTo(Description description) { } - private static Matcher<SagaResponse> eqToResponse(SagaResponse expected) { + private static Matcher<SagaResponse> eqToResponse(final SagaResponse expected) { return new TypeSafeMatcher<SagaResponse>() { @Override protected boolean matchesSafely(SagaResponse response) { ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [email protected] With regards, Apache Git Services
