Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow requests to be serialized as nothing instead of an empty object #926

Merged
merged 5 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions catalog-info.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,33 @@ spec:
devtools-team: {}
everyone:
access_level: READ_ONLY

---
# yaml-language-server: $schema=https://gist.githubusercontent.com/elasticmachine/988b80dae436cafea07d9a4a460a011d/raw/rre.schema.json
apiVersion: backstage.io/v1alpha1
kind: Resource
metadata:
name: buildkite-pipeline-elasticsearch-java-release
description: Buildkite release pipeline for elasticsearch-java
links:
- title: Pipeline
url: https://buildkite.com/elastic/elasticsearch-java-release

spec:
type: buildkite-pipeline
owner: group:devtools-team
system: buildkite
implementation:
apiVersion: buildkite.elastic.dev/v1
kind: Pipeline
metadata:
description: Elasticsearch Java Client
name: elasticsearch-java-release
spec:
repository: elastic/elasticsearch-java
pipeline_file: ".buildkite/release.yml"
teams:
devtools-team:
access_level: MANAGE_BUILD_AND_READ
everyone:
access_level: READ_ONLY
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,24 @@
import org.apache.http.message.BasicHeader;
import org.elasticsearch.client.RestClient;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;

public class EsqlArticle {

public static void main(String[] args) throws IOException, SQLException, InterruptedException {

String serverUrl = System.getenv("server-url");
String apiKey = System.getenv("api-key");
String booksUrl = "https://raw.githubusercontent" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -760,5 +760,6 @@ protected static void setupCountRequestDeserializer(ObjectDeserializer<CountRequ
}
return params;

}, SimpleEndpoint.emptyMap(), true, CountResponse._DESERIALIZER);
}, SimpleEndpoint.emptyMap(), SimpleEndpoint.nonEmptyJsonObject(SimpleEndpoint.returnSelf()),
CountResponse._DESERIALIZER);
}
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,8 @@ protected static void setupExplainRequestDeserializer(ObjectDeserializer<Explain
}
return params;

}, SimpleEndpoint.emptyMap(), true, ExplainResponse._DESERIALIZER);
}, SimpleEndpoint.emptyMap(), SimpleEndpoint.nonEmptyJsonObject(SimpleEndpoint.returnSelf()),
ExplainResponse._DESERIALIZER);

/**
* Create an "{@code explain}" endpoint.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -698,5 +698,6 @@ protected static void setupValidateQueryRequestDeserializer(ObjectDeserializer<V
}
return params;

}, SimpleEndpoint.emptyMap(), true, ValidateQueryResponse._DESERIALIZER);
}, SimpleEndpoint.emptyMap(), SimpleEndpoint.nonEmptyJsonObject(SimpleEndpoint.returnSelf()),
ValidateQueryResponse._DESERIALIZER);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package co.elastic.clients.json;

import jakarta.json.JsonValue;
import jakarta.json.stream.JsonGenerator;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
* A JSON generator that delegates to another generator.
* <p>
* All convenience methods that accept a property name and an event (value, start object, start array) call separately
* {@link #writeKey(String)} and the same method without the key name. This is meant to facilitate overloading
* of methods.
*/
public class DelegatingJsonGenerator implements JsonGenerator {
protected final JsonGenerator generator;

public DelegatingJsonGenerator(JsonGenerator generator) {
this.generator = generator;
}

public JsonGenerator unwrap() {
return generator;
};

@Override
public JsonGenerator writeStartObject() {
generator.writeStartObject();
return this;
}

@Override
public JsonGenerator writeKey(String s) {
generator.writeKey(s);
return this;
}

@Override
public JsonGenerator writeStartArray() {
generator.writeStartArray();
return this;
}

@Override
public JsonGenerator writeEnd() {
generator.writeEnd();
return this;
}

@Override
public JsonGenerator write(JsonValue jsonValue) {
generator.write(jsonValue);
return this;
}

@Override
public JsonGenerator write(String s) {
generator.write(s);
return this;
}

@Override
public JsonGenerator write(BigDecimal bigDecimal) {
generator.write(bigDecimal);
return this;
}

@Override
public JsonGenerator write(BigInteger bigInteger) {
generator.write(bigInteger);
return this;
}

@Override
public JsonGenerator write(int i) {
generator.write(i);
return this;
}

@Override
public JsonGenerator write(long l) {
generator.write(l);
return this;
}

@Override
public JsonGenerator write(double v) {
generator.write(v);
return this;
}

@Override
public JsonGenerator write(boolean b) {
generator.write(b);
return this;
}

@Override
public JsonGenerator writeNull() {
generator.writeNull();
return this;
}

@Override
public void close() {
generator.close();
}

@Override
public void flush() {
generator.flush();
}

//----- Convenience key+value methods

@Override
public final JsonGenerator writeStartObject(String s) {
this.writeKey(s);
return this.writeStartObject();
}

@Override
public final JsonGenerator writeStartArray(String s) {
this.writeKey(s);
return this.writeStartArray();
}

@Override
public final JsonGenerator write(String s, JsonValue jsonValue) {
this.writeKey(s);
return this.write(jsonValue);
}

@Override
public final JsonGenerator write(String s, String s1) {
this.writeKey(s);
return this.write(s1);
}

@Override
public final JsonGenerator write(String s, BigInteger bigInteger) {
this.writeKey(s);
return this.write(bigInteger);
}

@Override
public final JsonGenerator write(String s, BigDecimal bigDecimal) {
this.writeKey(s);
return this.write(bigDecimal);
}

@Override
public final JsonGenerator write(String s, int i) {
this.writeKey(s);
return this.write(i);
}

@Override
public final JsonGenerator write(String s, long l) {
this.writeKey(s);
return this.write(l);
}

@Override
public final JsonGenerator write(String s, double v) {
this.writeKey(s);
return this.write(v);
}

@Override
public final JsonGenerator write(String s, boolean b) {
this.writeKey(s);
return this.write(b);
}

@Override
public final JsonGenerator writeNull(String s) {
this.writeKey(s);
return this.writeNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import co.elastic.clients.json.BufferingJsonGenerator;
import co.elastic.clients.json.BufferingJsonpMapper;
import co.elastic.clients.json.DelegatingJsonGenerator;
import co.elastic.clients.json.JsonpDeserializer;
import co.elastic.clients.json.JsonpDeserializerBase;
import co.elastic.clients.json.JsonpMapper;
Expand Down Expand Up @@ -95,16 +96,23 @@ protected <T> JsonpDeserializer<T> getDefaultDeserializer(Type type) {
@Override
public <T> void serialize(T value, JsonGenerator generator) {

if (!(generator instanceof JacksonJsonpGenerator)) {
throw new IllegalArgumentException("Jackson's ObjectMapper can only be used with the JacksonJsonpProvider");
}

JsonpSerializer<T> serializer = findSerializer(value);
if (serializer != null) {
serializer.serialize(value, generator, this);
return;
}

// Delegating generators are used in higher levels of serialization (e.g. filter empty top-level objects).
// At this point the object is not a JsonpSerializable and we can assume we're in a nested property holding
// a user-provided type and can unwrap to find the underlying non-delegating generator.
while (generator instanceof DelegatingJsonGenerator) {
generator = ((DelegatingJsonGenerator) generator).unwrap();
}

if (!(generator instanceof JacksonJsonpGenerator)) {
throw new IllegalArgumentException("Jackson's ObjectMapper can only be used with the JacksonJsonpProvider");
}

com.fasterxml.jackson.core.JsonGenerator jkGenerator = ((JacksonJsonpGenerator)generator).jacksonGenerator();
try {
objectMapper.writeValue(jkGenerator, value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,24 @@ private <RequestT, ResponseT, ErrorT> TransportHttpClient.Request prepareTranspo
NoCopyByteArrayOutputStream baos = new NoCopyByteArrayOutputStream();
JsonGenerator generator = mapper.jsonProvider().createGenerator(baos);
mapper.serialize(body, generator);
generator.close();
bodyBuffers = Collections.singletonList(baos.asByteBuffer());
headers = JsonContentTypeHeaders;

// Some generators (e.g. Parsson) throw an exception if we close a generator
// that hasn't received any event. In that case, we ignore the exception
RuntimeException closeException = null;
try {
generator.close();
} catch (RuntimeException e) {
closeException = e;
}

if (baos.size() > 0) {
if (closeException != null) {
// We got some content and close failed
throw closeException;
}
bodyBuffers = Collections.singletonList(baos.asByteBuffer());
headers = JsonContentTypeHeaders;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ static <T, U> Function<T, U> returnNull() {
* that the input and output generic parameters are different, making it suitable for use in a wider range of use cases.
*/
@SuppressWarnings("unchecked")
static <T, U> Function<T, U> returnSelf() {
public static <T, U> Function<T, U> returnSelf() {
return (Function<T, U>) RETURN_SELF;
}

Expand Down
Loading
Loading