This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 801c636 RestClient API improvements.
801c636 is described below
commit 801c636e9badfa6c38e15d5590bfb0b6ec0caa00
Author: JamesBognar <[email protected]>
AuthorDate: Wed Jun 16 09:46:32 2021 -0400
RestClient API improvements.
---
.../main/java/org/apache/juneau/ContextCache.java | 20 ++-
.../org/apache/juneau/rest/client/RestClient.java | 130 +++++++++++---
.../juneau/rest/client/RestClientBuilder.java | 194 ++++++++++++++-------
.../org/apache/juneau/rest/client/RestRequest.java | 67 +++----
.../apache/juneau/rest/client/RestClient_Test.java | 2 +-
5 files changed, 290 insertions(+), 123 deletions(-)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextCache.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextCache.java
index 85e6a6e..1870abe 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextCache.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextCache.java
@@ -40,6 +40,7 @@ public class ContextCache {
private final
ConcurrentHashMap<Class<?>,ConcurrentHashMap<ContextProperties,Context>>
contextCache = new ConcurrentHashMap<>();
private final ConcurrentHashMap<Class<?>,String[]> prefixCache = new
ConcurrentHashMap<>();
+ private final ConcurrentHashMap<Class<?>,Boolean> cacheableMap = new
ConcurrentHashMap<>();
// When enabled, this will spit out cache-hit metrics to the console on
shutdown.
private static final boolean TRACK_CACHE_HITS =
Boolean.getBoolean("juneau.trackCacheHits");
@@ -97,6 +98,9 @@ public class ContextCache {
* @return The
*/
public <T extends Context> T create(Class<T> c, ContextProperties cp) {
+ if (! isCacheable(c))
+ return instantiate(c, cp);
+
String[] prefixes = getPrefixes(c);
if (prefixes == null)
@@ -139,6 +143,18 @@ public class ContextCache {
return m;
}
+ private boolean isCacheable(Class<?> c) {
+ Boolean b = cacheableMap.get(c);
+ if (b == null) {
+ b = true;
+ for (ConfigurableContext c2 :
ClassInfo.of(c).getAnnotations(ConfigurableContext.class))
+ if (c2.nocache())
+ b = false;
+ cacheableMap.put(c, b);
+ }
+ return b;
+ }
+
private String[] getPrefixes(Class<?> c) {
String[] prefixes = prefixCache.get(c);
if (prefixes == null) {
@@ -146,10 +162,6 @@ public class ContextCache {
for (ClassInfo c2 :
ClassInfo.of(c).getAllParentsChildFirst()) {
ConfigurableContext cc =
c2.getLastAnnotation(ConfigurableContext.class);
if (cc != null) {
- if (cc.nocache()) {
- prefixes = new String[0];
- break;
- }
if (cc.prefixes().length == 0)
ps.add(c2.getSimpleName());
else
diff --git
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index 03aca30..7534011 100644
---
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -39,6 +39,7 @@ import java.util.logging.*;
import java.util.regex.*;
import org.apache.http.*;
+import org.apache.http.Header;
import org.apache.http.client.*;
import org.apache.http.client.config.*;
import org.apache.http.client.entity.*;
@@ -54,6 +55,7 @@ import org.apache.juneau.collections.*;
import org.apache.juneau.cp.*;
import org.apache.juneau.http.remote.RemoteReturn;
import org.apache.juneau.http.resource.*;
+import org.apache.juneau.http.annotation.*;
import org.apache.juneau.http.entity.*;
import org.apache.juneau.http.header.*;
import org.apache.juneau.http.part.*;
@@ -1778,24 +1780,109 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
*/
public static final String RESTCLIENT_serializers = PREFIX +
"serializers.lo";
- static final String RESTCLIENT_skipEmptyHeaders = PREFIX +
"skipEmptyHeaders.b";
- static final String RESTCLIENT_skipEmptyQueryParameter = PREFIX +
"skipEmptyQueryParameters.b";
- static final String RESTCLIENT_skipEmptyFormDataParameters = PREFIX +
"skipEmptyFormDataParameters.b";
+ /**
+ * Configuration property: Skip empty form data.
+ *
+ * <h5 class='section'>Property:</h5>
+ * <ul class='spaced-list'>
+ * <li><b>ID:</b> {@link
org.apache.juneau.rest.client.RestClient#RESTCLIENT_skipEmptyFormData
RESTCLIENT_skipEmptyFormData}
+ * <li><b>Name:</b> <js>"RestClient.skipEmptyFormData.b"</js>
+ * <li><b>Data type:</b> {@link Boolean}
+ * <li><b>Default:</b> <jk>false</jk>.
+ * <li><b>Methods:</b>
+ * <ul>
+ * <li class='jm'>{@link
org.apache.juneau.rest.client.RestClientBuilder#skipEmptyFormData(boolean)}
+ * <li class='jm'>{@link
org.apache.juneau.rest.client.RestClientBuilder#skipEmptyFormData()}
+ * </ul>
+ * <li><b>Related:</b>
+ * <ul>
+ * <li class='ja'>{@link FormData#skipIfEmpty()}
+ * </ul>
+ * </ul>
+ *
+ * <h5 class='section'>Description:</h5>
+ * <p>
+ * When enabled, form data consisting of empty strings will be skipped
on requests.
+ * Note that <jk>null</jk> values are already skipped.
+ *
+ * <p>
+ * The {@link FormData#skipIfEmpty()} annotation overrides this setting.
+ */
+ public static final String RESTCLIENT_skipEmptyFormData = PREFIX +
"skipEmptyFormData.b";
+ /**
+ * Configuration property: Skip empty header data.
+ *
+ * <h5 class='section'>Property:</h5>
+ * <ul class='spaced-list'>
+ * <li><b>ID:</b> {@link
org.apache.juneau.rest.client.RestClient#RESTCLIENT_skipEmptyHeaders
RESTCLIENT_skipEmptyHeaders}
+ * <li><b>Name:</b> <js>"RestClient.skipEmptyHeaders.b"</js>
+ * <li><b>Data type:</b> {@link Boolean}
+ * <li><b>Default:</b> <jk>false</jk>.
+ * <li><b>Methods:</b>
+ * <ul>
+ * <li class='jm'>{@link
org.apache.juneau.rest.client.RestClientBuilder#skipEmptyHeaders(boolean)}
+ * <li class='jm'>{@link
org.apache.juneau.rest.client.RestClientBuilder#skipEmptyHeaders()}
+ * </ul>
+ * <li><b>Related:</b>
+ * <ul>
+ * <li class='ja'>{@link
org.apache.juneau.http.annotation.Header#skipIfEmpty()}
+ * </ul>
+ * </ul>
+ *
+ * <h5 class='section'>Description:</h5>
+ * <p>
+ * When enabled, header values consisting of empty strings will be
skipped on requests.
+ * Note that <jk>null</jk> values are already skipped.
+ *
+ * <p>
+ * The {@link org.apache.juneau.http.annotation.Header#skipIfEmpty()}
annotation overrides this setting.
+ */
+ public static final String RESTCLIENT_skipEmptyHeaders = PREFIX +
"skipEmptyHeaders.b";
+
+ /**
+ * Configuration property: Skip empty query data.
+ *
+ * <h5 class='section'>Property:</h5>
+ * <ul class='spaced-list'>
+ * <li><b>ID:</b> {@link
org.apache.juneau.rest.client.RestClient#RESTCLIENT_skipEmptyQueryData
RESTCLIENT_skipEmptyQueryData}
+ * <li><b>Name:</b> <js>"RestClient.skipEmptyQueryData.b"</js>
+ * <li><b>Data type:</b> {@link Boolean}
+ * <li><b>Default:</b> <jk>false</jk>.
+ * <li><b>Methods:</b>
+ * <ul>
+ * <li class='jm'>{@link
org.apache.juneau.rest.client.RestClientBuilder#skipEmptyQueryData(boolean)}
+ * <li class='jm'>{@link
org.apache.juneau.rest.client.RestClientBuilder#skipEmptyQueryData()}
+ * </ul>
+ * <li><b>Related:</b>
+ * <ul>
+ * <li class='ja'>{@link Query#skipIfEmpty()}
+ * </ul>
+ * </ul>
+ *
+ * <h5 class='section'>Description:</h5>
+ * <p>
+ * When enabled, query parameters consisting of empty strings will be
skipped on requests.
+ * Note that <jk>null</jk> values are already skipped.
+ *
+ * <p>
+ * The {@link Query#skipIfEmpty()} annotation overrides this setting.
+ */
+ public static final String RESTCLIENT_skipEmptyQueryData = PREFIX +
"skipEmptyQueryData.b";
- static final String RESTCLIENT_httpClient = PREFIX + "httpClient.o";
- static final String RESTCLIENT_httpClientBuilder = PREFIX +
"httpClientBuilder.o";
- static final String RESTCLIENT_headerDataBuilder = PREFIX +
"headerDataBuilder.o";
- static final String RESTCLIENT_formDataBuilder = PREFIX +
"formDataBuilder.o";
- static final String RESTCLIENT_queryDataBuilder = PREFIX +
"queryBuilder.o";
- static final String RESTCLIENT_pathDataBuilder = PREFIX +
"pathDataBuilder.o";
+ static final String RESTCLIENT_INTERNAL_httpClient = PREFIX +
"httpClient.o";
+ static final String RESTCLIENT_INTERNAL_httpClientBuilder = PREFIX +
"httpClientBuilder.o";
+ static final String RESTCLIENT_INTERNAL_headerDataBuilder = PREFIX +
"headerDataBuilder.o";
+ static final String RESTCLIENT_INTERNAL_formDataBuilder = PREFIX +
"formDataBuilder.o";
+ static final String RESTCLIENT_INTERNAL_queryDataBuilder = PREFIX +
"queryBuilder.o";
+ static final String RESTCLIENT_INTERNAL_pathDataBuilder = PREFIX +
"pathDataBuilder.o";
final HeaderListBuilder headerData;
final PartListBuilder queryData, formData, pathData;
final CloseableHttpClient httpClient;
private final HttpClientConnectionManager connectionManager;
- private final boolean keepHttpClientOpen, leakDetection;
+ private final boolean keepHttpClientOpen, leakDetection,
skipEmptyHeaders, skipEmptyQueryData, skipEmptyFormData;
private final BeanStore beanStore;
private final UrlEncodingSerializer urlEncodingSerializer; // Used for
form posts only.
final HttpPartSerializer partSerializer;
@@ -1856,11 +1943,14 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
@SuppressWarnings("unchecked")
protected RestClient(ContextProperties cp) {
super(cp);
- this.httpClient = cp.getInstance(RESTCLIENT_httpClient,
CloseableHttpClient.class).orElse(null);
- this.headerData = cp.getInstance(RESTCLIENT_headerDataBuilder,
HeaderListBuilder.class).orElseGet(HeaderListBuilder::new).copy();
- this.queryData = cp.getInstance(RESTCLIENT_queryDataBuilder,
PartListBuilder.class).orElseGet(PartListBuilder::new).copy();
- this.formData = cp.getInstance(RESTCLIENT_formDataBuilder,
PartListBuilder.class).orElseGet(PartListBuilder::new).copy();
- this.pathData = cp.getInstance(RESTCLIENT_pathDataBuilder,
PartListBuilder.class).orElseGet(PartListBuilder::new).copy();
+ this.httpClient =
cp.getInstance(RESTCLIENT_INTERNAL_httpClient,
CloseableHttpClient.class).orElse(null);
+ this.headerData =
cp.getInstance(RESTCLIENT_INTERNAL_headerDataBuilder,
HeaderListBuilder.class).orElseGet(HeaderListBuilder::new).copy();
+ this.queryData =
cp.getInstance(RESTCLIENT_INTERNAL_queryDataBuilder,
PartListBuilder.class).orElseGet(PartListBuilder::new).copy();
+ this.formData =
cp.getInstance(RESTCLIENT_INTERNAL_formDataBuilder,
PartListBuilder.class).orElseGet(PartListBuilder::new).copy();
+ this.pathData =
cp.getInstance(RESTCLIENT_INTERNAL_pathDataBuilder,
PartListBuilder.class).orElseGet(PartListBuilder::new).copy();
+ this.skipEmptyHeaders =
cp.getBoolean(RESTCLIENT_skipEmptyHeaders).orElse(false);
+ this.skipEmptyQueryData =
cp.getBoolean(RESTCLIENT_skipEmptyQueryData).orElse(false);
+ this.skipEmptyFormData =
cp.getBoolean(RESTCLIENT_skipEmptyFormData).orElse(false);
BeanStore bs = this.beanStore = new BeanStore()
.addBean(ContextProperties.class, cp)
@@ -3236,7 +3326,7 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
* @return <jk>true</jk> if empty request header values should be
ignored.
*/
protected boolean isSkipEmptyHeaders() {
- return false;
+ return skipEmptyHeaders;
}
/**
@@ -3244,8 +3334,8 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
*
* @return <jk>true</jk> if empty request query parameter values should
be ignored.
*/
- protected boolean isSkipEmptyQueryParameters() {
- return false;
+ protected boolean isSkipEmptyQueryData() {
+ return skipEmptyQueryData;
}
/**
@@ -3253,8 +3343,8 @@ public class RestClient extends BeanContext implements
HttpClient, Closeable, Re
*
* @return <jk>true</jk> if empty request form-data parameter values
should be ignored.
*/
- protected boolean isSkipEmptyFormDataParameters() {
- return false;
+ protected boolean isSkipEmptyFormData() {
+ return skipEmptyFormData;
}
//-----------------------------------------------------------------------------------------------------------------
diff --git
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
index b7bf597..ac5f1b2 100644
---
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
+++
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
@@ -15,7 +15,6 @@ package org.apache.juneau.rest.client;
import static org.apache.juneau.parser.InputStreamParser.*;
import static org.apache.juneau.rest.client.RestClient.*;
import static org.apache.juneau.BeanTraverseContext.*;
-import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.ExceptionUtils.*;
import static org.apache.juneau.serializer.OutputStreamSerializer.*;
@@ -37,6 +36,7 @@ import java.util.logging.*;
import javax.net.ssl.*;
import org.apache.http.*;
+import org.apache.http.Header;
import org.apache.http.auth.*;
import org.apache.http.client.*;
import org.apache.http.client.CookieStore;
@@ -54,6 +54,7 @@ import org.apache.http.protocol.*;
import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.html.*;
+import org.apache.juneau.http.annotation.*;
import org.apache.juneau.http.header.*;
import org.apache.juneau.http.header.Date;
import org.apache.juneau.http.part.*;
@@ -110,7 +111,7 @@ public class RestClientBuilder extends BeanContextBuilder {
*/
protected RestClientBuilder(RestClient copyFrom) {
super(copyFrom);
- HttpClientBuilder httpClientBuilder =
peek(HttpClientBuilder.class, RESTCLIENT_httpClientBuilder);
+ HttpClientBuilder httpClientBuilder =
peek(HttpClientBuilder.class, RESTCLIENT_INTERNAL_httpClientBuilder);
this.httpClientBuilder = httpClientBuilder != null ?
httpClientBuilder : getHttpClientBuilder();
if (copyFrom == null) {
this.headerData = HeaderList.create();
@@ -147,12 +148,12 @@ public class RestClientBuilder extends BeanContextBuilder
{
}
private ContextProperties contextProperties() {
- set(RESTCLIENT_httpClient, getHttpClient());
- set(RESTCLIENT_httpClientBuilder, getHttpClientBuilder());
- set(RESTCLIENT_headerDataBuilder, headerData);
- set(RESTCLIENT_formDataBuilder, formData);
- set(RESTCLIENT_queryDataBuilder, queryData);
- set(RESTCLIENT_pathDataBuilder, pathData);
+ set(RESTCLIENT_INTERNAL_httpClient, getHttpClient());
+ set(RESTCLIENT_INTERNAL_httpClientBuilder,
getHttpClientBuilder());
+ set(RESTCLIENT_INTERNAL_headerDataBuilder, headerData);
+ set(RESTCLIENT_INTERNAL_formDataBuilder, formData);
+ set(RESTCLIENT_INTERNAL_queryDataBuilder, queryData);
+ set(RESTCLIENT_INTERNAL_pathDataBuilder, pathData);
return getContextProperties();
}
@@ -1725,10 +1726,9 @@ public class RestClientBuilder extends
BeanContextBuilder {
public RestClientBuilder headerPairs(String...pairs) {
if (pairs.length % 2 != 0)
throw new RuntimeException("Odd number of parameters
passed into headerPairs(String...)");
- ArrayList<Header> l = new ArrayList<>();
+ HeaderListBuilder b = getHeaderData();
for (int i = 0; i < pairs.length; i+=2)
- l.add(createHeader(stringify(pairs[i]), pairs[i+1]));
- getHeaderData().append(l);
+ b.append(pairs[i], pairs[i+1]);
return this;
}
@@ -1750,10 +1750,9 @@ public class RestClientBuilder extends
BeanContextBuilder {
public RestClientBuilder queryDataPairs(String...pairs) {
if (pairs.length % 2 != 0)
throw new RuntimeException("Odd number of parameters
passed into queryDataPairs(String...)");
- ArrayList<NameValuePair> l = new ArrayList<>();
+ PartListBuilder b = getQueryData();
for (int i = 0; i < pairs.length; i+=2)
- l.add(getQueryData().createPart(stringify(pairs[i]),
pairs[i+1]));
- getQueryData().append(l);
+ b.append(pairs[i], pairs[i+1]);
return this;
}
@@ -1775,10 +1774,9 @@ public class RestClientBuilder extends
BeanContextBuilder {
public RestClientBuilder formDataPairs(String...pairs) {
if (pairs.length % 2 != 0)
throw new RuntimeException("Odd number of parameters
passed into formDataPairs(String...)");
- ArrayList<NameValuePair> l = new ArrayList<>();
+ PartListBuilder b = getFormData();
for (int i = 0; i < pairs.length; i+=2)
- l.add(getFormData().createPart(stringify(pairs[i]),
pairs[i+1]));
- getFormData().append(l);
+ b.append(pairs[i], pairs[i+1]);
return this;
}
@@ -1800,10 +1798,9 @@ public class RestClientBuilder extends
BeanContextBuilder {
public RestClientBuilder pathDataPairs(String...pairs) {
if (pairs.length % 2 != 0)
throw new RuntimeException("Odd number of parameters
passed into pathDataPairs(String...)");
- ArrayList<NameValuePair> l = new ArrayList<>();
+ PartListBuilder b = getPathData();
for (int i = 0; i < pairs.length; i+=2)
- l.add(getFormData().createPart(stringify(pairs[i]),
pairs[i+1]));
- getPathData().set(l);
+ b.append(pairs[i], pairs[i+1]);
return this;
}
@@ -3402,6 +3399,117 @@ public class RestClientBuilder extends
BeanContextBuilder {
return prependTo(RESTCLIENT_serializers, value);
}
+ /**
+ * <i><l>RestClient</l> configuration property: </i> Skip empty
form data.
+ *
+ * <p>
+ * When enabled, form data consisting of empty strings will be skipped
on requests.
+ * Note that <jk>null</jk> values are already skipped.
+ *
+ * <p>
+ * The {@link FormData#skipIfEmpty()} annotation overrides this setting.
+ *
+ * @param value
+ * The new value for this setting.
+ * <br>The default is <jk>false</jk>.
+ * @return This object (for method chaining).
+ */
+ @FluentSetter
+ public RestClientBuilder skipEmptyFormData(boolean value) {
+ return set(RESTCLIENT_skipEmptyFormData, value);
+ }
+
+ /**
+ * <i><l>RestClient</l> configuration property: </i> Skip empty
form data.
+ *
+ * <p>
+ * When enabled, form data consisting of empty strings will be skipped
on requests.
+ * Note that <jk>null</jk> values are already skipped.
+ *
+ * <p>
+ * The {@link FormData#skipIfEmpty()} annotation overrides this setting.
+ *
+ * @return This object (for method chaining).
+ */
+ @FluentSetter
+ public RestClientBuilder skipEmptyFormData() {
+ return skipEmptyFormData(true);
+ }
+
+ /**
+ * <i><l>RestClient</l> configuration property: </i> Skip empty
headers.
+ *
+ * <p>
+ * When enabled, headers consisting of empty strings will be skipped on
requests.
+ * Note that <jk>null</jk> values are already skipped.
+ *
+ * <p>
+ * The {@link org.apache.juneau.http.annotation.Header#skipIfEmpty()}
annotation overrides this setting.
+ *
+ * @param value
+ * The new value for this setting.
+ * <br>The default is <jk>false</jk>.
+ * @return This object (for method chaining).
+ */
+ @FluentSetter
+ public RestClientBuilder skipEmptyHeaders(boolean value) {
+ return set(RESTCLIENT_skipEmptyHeaders, value);
+ }
+
+ /**
+ * <i><l>RestClient</l> configuration property: </i> Skip empty
headers.
+ *
+ * <p>
+ * When enabled, headers consisting of empty strings will be skipped on
requests.
+ * Note that <jk>null</jk> values are already skipped.
+ *
+ * <p>
+ * The {@link org.apache.juneau.http.annotation.Header#skipIfEmpty()}
annotation overrides this setting.
+ *
+ * @return This object (for method chaining).
+ */
+ @FluentSetter
+ public RestClientBuilder skipEmptyHeaders() {
+ return skipEmptyHeaders(true);
+ }
+
+ /**
+ * <i><l>RestClient</l> configuration property: </i> Skip empty
query data.
+ *
+ * <p>
+ * When enabled, query parameters consisting of empty strings will be
skipped on requests.
+ * Note that <jk>null</jk> values are already skipped.
+ *
+ * <p>
+ * The {@link Query#skipIfEmpty()} annotation overrides this setting.
+ *
+ * @param value
+ * The new value for this setting.
+ * <br>The default is <jk>false</jk>.
+ * @return This object (for method chaining).
+ */
+ @FluentSetter
+ public RestClientBuilder skipEmptyQueryData(boolean value) {
+ return set(RESTCLIENT_skipEmptyQueryData, value);
+ }
+
+ /**
+ * <i><l>RestClient</l> configuration property: </i> Skip empty
query data.
+ *
+ * <p>
+ * When enabled, query parameters consisting of empty strings will be
skipped on requests.
+ * Note that <jk>null</jk> values are already skipped.
+ *
+ * <p>
+ * The {@link Query#skipIfEmpty()} annotation overrides this setting.
+ *
+ * @return This object (for method chaining).
+ */
+ @FluentSetter
+ public RestClientBuilder skipEmptyQueryData() {
+ return skipEmptyQueryData(true);
+ }
+
//-----------------------------------------------------------------------------------------------------------------
// BeanTraverse Properties
//-----------------------------------------------------------------------------------------------------------------
@@ -5725,50 +5833,4 @@ public class RestClientBuilder extends
BeanContextBuilder {
httpClientBuilder.evictIdleConnections(maxIdleTime,
maxIdleTimeUnit);
return this;
}
-
-
//------------------------------------------------------------------------------------------------------------------
- // Utility methods.
-
//------------------------------------------------------------------------------------------------------------------
-
- /**
- * Creates a header from the specified name/value pair.
- *
- * @param name The header name.
- * @param value The header value.
- * @return A new header, or <jk>null</jk> if the name was <jk>null</jk>
or empty.
- */
- protected Header createHeader(String name, Object value) {
- String n = stringify(name);
- if (isEmpty(n))
- return null;
- return getHeaderData().createHeader(n, value);
- }
-
- /**
- * Creates a query parameter from the specified name/value pair.
- *
- * @param name The parameter name.
- * @param value The parameter value.
- * @return A new parameter, or <jk>null</jk> if the name was
<jk>null</jk> or empty.
- */
- protected NameValuePair createQueryPart(String name, Object value) {
- String n = stringify(name);
- if (isEmpty(n))
- return null;
- return getQueryData().createPart(n, value);
- }
-
- /**
- * Creates a form-data parameter from the specified name/value pair.
- *
- * @param name The parameter name.
- * @param value The parameter value.
- * @return A new parameter, or <jk>null</jk> if the name was
<jk>null</jk> or empty.
- */
- protected NameValuePair createFormDataPart(String name, Object value) {
- String n = stringify(name);
- if (isEmpty(n))
- return null;
- return getFormData().createPart(n, value);
- }
}
diff --git
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
index 45d3586..1e1833e 100644
---
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
+++
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
@@ -15,7 +15,6 @@ package org.apache.juneau.rest.client;
import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.ExceptionUtils.*;
-import static org.apache.juneau.ListOperation.*;
import static org.apache.juneau.httppart.HttpPartType.*;
import static org.apache.juneau.http.HttpEntities.*;
import static org.apache.juneau.http.HttpHeaders.*;
@@ -1226,10 +1225,9 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
public RestRequest headerPairs(String...pairs) {
if (pairs.length % 2 != 0)
throw runtimeException("Odd number of parameters passed
into headerPairs(String...)");
- List<Header> l = new ArrayList<>();
+ HeaderListBuilder b = getHeaderDataBuilder();
for (int i = 0; i < pairs.length; i+=2)
- l.add(createHeader(stringify(pairs[i]), pairs[i+1]));
- getHeaderDataBuilder().add(APPEND, l);
+ b.append(pairs[i], pairs[i+1]);
return this;
}
@@ -1256,10 +1254,9 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
public RestRequest queryDataPairs(String...pairs) throws
RestCallException {
if (pairs.length % 2 != 0)
throw runtimeException("Odd number of parameters passed
into queryDataPairs(String...)");
- List<NameValuePair> l = new ArrayList<>();
+ PartListBuilder b = getQueryDataBuilder();
for (int i = 0; i < pairs.length; i+=2)
- l.add(createPart(QUERY, stringify(pairs[i]),
pairs[i+1]));
- getQueryDataBuilder().add(APPEND, l);
+ b.append(pairs[i], pairs[i+1]);
return this;
}
@@ -1286,10 +1283,9 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
public RestRequest formDataPairs(String...pairs) throws
RestCallException {
if (pairs.length % 2 != 0)
throw runtimeException("Odd number of parameters passed
into formDataPairs(String...)");
- List<NameValuePair> l = new ArrayList<>();
+ PartListBuilder b = getFormDataBuilder();
for (int i = 0; i < pairs.length; i+=2)
- l.add(createPart(FORMDATA, stringify(pairs[i]),
pairs[i+1]));
- getFormDataBuilder().add(APPEND, l);
+ b.append(pairs[i], pairs[i+1]);
return this;
}
@@ -1318,19 +1314,21 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
public RestRequest pathDataPairs(String...pairs) {
if (pairs.length % 2 != 0)
throw runtimeException("Odd number of parameters passed
into pathDataPairs(String...)");
- List<NameValuePair> l = new ArrayList<>();
+ PartListBuilder b = getPathDataBuilder();
for (int i = 0; i < pairs.length; i+=2)
- l.add(createPart(PATH, stringify(pairs[i]),
pairs[i+1]));
- getPathDataBuilder().add(SET, l);
+ b.set(pairs[i], pairs[i+1]);
return this;
}
/**
* Appends multiple headers to the request from properties defined on a
Java bean.
*
+ * <p>
+ * Uses {@link PropertyNamerDUCS} for resolving the header names from
property names.
+ *
* <h5 class='section'>Example:</h5>
* <p class='bcode w800'>
- * <ja>@Bean</ja>(propertyNamer=PropertyNamerDUCS.<jk>class</jk>)
<jc>// Use Dash-UpperCase-Start property names.</jc>
+ * <ja>@Bean</ja>
* <jk>public class<jk> MyHeaders {
* <jk>public</jk> String getFooBar() { <jk>return</jk>
<js>"baz"</js>; }
* <jk>public</jk> Integer getQux() { <jk>return</jk> 123;
}
@@ -1350,8 +1348,8 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
if (! isBean(value))
throw runtimeException("Object passed into
headersBean(Object) is not a bean.");
HeaderListBuilder b = getHeaderDataBuilder();
- for (Map.Entry<String,Object> e : toBeanMap(value).entrySet())
- b.append(createHeader(e.getKey(),
stringify(e.getValue())));
+ for (Map.Entry<String,Object> e : toBeanMap(value,
PropertyNamerDUCS.INSTANCE).entrySet())
+ b.append(createHeader(e.getKey(), e.getValue()));
return this;
}
@@ -1380,7 +1378,7 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
throw runtimeException("Object passed into
queryDataBean(Object) is not a bean.");
PartListBuilder b = getQueryDataBuilder();
for (Map.Entry<String,Object> e : toBeanMap(value).entrySet())
- b.append(createPart(QUERY, e.getKey(),
stringify(e.getValue())));
+ b.append(createPart(QUERY, e.getKey(), e.getValue()));
return this;
}
@@ -1409,7 +1407,7 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
throw runtimeException("Object passed into
formDataBean(Object) is not a bean.");
PartListBuilder b = getFormDataBuilder();
for (Map.Entry<String,Object> e : toBeanMap(value).entrySet())
- b.append(createPart(FORMDATA, e.getKey(),
stringify(e.getValue())));
+ b.append(createPart(FORMDATA, e.getKey(),
e.getValue()));
return this;
}
@@ -1438,7 +1436,7 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
throw runtimeException("Object passed into
pathDataBean(Object) is not a bean.");
PartListBuilder b = getPathDataBuilder();
for (Map.Entry<String,Object> e : toBeanMap(value).entrySet())
- b.set(createPart(PATH, e.getKey(),
stringify(e.getValue())));
+ b.set(createPart(PATH, e.getKey(), e.getValue()));
return this;
}
@@ -3098,8 +3096,14 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
protected NameValuePair createPart(String name, Object value,
HttpPartType type, HttpPartSerializer serializer, HttpPartSchema schema,
Boolean skipIfEmpty) {
if (isEmpty(name))
return null;
- if (skipIfEmpty == null)
- skipIfEmpty = client.isSkipEmptyHeaders();
+ if (skipIfEmpty == null) {
+ if (type == QUERY)
+ skipIfEmpty = client.isSkipEmptyQueryData();
+ else if (type == FORMDATA)
+ skipIfEmpty = client.isSkipEmptyFormData();
+ else
+ skipIfEmpty = false;
+ }
if (serializer == null)
serializer = client.getPartSerializer();
return new SerializedPart(name, value, type,
getPartSerializerSession(serializer), schema, skipIfEmpty);
@@ -3149,16 +3153,17 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
private class SimplePart implements NameValuePair {
final String name;
final String value;
- final boolean skipIfEmpty;
SimplePart(NameValuePair x, boolean skipIfEmpty) {
- if (x instanceof SerializedHeader)
- x =
((SerializedHeader)x).copyWith(getPartSerializerSession(), null);
- if (x instanceof SerializedPart)
- x =
((SerializedPart)x).copyWith(getPartSerializerSession(), null);
name = x.getName();
- value = x.getValue();
- this.skipIfEmpty = skipIfEmpty;
+ if (x instanceof SerializedHeader) {
+ value =
((SerializedHeader)x).copyWith(getPartSerializerSession(), null).getValue();
+ } else if (x instanceof SerializedPart) {
+ value =
((SerializedPart)x).copyWith(getPartSerializerSession(), null).getValue();
+ } else {
+ String v = x.getValue();
+ value = (isEmpty(v) && skipIfEmpty) ? null : v;
+ }
}
boolean isValid() {
@@ -3166,8 +3171,6 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
return false;
if (value == null)
return false;
- if (isEmpty(value) && skipIfEmpty)
- return false;
return true;
}
@@ -3184,13 +3187,13 @@ public class RestRequest extends BeanSession implements
HttpUriRequest, Configur
private class SimpleQuery extends SimplePart {
SimpleQuery(NameValuePair x) {
- super(x, client.isSkipEmptyQueryParameters());
+ super(x, client.isSkipEmptyQueryData());
}
}
private class SimpleFormData extends SimplePart {
SimpleFormData(NameValuePair x) {
- super(x, client.isSkipEmptyFormDataParameters());
+ super(x, client.isSkipEmptyFormData());
}
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java
index b183e9c..8b28992 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/rest/client/RestClient_Test.java
@@ -94,7 +94,7 @@ public class RestClient_Test {
RestClient.create().build().closeQuietly();
RestClient.create().keepHttpClientOpen().build().close();
RestClient.create().keepHttpClientOpen().build().closeQuietly();
-
RestClient.create().set(RESTCLIENT_httpClient,null).keepHttpClientOpen().build().close();
+
RestClient.create().set(RESTCLIENT_INTERNAL_httpClient,null).keepHttpClientOpen().build().close();
ExecutorService es = new
ThreadPoolExecutor(1,1,30,TimeUnit.SECONDS,new
ArrayBlockingQueue<Runnable>(10));
RestClient.create().executorService(es,true).build().close();