You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/07/18 11:46:36 UTC
[camel] branch camel-3.x updated: fix!: specify array name when fetching collections instead of inferring the array name since it's not always going to work (#10715)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-3.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-3.x by this push:
new e44a7e7d66c fix!: specify array name when fetching collections instead of inferring the array name since it's not always going to work (#10715)
e44a7e7d66c is described below
commit e44a7e7d66c6ac72e8bb377d64e82dc288d65606
Author: Claude Mamo <82...@users.noreply.github.com>
AuthorDate: Tue Jul 18 13:46:30 2023 +0200
fix!: specify array name when fetching collections instead of inferring the array name since it's not always going to work (#10715)
---
.../java/org/apache/camel/component/dhis2/api/Dhis2Get.java | 9 ++++-----
.../apache/camel/component/dhis2/api/Dhis2GetTestCase.java | 6 +++---
.../camel/component/dhis2/Dhis2EndpointUriFactory.java | 3 ++-
.../component/dhis2/Dhis2GetEndpointConfiguration.java | 13 ++++++++++++-
.../dhis2/Dhis2GetEndpointConfigurationConfigurer.java | 7 +++++++
.../camel/component/dhis2/internal/Dhis2GetApiMethod.java | 1 +
.../resources/org/apache/camel/component/dhis2/dhis2.json | 4 ++--
.../src/main/docs/dhis2-component.adoc | 13 +++++++------
.../java/org/apache/camel/component/dhis2/Dhis2GetIT.java | 11 +----------
9 files changed, 39 insertions(+), 28 deletions(-)
diff --git a/components/camel-dhis2/camel-dhis2-api/src/main/java/org/apache/camel/component/dhis2/api/Dhis2Get.java b/components/camel-dhis2/camel-dhis2-api/src/main/java/org/apache/camel/component/dhis2/api/Dhis2Get.java
index fcefb54a9eb..9ccdd50ae0d 100644
--- a/components/camel-dhis2/camel-dhis2-api/src/main/java/org/apache/camel/component/dhis2/api/Dhis2Get.java
+++ b/components/camel-dhis2/camel-dhis2-api/src/main/java/org/apache/camel/component/dhis2/api/Dhis2Get.java
@@ -76,7 +76,8 @@ public class Dhis2Get {
}
public <T> Iterator<T> collection(
- String path, String itemType, Boolean paging, String fields, String filter, RootJunctionEnum rootJunction,
+ String path, String itemType, String arrayName, Boolean paging, String fields, String filter,
+ RootJunctionEnum rootJunction,
Map<String, Object> queryParams) {
GetOperation getOperation = newGetOperation(path, fields, filter, rootJunction, queryParams);
Iterable<T> iterable;
@@ -89,12 +90,10 @@ public class Dhis2Get {
}
if (itemType == null) {
- iterable = (Iterable<T>) iteratorDhis2Response
- .returnAs(Map.class, path);
+ iterable = (Iterable<T>) iteratorDhis2Response.returnAs(Map.class, arrayName);
} else {
try {
- iterable = (Iterable<T>) iteratorDhis2Response
- .returnAs(Class.forName(itemType), path);
+ iterable = (Iterable<T>) iteratorDhis2Response.returnAs(Class.forName(itemType), arrayName);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
diff --git a/components/camel-dhis2/camel-dhis2-api/src/test/java/org/apache/camel/component/dhis2/api/Dhis2GetTestCase.java b/components/camel-dhis2/camel-dhis2-api/src/test/java/org/apache/camel/component/dhis2/api/Dhis2GetTestCase.java
index 325a4f692ec..706143d5fe2 100644
--- a/components/camel-dhis2/camel-dhis2-api/src/test/java/org/apache/camel/component/dhis2/api/Dhis2GetTestCase.java
+++ b/components/camel-dhis2/camel-dhis2-api/src/test/java/org/apache/camel/component/dhis2/api/Dhis2GetTestCase.java
@@ -184,7 +184,7 @@ public class Dhis2GetTestCase {
"https://play.dhis2.org/2.39.0.1", "", null, new JacksonConverterFactory(), getOperation));
Dhis2Get dhis2Get = new Dhis2Get(dhis2Client);
- dhis2Get.collection("bunnies", null, null, null, null, null, Map.of("foo", "bar"));
+ dhis2Get.collection("bunnies", null, "bunnies", null, null, null, null, Map.of("foo", "bar"));
verify(getOperation, times(1)).withParameter("foo", "bar");
}
@@ -216,7 +216,7 @@ public class Dhis2GetTestCase {
new JacksonConverterFactory(), getOperation));
Dhis2Get dhis2Get = new Dhis2Get(dhis2Client);
- dhis2Get.collection("bunnies", null, null, null, null, RootJunctionEnum.OR, null);
+ dhis2Get.collection("bunnies", null, "bunnies", null, null, null, RootJunctionEnum.OR, null);
verify(getOperation, times(1)).withOrRootJunction();
}
@@ -246,7 +246,7 @@ public class Dhis2GetTestCase {
"https://play.dhis2.org/2.39.0.1", "", null, new JacksonConverterFactory(), getOperation));
Dhis2Get dhis2Get = new Dhis2Get(dhis2Client);
- dhis2Get.collection("bunnies", null, null, null, null, RootJunctionEnum.AND, null);
+ dhis2Get.collection("bunnies", null, "bunnies", null, null, null, RootJunctionEnum.AND, null);
verify(getOperation, times(1)).withAndRootJunction();
}
}
diff --git a/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2EndpointUriFactory.java b/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2EndpointUriFactory.java
index 4a7b44074cd..0bcc1c424df 100644
--- a/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2EndpointUriFactory.java
+++ b/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2EndpointUriFactory.java
@@ -21,8 +21,9 @@ public class Dhis2EndpointUriFactory extends org.apache.camel.support.component.
private static final Set<String> SECRET_PROPERTY_NAMES;
private static final Set<String> MULTI_VALUE_PREFIXES;
static {
- Set<String> props = new HashSet<>(39);
+ Set<String> props = new HashSet<>(40);
props.add("apiName");
+ props.add("arrayName");
props.add("backoffErrorThreshold");
props.add("backoffIdleThreshold");
props.add("backoffMultiplier");
diff --git a/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2GetEndpointConfiguration.java b/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2GetEndpointConfiguration.java
index 9ec1227a69f..7f7a9e99a38 100644
--- a/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2GetEndpointConfiguration.java
+++ b/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2GetEndpointConfiguration.java
@@ -16,10 +16,13 @@ import org.apache.camel.spi.UriParams;
*/
@ApiParams(apiName = "get",
description = "",
- apiMethods = {@ApiMethod(methodName = "collection", signatures={"java.util.Iterator collection(String path, String itemType, Boolean paging, String fields, String filter, org.apache.camel.component.dhis2.api.RootJunctionEnum rootJunction, java.util.Map<String, Object> queryParams)"}), @ApiMethod(methodName = "resource", signatures={"java.io.InputStream resource(String path, String fields, String filter, org.apache.camel.component.dhis2.api.RootJunctionEnum rootJunction, java.u [...]
+ apiMethods = {@ApiMethod(methodName = "collection", signatures={"java.util.Iterator collection(String path, String itemType, String arrayName, Boolean paging, String fields, String filter, org.apache.camel.component.dhis2.api.RootJunctionEnum rootJunction, java.util.Map<String, Object> queryParams)"}), @ApiMethod(methodName = "resource", signatures={"java.io.InputStream resource(String path, String fields, String filter, org.apache.camel.component.dhis2.api.RootJunctionEnum ro [...]
@UriParams
@Configurer(extended = true)
public final class Dhis2GetEndpointConfiguration extends Dhis2Configuration {
+ @UriParam
+ @ApiParam(optional = false, apiMethods = {@ApiMethod(methodName = "collection")})
+ private String arrayName;
@UriParam
@ApiParam(optional = true, apiMethods = {@ApiMethod(methodName = "collection"), @ApiMethod(methodName = "resource")})
private String fields;
@@ -42,6 +45,14 @@ public final class Dhis2GetEndpointConfiguration extends Dhis2Configuration {
@ApiParam(optional = true, apiMethods = {@ApiMethod(methodName = "collection"), @ApiMethod(methodName = "resource")})
private org.apache.camel.component.dhis2.api.RootJunctionEnum rootJunction;
+ public String getArrayName() {
+ return arrayName;
+ }
+
+ public void setArrayName(String arrayName) {
+ this.arrayName = arrayName;
+ }
+
public String getFields() {
return fields;
}
diff --git a/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2GetEndpointConfigurationConfigurer.java b/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2GetEndpointConfigurationConfigurer.java
index d68646f3074..9670058b051 100644
--- a/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2GetEndpointConfigurationConfigurer.java
+++ b/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/Dhis2GetEndpointConfigurationConfigurer.java
@@ -21,6 +21,7 @@ public class Dhis2GetEndpointConfigurationConfigurer extends org.apache.camel.su
static {
Map<String, Object> map = new CaseInsensitiveMap();
map.put("ApiName", org.apache.camel.component.dhis2.internal.Dhis2ApiName.class);
+ map.put("ArrayName", java.lang.String.class);
map.put("BaseApiUrl", java.lang.String.class);
map.put("Client", org.hisp.dhis.integration.sdk.api.Dhis2Client.class);
map.put("Fields", java.lang.String.class);
@@ -42,6 +43,8 @@ public class Dhis2GetEndpointConfigurationConfigurer extends org.apache.camel.su
switch (ignoreCase ? name.toLowerCase() : name) {
case "apiname":
case "ApiName": target.setApiName(property(camelContext, org.apache.camel.component.dhis2.internal.Dhis2ApiName.class, value)); return true;
+ case "arrayname":
+ case "ArrayName": target.setArrayName(property(camelContext, java.lang.String.class, value)); return true;
case "baseapiurl":
case "BaseApiUrl": target.setBaseApiUrl(property(camelContext, java.lang.String.class, value)); return true;
case "client":
@@ -80,6 +83,8 @@ public class Dhis2GetEndpointConfigurationConfigurer extends org.apache.camel.su
switch (ignoreCase ? name.toLowerCase() : name) {
case "apiname":
case "ApiName": return org.apache.camel.component.dhis2.internal.Dhis2ApiName.class;
+ case "arrayname":
+ case "ArrayName": return java.lang.String.class;
case "baseapiurl":
case "BaseApiUrl": return java.lang.String.class;
case "client":
@@ -114,6 +119,8 @@ public class Dhis2GetEndpointConfigurationConfigurer extends org.apache.camel.su
switch (ignoreCase ? name.toLowerCase() : name) {
case "apiname":
case "ApiName": return target.getApiName();
+ case "arrayname":
+ case "ArrayName": return target.getArrayName();
case "baseapiurl":
case "BaseApiUrl": return target.getBaseApiUrl();
case "client":
diff --git a/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/internal/Dhis2GetApiMethod.java b/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/internal/Dhis2GetApiMethod.java
index 66cca60bd5c..7e37f358f5e 100644
--- a/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/internal/Dhis2GetApiMethod.java
+++ b/components/camel-dhis2/camel-dhis2-component/src/generated/java/org/apache/camel/component/dhis2/internal/Dhis2GetApiMethod.java
@@ -25,6 +25,7 @@ public enum Dhis2GetApiMethod implements ApiMethod {
"collection",
arg("path", String.class),
arg("itemType", String.class),
+ arg("arrayName", String.class),
arg("paging", Boolean.class),
arg("fields", String.class),
arg("filter", String.class),
diff --git a/components/camel-dhis2/camel-dhis2-component/src/generated/resources/org/apache/camel/component/dhis2/dhis2.json b/components/camel-dhis2/camel-dhis2-component/src/generated/resources/org/apache/camel/component/dhis2/dhis2.json
index 2cf4346ecd6..69bc25a9b77 100644
--- a/components/camel-dhis2/camel-dhis2-component/src/generated/resources/org/apache/camel/component/dhis2/dhis2.json
+++ b/components/camel-dhis2/camel-dhis2-component/src/generated/resources/org/apache/camel/component/dhis2/dhis2.json
@@ -63,14 +63,14 @@
},
"apis": {
"delete": { "consumerOnly": false, "producerOnly": false, "description": "", "methods": { "resource": { "description": "", "signatures": [ "java.io.InputStream resource(String path, Object resource, java.util.Map<String, Object> queryParams)" ] } } },
- "get": { "consumerOnly": false, "producerOnly": false, "description": "", "methods": { "collection": { "description": "", "signatures": [ "java.util.Iterator collection(String path, String itemType, Boolean paging, String fields, String filter, org.apache.camel.component.dhis2.api.RootJunctionEnum rootJunction, java.util.Map<String, Object> queryParams)" ] }, "resource": { "description": "", "signatures": [ "java.io.InputStream resource(String path, String fields, String filter, org. [...]
+ "get": { "consumerOnly": false, "producerOnly": false, "description": "", "methods": { "collection": { "description": "", "signatures": [ "java.util.Iterator collection(String path, String itemType, String arrayName, Boolean paging, String fields, String filter, org.apache.camel.component.dhis2.api.RootJunctionEnum rootJunction, java.util.Map<String, Object> queryParams)" ] }, "resource": { "description": "", "signatures": [ "java.io.InputStream resource(String path, String fields, S [...]
"post": { "consumerOnly": false, "producerOnly": false, "description": "", "methods": { "resource": { "description": "", "signatures": [ "java.io.InputStream resource(String path, Object resource, java.util.Map<String, Object> queryParams)" ] } } },
"put": { "consumerOnly": false, "producerOnly": false, "description": "", "methods": { "resource": { "description": "", "signatures": [ "java.io.InputStream resource(String path, Object resource, java.util.Map<String, Object> queryParams)" ] } } },
"resourceTables": { "consumerOnly": false, "producerOnly": false, "description": "", "methods": { "analytics": { "description": "", "signatures": [ "void analytics(Boolean skipAggregate, Boolean skipEvents, Integer lastYears, Integer interval)" ] } } }
},
"apiProperties": {
"delete": { "methods": { "resource": { "properties": { "path": { "kind": "parameter", "displayName": "Path", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "", "optional": false }, "queryParams": { "kind": "parameter", "displayName": "Query Params", "group": "common", "label": "", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.Strin [...]
- "get": { "methods": { "collection": { "properties": { "fields": { "kind": "parameter", "displayName": "Fields", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "", "optional": true }, "filter": { "kind": "parameter", "displayName": "Filter", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false [...]
+ "get": { "methods": { "collection": { "properties": { "arrayName": { "kind": "parameter", "displayName": "Array Name", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "", "optional": false }, "fields": { "kind": "parameter", "displayName": "Fields", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated [...]
"post": { "methods": { "resource": { "properties": { "path": { "kind": "parameter", "displayName": "Path", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "", "optional": false }, "queryParams": { "kind": "parameter", "displayName": "Query Params", "group": "common", "label": "", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, [...]
"put": { "methods": { "resource": { "properties": { "path": { "kind": "parameter", "displayName": "Path", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "", "optional": false }, "queryParams": { "kind": "parameter", "displayName": "Query Params", "group": "common", "label": "", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, [...]
"resourceTables": { "methods": { "analytics": { "properties": { "interval": { "kind": "parameter", "displayName": "Interval", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "autowired": false, "secret": false, "description": "", "optional": true }, "lastYears": { "kind": "parameter", "displayName": "Last Years", "group": "common", "label": "", "required": false, "type": "integer", "javaType": "java.lang.Inte [...]
diff --git a/components/camel-dhis2/camel-dhis2-component/src/main/docs/dhis2-component.adoc b/components/camel-dhis2/camel-dhis2-component/src/main/docs/dhis2-component.adoc
index d02c0bd4e06..5a402a17f5d 100644
--- a/components/camel-dhis2/camel-dhis2-component/src/main/docs/dhis2-component.adoc
+++ b/components/camel-dhis2/camel-dhis2-component/src/main/docs/dhis2-component.adoc
@@ -100,6 +100,7 @@ The get/collection API method has the parameters listed in the table below:
| Parameter | Description | Type
| path | Resource URL path | String
| itemType | Fully-qualified Java class name to deserialise items into| String
+| arrayName | JSON property name holding the array to read | String
| paging | Turn paging on/off | Boolean
| fields | Comma-delimited list of fields to fetch | String
| filter | Search criteria | String
@@ -120,7 +121,7 @@ public class MyRouteBuilder extends RouteBuilder {
public void configure() {
from("direct:getCollection")
- .to("dhis2://get/collection?path=organisationUnits&itemType=org.hisp.dhis.api.model.v2_39_1.OrganisationUnit&username=admin&password=district&baseApiUrl=https://play.dhis2.org/2.39.1/api")
+ .to("dhis2://get/collection?path=organisationUnits&itemType=org.hisp.dhis.api.model.v2_39_1.OrganisationUnit&arrayName=organisationUnits&username=admin&password=district&baseApiUrl=https://play.dhis2.org/2.39.1/api")
.split().body().log("${body}");
}
}
@@ -138,7 +139,7 @@ public class MyRouteBuilder extends RouteBuilder {
public void configure() {
from("direct:getCollection")
- .to("dhis2://get/collection?path=organisationUnits&fields=code&itemType=org.hisp.dhis.api.model.v2_39_1.OrganisationUnit&username=admin&password=district&baseApiUrl=https://play.dhis2.org/2.39.1/api")
+ .to("dhis2://get/collection?path=organisationUnits&fields=code&itemType=org.hisp.dhis.api.model.v2_39_1.OrganisationUnit&arrayName=organisationUnits&username=admin&password=district&baseApiUrl=https://play.dhis2.org/2.39.1/api")
.split().body().log("${body}");
}
}
@@ -156,7 +157,7 @@ public class MyRouteBuilder extends RouteBuilder {
public void configure() {
from("direct:getCollection")
- .to("dhis2://get/collection?path=users&filter=phoneNumber:!null:&itemType=org.hisp.dhis.api.model.v2_39_1.User&username=admin&password=district&baseApiUrl=https://play.dhis2.org/2.39.1/api")
+ .to("dhis2://get/collection?path=users&filter=phoneNumber:!null:&itemType=org.hisp.dhis.api.model.v2_39_1.User&arrayName=users&username=admin&password=district&baseApiUrl=https://play.dhis2.org/2.39.1/api")
.split().body().log("${body}");
}
}
@@ -217,13 +218,13 @@ public class MyRouteBuilder extends RouteBuilder {
public void configure() {
from("direct:postResource")
- .process(exchange -> exchange.getMessage().setBody(new DataValueSet().withCompleteDate(
+ .setBody(exchange -> new DataValueSet().withCompleteDate(
ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT))
.withOrgUnit("O6uvpzGd5pu")
.withDataSet("lyLU2wR22tC").withPeriod(PeriodBuilder.monthOf(new Date(), -1))
.withDataValues(
- List.of(new DataValue__1().withDataElement("aIJZ2d2QgVV").withValue("20")))))
- .to("dhis2://post/resource?path=dataValueSets&inBody=resource&username=admin&password=district&baseApiUrl=https://play.dhis2.org/2.39.1/api")
+ List.of(new DataValue__1().withDataElement("aIJZ2d2QgVV").withValue("20"))))
+ .to("dhis2://post/resource?path=dataValueSets&username=admin&password=district&baseApiUrl=https://play.dhis2.org/2.39.1/api")
.unmarshal().json(ImportReportWebMessageResponse.class)
.choice()
.when(exchange -> !exchange.getMessage().getBody(ImportReportWebMessageResponse.class).getStatus().get().equals(DescriptiveWebMessage.Status.OK))
diff --git a/components/camel-dhis2/camel-dhis2-component/src/test/java/org/apache/camel/component/dhis2/Dhis2GetIT.java b/components/camel-dhis2/camel-dhis2-component/src/test/java/org/apache/camel/component/dhis2/Dhis2GetIT.java
index db2e47ac047..c580a75f5da 100644
--- a/components/camel-dhis2/camel-dhis2-component/src/test/java/org/apache/camel/component/dhis2/Dhis2GetIT.java
+++ b/components/camel-dhis2/camel-dhis2-component/src/test/java/org/apache/camel/component/dhis2/Dhis2GetIT.java
@@ -42,17 +42,12 @@ public class Dhis2GetIT extends AbstractDhis2TestSupport {
@Test
public void testCollection() throws Exception {
final Map<String, Object> headers = new HashMap<String, Object>();
- // parameter type is String
headers.put("CamelDhis2.path", "organisationUnits");
- // parameter type is String
headers.put("CamelDhis2.itemType", "org.hisp.dhis.api.model.v2_39_1.OrganisationUnit");
- // parameter type is Boolean
+ headers.put("CamelDhis2.arrayName", "organisationUnits");
headers.put("CamelDhis2.paging", true);
- // parameter type is String
headers.put("CamelDhis2.fields", null);
- // parameter type is String
headers.put("CamelDhis2.filter", null);
- // parameter type is java.util.Map
headers.put("CamelDhis2.queryParams", new HashMap<>());
final java.util.Iterator result = requestBodyAndHeaders("direct://COLLECTION", null, headers);
@@ -64,13 +59,9 @@ public class Dhis2GetIT extends AbstractDhis2TestSupport {
@Test
public void testResource() throws Exception {
final Map<String, Object> headers = new HashMap<String, Object>();
- // parameter type is String
headers.put("CamelDhis2.path", String.format("organisationUnits/%s", Environment.ORG_UNIT_ID));
- // parameter type is String
headers.put("CamelDhis2.fields", null);
- // parameter type is String
headers.put("CamelDhis2.filter", null);
- // parameter type is java.util.Map
headers.put("CamelDhis2.queryParams", null);
final java.io.InputStream result = requestBodyAndHeaders("direct://RESOURCE", null, headers);