Skip to content

Commit

Permalink
Merge pull request #1663 from stripe/richardm-fix-autopagination-dese…
Browse files Browse the repository at this point in the history
…rialization-issue

Flow type information further into autopagination requests
  • Loading branch information
richardm-stripe committed Oct 5, 2023
2 parents cbb5e8e + 174f052 commit b48ef46
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 24 deletions.
8 changes: 6 additions & 2 deletions src/main/java/com/stripe/model/PagingIterable.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.stripe.model;

import com.stripe.net.StripeResponseGetter;
import java.lang.reflect.Type;
import java.util.Iterator;

/**
Expand All @@ -10,15 +11,18 @@
public class PagingIterable<T extends HasId> implements Iterable<T> {
private final StripeCollectionInterface<T> page;
private final StripeResponseGetter responseGetter;
private final Type pageType;

PagingIterable(final StripeCollectionInterface<T> page, StripeResponseGetter responseGetter) {
PagingIterable(
final StripeCollectionInterface<T> page, StripeResponseGetter responseGetter, Type pageType) {

this.page = page;
this.responseGetter = responseGetter;
this.pageType = pageType;
}

@Override
public Iterator<T> iterator() {
return new PagingIterator<>(page, responseGetter);
return new PagingIterator<>(page, responseGetter, pageType);
}
}
13 changes: 7 additions & 6 deletions src/main/java/com/stripe/model/PagingIterator.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.stripe.model;

import com.stripe.net.*;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
Expand All @@ -9,19 +10,20 @@
public class PagingIterator<T extends HasId> extends ApiResource implements Iterator<T> {
private final String url;

@SuppressWarnings("rawtypes")
private final Class<? extends StripeCollectionInterface> collectionType;
private final Type pageType;

private StripeCollectionInterface<T> currentCollection;
private Iterator<T> currentDataIterator;

private String lastId;

PagingIterator(
final StripeCollectionInterface<T> stripeCollection, StripeResponseGetter responseGetter) {
final StripeCollectionInterface<T> stripeCollection,
StripeResponseGetter responseGetter,
Type pageType) {
this.url = stripeCollection.getUrl();

this.collectionType = stripeCollection.getClass();
this.pageType = pageType;

this.currentCollection = stripeCollection;
this.currentDataIterator = stripeCollection.getData().iterator();
Expand Down Expand Up @@ -76,7 +78,6 @@ public void remove() {
private StripeCollectionInterface<T> list(
final Map<String, Object> params, final RequestOptions options) throws Exception {
return getResponseGetter()
.request(
BaseAddress.API, RequestMethod.GET, url, params, collectionType, options, ApiMode.V1);
.request(BaseAddress.API, RequestMethod.GET, url, params, pageType, options, ApiMode.V1);
}
}
9 changes: 7 additions & 2 deletions src/main/java/com/stripe/model/SearchPagingIterable.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.stripe.model;

import com.stripe.net.StripeResponseGetter;
import java.lang.reflect.Type;
import java.util.Iterator;

/**
Expand All @@ -10,15 +11,19 @@
public class SearchPagingIterable<T> implements Iterable<T> {
private final StripeSearchResultInterface<T> page;
private final StripeResponseGetter responseGetter;
private final Type pageType;

SearchPagingIterable(
final StripeSearchResultInterface<T> page, StripeResponseGetter responseGetter) {
final StripeSearchResultInterface<T> page,
StripeResponseGetter responseGetter,
Type pageType) {
this.page = page;
this.responseGetter = responseGetter;
this.pageType = pageType;
}

@Override
public Iterator<T> iterator() {
return new SearchPagingIterator<>(page, responseGetter);
return new SearchPagingIterator<>(page, responseGetter, pageType);
}
}
14 changes: 6 additions & 8 deletions src/main/java/com/stripe/model/SearchPagingIterator.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.stripe.model;

import com.stripe.net.*;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
Expand All @@ -9,8 +10,7 @@
public class SearchPagingIterator<T> extends ApiResource implements Iterator<T> {
private final String url;

@SuppressWarnings("rawtypes")
private final Class<? extends StripeSearchResultInterface> collectionType;
private final Type pageType;

private StripeSearchResultInterface<T> currentSearchResult;
private Iterator<T> currentDataIterator;
Expand All @@ -19,14 +19,14 @@ public class SearchPagingIterator<T> extends ApiResource implements Iterator<T>

SearchPagingIterator(
final StripeSearchResultInterface<T> stripeSearchResult,
StripeResponseGetter responseGetter) {
StripeResponseGetter responseGetter,
Type pageType) {
this.url = stripeSearchResult.getUrl();
this.nextPage = stripeSearchResult.getNextPage();

this.collectionType = stripeSearchResult.getClass();

this.currentSearchResult = stripeSearchResult;
this.currentDataIterator = stripeSearchResult.getData().iterator();
this.pageType = pageType;
setResponseGetter(responseGetter);
}

Expand Down Expand Up @@ -74,11 +74,9 @@ public void remove() {
throw new UnsupportedOperationException();
}

@SuppressWarnings("unchecked")
private StripeSearchResultInterface<T> search(
final Map<String, Object> params, final RequestOptions options) throws Exception {
return getResponseGetter()
.request(
BaseAddress.API, RequestMethod.GET, url, params, collectionType, options, ApiMode.V1);
.request(BaseAddress.API, RequestMethod.GET, url, params, pageType, options, ApiMode.V1);
}
}
10 changes: 7 additions & 3 deletions src/main/java/com/stripe/model/StripeCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.stripe.net.RequestOptions;
import com.stripe.net.StripeResponseGetter;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import lombok.EqualsAndHashCode;
Expand Down Expand Up @@ -58,16 +59,19 @@ public class StripeCollection<T extends HasId> extends StripeObject
@Setter(onMethod = @__({@Override}))
private Map<String, Object> requestParams;

@Setter(onMethod = @__({@Override}))
private transient Type pageTypeToken;

public Iterable<T> autoPagingIterable() {
this.responseGetter.validateRequestOptions(this.requestOptions);
return new PagingIterable<>(this, responseGetter);
return new PagingIterable<>(this, responseGetter, pageTypeToken);
}

public Iterable<T> autoPagingIterable(Map<String, Object> params) {
this.responseGetter.validateRequestOptions(this.requestOptions);

this.setRequestParams(params);
return new PagingIterable<>(this, responseGetter);
return new PagingIterable<>(this, responseGetter, pageTypeToken);
}

/**
Expand All @@ -82,7 +86,7 @@ public Iterable<T> autoPagingIterable(Map<String, Object> params, RequestOptions
this.responseGetter.validateRequestOptions(options);
this.setRequestOptions(options);
this.setRequestParams(params);
return new PagingIterable<>(this, responseGetter);
return new PagingIterable<>(this, responseGetter, pageTypeToken);
}

@Override
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/stripe/model/StripeCollectionInterface.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.stripe.model;

import com.stripe.net.RequestOptions;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -34,4 +35,7 @@ public interface StripeCollectionInterface<T> extends StripeObjectInterface {
* pagination.
*/
void setRequestParams(Map<String, Object> requestParams);

// TODO (major) remove the default implementation and make this required
default void setPageTypeToken(Type type) {};
}
10 changes: 7 additions & 3 deletions src/main/java/com/stripe/model/StripeSearchResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.stripe.net.RequestOptions;
import com.stripe.net.StripeResponseGetter;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import lombok.EqualsAndHashCode;
Expand Down Expand Up @@ -44,15 +45,18 @@ public class StripeSearchResult<T> extends StripeObject
@Setter(onMethod = @__({@Override}))
private Map<String, Object> requestParams;

@Setter(onMethod = @__({@Override}))
private transient Type pageTypeToken;

public Iterable<T> autoPagingIterable() {
this.responseGetter.validateRequestOptions(this.requestOptions);
return new SearchPagingIterable<>(this, responseGetter);
return new SearchPagingIterable<>(this, responseGetter, pageTypeToken);
}

public Iterable<T> autoPagingIterable(Map<String, Object> params) {
this.responseGetter.validateRequestOptions(this.requestOptions);
this.setRequestParams(params);
return new SearchPagingIterable<>(this, responseGetter);
return new SearchPagingIterable<>(this, responseGetter, pageTypeToken);
}

/**
Expand All @@ -67,7 +71,7 @@ public Iterable<T> autoPagingIterable(Map<String, Object> params, RequestOptions
this.responseGetter.validateRequestOptions(options);
this.setRequestOptions(options);
this.setRequestParams(params);
return new SearchPagingIterable<>(this, responseGetter);
return new SearchPagingIterable<>(this, responseGetter, pageTypeToken);
}

@Override
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/stripe/net/ApiResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ private static Gson createGson(boolean shouldSetResponseGetter) {
.registerTypeAdapter(Event.Request.class, new EventRequestDeserializer())
.registerTypeAdapter(ExpandableField.class, new ExpandableFieldDeserializer())
.registerTypeAdapter(StripeRawJsonObject.class, new StripeRawJsonObjectDeserializer())
.registerTypeAdapterFactory(new StripeCollectionItemTypeSettingFactory())
.addReflectionAccessFilter(
new ReflectionAccessFilter() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.stripe.net;

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.stripe.model.*;
import java.io.IOException;

class StripeCollectionItemTypeSettingFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);

return new TypeAdapter<T>() {
@Override
public void write(JsonWriter out, T value) throws IOException {
delegate.write(out, value);
}

@Override
public T read(JsonReader in) throws IOException {
T obj = delegate.read(in);
if (obj instanceof StripeCollectionInterface) {
((StripeCollectionInterface<?>) obj).setPageTypeToken(type.getType());
}
return obj;
}
};
}
}
35 changes: 35 additions & 0 deletions src/test/java/com/stripe/model/PagingIteratorTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.stripe.model;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.verifyNoMoreInteractions;

Expand All @@ -13,6 +14,7 @@
import com.stripe.net.RequestOptions.RequestOptionsBuilder;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.Getter;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -361,4 +363,37 @@ public void testAutoPaginationRequestOptionsPropagation() throws StripeException
assertEquals("pm_126", models.get(3).getId());
assertEquals("pm_127", models.get(4).getId());
}

@Test
public void testPaginationWithStripeClient() throws StripeException {
StripeResponse firstResponse =
new StripeResponse(
200,
HttpHeaders.of(Collections.emptyMap()),
"{\"object\": \"list\", \"url\": \"/v1/subscriptions\", \"data\": [{\"object\": \"subscription\", \"id\": \"1\"}], \"has_more\": true}");
StripeResponse secondResponse =
new StripeResponse(
200,
HttpHeaders.of(Collections.emptyMap()),
"{\"object\": \"list\", \"url\": \"/v1/subscriptions\", \"data\": [{\"object\": \"subscription\", \"id\": \"2\"}], \"has_more\": false}");

AtomicInteger count = new AtomicInteger(0);
Mockito.doAnswer(
new Answer<StripeResponse>() {
public StripeResponse answer(InvocationOnMock invocation) {
if (count.getAndIncrement() == 0) {
return firstResponse;
}
return secondResponse;
}
})
.when(httpClientSpy)
.requestWithRetries(Mockito.<StripeRequest>any());
List<String> seen = new ArrayList<String>();
for (final Subscription sub : mockClient.subscriptions().list().autoPagingIterable()) {
assertInstanceOf(Subscription.class, sub);
seen.add(sub.getId());
}
assertEquals(2, seen.size());
}
}

0 comments on commit b48ef46

Please sign in to comment.