Skip to content

Commit c494634

Browse files
authored
Alignment of client service APIs between Db and Web Clients. (helidon-io#1863)
* Alignment of client service APIs between Db and Web Clients. Signed-off-by: Tomas Langer <tomas.langer@oracle.com>
1 parent 4e55096 commit c494634

71 files changed

Lines changed: 1507 additions & 1257 deletions

File tree

Some content is hidden

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

dbclient/common/src/main/java/io/helidon/dbclient/common/AbstractStatement.java

Lines changed: 35 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,10 @@
1919
import java.util.Map;
2020
import java.util.Objects;
2121
import java.util.concurrent.CompletableFuture;
22-
import java.util.concurrent.CompletionStage;
2322

24-
import io.helidon.common.context.Context;
25-
import io.helidon.common.context.Contexts;
2623
import io.helidon.common.mapper.MapperManager;
27-
import io.helidon.dbclient.DbInterceptor;
28-
import io.helidon.dbclient.DbInterceptorContext;
24+
import io.helidon.common.reactive.Single;
25+
import io.helidon.dbclient.DbClientServiceContext;
2926
import io.helidon.dbclient.DbMapperManager;
3027
import io.helidon.dbclient.DbStatement;
3128
import io.helidon.dbclient.DbStatementType;
@@ -38,89 +35,54 @@
3835
*/
3936
public abstract class AbstractStatement<S extends DbStatement<S, R>, R> implements DbStatement<S, R> {
4037

38+
private final DbClientContext clientContext;
39+
private final DbStatementContext statementContext;
40+
4141
private ParamType paramType = ParamType.UNKNOWN;
4242
private StatementParameters parameters;
43-
private final DbStatementType dbStatementType;
44-
private final String statementName;
45-
private final String statement;
46-
private final DbMapperManager dbMapperManager;
47-
private final MapperManager mapperManager;
48-
private final InterceptorSupport interceptors;
4943

5044
/**
5145
* Statement that handles parameters.
5246
*
53-
* @param dbStatementType type of this statement
54-
* @param statementName name of this statement
55-
* @param statement text of this statement
56-
* @param dbMapperManager db mapper manager to use when mapping types to parameters
57-
* @param mapperManager mapper manager to use when mapping results
58-
* @param interceptors interceptors to be executed
47+
* @param statementContext database statement configuration and context
5948
*/
60-
protected AbstractStatement(DbStatementType dbStatementType,
61-
String statementName,
62-
String statement,
63-
DbMapperManager dbMapperManager,
64-
MapperManager mapperManager,
65-
InterceptorSupport interceptors) {
66-
this.dbStatementType = dbStatementType;
67-
this.statementName = statementName;
68-
this.statement = statement;
69-
this.dbMapperManager = dbMapperManager;
70-
this.mapperManager = mapperManager;
71-
this.interceptors = interceptors;
49+
protected AbstractStatement(DbStatementContext statementContext) {
50+
this.statementContext = statementContext;
51+
this.clientContext = statementContext.clientContext();
7252
}
7353

7454
@Override
7555
public R execute() {
7656
CompletableFuture<Long> queryFuture = new CompletableFuture<>();
7757
CompletableFuture<Void> statementFuture = new CompletableFuture<>();
78-
DbInterceptorContext dbContext = DbInterceptorContext.create(dbType())
58+
DbClientServiceContext dbContext = DbClientServiceContext.create(dbType())
7959
.resultFuture(queryFuture)
8060
.statementFuture(statementFuture);
8161

8262
update(dbContext);
83-
CompletionStage<DbInterceptorContext> dbContextFuture = invokeInterceptors(dbContext);
63+
Single<DbClientServiceContext> dbContextFuture = clientContext.invokeServices(dbContext);
8464
return doExecute(dbContextFuture, statementFuture, queryFuture);
8565
}
8666

87-
/**
88-
* Invoke all interceptors.
89-
*
90-
* @param dbContext initial interceptor context
91-
* @return future with the result of interceptors processing
92-
*/
93-
CompletionStage<DbInterceptorContext> invokeInterceptors(DbInterceptorContext dbContext) {
94-
CompletableFuture<DbInterceptorContext> result = CompletableFuture.completedFuture(dbContext);
95-
96-
dbContext.context(Contexts.context().orElseGet(Context::create));
97-
98-
for (DbInterceptor interceptor : interceptors.interceptors(statementType(), statementName())) {
99-
result = result.thenCompose(interceptor::statement);
100-
}
101-
102-
return result;
103-
}
104-
10567
/**
10668
* Type of this statement.
10769
*
10870
* @return statement type
10971
*/
11072
protected DbStatementType statementType() {
111-
return dbStatementType;
73+
return statementContext.statementType();
11274
}
11375

11476
/**
11577
* Execute the statement against the database.
11678
*
117-
* @param dbContext future that completes after all interceptors are invoked
79+
* @param dbContext future that completes after all services are invoked
11880
* @param statementFuture future that should complete when the statement finishes execution
11981
* @param queryFuture future that should complete when the result set is fully read (if one exists),
12082
* otherwise complete same as statementFuture
12183
* @return result of this db statement.
12284
*/
123-
protected abstract R doExecute(CompletionStage<DbInterceptorContext> dbContext,
85+
protected abstract R doExecute(Single<DbClientServiceContext> dbContext,
12486
CompletableFuture<Void> statementFuture,
12587
CompletableFuture<Long> queryFuture);
12688

@@ -131,6 +93,15 @@ protected abstract R doExecute(CompletionStage<DbInterceptorContext> dbContext,
13193
*/
13294
protected abstract String dbType();
13395

96+
/**
97+
* Context of the DB client.
98+
*
99+
* @return context with access to client wide configuration and runtime
100+
*/
101+
public DbClientContext clientContext() {
102+
return clientContext;
103+
}
104+
134105
@Override
135106
public S params(List<?> parameters) {
136107
Objects.requireNonNull(parameters, "Parameters cannot be null (may be an empty list)");
@@ -191,7 +162,7 @@ protected ParamType paramType() {
191162
* @return mapper manager for DB types
192163
*/
193164
protected DbMapperManager dbMapperManager() {
194-
return dbMapperManager;
165+
return clientContext.dbMapperManager();
195166
}
196167

197168
/**
@@ -200,7 +171,7 @@ protected DbMapperManager dbMapperManager() {
200171
* @return generic mapper manager
201172
*/
202173
protected MapperManager mapperManager() {
203-
return mapperManager;
174+
return clientContext.mapperManager();
204175
}
205176

206177
/**
@@ -231,7 +202,7 @@ protected List<Object> indexedParams() {
231202
* @return name of this statement (never null, may be generated)
232203
*/
233204
protected String statementName() {
234-
return statementName;
205+
return statementContext.statementName();
235206
}
236207

237208
/**
@@ -240,23 +211,23 @@ protected String statementName() {
240211
* @return text of this statement
241212
*/
242213
protected String statement() {
243-
return statement;
214+
return statementContext.statement();
244215
}
245216

246217
/**
247-
* Update the interceptor context with the statement name, statement and
218+
* Update the client service context with the statement name, statement and
248219
* statement parameters.
249220
*
250-
* @param dbContext interceptor context
221+
* @param dbContext client service context
251222
*/
252-
protected void update(DbInterceptorContext dbContext) {
253-
dbContext.statementName(statementName);
223+
protected void update(DbClientServiceContext dbContext) {
224+
dbContext.statementName(statementContext.statementName());
254225
initParameters(ParamType.INDEXED);
255226

256227
if (paramType == ParamType.NAMED) {
257-
dbContext.statement(statement, parameters.namedParams());
228+
dbContext.statement(statementContext.statement(), parameters.namedParams());
258229
} else {
259-
dbContext.statement(statement, parameters.indexedParams());
230+
dbContext.statement(statementContext.statement(), parameters.indexedParams());
260231
}
261232
dbContext.statementType(statementType());
262233
}
@@ -279,13 +250,13 @@ private void initParameters(ParamType type) {
279250
switch (type) {
280251
case NAMED:
281252
this.paramType = ParamType.NAMED;
282-
this.parameters = new NamedStatementParameters(dbMapperManager);
253+
this.parameters = new NamedStatementParameters(clientContext.dbMapperManager());
283254
break;
284255
case INDEXED:
285256
case UNKNOWN:
286257
default:
287258
this.paramType = ParamType.INDEXED;
288-
this.parameters = new IndexedStatementParameters(dbMapperManager);
259+
this.parameters = new IndexedStatementParameters(clientContext.dbMapperManager());
289260
break;
290261
}
291262
}
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*
2+
* Copyright (c) 2020 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.helidon.dbclient.common;
18+
19+
import java.util.List;
20+
import java.util.concurrent.CompletableFuture;
21+
22+
import io.helidon.common.context.Context;
23+
import io.helidon.common.context.Contexts;
24+
import io.helidon.common.mapper.MapperManager;
25+
import io.helidon.common.reactive.Single;
26+
import io.helidon.dbclient.DbClientService;
27+
import io.helidon.dbclient.DbClientServiceContext;
28+
import io.helidon.dbclient.DbMapperManager;
29+
import io.helidon.dbclient.DbStatements;
30+
31+
/**
32+
* Context of the whole client.
33+
* <p>
34+
* This instance holds configuration and runtimes that are shared by any exec within this client runtime.
35+
*/
36+
public class DbClientContext {
37+
private final DbMapperManager dbMapperManager;
38+
private final MapperManager mapperManager;
39+
private final List<DbClientService> clientServices;
40+
private final DbStatements statements;
41+
42+
/**
43+
* Create an instance from builder.
44+
*
45+
* @param builder the builder base your builder must extend
46+
*/
47+
protected DbClientContext(BuilderBase<?> builder) {
48+
this.dbMapperManager = builder.dbMapperManager;
49+
this.mapperManager = builder.mapperManager;
50+
this.clientServices = builder.clientServices;
51+
this.statements = builder.statements;
52+
}
53+
54+
/**
55+
* Create a new builder for context.
56+
*
57+
* @return a new builder instance
58+
*/
59+
public static Builder builder() {
60+
return new Builder();
61+
}
62+
63+
/**
64+
* Invoke all configured client services and return a single that completes once all the
65+
* client services complete.
66+
*
67+
* @param dbContext context for client services
68+
* @return a single with the same or modified client service context
69+
*/
70+
public Single<DbClientServiceContext> invokeServices(DbClientServiceContext dbContext) {
71+
CompletableFuture<DbClientServiceContext> result = CompletableFuture.completedFuture(dbContext);
72+
73+
dbContext.context(Contexts.context().orElseGet(Context::create));
74+
75+
for (DbClientService service : clientServices) {
76+
result = result.thenCompose(service::statement);
77+
}
78+
79+
return Single.from(result);
80+
}
81+
82+
/**
83+
* Configured statements.
84+
*
85+
* @return statements
86+
*/
87+
public DbStatements statements() {
88+
return statements;
89+
}
90+
91+
/**
92+
* Configured DB Mapper manager.
93+
*
94+
* @return DB mapper manager
95+
*/
96+
public DbMapperManager dbMapperManager() {
97+
return dbMapperManager;
98+
}
99+
100+
/**
101+
* Configured mapper manager.
102+
*
103+
* @return mapper manager
104+
*/
105+
public MapperManager mapperManager() {
106+
return mapperManager;
107+
}
108+
109+
/**
110+
* Fluent API builder for {@link io.helidon.dbclient.common.DbClientContext}.
111+
*/
112+
public static final class Builder extends BuilderBase<Builder> implements io.helidon.common.Builder<DbClientContext> {
113+
@Override
114+
public DbClientContext build() {
115+
return new DbClientContext(this);
116+
}
117+
}
118+
119+
/**
120+
* A common base for builders for classes that want to extend {@link io.helidon.dbclient.common.DbClientContext}.
121+
*
122+
* @param <T> type of the builder extending this builder, to keep fluent API
123+
*/
124+
public static class BuilderBase<T extends BuilderBase<T>> {
125+
@SuppressWarnings("unchecked")
126+
private final T me = (T) this;
127+
128+
private DbMapperManager dbMapperManager;
129+
private MapperManager mapperManager;
130+
private List<DbClientService> clientServices;
131+
private DbStatements statements;
132+
133+
/**
134+
* No-op constructor.
135+
*/
136+
protected BuilderBase() {
137+
}
138+
139+
/**
140+
* Configure the DB mapper manager to use.
141+
*
142+
* @param dbMapperManager DB mapper manager
143+
* @return updated builder instance
144+
*/
145+
public T dbMapperManager(DbMapperManager dbMapperManager) {
146+
this.dbMapperManager = dbMapperManager;
147+
return me;
148+
}
149+
150+
/**
151+
* Configure the mapper manager to use.
152+
*
153+
* @param mapperManager mapper manager
154+
* @return updated builder instance
155+
*/
156+
public T mapperManager(MapperManager mapperManager) {
157+
this.mapperManager = mapperManager;
158+
return me;
159+
}
160+
161+
/**
162+
* Configure the client services to use.
163+
*
164+
* @param clientServices client service list
165+
* @return updated builder instance
166+
*/
167+
public T clientServices(List<DbClientService> clientServices) {
168+
this.clientServices = clientServices;
169+
return me;
170+
}
171+
172+
/**
173+
* Configure the db statements to use.
174+
*
175+
* @param statements statements
176+
* @return updated builder instance
177+
*/
178+
public T statements(DbStatements statements) {
179+
this.statements = statements;
180+
return me;
181+
}
182+
}
183+
}

0 commit comments

Comments
 (0)