diff --git a/pom.xml b/pom.xml index 99b704d6..5b55dff8 100644 --- a/pom.xml +++ b/pom.xml @@ -297,11 +297,6 @@ - - com.google.guava - guava - 19.0 - org.springframework spring-web @@ -325,13 +320,7 @@ 1.0.1 - - org.zalando - problem - 0.7.0 - - - + com.fasterxml.jackson.core jackson-core @@ -347,8 +336,6 @@ jackson-databind 2.7.4 - - com.fasterxml.jackson.module jackson-module-parameter-names @@ -364,11 +351,6 @@ jackson-datatype-jsr310 2.7.4 - - com.fasterxml.jackson.datatype - jackson-datatype-guava - 2.7.4 - @@ -386,7 +368,7 @@ org.mockito mockito-core - 2.0.86-beta + 2.2.28 test diff --git a/src/main/java/org/zalando/fahrschein/CursorManager.java b/src/main/java/org/zalando/fahrschein/CursorManager.java index e25ebd54..e93a040a 100644 --- a/src/main/java/org/zalando/fahrschein/CursorManager.java +++ b/src/main/java/org/zalando/fahrschein/CursorManager.java @@ -1,12 +1,12 @@ package org.zalando.fahrschein; -import com.google.common.collect.Ordering; import org.zalando.fahrschein.domain.Cursor; import org.zalando.fahrschein.domain.Partition; import org.zalando.fahrschein.domain.Subscription; import java.io.IOException; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -16,7 +16,7 @@ */ public interface CursorManager { - Ordering OFFSET_ORDERING = Ordering.natural().nullsFirst().onResultOf((String offset) -> "BEGIN".equals(offset) ? null : Long.parseLong(offset)); + Comparator OFFSET_COMPARATOR = Comparator.nullsFirst(Comparator.comparing((String offset) -> "BEGIN".equals(offset) ? null : Long.parseLong(offset))); void onSuccess(String eventName, Cursor cursor) throws IOException; @@ -59,7 +59,7 @@ default void updatePartitions(String eventName, List partitions) thro for (Partition partition : partitions) { final Cursor cursor = cursorsByPartition.get(partition.getPartition()); - if (cursor == null || (!"BEGIN".equals(cursor.getOffset()) && OFFSET_ORDERING.compare(cursor.getOffset(), partition.getOldestAvailableOffset()) < 0)) { + if (cursor == null || (!"BEGIN".equals(cursor.getOffset()) && OFFSET_COMPARATOR.compare(cursor.getOffset(), partition.getOldestAvailableOffset()) < 0)) { onSuccess(eventName, new Cursor(partition.getPartition(), "BEGIN")); } } diff --git a/src/main/java/org/zalando/fahrschein/ExponentialBackoffStrategy.java b/src/main/java/org/zalando/fahrschein/ExponentialBackoffStrategy.java index 56fcd994..03d6e7c4 100644 --- a/src/main/java/org/zalando/fahrschein/ExponentialBackoffStrategy.java +++ b/src/main/java/org/zalando/fahrschein/ExponentialBackoffStrategy.java @@ -5,7 +5,8 @@ import java.io.IOException; -import static com.google.common.base.Preconditions.checkState; +import static org.zalando.fahrschein.Preconditions.checkState; + public class ExponentialBackoffStrategy implements BackoffStrategy { private static final Logger LOG = LoggerFactory.getLogger(ExponentialBackoffStrategy.class); diff --git a/src/main/java/org/zalando/fahrschein/IOProblem.java b/src/main/java/org/zalando/fahrschein/IOProblem.java index d78516ae..46ad614e 100644 --- a/src/main/java/org/zalando/fahrschein/IOProblem.java +++ b/src/main/java/org/zalando/fahrschein/IOProblem.java @@ -1,90 +1,61 @@ package org.zalando.fahrschein; -import org.zalando.problem.Problem; + +import org.springframework.http.HttpStatus; import javax.annotation.Nullable; -import javax.ws.rs.core.Response; import java.io.IOException; import java.net.URI; import java.util.Optional; @SuppressWarnings("serial") -public class IOProblem extends IOException implements Problem { - static final class Status implements Response.StatusType { - private final int statusCode; - private final String reasonPhrase; - - Status(final int statusCode, final String reasonPhrase) { - this.statusCode = statusCode; - this.reasonPhrase = reasonPhrase; - } - - @Override - public int getStatusCode() { - return statusCode; - } - - @Override - public Response.Status.Family getFamily() { - return Response.Status.Family.familyOf(statusCode); - } - - @Override - public String getReasonPhrase() { - return reasonPhrase; - } - } +public class IOProblem extends IOException { private final URI type; private final String title; - private final Response.StatusType status; + private final int statusCode; @Nullable private final String detail; @Nullable private final URI instance; - public IOProblem(final URI type, final String title, final Response.StatusType status, @Nullable final String detail, @Nullable final URI instance) { - super(formatMessage(type, title, status.getStatusCode(), detail)); + public IOProblem(final URI type, final String title, final int statusCode, @Nullable final String detail, @Nullable final URI instance) { + super(formatMessage(type, title, statusCode, detail)); this.type = type; this.title = title; - this.status = status; + this.statusCode = statusCode; this.detail = detail; this.instance = instance; } - public IOProblem(final URI type, final String title, final Response.StatusType status, @Nullable final String detail) { - this(type, title, status, detail, null); + public IOProblem(final URI type, final String title, final int statusCode, @Nullable final String detail) { + this(type, title, statusCode, detail, null); } - public IOProblem(final URI type, final String title, final Response.StatusType status) { - this(type, title, status, null, null); + public IOProblem(final URI type, final String title, final int statusCode) { + this(type, title, statusCode, null, null); } private static String formatMessage(final URI type, final String title, final int status, @Nullable final String detail) { return String.format("Problem [%s] with status [%d]: [%s] [%s]", type, status, title, detail == null ? "" : detail); } - @Override public URI getType() { return type; } - @Override public String getTitle() { return title; } - @Override - public Response.StatusType getStatus() { - return status; + public int getStatusCode() { + return statusCode; } - @Override public Optional getDetail() { return Optional.ofNullable(detail); } - @Override public Optional getInstance() { return Optional.ofNullable(instance); } diff --git a/src/main/java/org/zalando/fahrschein/ManagedCursorManager.java b/src/main/java/org/zalando/fahrschein/ManagedCursorManager.java index 9194671a..eb61dedb 100644 --- a/src/main/java/org/zalando/fahrschein/ManagedCursorManager.java +++ b/src/main/java/org/zalando/fahrschein/ManagedCursorManager.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.Iterables; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpMethod; @@ -83,7 +82,7 @@ public ManagedCursorManager(URI baseUri, ClientHttpRequestFactory clientHttpRequ @Override public void addSubscription(Subscription subscription) { - final String eventName = Iterables.getOnlyElement(subscription.getEventTypes()); + final String eventName = subscription.getEventTypes().iterator().next(); LOG.debug("Adding subscription [{}] to event [{}]", subscription.getId(), eventName); @@ -92,7 +91,7 @@ public void addSubscription(Subscription subscription) { @Override public void addStreamId(Subscription subscription, String streamId) { - final String eventName = Iterables.getOnlyElement(subscription.getEventTypes()); + final String eventName = subscription.getEventTypes().iterator().next(); LOG.debug("Adding stream id [{}] for subscription [{}] to event [{}]", streamId, subscription.getId(), eventName); diff --git a/src/main/java/org/zalando/fahrschein/NakadiClient.java b/src/main/java/org/zalando/fahrschein/NakadiClient.java index 750590d8..c6e3e108 100644 --- a/src/main/java/org/zalando/fahrschein/NakadiClient.java +++ b/src/main/java/org/zalando/fahrschein/NakadiClient.java @@ -20,7 +20,7 @@ import java.util.Collections; import java.util.List; -import static com.google.common.base.Preconditions.checkState; +import static org.zalando.fahrschein.Preconditions.checkState; public class NakadiClient { private static final Logger LOG = LoggerFactory.getLogger(NakadiClient.class); diff --git a/src/main/java/org/zalando/fahrschein/NakadiClientBuilder.java b/src/main/java/org/zalando/fahrschein/NakadiClientBuilder.java index a7a7243d..1395cc89 100644 --- a/src/main/java/org/zalando/fahrschein/NakadiClientBuilder.java +++ b/src/main/java/org/zalando/fahrschein/NakadiClientBuilder.java @@ -6,8 +6,8 @@ import javax.annotation.Nullable; import java.net.URI; -import static com.google.common.base.Preconditions.checkNotNull; import static java.util.Optional.ofNullable; +import static org.zalando.fahrschein.Preconditions.checkNotNull; public final class NakadiClientBuilder { public static final int DEFAULT_CONNECT_TIMEOUT = 500; diff --git a/src/main/java/org/zalando/fahrschein/NakadiReader.java b/src/main/java/org/zalando/fahrschein/NakadiReader.java index 6a3f2322..464e807a 100644 --- a/src/main/java/org/zalando/fahrschein/NakadiReader.java +++ b/src/main/java/org/zalando/fahrschein/NakadiReader.java @@ -8,8 +8,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.ObjectWriter; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Iterables; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpMethod; @@ -38,10 +36,10 @@ import java.util.Optional; import java.util.stream.Collectors; -import static com.google.common.base.Preconditions.checkState; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; +import static org.zalando.fahrschein.Preconditions.checkState; class NakadiReader implements IORunnable { @@ -67,7 +65,7 @@ class NakadiReader implements IORunnable { private final MetricsCollector metricsCollector; NakadiReader(URI uri, ClientHttpRequestFactory clientHttpRequestFactory, BackoffStrategy backoffStrategy, CursorManager cursorManager, ObjectMapper objectMapper, String eventName, Optional subscription, Optional lock, Class eventClass, Listener listener, final MetricsCollector metricsCollector) { - checkState(!subscription.isPresent() || eventName.equals(Iterables.getOnlyElement(subscription.get().getEventTypes())), "Only subscriptions to single event types are currently supported"); + checkState(!subscription.isPresent() || (subscription.get().getEventTypes().size() == 1 && eventName.equals(subscription.get().getEventTypes().iterator().next())), "Only subscriptions to single event types are currently supported"); this.uri = uri; this.clientHttpRequestFactory = clientHttpRequestFactory; @@ -83,10 +81,6 @@ class NakadiReader implements IORunnable { this.jsonFactory = objectMapper.getFactory(); this.eventReader = objectMapper.reader().forType(eventClass); this.cursorHeaderWriter = DefaultObjectMapper.INSTANCE.writerFor(COLLECTION_OF_CURSORS); - - if (clientHttpRequestFactory instanceof HttpComponentsClientHttpRequestFactory) { - LOG.warn("Using [{}] might block during reconnection, please consider using another implementation of ClientHttpRequestFactory", clientHttpRequestFactory.getClass().getName()); - } } static class JsonInput implements Closeable { @@ -258,7 +252,9 @@ public void run() throws IOException { } } - @VisibleForTesting + /* + * @VisibleForTesting + */ void runInternal() throws IOException, BackoffException { LOG.info("Starting to listen for events for [{}]", eventName); @@ -307,7 +303,9 @@ void runInternal() throws IOException, BackoffException { } } - @VisibleForTesting + /* + * @VisibleForTesting + */ void readSingleBatch() throws IOException { try (final JsonInput jsonInput = openJsonInput()) { final JsonParser jsonParser = jsonInput.getJsonParser(); diff --git a/src/main/java/org/zalando/fahrschein/Preconditions.java b/src/main/java/org/zalando/fahrschein/Preconditions.java new file mode 100644 index 00000000..3039389d --- /dev/null +++ b/src/main/java/org/zalando/fahrschein/Preconditions.java @@ -0,0 +1,67 @@ +package org.zalando.fahrschein; + +import javax.annotation.Nullable; + +import static java.lang.String.format; + +public final class Preconditions { + private Preconditions() { + } + + public static void checkArgument(boolean expression) { + if (!expression) { + throw new IllegalArgumentException(); + } + } + + public static void checkArgument(boolean expression, Object errorMessage) { + if (!expression) { + throw new IllegalArgumentException(String.valueOf(errorMessage)); + } + } + + public static void checkArgument(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) { + if (!expression) { + throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs)); + } + } + + public static void checkState(boolean expression) { + if (!expression) { + throw new IllegalStateException(); + } + } + + public static void checkState(boolean expression, Object errorMessage) { + if (!expression) { + throw new IllegalStateException(String.valueOf(errorMessage)); + } + } + + public static void checkState(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) { + if (!expression) { + throw new IllegalStateException(format(errorMessageTemplate, errorMessageArgs)); + } + } + + public static T checkNotNull(@Nullable T reference) { + if (reference == null) { + throw new NullPointerException(); + } + return reference; + } + + public static T checkNotNull(@Nullable T reference, Object errorMessage) { + if (reference == null) { + throw new NullPointerException(String.valueOf(errorMessage)); + } + return reference; + } + + public static T checkNotNull(@Nullable T reference, String errorMessageTemplate, Object... errorMessageArgs) { + if (reference == null) { + throw new NullPointerException(format(errorMessageTemplate, errorMessageArgs)); + } + return reference; + } +} diff --git a/src/main/java/org/zalando/fahrschein/ProblemHandlingClientHttpRequest.java b/src/main/java/org/zalando/fahrschein/ProblemHandlingClientHttpRequest.java index 4a3b85ab..7a289c5c 100644 --- a/src/main/java/org/zalando/fahrschein/ProblemHandlingClientHttpRequest.java +++ b/src/main/java/org/zalando/fahrschein/ProblemHandlingClientHttpRequest.java @@ -41,20 +41,19 @@ public ClientHttpResponse execute() throws IOException { final int statusCode = response.getRawStatusCode(); if (statusCode >= 400) { final String statusText = response.getStatusText(); - final IOProblem.Status status = new IOProblem.Status(statusCode, statusText); final MediaType contentType = response.getHeaders().getContentType(); if (contentType != null && isProblemContentType(contentType)) { try (InputStream is = response.getBody()) { - final IOProblem problem = deserializeProblem(is, status); + final IOProblem problem = deserializeProblem(is, statusCode); if (problem != null) { throw problem; } else { - throw new IOProblem(DEFAULT_PROBLEM_TYPE, statusText, status); + throw new IOProblem(DEFAULT_PROBLEM_TYPE, statusText, statusCode); } } } else { - throw new IOProblem(DEFAULT_PROBLEM_TYPE, statusText, status); + throw new IOProblem(DEFAULT_PROBLEM_TYPE, statusText, statusCode); } } } catch (Throwable throwable) { @@ -80,7 +79,7 @@ private boolean isProblemContentType(final MediaType contentType) { return false; } - private @Nullable IOProblem deserializeProblem(final InputStream is, final IOProblem.Status status) throws IOException { + private @Nullable IOProblem deserializeProblem(final InputStream is, final int statusCode) throws IOException { final JsonNode rootNode = objectMapper.readTree(is); final JsonNode typeNode = rootNode.get("type"); @@ -96,7 +95,7 @@ private boolean isProblemContentType(final MediaType contentType) { final JsonNode instanceNode = rootNode.get("instance"); final String instance = instanceNode == null ? null : instanceNode.asText(null); - return new IOProblem(URI.create(type), title, status, detail, instance == null ? null : URI.create(instance)); + return new IOProblem(URI.create(type), title, statusCode, detail, instance == null ? null : URI.create(instance)); } else { final JsonNode errorNode = rootNode.get("error"); final JsonNode descriptionNode = rootNode.get("error_description"); @@ -105,7 +104,7 @@ private boolean isProblemContentType(final MediaType contentType) { final String error = errorNode.asText(); final String description = descriptionNode.asText(); - return new IOProblem(DEFAULT_PROBLEM_TYPE, error, status, description); + return new IOProblem(DEFAULT_PROBLEM_TYPE, error, statusCode, description); } else { return null; } diff --git a/src/main/java/org/zalando/fahrschein/StreamBuilders.java b/src/main/java/org/zalando/fahrschein/StreamBuilders.java index 557f8660..55fc867b 100644 --- a/src/main/java/org/zalando/fahrschein/StreamBuilders.java +++ b/src/main/java/org/zalando/fahrschein/StreamBuilders.java @@ -1,7 +1,6 @@ package org.zalando.fahrschein; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.collect.Iterables; import org.springframework.http.client.ClientHttpRequestFactory; import org.zalando.fahrschein.domain.Lock; import org.zalando.fahrschein.domain.Subscription; @@ -84,7 +83,7 @@ protected URI getURI(String queryString) { @Override protected String getEventName() { - return Iterables.getOnlyElement(subscription.getEventTypes()); + return subscription.getEventTypes().iterator().next(); } @Override diff --git a/src/main/java/org/zalando/fahrschein/StreamParameters.java b/src/main/java/org/zalando/fahrschein/StreamParameters.java index fbca0772..894172fc 100644 --- a/src/main/java/org/zalando/fahrschein/StreamParameters.java +++ b/src/main/java/org/zalando/fahrschein/StreamParameters.java @@ -1,11 +1,10 @@ package org.zalando.fahrschein; -import com.google.common.base.Joiner; - import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; public class StreamParameters { @Nullable @@ -56,7 +55,8 @@ String toQueryString() { if (maxUncommittedEvents != null) { params.add("max_uncommitted_events=" + maxUncommittedEvents); } - return Joiner.on("&").join(params); + + return params.stream().collect(Collectors.joining()); } public StreamParameters withBatchLimit(int batchLimit) { diff --git a/src/main/java/org/zalando/fahrschein/ZignAccessTokenProvider.java b/src/main/java/org/zalando/fahrschein/ZignAccessTokenProvider.java index 485cd747..a0c90bc7 100644 --- a/src/main/java/org/zalando/fahrschein/ZignAccessTokenProvider.java +++ b/src/main/java/org/zalando/fahrschein/ZignAccessTokenProvider.java @@ -1,51 +1,70 @@ package org.zalando.fahrschein; -import com.google.common.base.Charsets; -import com.google.common.base.Throwables; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.io.CharStreams; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nullable; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; +import java.io.Reader; +import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.atomic.AtomicReference; public class ZignAccessTokenProvider implements AccessTokenProvider { private static final Logger LOG = LoggerFactory.getLogger(ZignAccessTokenProvider.class); + private static final long CACHE_DURATION = 5 * 60 * 1000L; - private LoadingCache zignCache = CacheBuilder.newBuilder() - .expireAfterWrite(5, TimeUnit.MINUTES) - .build(new CacheLoader() { - @Override - public String load(final String key) throws Exception { - return zign(); - } - }); + static class Entry { + final long timestamp; + final String value; + Entry(long timestamp, String value) { + this.timestamp = timestamp; + this.value = value; + } + } + + private final AtomicReference token = new AtomicReference<>(); + + private static String readAll(InputStream inputStream) throws IOException { + try (final Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { + final StringBuilder sb = new StringBuilder(); + final char[] buf = new char[1024]; + int len; + while ((len = reader.read(buf)) != -1) { + sb.append(buf, 0, len); + } + return sb.toString(); + } + } private static String zign() throws IOException { LOG.info("Refreshing token from zign..."); - final Process zign = new ProcessBuilder("zign", "token", "uid").start(); - try (final InputStream inputStream = zign.getInputStream()) { - return CharStreams.toString(new InputStreamReader(inputStream, Charsets.UTF_8)).trim(); - } finally { - LOG.debug("Refreshed token from zign"); + final Process zign = new ProcessBuilder("zign", "token", "uid").start(); + try (final InputStream inputStream = zign.getInputStream()) { + return readAll(inputStream).trim(); + } finally { + LOG.debug("Refreshed token from zign"); + } + } + + private static Entry update(@Nullable Entry entry) { + final long now = System.currentTimeMillis(); + try { + return entry == null || entry.timestamp < now - CACHE_DURATION ? new Entry(now, zign()) : entry; + } catch (IOException e) { + throw new UncheckedIOException(e); } } @Override public String getAccessToken() throws IOException { try { - return zignCache.get(""); - } catch (ExecutionException e) { - final Throwable cause = e.getCause(); - Throwables.propagateIfInstanceOf(cause, IOException.class); - throw Throwables.propagate(cause); + return token.updateAndGet(ZignAccessTokenProvider::update).value; + } catch (UncheckedIOException e) { + throw e.getCause(); } } diff --git a/src/main/java/org/zalando/fahrschein/domain/Lock.java b/src/main/java/org/zalando/fahrschein/domain/Lock.java index c5125acf..d4d05ee1 100644 --- a/src/main/java/org/zalando/fahrschein/domain/Lock.java +++ b/src/main/java/org/zalando/fahrschein/domain/Lock.java @@ -5,7 +5,7 @@ import java.util.Collections; import java.util.List; -import static com.google.common.base.Preconditions.checkState; +import static org.zalando.fahrschein.Preconditions.checkState; @Immutable public final class Lock { diff --git a/src/main/java/org/zalando/fahrschein/jdbc/JdbcCursorManager.java b/src/main/java/org/zalando/fahrschein/jdbc/JdbcCursorManager.java index 1dacd54a..875f3b05 100644 --- a/src/main/java/org/zalando/fahrschein/jdbc/JdbcCursorManager.java +++ b/src/main/java/org/zalando/fahrschein/jdbc/JdbcCursorManager.java @@ -13,8 +13,8 @@ import java.util.Collection; import java.util.List; -import static com.google.common.base.Preconditions.checkState; import static java.lang.String.format; +import static org.zalando.fahrschein.Preconditions.checkState; public class JdbcCursorManager implements CursorManager { diff --git a/src/main/java/org/zalando/fahrschein/jdbc/JdbcPartitionManager.java b/src/main/java/org/zalando/fahrschein/jdbc/JdbcPartitionManager.java index c37f90fb..f94bbadd 100644 --- a/src/main/java/org/zalando/fahrschein/jdbc/JdbcPartitionManager.java +++ b/src/main/java/org/zalando/fahrschein/jdbc/JdbcPartitionManager.java @@ -15,10 +15,10 @@ import java.util.Map; import java.util.Optional; -import static com.google.common.base.Preconditions.checkState; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; +import static org.zalando.fahrschein.Preconditions.checkState; public class JdbcPartitionManager implements PartitionManager { private static final Logger LOG = LoggerFactory.getLogger(JdbcPartitionManager.class); diff --git a/src/main/java/org/zalando/fahrschein/redis/Codec.java b/src/main/java/org/zalando/fahrschein/redis/Codec.java index 6cfc1be4..d9722a35 100644 --- a/src/main/java/org/zalando/fahrschein/redis/Codec.java +++ b/src/main/java/org/zalando/fahrschein/redis/Codec.java @@ -1,22 +1,26 @@ package org.zalando.fahrschein.redis; -import com.google.common.base.Joiner; -import com.google.common.base.Splitter; - import java.nio.charset.Charset; - -import static com.google.common.collect.Iterables.toArray; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; class Codec { - public static final char DELIMITER = 0; - public static final Charset UTF8 = Charset.forName("UTF-8"); - - public static final Joiner JOINER = Joiner.on(DELIMITER); - public static final Splitter SPLITTER = Splitter.on(DELIMITER); + private static final char DELIMITER_CHAR = 0; + private static final String DELIMITER_STRING = String.valueOf(DELIMITER_CHAR); + private static final Charset UTF8 = Charset.forName("UTF-8"); public byte[] serialize(final String... values) { - return JOINER.join(values).getBytes(UTF8); + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < values.length; i++) { + sb.append(values[i]); + if (i < values.length-1) { + sb.append(DELIMITER_CHAR); + } + + } + return sb.toString().getBytes(UTF8); } public String[] deserialize(final byte[] bytes) { @@ -24,7 +28,12 @@ public String[] deserialize(final byte[] bytes) { return null; } - return toArray(SPLITTER.split(new String(bytes, UTF8)), String.class); + List result = new ArrayList<>(); + StringTokenizer st = new StringTokenizer(new String(bytes, UTF8), DELIMITER_STRING); + while (st.hasMoreTokens()) { + result.add(st.nextToken()); + } + return result.toArray(new String[result.size()]); } } diff --git a/src/test/java/org/zalando/fahrschein/AbstractCursorManagerTest.java b/src/test/java/org/zalando/fahrschein/AbstractCursorManagerTest.java index 1cdce40c..b2e8ce40 100644 --- a/src/test/java/org/zalando/fahrschein/AbstractCursorManagerTest.java +++ b/src/test/java/org/zalando/fahrschein/AbstractCursorManagerTest.java @@ -1,14 +1,11 @@ package org.zalando.fahrschein; -import com.google.common.collect.Iterables; -import com.google.common.collect.Ordering; import org.junit.Test; import org.springframework.transaction.annotation.Transactional; import org.zalando.fahrschein.domain.Cursor; import java.io.IOException; -import java.util.Collection; -import java.util.List; +import java.util.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -36,7 +33,7 @@ public void shouldCreateCursorOnSuccess() throws IOException { assertNotNull(cursors); assertEquals(1, cursors.size()); - final Cursor cursor = Iterables.getOnlyElement(cursors); + final Cursor cursor = cursors.iterator().next(); assertEquals("0", cursor.getPartition()); assertEquals("123", cursor.getOffset()); } @@ -50,7 +47,7 @@ public void shouldUpdateCursorOnSuccess() throws IOException { assertNotNull(cursors); assertEquals(1, cursors.size()); - final Cursor cursor = Iterables.getOnlyElement(cursors); + final Cursor cursor = cursors.iterator().next(); assertEquals("0", cursor.getPartition()); assertEquals("123", cursor.getOffset()); } @@ -61,7 +58,7 @@ public void shouldUpdateCursorOnSuccess() throws IOException { assertNotNull(cursors); assertEquals(1, cursors.size()); - final Cursor cursor = Iterables.getOnlyElement(cursors); + final Cursor cursor = cursors.iterator().next(); assertEquals("0", cursor.getPartition()); assertEquals("124", cursor.getOffset()); } @@ -72,8 +69,9 @@ public void shouldCreateCursorsForMultiplePartitions() throws IOException { cursorManager().onSuccess("test", new Cursor("0", "12")); cursorManager().onSuccess("test", new Cursor("1", "13")); + final List cursors = new ArrayList<>(cursorManager().getCursors("test")); + Collections.sort(cursors, Comparator.comparing(Cursor::getPartition)); - final List cursors = Ordering.natural().onResultOf(Cursor::getPartition).sortedCopy(cursorManager().getCursors("test")); assertNotNull(cursors); assertEquals(2, cursors.size()); diff --git a/src/test/java/org/zalando/fahrschein/ProblemHandlingClientHttpRequestTest.java b/src/test/java/org/zalando/fahrschein/ProblemHandlingClientHttpRequestTest.java index af5b8626..fcfb1dbc 100644 --- a/src/test/java/org/zalando/fahrschein/ProblemHandlingClientHttpRequestTest.java +++ b/src/test/java/org/zalando/fahrschein/ProblemHandlingClientHttpRequestTest.java @@ -9,9 +9,7 @@ import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpResponse; -import org.zalando.problem.Problem; -import javax.ws.rs.core.Response; import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.URI; @@ -32,14 +30,6 @@ public class ProblemHandlingClientHttpRequestTest { private final ClientHttpResponse clientHttpResponse = Mockito.mock(ClientHttpResponse.class); private final ProblemHandlingClientHttpRequest problemHandlingClientHttpRequest = new ProblemHandlingClientHttpRequest(clientHttpRequest); - private Integer statusCode(final Problem problem) { - return problem.getStatus().getStatusCode(); - } - - private Response.Status.Family statusFamily(final Problem problem) { - return problem.getStatus().getFamily(); - } - @Test public void shouldCreateProblemFromStatusAndText() throws IOException { when(clientHttpResponse.getRawStatusCode()).thenReturn(HttpStatus.CONFLICT.value()); @@ -53,8 +43,7 @@ public void shouldCreateProblemFromStatusAndText() throws IOException { when(clientHttpRequest.execute()).thenReturn(clientHttpResponse); expectedException.expect(instanceOf(IOProblem.class)); - expectedException.expect(hasFeature("status code", this::statusCode, equalTo(HttpStatus.CONFLICT.value()))); - expectedException.expect(hasFeature("status family", this::statusFamily, equalTo(Response.Status.Family.CLIENT_ERROR))); + expectedException.expect(hasFeature("status code", IOProblem::getStatusCode, equalTo(HttpStatus.CONFLICT.value()))); expectedException.expect(hasFeature("type", IOProblem::getType, equalTo(URI.create("about:blank")))); expectedException.expect(hasFeature("title", IOProblem::getTitle, equalTo("conflict"))); expectedException.expect(hasFeature("detail", IOProblem::getDetail, equalTo(Optional.empty()))); @@ -76,11 +65,10 @@ public void shouldDeserializeProblemJson() throws IOException { when(clientHttpRequest.execute()).thenReturn(clientHttpResponse); expectedException.expect(instanceOf(IOProblem.class)); - expectedException.expect(hasFeature("status code", this::statusCode, equalTo(HttpStatus.NOT_FOUND.value()))); - expectedException.expect(hasFeature("status family", this::statusFamily, equalTo(Response.Status.Family.CLIENT_ERROR))); - expectedException.expect(hasFeature("type", Problem::getType, equalTo(URI.create("http://httpstatus.es/404")))); - expectedException.expect(hasFeature("title", Problem::getTitle, equalTo("Not Found"))); - expectedException.expect(hasFeature("detail", Problem::getDetail, equalTo(Optional.of("EventType does not exist.")))); + expectedException.expect(hasFeature("status code", IOProblem::getStatusCode, equalTo(HttpStatus.NOT_FOUND.value()))); + expectedException.expect(hasFeature("type", IOProblem::getType, equalTo(URI.create("http://httpstatus.es/404")))); + expectedException.expect(hasFeature("title", IOProblem::getTitle, equalTo("Not Found"))); + expectedException.expect(hasFeature("detail", IOProblem::getDetail, equalTo(Optional.of("EventType does not exist.")))); problemHandlingClientHttpRequest.execute(); } @@ -99,11 +87,10 @@ public void shouldDeserializeOAuthError() throws IOException { when(clientHttpRequest.execute()).thenReturn(clientHttpResponse); expectedException.expect(instanceOf(IOProblem.class)); - expectedException.expect(hasFeature("status code", this::statusCode, equalTo(HttpStatus.BAD_REQUEST.value()))); - expectedException.expect(hasFeature("status family", this::statusFamily, equalTo(Response.Status.Family.CLIENT_ERROR))); - expectedException.expect(hasFeature("type", Problem::getType, equalTo(URI.create("about:blank")))); - expectedException.expect(hasFeature("title", Problem::getTitle, equalTo("invalid_request"))); - expectedException.expect(hasFeature("detail", Problem::getDetail, equalTo(Optional.of("Access Token not valid")))); + expectedException.expect(hasFeature("status code", IOProblem::getStatusCode, equalTo(HttpStatus.BAD_REQUEST.value()))); + expectedException.expect(hasFeature("type", IOProblem::getType, equalTo(URI.create("about:blank")))); + expectedException.expect(hasFeature("title", IOProblem::getTitle, equalTo("invalid_request"))); + expectedException.expect(hasFeature("detail", IOProblem::getDetail, equalTo(Optional.of("Access Token not valid")))); problemHandlingClientHttpRequest.execute(); } diff --git a/src/test/java/org/zalando/fahrschein/salesorder/Main.java b/src/test/java/org/zalando/fahrschein/salesorder/Main.java index 744015f4..cdc051c9 100644 --- a/src/test/java/org/zalando/fahrschein/salesorder/Main.java +++ b/src/test/java/org/zalando/fahrschein/salesorder/Main.java @@ -6,7 +6,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.datatype.guava.GuavaModule; import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; @@ -62,7 +61,6 @@ public static void main(String[] args) throws IOException, InterruptedException objectMapper.registerModule(new JavaTimeModule()); objectMapper.registerModule(new Jdk8Module()); objectMapper.registerModule(new MoneyModule()); - objectMapper.registerModule(new GuavaModule()); objectMapper.registerModule(new ParameterNamesModule()); AtomicInteger counter = new AtomicInteger();