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

[8.1] Restructure and enhance docs (#243) #246

Merged
merged 1 commit into from
Apr 18, 2022
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
274 changes: 0 additions & 274 deletions docs/api-conventions.asciidoc

This file was deleted.

19 changes: 19 additions & 0 deletions docs/api-conventions/blocking-and-async.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[[blocking-and-async]]
=== Blocking and asynchronous clients

API clients come in two flavors: blocking and asynchronous. All methods on
asynchronous clients return a standard `CompletableFuture`.

Both flavors can be used at the same time depending on your needs, sharing the
same transport object:

["source","java"]
--------------------------------------------------
ElasticsearchTransport transport = ...
include-tagged::{doc-tests-src}/api_conventions/ApiConventionsTest.java[blocking-and-async]
--------------------------------------------------

Although we won't go in deeper details on asynchronous programming in Java, remember to handle failures of asynchronous tasks. It's easy to overlook them and have errors go unnoticed.

{doc-tests-blurb}
68 changes: 68 additions & 0 deletions docs/api-conventions/building-objects.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
[[building-objects]]
=== Building API objects

[discrete]
==== Builder objects

All data types in the {java-client} are immutable. Object creation uses the
https://www.informit.com/articles/article.aspx?p=1216151&seqNum=2[builder pattern]
that was popularized in *Effective Java* in 2008.

["source","java"]
--------------------------------------------------
ElasticsearchClient client = ...
include-tagged::{doc-tests-src}/api_conventions/ApiConventionsTest.java[builders]
--------------------------------------------------

Note that a builder should not be reused after its `build()` method has been
called.

[discrete]
==== Builder lambda expressions

Although this works nicely, having to instantiate builder classes and call the
`build()` method is a bit verbose. So every property setter in the {java-client} also
accepts a lambda expression that takes a newly created builder as a parameter
and returns a populated builder. The snippet above can also be written as:

["source","java"]
--------------------------------------------------
ElasticsearchClient client = ...
include-tagged::{doc-tests-src}/api_conventions/ApiConventionsTest.java[builder-lambdas]
--------------------------------------------------

This approach allows for much more concise code, and also avoids importing
classes (and even remembering their names) since types are inferred from the
method parameter signature.

Note in the above example that builder variables are only used to start a chain
of property setters. The names of these variables are therefore unimportant and
can be shortened to improve readability:

["source","java"]
--------------------------------------------------
ElasticsearchClient client = ...
include-tagged::{doc-tests-src}/api_conventions/ApiConventionsTest.java[builder-lambdas-short]
--------------------------------------------------

Builder lambdas become particularly useful with complex nested queries like the
one below, taken from the
{ref}/query-dsl-intervals-query.html[intervals query API documentation].

This example also highlights a useful naming convention for builder parameters in
deeply nested structures. For lambda expressions with a single argument, Kotlin
provides the implicit `it` parameter and Scala allows use of `_`. This can be approximated
in Java by using an underscore or a single letter prefix followed by a number representing the depth
level (i.e. `_0`, `_1`, or `b0`, `b1` and so on). Not only does this remove the need to create
throw-away variable names, but it also improves code readability. Correct indentation
also allows the structure of the query to stand out.

["source","java"]
--------------------------------------------------
ElasticsearchClient client = ...
include-tagged::{doc-tests-src}/api_conventions/ApiConventionsTest.java[builder-intervals]
--------------------------------------------------
<1> Search results will be mapped to `SomeApplicationData` instances to
be readily available to the application.

{doc-tests-blurb}
15 changes: 15 additions & 0 deletions docs/api-conventions/exceptions.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[[exceptions]]
=== Exceptions

Client methods can throw two kinds of exceptions:

* Requests that were received by the {es} server but that were rejected
(validation error, server internal timeout exceeded, etc) will produce an
`ElasticsearchException`. This exception contains details about the error,
provided by {es}.

* Requests that failed to reach the server (network error, server unavailable,
etc) will produce a `TransportException`. That exception's cause is the exception
thrown by the lower-level implementation. In the case of the `RestClientTransport`
it will be a `ResponseException` that contains the low level HTTP response.

Loading