Move SDK documentation to RTD
[dcaegen2.git] / docs / sections / sdk / apis.rst
1 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
2 .. http://creativecommons.org/licenses/by/4.0
3
4 Available APIs
5 ==============
6
7 .. toctree::
8     :depth: 3
9
10
11 cbs-client - a Config Binding Service client
12 --------------------------------------------
13 CbsClientFactory can be used to lookup for CBS in your application. Returned CbsClient can then be used to get a configuration, poll for configuration or poll for configuration changes.
14
15 The following CBS endpoints are supported by means of different CbsRequests:
16  - get-configuration created by CbsRequests.getConfiguration method - returns the service configuration
17  - get-by-key created by CbsRequests.getByKey method - returns componentName:key entry from Consul
18  - get-all created by CbsRequests.getAll method - returns everything which relates to the service (configuration, policies, etc.)
19
20 Sample usage:
21
22 .. code-block:: java
23
24     // Generate RequestID and InvocationID which will be used when logging and in HTTP requests
25     final RequestDiagnosticContext diagnosticContext = RequestDiagnosticContext.create();
26     final CbsRequest request = CbsRequests.getConfiguration(diagnosticContext);
27
28     // Read necessary properties from the environment
29     final CbsClientConfiguration config = CbsClientConfiguration.fromEnvironment();
30
31     // Create the client and use it to get the configuration
32     CbsClientFactory.createCbsClient(config)
33             .flatMap(cbsClient -> cbsClient.get(request))
34             .subscribe(
35                     jsonObject -> {
36                         // do a stuff with your JSON configuration using GSON API
37                         final int port = Integer.parseInt(jsonObject.get("collector.listen_port").getAsString());
38                         // ...
39                     },
40                     throwable -> {
41                         logger.warn("Ooops", throwable);
42                     });
43
44
45 Note that a subscribe handler can/will be called in separate thread asynchronously after CBS address lookup succeeds and CBS service call returns a result.
46
47 If you are interested in calling CBS periodically and react only when the configuration changed you can use updates method:
48
49 .. code-block:: java
50
51     // Generate RequestID and InvocationID which will be used when logging and in HTTP requests
52     final RequestDiagnosticContext diagnosticContext = RequestDiagnosticContext.create();
53     final CbsRequest request = CbsRequests.getConfiguration(diagnosticContext);
54
55     // Read necessary configuration from the environment
56     final CbsClientConfiguration config = CbsClientConfiguration.fromEnvironment();
57
58     // Polling properties
59     final Duration initialDelay = Duration.ofSeconds(5);
60     final Duration period = Duration.ofMinutes(1);
61
62     // Create the client and use it to get the configuration
63     CbsClientFactory.createCbsClient(config)
64             .flatMapMany(cbsClient -> cbsClient.updates(request, initialDelay, period))
65             .subscribe(
66                     jsonObject -> {
67                         // do a stuff with your JSON configuration using GSON API
68                         final int port = Integer.parseInt(jsonObject.get("collector.listen_port").getAsString());
69                         // ...
70                     },
71                     throwable -> {
72                         logger.warn("Ooops", throwable);
73                     });
74
75 The most significant change is in line 14. We are using flatMapMany since we want to map one CbsClient to many JsonObject updates. After 5 seconds CbsClient will call CBS every minute. If the configuration has changed it will pass the JsonObject downstream - in our case consumer of JsonObject will be called.
76
77 Parsing streams' definitions:
78
79 - CBS configuration response contains various service-specific entries. It also contains a standardized DCAE streams definitions as streams_publishes and streams_subscribes JSON objects. CBS Client API provides a way of parsing this part of configuration so you can use Java objects instead of low-level GSON API.
80 - Because streams definitions are a simple value objects we were not able to provide you a nice polymorphic API. Instead you have 2-level API at your disposal:
81     - You can extract raw streams  by means of DataStreams.namedSinks (for streams_publishes) and DataStreams.namedSources (for streams_subscribes).
82     - Then you will be able to parse the specific entry from returned collection to a desired stream type by means of parsers built by StreamFromGsonParsers factory.
83
84 - Sample usage:
85
86     .. code-block:: java
87
88         final CbsRequest request = CbsRequests.getConfiguration(RequestDiagnosticContext.create());
89         final StreamFromGsonParser<MessageRouterSink> mrSinkParser = StreamFromGsonParsers.messageRouterSinkParser();
90
91         CbsClientFactory.createCbsClient(CbsClientConfiguration.fromEnvironment())
92             .flatMapMany(cbsClient -> cbsClient.updates(request, Duration.ofSeconds(5), Duration.ofMinutes(1)))
93             .map(DataStreams::namedSinks)
94             .map(sinks -> sinks.filter(StreamPredicates.streamOfType(MESSAGE_ROUTER)).map(mrSinkParser::unsafeParse).toList())
95             .subscribe(
96                 mrSinks -> mrSinks.forEach(mrSink -> {
97                     logger.info(mrSink.name()); // name = the configuration key
98                     logger.info(mrSink.aafCredentials().username()); // = aaf_username
99                     logger.info(mrSink.topicUrl());
100                     // ...
101                 }),
102                 throwable -> logger.warn("Ooops", throwable)
103         );
104
105     For details and sample usage please refer to JavaDoc and unit and integration tests. Especially `CbsClientImplIT <https://gerrit.onap.org/r/gitweb?p=dcaegen2/services/sdk.git;a=blob;f=rest-services/cbs-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/impl/CbsClientImplIT.java;hb=HEAD>`_, `MessageRouterSinksIT <https://gerrit.onap.org/r/gitweb?p=dcaegen2/services/sdk.git;a=blob;f=rest-services/cbs-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/api/streams/MessageRouterSinksIT.java;hb=HEAD>`_ and  `MixedDmaapStreamsIT <https://gerrit.onap.org/r/gitweb?p=dcaegen2/services/sdk.git;a=blob;f=rest-services/cbs-client/src/test/java/org/onap/dcaegen2/services/sdk/rest/services/cbs/client/api/streams/MixedDmaapStreamsIT.java;hb=HEAD>`_ might be useful.
106
107 - INFO
108     Results of these parsers (MessageRouterSink, MessageRouterSource) can be directly used to connect to DMaaP MR by means of dmaap-client API described below.
109
110 crypt-password - an utility for BCrypt passwords
111 ------------------------------------------------
112 Library to generate and match cryptography password using BCrypt algorithm
113
114 .. code-block:: java
115
116     java -jar crypt-password-${sdk.version}.jar password_to_crypt
117
118     $2a$10$iDEKdKknakPqH5XZb6wEmeBP2SMRwwiWHy8RNioUTNycIomjIqCAO
119
120 Can be used like maven dependency to match generated password.
121
122 dmaap-client - a DMaaP MR client
123 --------------------------------
124 After parsing CBS sink definitions you will get a Source or Sink value object. It can be then directly used to communicate with DMaaP Message Router REST API.
125
126 Writing message publisher
127
128 .. code-block:: java
129
130     final MessageRouterPublisher publisher = DmaapClientFactory.createMessageRouterPublisher();
131     final MessageRouterSink sinkDefinition; //... Sink definition obtained by parsing CBS response
132     final MessageRouterPublishRequest request = ImmutableMessageRouterPublishRequest.builder()
133             .sinkDefinition(sinkDefinition)
134             .build();
135
136     Flux.just(1, 2, 3)
137             .map(JsonPrimitive::new)
138             .transform(input -> publisher.put(request, input))
139             .subscribe(resp -> {
140                         if (resp.successful()) {
141                             logger.debug("Sent a batch of messages to the MR");
142                         } else {
143                             logger.warn("Message sending has failed: {}", resp.failReason());
144                         }
145                     },
146                     ex -> {
147                         logger.warn("An unexpected error while sending messages to DMaaP", ex);
148                     });
149
150 Note that we are using Reactor transform operator. As an alternative you could assign Flux of JSON values to the variable and then invoke publisher.put on it. The important performance-related thing to remember is that you should feed the put method with a stream of messages instead of multiple calls with single messages. This way the client API will be able to send them in batches which should significantly improve performance (at least on transfer level).
151
152 Writing message subscriber
153
154 .. code-block:: java
155
156     final MessageRouterSource sourceDefinition; //... Source definition obtained by parsing CBS response
157     final MessageRouterSubscribeRequest request = ImmutableMessageRouterSubscribeRequest.builder()
158             .sourceDefinition(sourceDefinition)
159             .build();
160
161     cut.subscribeForElements(request, Duration.ofMinutes(1))
162             .map(JsonElement::getAsJsonObject)
163             .subscribe(json -> {
164                     // application logic
165                 },
166                 ex -> {
167                     logger.warn("An unexpected error while receiving messages from DMaaP", ex);
168                 });
169
170 hvvesclient-producer - a reference Java implementation of High Volume VES Collector client
171 ------------------------------------------------------------------------------------------
172 This library is used in xNF simulator which helps us test HV VES Collector in CSIT tests. You may use it as a reference when implementing your code in non-JVM language or directly when using Java/Kotlin/etc.
173
174 Sample usage:
175
176 .. code-block:: java
177
178     final ProducerOptions producerOptions = ImmutableProducerOptions.builder()
179             .collectorAddresses(HashSet.of(
180                     InetSocketAddress.createUnresolved("dcae-hv-ves-collector", 30222)))
181             .build();
182     final HvVesProducer hvVesProducer = HvVesProducerFactory.create(producerOptions);
183
184     Flux<VesEvent> events; // ...
185     Mono.from(hvVesProducer.send(events))
186             .doOnSuccess(() -> logger.info("All events has been sent"))
187             .doOnError(ex -> logger.warn("Failed to send one or more events", ex))
188             .subscribe();