Skip to content

Commit 34897e3

Browse files
committed
Fix issue with Parsson, move things around, update test
1 parent ae97403 commit 34897e3

File tree

6 files changed

+169
-129
lines changed

6 files changed

+169
-129
lines changed

catalog-info.yaml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,33 @@ spec:
2626
devtools-team: {}
2727
everyone:
2828
access_level: READ_ONLY
29+
30+
---
31+
# yaml-language-server: $schema=https://gist.githubusercontent.com/elasticmachine/988b80dae436cafea07d9a4a460a011d/raw/rre.schema.json
32+
apiVersion: backstage.io/v1alpha1
33+
kind: Resource
34+
metadata:
35+
name: buildkite-pipeline-elasticsearch-java-release
36+
description: Buildkite release pipeline for elasticsearch-java
37+
links:
38+
- title: Pipeline
39+
url: https://buildkite.com/elastic/elasticsearch-java-release
40+
41+
spec:
42+
type: buildkite-pipeline
43+
owner: group:devtools-team
44+
system: buildkite
45+
implementation:
46+
apiVersion: buildkite.elastic.dev/v1
47+
kind: Pipeline
48+
metadata:
49+
description: Elasticsearch Java Client
50+
name: elasticsearch-java-release
51+
spec:
52+
repository: elastic/elasticsearch-java
53+
pipeline_file: ".buildkite/release.yml"
54+
teams:
55+
devtools-team:
56+
access_level: MANAGE_BUILD_AND_READ
57+
everyone:
58+
access_level: READ_ONLY

java-client/src/main/java/co/elastic/clients/transport/ElasticsearchTransportBase.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,21 @@ private <RequestT, ResponseT, ErrorT> TransportHttpClient.Request prepareTranspo
259259
NoCopyByteArrayOutputStream baos = new NoCopyByteArrayOutputStream();
260260
JsonGenerator generator = mapper.jsonProvider().createGenerator(baos);
261261
mapper.serialize(body, generator);
262-
generator.close();
262+
263+
// Some generators (e.g. Parsson) throw an exception if we close a generator
264+
// that hasn't received any event. In that case, we ignore the exception
265+
RuntimeException closeException = null;
266+
try {
267+
generator.close();
268+
} catch (RuntimeException e) {
269+
closeException = e;
270+
}
271+
263272
if (baos.size() > 0) {
273+
if (closeException != null) {
274+
// We got some content and close failed
275+
throw closeException;
276+
}
264277
bodyBuffers = Collections.singletonList(baos.asByteBuffer());
265278
headers = JsonContentTypeHeaders;
266279
}

java-client/src/main/java/co/elastic/clients/transport/endpoints/EndpointBase.java

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,11 @@
2121

2222
import co.elastic.clients.elasticsearch._types.ErrorCause;
2323
import co.elastic.clients.elasticsearch._types.ErrorResponse;
24-
import co.elastic.clients.json.DelegatingJsonGenerator;
2524
import co.elastic.clients.json.JsonpDeserializer;
2625
import co.elastic.clients.json.JsonpDeserializerBase;
2726
import co.elastic.clients.json.JsonpMapper;
28-
import co.elastic.clients.json.JsonpSerializable;
2927
import co.elastic.clients.json.JsonpUtils;
3028
import co.elastic.clients.transport.Endpoint;
31-
import jakarta.json.stream.JsonGenerator;
3229
import jakarta.json.stream.JsonParser;
3330

3431
import javax.annotation.Nullable;
@@ -68,62 +65,10 @@ static <T, U> Function<T, U> returnNull() {
6865
* that the input and output generic parameters are different, making it suitable for use in a wider range of use cases.
6966
*/
7067
@SuppressWarnings("unchecked")
71-
static <T, U> Function<T, U> returnSelf() {
68+
public static <T, U> Function<T, U> returnSelf() {
7269
return (Function<T, U>) RETURN_SELF;
7370
}
7471

75-
/**
76-
* Wraps a function's result with a serializable object that will serialize to nothing if the wrapped
77-
* object's serialization has no property, i.e. it will either produce an empty object or nothing.
78-
*/
79-
public static <T, U extends JsonpSerializable> Function<T, Object> nonEmptyJsonObject(Function<T, U> getter) {
80-
return (x -> x == null ? null : new NonEmptySerializable(getter.apply(x)));
81-
}
82-
83-
private static final class NonEmptySerializable implements JsonpSerializable {
84-
private final Object value;
85-
86-
NonEmptySerializable(Object value) {
87-
this.value = value;
88-
}
89-
90-
@Override
91-
public void serialize(JsonGenerator generator, JsonpMapper mapper) {
92-
// Track the first property to start the top-level object, and end it if needed in close()
93-
JsonGenerator filter = new DelegatingJsonGenerator(generator) {
94-
boolean gotKey = false;
95-
96-
@Override
97-
public JsonGenerator writeStartObject() {
98-
if (gotKey) {
99-
super.writeStartObject();
100-
}
101-
return this;
102-
}
103-
104-
@Override
105-
public JsonGenerator writeKey(String s) {
106-
if (!gotKey) {
107-
gotKey = true;
108-
super.writeStartObject();
109-
}
110-
super.writeKey(s);
111-
return this;
112-
}
113-
114-
@Override
115-
public JsonGenerator writeEnd() {
116-
if (gotKey) {
117-
super.writeEnd();
118-
}
119-
return this;
120-
}
121-
};
122-
123-
mapper.serialize(value, filter);
124-
}
125-
}
126-
12772
protected final String id;
12873
protected final Function<RequestT, String> method;
12974
protected final Function<RequestT, String> requestUrl;

java-client/src/main/java/co/elastic/clients/transport/endpoints/SimpleEndpoint.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@
2020
package co.elastic.clients.transport.endpoints;
2121

2222
import co.elastic.clients.elasticsearch._types.ErrorResponse;
23+
import co.elastic.clients.json.DelegatingJsonGenerator;
2324
import co.elastic.clients.json.JsonpDeserializer;
25+
import co.elastic.clients.json.JsonpMapper;
26+
import co.elastic.clients.json.JsonpSerializable;
2427
import co.elastic.clients.transport.JsonEndpoint;
28+
import jakarta.json.stream.JsonGenerator;
2529

2630
import java.util.Map;
2731
import java.util.function.Function;
@@ -86,4 +90,56 @@ public <NewResponseT> SimpleEndpoint<RequestT, NewResponseT> withResponseDeseria
8690
newResponseParser
8791
);
8892
}
93+
94+
/**
95+
* Wraps a function's result with a serializable object that will serialize to nothing if the wrapped
96+
* object's serialization has no property, i.e. it will either produce an empty object or nothing.
97+
*/
98+
public static <T, U extends JsonpSerializable> Function<T, Object> nonEmptyJsonObject(Function<T, U> getter) {
99+
return (x -> x == null ? null : new NonEmptySerializable(getter.apply(x)));
100+
}
101+
102+
private static final class NonEmptySerializable implements JsonpSerializable {
103+
private final Object value;
104+
105+
NonEmptySerializable(Object value) {
106+
this.value = value;
107+
}
108+
109+
@Override
110+
public void serialize(JsonGenerator generator, JsonpMapper mapper) {
111+
// Track the first property to start the top-level object, and end it if needed in close()
112+
JsonGenerator filter = new DelegatingJsonGenerator(generator) {
113+
boolean gotKey = false;
114+
115+
@Override
116+
public JsonGenerator writeStartObject() {
117+
if (gotKey) {
118+
super.writeStartObject();
119+
}
120+
return this;
121+
}
122+
123+
@Override
124+
public JsonGenerator writeKey(String s) {
125+
if (!gotKey) {
126+
gotKey = true;
127+
super.writeStartObject();
128+
}
129+
super.writeKey(s);
130+
return this;
131+
}
132+
133+
@Override
134+
public JsonGenerator writeEnd() {
135+
if (gotKey) {
136+
super.writeEnd();
137+
}
138+
return this;
139+
}
140+
};
141+
142+
mapper.serialize(value, filter);
143+
}
144+
}
89145
}

java-client/src/test/java/co/elastic/clients/transport/TransportTest.java

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -20,41 +20,26 @@
2020
package co.elastic.clients.transport;
2121

2222
import co.elastic.clients.elasticsearch.ElasticsearchClient;
23-
import co.elastic.clients.json.JsonpMapper;
24-
import co.elastic.clients.json.JsonpSerializable;
2523
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
26-
import co.elastic.clients.testkit.MockHttpClient;
27-
import co.elastic.clients.transport.endpoints.EndpointBase;
28-
import co.elastic.clients.transport.endpoints.SimpleEndpoint;
29-
import co.elastic.clients.transport.endpoints.SimpleJsonEndpoint;
3024
import co.elastic.clients.transport.http.RepeatableBodyResponse;
31-
import co.elastic.clients.transport.http.TransportHttpClient;
3225
import co.elastic.clients.transport.rest_client.RestClientOptions;
3326
import co.elastic.clients.transport.rest_client.RestClientTransport;
3427
import co.elastic.clients.util.BinaryData;
3528
import com.sun.net.httpserver.HttpServer;
36-
import jakarta.json.JsonObject;
37-
import jakarta.json.JsonObjectBuilder;
38-
import jakarta.json.stream.JsonGenerator;
3929
import org.apache.http.HttpHost;
4030
import org.elasticsearch.client.RequestOptions;
4131
import org.elasticsearch.client.Response;
4232
import org.elasticsearch.client.RestClient;
43-
import org.jetbrains.annotations.Nullable;
4433
import org.junit.jupiter.api.Assertions;
4534
import org.junit.jupiter.api.Test;
4635

4736
import java.io.BufferedReader;
48-
import java.io.IOException;
4937
import java.io.InputStreamReader;
5038
import java.io.OutputStream;
5139
import java.net.InetAddress;
5240
import java.net.InetSocketAddress;
5341
import java.nio.charset.StandardCharsets;
54-
import java.util.ArrayList;
5542
import java.util.Collections;
56-
import java.util.List;
57-
import java.util.Map;
5843

5944
import static co.elastic.clients.util.ContentType.APPLICATION_JSON;
6045

@@ -167,60 +152,4 @@ public void testOriginalJsonBodyRetrievalException() throws Exception {
167152
assertEquals("definitely not json",sb.toString());
168153
}
169154
}
170-
171-
@Test
172-
public void testNoBodyForEmptyObject() throws Exception {
173-
174-
List<TransportHttpClient.Request> requests = new ArrayList<>();
175-
176-
MockHttpClient httpClient = new MockHttpClient() {
177-
@Override
178-
public Response performRequest(String endpointId, @Nullable Node node, Request request, TransportOptions option) throws IOException {
179-
requests.add(request);
180-
return super.performRequest(endpointId, node, request, option);
181-
}
182-
};
183-
184-
httpClient.add("/test", "text/plain", "hello");
185-
186-
JsonpMapper mapper = new JacksonJsonpMapper();
187-
ElasticsearchTransport transport = new ElasticsearchTransportBase(httpClient, null, mapper) {};
188-
189-
// Send empty object = true (legacy constructor)
190-
SimpleEndpoint<TestValue, Void> endpoint = new SimpleEndpoint<>(
191-
"test-endpoint",
192-
x -> "GET",
193-
x -> "/test",
194-
x -> Collections.emptyMap(), // path params
195-
x -> Collections.emptyMap(), // query params
196-
x -> Collections.emptyMap(), // headers
197-
EndpointBase.nonEmptyJsonObject(x -> x),
198-
null
199-
);
200-
201-
transport.performRequest(new TestValue(null), endpoint, null);
202-
transport.performRequest(new TestValue("hi"), endpoint, null);
203-
204-
assertNull(requests.get(0).body());
205-
assertNotNull(requests.get(1).body());
206-
207-
}
208-
209-
private static class TestValue implements JsonpSerializable {
210-
211-
private final String value;
212-
213-
public TestValue(String value) {
214-
this.value = value;
215-
}
216-
217-
@Override
218-
public void serialize(JsonGenerator generator, JsonpMapper mapper) {
219-
generator.writeStartObject();
220-
if (value != null) {
221-
generator.write("value", value);
222-
}
223-
generator.writeEnd();
224-
}
225-
}
226155
}
Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,71 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
120
package co.elastic.clients.transport.endpoints;
221

3-
public class SimpleEndpointTest {
22+
import co.elastic.clients.elasticsearch.ElasticsearchClient;
23+
import co.elastic.clients.elasticsearch.core.CountResponse;
24+
import co.elastic.clients.testkit.MockHttpClient;
25+
import co.elastic.clients.testkit.ModelTestCase;
26+
import co.elastic.clients.transport.ElasticsearchTransport;
27+
import co.elastic.clients.transport.ElasticsearchTransportBase;
28+
import co.elastic.clients.transport.TransportOptions;
29+
import co.elastic.clients.transport.http.TransportHttpClient;
30+
import org.jetbrains.annotations.Nullable;
31+
import org.junit.jupiter.api.Test;
32+
33+
import java.io.IOException;
34+
import java.util.ArrayList;
35+
import java.util.List;
36+
37+
public class SimpleEndpointTest extends ModelTestCase {
38+
39+
@Test
40+
public void testNoBodyForEmptyObject() throws Exception {
41+
42+
List<TransportHttpClient.Request> requests = new ArrayList<>();
43+
44+
MockHttpClient httpClient = new MockHttpClient() {
45+
@Override
46+
public Response performRequest(
47+
String endpointId, @Nullable Node node, Request request, TransportOptions option
48+
) throws IOException {
49+
requests.add(request);
50+
return super.performRequest(endpointId, node, request, option);
51+
}
52+
};
53+
54+
httpClient.add("/_count", "application/json", toJson(
55+
CountResponse.of(c -> c
56+
.count(1)
57+
.shards(s -> s.successful(1).failed(0).total(1))
58+
)));
59+
60+
ElasticsearchTransport transport = new ElasticsearchTransportBase(httpClient, null, mapper) {};
61+
ElasticsearchClient client = new ElasticsearchClient(transport, null);
62+
63+
client.count();
64+
client.count(c -> c.q("foo:bar"));
65+
client.count(c -> c.query(q -> q.term(t -> t.field("foo").value("bar"))));
66+
67+
assertNull(requests.get(0).body());
68+
assertNull(requests.get(1).body());
69+
assertNotNull(requests.get(2).body());
70+
}
471
}

0 commit comments

Comments
 (0)