Skip to content

Commit 1c6d1b5

Browse files
author
Hadi Eskandari
committed
Add sample to create the client via dynamic proxy
1 parent 61f51a7 commit 1c6d1b5

File tree

5 files changed

+141
-4
lines changed

5 files changed

+141
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ This section is for maintaining a changelog for all breaking changes for the cli
1818
- Document HTTP/2 support ([#330](https://github.com/opensearch-project/opensearch-java/pull/330))
1919
- Expose HTTP status code through `ResponseException#status` ([#756](https://github.com/opensearch-project/opensearch-java/pull/756))
2020
- Added missing WrapperQuery accessors and builder methods ([#806](https://github.com/opensearch-project/opensearch-java/pull/806))
21-
21+
- Added a sample for creating OpenSearchClient via dynamic proxy ([#847](https://github.com/opensearch-project/opensearch-java/pull/847))
2222

2323
### Dependencies
2424

samples/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ dependencies {
2424
implementation("org.apache.logging.log4j", "log4j-slf4j2-impl","[2.17.1,3.0)")
2525
implementation("commons-logging", "commons-logging", "1.2")
2626
implementation("com.fasterxml.jackson.core", "jackson-databind", "2.15.2")
27+
implementation("cglib", "cglib", "3.3.0")
2728
}
2829

2930
spotless {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.client.samples;
10+
11+
import java.lang.reflect.InvocationTargetException;
12+
import java.lang.reflect.Method;
13+
import net.sf.cglib.proxy.Enhancer;
14+
import net.sf.cglib.proxy.MethodInterceptor;
15+
import net.sf.cglib.proxy.MethodProxy;
16+
import org.apache.logging.log4j.LogManager;
17+
import org.apache.logging.log4j.Logger;
18+
import org.opensearch.client.opensearch.OpenSearchClient;
19+
import org.opensearch.client.transport.OpenSearchTransport;
20+
21+
public class OpenSearchClientProxy implements MethodInterceptor {
22+
23+
private static final Logger LOGGER = LogManager.getLogger(OpenSearchClientProxy.class);
24+
25+
public static OpenSearchClient create(OpenSearchTransport transport) throws Exception {
26+
if (transport == null) {
27+
throw new Exception("Cannot build OpenSearchClient without a transport.");
28+
}
29+
30+
LOGGER.info("Using {} transport", transport.getClass().getName());
31+
32+
final var interceptor = new OpenSearchClientProxy();
33+
final var enhancer = new Enhancer();
34+
35+
enhancer.setSuperclass(OpenSearchClient.class);
36+
enhancer.setCallback(interceptor);
37+
38+
final var argTypes = new Class[] { OpenSearchTransport.class };
39+
final var args = new Object[] { transport };
40+
return (OpenSearchClient) enhancer.create(argTypes, args);
41+
}
42+
43+
@Override
44+
public Object intercept(final Object obj, final Method method, final Object[] args, final MethodProxy proxy) throws Throwable {
45+
LOGGER.info("Invoking method: {}", method.getName());
46+
final Object result;
47+
48+
try {
49+
LOGGER.info("Entering method: {}", method.getName());
50+
result = proxy.invokeSuper(obj, args);
51+
} catch (final InvocationTargetException e) {
52+
throw e.getTargetException();
53+
} finally {
54+
LOGGER.info("Exiting method: {}", method.getName());
55+
}
56+
return result;
57+
}
58+
}

samples/src/main/java/org/opensearch/client/samples/SampleClient.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
import org.apache.hc.core5.ssl.SSLContextBuilder;
2222
import org.opensearch.client.json.jackson.JacksonJsonpMapper;
2323
import org.opensearch.client.opensearch.OpenSearchClient;
24+
import org.opensearch.client.transport.OpenSearchTransport;
2425
import org.opensearch.client.transport.httpclient5.ApacheHttpClient5TransportBuilder;
2526

2627
public class SampleClient {
27-
public static OpenSearchClient create() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
28+
29+
public static OpenSearchTransport createTransport() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
2830
var env = System.getenv();
2931
var https = Boolean.parseBoolean(env.getOrDefault("HTTPS", "true"));
3032
var hostname = env.getOrDefault("HOST", "localhost");
@@ -36,7 +38,7 @@ public static OpenSearchClient create() throws NoSuchAlgorithmException, KeyStor
3638

3739
final var sslContext = SSLContextBuilder.create().loadTrustMaterial(null, (chains, authType) -> true).build();
3840

39-
final var transport = ApacheHttpClient5TransportBuilder.builder(hosts)
41+
return ApacheHttpClient5TransportBuilder.builder(hosts)
4042
.setMapper(new JacksonJsonpMapper())
4143
.setHttpClientConfigCallback(httpClientBuilder -> {
4244
final var credentialsProvider = new BasicCredentialsProvider();
@@ -55,6 +57,9 @@ public static OpenSearchClient create() throws NoSuchAlgorithmException, KeyStor
5557
return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider).setConnectionManager(connectionManager);
5658
})
5759
.build();
58-
return new OpenSearchClient(transport);
60+
}
61+
62+
public static OpenSearchClient create() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
63+
return new OpenSearchClient(createTransport());
5964
}
6065
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package org.opensearch.client.samples;
2+
3+
import org.apache.logging.log4j.LogManager;
4+
import org.apache.logging.log4j.Logger;
5+
import org.opensearch.client.opensearch._types.mapping.IntegerNumberProperty;
6+
import org.opensearch.client.opensearch._types.mapping.Property;
7+
import org.opensearch.client.opensearch._types.mapping.TypeMapping;
8+
import org.opensearch.client.opensearch.core.IndexRequest;
9+
import org.opensearch.client.opensearch.core.SearchResponse;
10+
import org.opensearch.client.opensearch.indices.CreateIndexRequest;
11+
import org.opensearch.client.opensearch.indices.DeleteIndexRequest;
12+
import org.opensearch.client.opensearch.indices.IndexSettings;
13+
import org.opensearch.client.samples.util.IndexData;
14+
15+
/**
16+
* Run with: <c>./gradlew :samples:run -Dsamples.mainClass=SampleProxyClient</c>
17+
*/
18+
public class SampleProxyClient {
19+
20+
private static final Logger LOGGER = LogManager.getLogger(SampleProxyClient.class);
21+
22+
public static void main(String[] args) {
23+
try {
24+
var transport = SampleClient.createTransport();
25+
var client = OpenSearchClientProxy.create(transport);
26+
27+
final var indexName = "my-index";
28+
29+
if (!client.indices().exists(r -> r.index(indexName)).value()) {
30+
LOGGER.info("Creating index {}", indexName);
31+
IndexSettings settings = new IndexSettings.Builder().numberOfShards("2").numberOfReplicas("1").build();
32+
TypeMapping mapping = new TypeMapping.Builder().properties(
33+
"age",
34+
new Property.Builder().integer(new IntegerNumberProperty.Builder().build()).build()
35+
).build();
36+
CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder().index(indexName)
37+
.settings(settings)
38+
.mappings(mapping)
39+
.build();
40+
client.indices().create(createIndexRequest);
41+
}
42+
43+
LOGGER.info("Indexing documents");
44+
IndexData indexData = new IndexData("Document 1", "Text for document 1");
45+
IndexRequest<IndexData> indexRequest = new IndexRequest.Builder<IndexData>().index(indexName)
46+
.id("1")
47+
.document(indexData)
48+
.build();
49+
client.index(indexRequest);
50+
51+
indexData = new IndexData("Document 2", "Text for document 2");
52+
indexRequest = new IndexRequest.Builder<IndexData>().index(indexName).id("2").document(indexData).build();
53+
client.index(indexRequest);
54+
55+
// wait for the document to index
56+
Thread.sleep(3000);
57+
58+
SearchResponse<IndexData> searchResponse = client.search(s -> s.index(indexName), IndexData.class);
59+
for (var hit : searchResponse.hits().hits()) {
60+
LOGGER.info("Found {} with score {}", hit.source(), hit.score());
61+
}
62+
63+
LOGGER.info("Deleting document with id 1");
64+
client.delete(d -> d.index(indexName).id("1"));
65+
66+
LOGGER.info("Deleting index {}", indexName);
67+
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest.Builder().index(indexName).build();
68+
client.indices().delete(deleteIndexRequest);
69+
} catch (Exception e) {
70+
LOGGER.error("Unexpected exception", e);
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)