Skip to content

Commit 858f8b3

Browse files
authored
Add initial version of Serverless client (#656)
1 parent 16e2c19 commit 858f8b3

File tree

1,788 files changed

+439164
-97
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,788 files changed

+439164
-97
lines changed

config/checkstyle/checkstyle_suppressions.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424

2525
<suppressions>
2626
<!-- Do not enforce line length on generated code -->
27-
<suppress files="client[/\\]src[/\\]main[/\\]java[/\\]co[/\\]elastic[/\\]clients[/\\]elasticsearch[^.]*\.java" checks="LineLength" />
28-
<suppress files="client[/\\]src[/\\]main[/\\]java[/\\]co[/\\]elastic[/\\]clients[/\\]elasticsearch[^.]*\.java" checks="UnusedImports" />
29-
<suppress files="client[/\\]src[/\\]main[/\\]java[/\\]co[/\\]elastic[/\\]clients[/\\]elasticsearch[/\\]Elasticsearch[^.]*\.java" checks="LineLength" />
30-
<suppress files="client[/\\]src[/\\]main[/\\]java[/\\]co[/\\]elastic[/\\]clients[/\\]elasticsearch[/\\]Elasticsearch[^.]*\.java" checks="UnusedImports" />
27+
<suppress files="[/\\]src[/\\]main[/\\]java[/\\]co[/\\]elastic[/\\]clients[/\\]elasticsearch[^.]*\.java" checks="LineLength" />
28+
<suppress files="[/\\]src[/\\]main[/\\]java[/\\]co[/\\]elastic[/\\]clients[/\\]elasticsearch[^.]*\.java" checks="UnusedImports" />
29+
<suppress files="[/\\]src[/\\]main[/\\]java[/\\]co[/\\]elastic[/\\]clients[/\\]elasticsearch[/\\]Elasticsearch[^.]*\.java" checks="LineLength" />
30+
<suppress files="[/\\]src[/\\]main[/\\]java[/\\]co[/\\]elastic[/\\]clients[/\\]elasticsearch[/\\]Elasticsearch[^.]*\.java" checks="UnusedImports" />
3131
<!-- Do not check temp files: 'temp' packages and 'FooTemp.java' files -->
3232
<suppress files="[/\\]temp[/\\]" checks="." />
3333
<suppress files="Temp.java*" checks="." />

config/version-serverless.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
8.11.0

java-client-serverless/README.md

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,39 @@
1-
Home for the Serverless Java client
1+
# Java API client for the Elasticsearch Serverless Service.
2+
3+
A flavor of the Java API client for the upcoming [Elasticsearch Serverless Service](https://www.elastic.co/search-labs/stateless-your-new-state-of-find-with-elasticsearch).
4+
5+
6+
The major difference is that Elasticsearch Serverless will abstract all infrastructure concerns from users, and as such has a reduced API surface. This new flavor of the Elasticsearch Java API client uses the same base framework and same package names as the "regular" client, but with a reduced number of APIs.
7+
8+
It is meant for users who want to ensure their code will work on the current Elasticsearch and the upcoming Serverless flavor.
9+
10+
## Usage
11+
12+
In the initial preview phase, this new flavor of the Java API client is published on the [GitHub project's Maven repository](https://github.com/elastic/elasticsearch-java/packages/1934787).
13+
14+
To install it, you need to add this repository to your project. This requires to authenticate to GitHub with an application token. Example with Gradle:
15+
16+
```
17+
repositories {
18+
maven {
19+
name = "GitHubElasticsearchJava"
20+
url = uri("https://maven.pkg.github.com/elastic/elasticsearch-java")
21+
// See https://docs.gradle.org/current/samples/sample_publishing_credentials.html
22+
credentials(PasswordCredentials::class)
23+
}
24+
}
25+
26+
dependencies {
27+
implementation("co.elastic.clients", "elasticsearch-java-serverless", "1.0.0-20231031-SNAPSHOT")
28+
}
29+
```
30+
31+
## Implementation details
32+
33+
This project is parallel to [java-client](../java-client). The Java packages that are common to both projects are shared using symbolic links from this project to [java-client](../java-client). This ensures minimal disruption in the code layout and build system while avoiding code duplication.
34+
35+
In the future, the Java API client will be split into different modules, and there will be parent modules for the two flavors with dependencies on child modules.
36+
37+
38+
239

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
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+
20+
import com.github.jk1.license.ProjectData
21+
import com.github.jk1.license.render.LicenseDataCollector
22+
import com.github.jk1.license.render.ReportRenderer
23+
import java.io.File
24+
import java.io.FileWriter
25+
26+
plugins {
27+
java
28+
`java-library`
29+
checkstyle
30+
`maven-publish`
31+
id("com.github.jk1.dependency-license-report") version "2.2"
32+
id("de.thetaphi.forbiddenapis") version "3.4"
33+
}
34+
35+
// GitHub Maven repo doesn't like 1.0.0+20231031-SNAPSHOT
36+
version = "1.0.0-20231031-SNAPSHOT"
37+
38+
java {
39+
targetCompatibility = JavaVersion.VERSION_1_8
40+
sourceCompatibility = JavaVersion.VERSION_1_8
41+
42+
withJavadocJar()
43+
withSourcesJar()
44+
}
45+
46+
sourceSets {
47+
main {
48+
java.srcDir("src/main-flavored/java")
49+
}
50+
}
51+
52+
forbiddenApis {
53+
signaturesFiles = files(File(rootProject.projectDir, "config/forbidden-apis.txt"))
54+
suppressAnnotations = setOf("co.elastic.clients.util.AllowForbiddenApis")
55+
}
56+
57+
tasks.forbiddenApisMain {
58+
bundledSignatures = setOf("jdk-system-out")
59+
}
60+
61+
tasks.getByName<ProcessResources>("processResources") {
62+
eachFile {
63+
if (name != "apis.json") {
64+
// Only process main source-set resources (test files are large)
65+
expand(
66+
"version" to version,
67+
"git_revision" to (if (rootProject.extra.has("gitHashFull")) rootProject.extra["gitHashFull"] else "unknown")
68+
)
69+
}
70+
}
71+
}
72+
73+
tasks.withType<Test> {
74+
useJUnitPlatform()
75+
}
76+
77+
tasks.withType<Jar> {
78+
doFirst {
79+
if (rootProject.extra.has("gitHashFull")) {
80+
val jar = this as Jar
81+
jar.manifest.attributes["X-Git-Revision"] = rootProject.extra["gitHashFull"]
82+
jar.manifest.attributes["X-Git-Commit-Time"] = rootProject.extra["gitCommitTime"]
83+
} else {
84+
throw GradleException("No git information available")
85+
}
86+
}
87+
88+
manifest {
89+
attributes["Implementation-Title"] = "Elasticsearch Java client (Serverless edition)"
90+
attributes["Implementation-Vendor"] = "Elastic"
91+
attributes["Implementation-URL"] = "https://github.com/elastic/elasticsearch-java/"
92+
attributes["Build-Date"] = rootProject.extra["buildTime"]
93+
}
94+
95+
metaInf {
96+
from("../LICENSE.txt")
97+
from("../NOTICE.txt")
98+
}
99+
}
100+
101+
tasks.withType<Javadoc> {
102+
val opt = options as StandardJavadocDocletOptions
103+
// Gradle calls javadoc with a list of file and not a path. This prevents doc-files from being copied.
104+
opt.addStringOption("sourcepath", project.projectDir.path + "/src/main/java")
105+
opt.docFilesSubDirs(true)
106+
opt.addBooleanOption("Xdoclint:-missing", true)
107+
108+
doLast {
109+
// Javadoc adds its decoration to html doc files, including quite some JS. This slows down the api spec
110+
// redirector that doesn't need it. So overwrite the target file with the original one.
111+
val specFile = "co/elastic/clients/elasticsearch/doc-files/api-spec.html"
112+
val source = File(project.projectDir, "src/main/java/" + specFile)
113+
val target = File(project.projectDir, "build/docs/javadoc/" + specFile)
114+
source.copyTo(target, overwrite = true)
115+
}
116+
}
117+
118+
publishing {
119+
repositories {
120+
maven {
121+
// See https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry
122+
// and https://docs.gradle.org/current/samples/sample_publishing_credentials.html
123+
name = "ESJavaGithubPackages"
124+
url = uri("https://maven.pkg.github.com/elastic/elasticsearch-java")
125+
credentials(PasswordCredentials::class)
126+
}
127+
128+
maven {
129+
name = "Build"
130+
url = uri("${rootProject.buildDir}/repository")
131+
}
132+
}
133+
134+
publications {
135+
register<MavenPublication>("maven") {
136+
from(components["java"])
137+
pom {
138+
name.set("Elasticsearch Java API Client (Serverless edition)")
139+
artifactId = "elasticsearch-java-serverless"
140+
description.set("Java API Client for Elasticsearch Serverless")
141+
url.set("https://github.com/elastic/elasticsearch-java/")
142+
licenses {
143+
license {
144+
name.set("The Apache Software License, Version 2.0")
145+
url.set("https://www.apache.org/licenses/LICENSE-2.0.txt")
146+
}
147+
}
148+
developers {
149+
developer {
150+
name.set("Elastic")
151+
url.set("https://www.elastic.co")
152+
inceptionYear.set("2020")
153+
}
154+
}
155+
scm {
156+
connection.set("scm:git:https://github.com/elastic/elasticsearch-java.git")
157+
developerConnection.set("scm:git:ssh://[email protected]:elastic/elasticsearch-java.git")
158+
url.set("https://github.com/elastic/elasticsearch-java/")
159+
}
160+
161+
// Fixed version in Serverless.
162+
// withXml {
163+
// // Set the version of dependencies of the org.elasticsearch.client group to the one that we are building.
164+
// // Since the unified release process releases everything at once, this ensures all published artifacts depend
165+
// // on the exact same version. This assumes of course that the binary API and the behavior of these dependencies
166+
// // are the same as the one used in the dependency section below.
167+
// val xPathFactory = javax.xml.xpath.XPathFactory.newInstance()
168+
// val depSelector = xPathFactory.newXPath()
169+
// .compile("/project/dependencies/dependency[groupId/text() = 'org.elasticsearch.client']")
170+
// val versionSelector = xPathFactory.newXPath().compile("version")
171+
//
172+
// var foundVersion = false;
173+
//
174+
// val deps = depSelector.evaluate(asElement().ownerDocument, javax.xml.xpath.XPathConstants.NODESET)
175+
// as org.w3c.dom.NodeList
176+
//
177+
// for (i in 0 until deps.length) {
178+
// val dep = deps.item(i)
179+
// val version = versionSelector.evaluate(dep, javax.xml.xpath.XPathConstants.NODE) as org.w3c.dom.Element
180+
// foundVersion = true;
181+
// version.textContent = project.version.toString()
182+
// }
183+
//
184+
// if (!foundVersion) {
185+
// throw GradleException("Could not find a 'org.elasticsearch.client' to update dependency version in the POM.")
186+
// }
187+
// }
188+
}
189+
}
190+
}
191+
}
192+
193+
dependencies {
194+
val elasticsearchVersion = "8.9.0"
195+
val jacksonVersion = "2.13.3"
196+
val openTelemetryVersion = "1.29.0"
197+
198+
// Apache 2.0
199+
// https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-low.html
200+
api("org.elasticsearch.client", "elasticsearch-rest-client", elasticsearchVersion)
201+
202+
// Apache 2.0
203+
// https://search.maven.org/artifact/com.google.code.findbugs/jsr305
204+
api("com.google.code.findbugs:jsr305:3.0.2")
205+
206+
// EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
207+
// https://github.com/eclipse-ee4j/jsonp
208+
api("jakarta.json:jakarta.json-api:2.0.1")
209+
210+
// Needed even if using Jackson to have an implementation of the Jsonp object model
211+
// EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
212+
// https://github.com/eclipse-ee4j/parsson
213+
api("org.eclipse.parsson:parsson:1.0.0")
214+
215+
// OpenTelemetry API for native instrumentation of the client.
216+
// Apache 2.0
217+
// https://github.com/open-telemetry/opentelemetry-java
218+
implementation("io.opentelemetry", "opentelemetry-api", openTelemetryVersion)
219+
// Use it once it's stable (see Instrumentation.java). Limited to tests for now.
220+
testImplementation("io.opentelemetry", "opentelemetry-semconv", "$openTelemetryVersion-alpha")
221+
222+
// EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
223+
// https://github.com/eclipse-ee4j/jsonb-api
224+
compileOnly("jakarta.json.bind", "jakarta.json.bind-api", "2.0.0")
225+
testImplementation("jakarta.json.bind", "jakarta.json.bind-api", "2.0.0")
226+
227+
// Apache 2.0
228+
// https://github.com/FasterXML/jackson
229+
compileOnly("com.fasterxml.jackson.core", "jackson-core", jacksonVersion)
230+
compileOnly("com.fasterxml.jackson.core", "jackson-databind", jacksonVersion)
231+
testImplementation("com.fasterxml.jackson.core", "jackson-core", jacksonVersion)
232+
testImplementation("com.fasterxml.jackson.core", "jackson-databind", jacksonVersion)
233+
234+
// EPL-2.0 OR BSD-3-Clause
235+
// https://eclipse-ee4j.github.io/yasson/
236+
testImplementation("org.eclipse", "yasson", "2.0.4") {
237+
// Exclude Glassfish as we use Parsson (basically Glassfish renamed in the Jakarta namespace).
238+
exclude(group = "org.glassfish", module = "jakarta.json")
239+
}
240+
241+
// Apache-2.0
242+
testImplementation("commons-io:commons-io:2.11.0")
243+
244+
// EPL-2.0
245+
// https://junit.org/junit5/
246+
testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2")
247+
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2")
248+
249+
// MIT
250+
// https://github.com/classgraph/classgraph
251+
testImplementation("io.github.classgraph:classgraph:4.8.147")
252+
253+
// MIT
254+
// https://www.testcontainers.org/
255+
testImplementation("org.testcontainers", "testcontainers", "1.17.3")
256+
testImplementation("org.testcontainers", "elasticsearch", "1.17.3")
257+
258+
259+
testImplementation("io.opentelemetry", "opentelemetry-sdk", openTelemetryVersion)
260+
}
261+
262+
263+
licenseReport {
264+
renderers = arrayOf(SpdxReporter(File(rootProject.buildDir, "release/dependencies.csv")))
265+
excludeGroups = arrayOf("org.elasticsearch.client")
266+
}
267+
268+
class SpdxReporter(val dest: File) : ReportRenderer {
269+
// License names to their SPDX identifier
270+
val spdxIds = mapOf(
271+
"The Apache License, Version 2.0" to "Apache-2.0",
272+
"Apache License, Version 2.0" to "Apache-2.0",
273+
"The Apache Software License, Version 2.0" to "Apache-2.0",
274+
"BSD Zero Clause License" to "0BSD",
275+
"Eclipse Public License 2.0" to "EPL-2.0",
276+
"Eclipse Public License v. 2.0" to "EPL-2.0",
277+
"Eclipse Public License - v 2.0" to "EPL-2.0",
278+
"GNU General Public License, version 2 with the GNU Classpath Exception" to "GPL-2.0 WITH Classpath-exception-2.0",
279+
"COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0" to "CDDL-1.0"
280+
)
281+
282+
private fun quote(str: String): String {
283+
return if (str.contains(',') || str.contains("\"")) {
284+
"\"" + str.replace("\"", "\"\"") + "\""
285+
} else {
286+
str
287+
}
288+
}
289+
290+
override fun render(data: ProjectData?) {
291+
dest.parentFile.mkdirs()
292+
FileWriter(dest).use { out ->
293+
out.append("name,url,version,revision,license\n")
294+
data?.allDependencies?.forEach { dep ->
295+
296+
val depVersion = dep.version
297+
val depName = dep.group + ":" + dep.name
298+
299+
val info = LicenseDataCollector.multiModuleLicenseInfo(dep)
300+
val depUrl = info.moduleUrls.first()
301+
302+
val licenseIds = info.licenses.mapNotNull { license ->
303+
license.name?.let {
304+
checkNotNull(spdxIds[it]) { "No SPDX identifier for $license" }
305+
}
306+
}.toSet()
307+
308+
// Combine multiple licenses.
309+
// See https://spdx.github.io/spdx-spec/appendix-IV-SPDX-license-expressions/#composite-license-expressions
310+
val licenseId = licenseIds.joinToString(" OR ")
311+
312+
out.append("${quote(depName)},${quote(depUrl)},${quote(depVersion)},,${quote(licenseId)}\n")
313+
}
314+
}
315+
}
316+
}

0 commit comments

Comments
 (0)