Skip to content

Commit 2349013

Browse files
author
Gerald Unterrainer
committed
Merge branch 'develop'
2 parents ea46219 + fbc6de3 commit 2349013

25 files changed

+312
-170
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
<modelVersion>4.0.0</modelVersion>
1919
<artifactId>http-server</artifactId>
20-
<version>0.2.17</version>
20+
<version>0.2.18</version>
2121
<name>HttpServer</name>
2222
<packaging>jar</packaging>
2323

src/main/java/info/unterrainer/commons/httpserver/GenericHandlerGroup.java

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
import info.unterrainer.commons.httpserver.enums.Endpoint;
1414
import info.unterrainer.commons.httpserver.enums.QueryField;
1515
import info.unterrainer.commons.httpserver.exceptions.BadRequestException;
16+
import info.unterrainer.commons.httpserver.extensions.AsyncExtensionContext;
17+
import info.unterrainer.commons.httpserver.extensions.AsyncExtensionContextBaseMapper;
18+
import info.unterrainer.commons.httpserver.extensions.AsyncExtensionContextMapper;
1619
import info.unterrainer.commons.httpserver.interceptors.InterceptorData;
1720
import info.unterrainer.commons.httpserver.interceptors.delegates.GetListInterceptor;
1821
import info.unterrainer.commons.httpserver.jsons.ListJson;
@@ -41,6 +44,7 @@ public class GenericHandlerGroup<P extends BasicJpa, J extends BasicJson, E> imp
4144
private final List<Endpoint> endpoints;
4245
private final List<GetListInterceptor> getListInterceptors;
4346
private final HandlerExtensions<P, J, E> extensions;
47+
private final List<AsyncExtensionContextMapper> asyncExtensionContextMappers;
4448
private final LinkedHashMap<Endpoint, Role[]> accessRoles;
4549
private final ExecutorService executorService;
4650
private final HandlerUtils hu = new HandlerUtils();
@@ -81,6 +85,15 @@ private boolean endpointsToCreate(final List<Endpoint> endpointList) {
8185
return false;
8286
}
8387

88+
private AsyncExtensionContext makeAsyncExtensionContextFor(final Context ctx) {
89+
AsyncExtensionContext asyncCtx = new AsyncExtensionContext();
90+
for (AsyncExtensionContextMapper e : asyncExtensionContextMappers)
91+
e.map(ctx, asyncCtx);
92+
AsyncExtensionContextBaseMapper m = new AsyncExtensionContextBaseMapper();
93+
m.map(ctx, asyncCtx);
94+
return asyncCtx;
95+
}
96+
8497
private Role[] rolesFor(final List<Endpoint> endpointList) {
8598
List<Role> roles = new ArrayList<>();
8699
for (Entry<Endpoint, Role[]> entry : accessRoles.entrySet())
@@ -90,11 +103,12 @@ private Role[] rolesFor(final List<Endpoint> endpointList) {
90103
}
91104

92105
private void getEntry(final Context ctx) {
93-
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction();
106+
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction(ctx);
94107

95108
P jpa = hu.getJpaById(ctx, transaction.getManager(), dao);
96109
J json = orikaMapper.map(jpa, jsonType);
97-
json = extensions.runPostGetSingle(ctx, transaction.getManager(), jpa.getId(), jpa, json, executorService);
110+
json = extensions.runPostGetSingle(ctx, makeAsyncExtensionContextFor(ctx), transaction.getManager(),
111+
jpa.getId(), jpa, json, executorService);
98112

99113
transaction.end();
100114
ctx.attribute(Attribute.RESPONSE_OBJECT, json);
@@ -123,7 +137,7 @@ private void getList(final Context ctx) {
123137
e.getMessage());
124138
}
125139

126-
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction();
140+
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction(ctx);
127141

128142
ListJson<P> bList = dao.getList(transaction.getManager(), offset, size, interceptorResult.getSelectClause(),
129143
interceptorResult.getJoinClause(), interceptorResult.getWhereClause(), interceptorResult.getParams(),
@@ -134,7 +148,8 @@ private void getList(final Context ctx) {
134148

135149
hu.setPaginationParamsFor(jList, offset, size, bList.getCount(), interceptorResult.getPartOfQueryString(), ctx);
136150

137-
jList = extensions.runPostGetList(ctx, transaction.getManager(), size, offset, bList, jList, executorService);
151+
jList = extensions.runPostGetList(ctx, makeAsyncExtensionContextFor(ctx), transaction.getManager(), size,
152+
offset, bList, jList, executorService);
138153

139154
transaction.end();
140155
ctx.attribute(Attribute.RESPONSE_OBJECT, jList);
@@ -145,14 +160,15 @@ private void create(final Context ctx) throws IOException {
145160
try {
146161
J json = jsonMapper.fromStringTo(jsonType, b);
147162
P mappedJpa = orikaMapper.map(json, jpaType);
148-
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction();
163+
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction(ctx);
149164

150-
mappedJpa = extensions.runPreInsert(ctx, transaction.getManager(), json, mappedJpa, executorService);
165+
mappedJpa = extensions.runPreInsert(ctx, makeAsyncExtensionContextFor(ctx), transaction.getManager(), json,
166+
mappedJpa, executorService);
151167
P createdJpa = dao.create(transaction.getManager(), mappedJpa, hu.getWriteTenantIdsFrom(ctx));
152168
J r = orikaMapper.map(createdJpa, jsonType);
153169

154-
r = extensions.runPostInsert(ctx, transaction.getManager(), json, mappedJpa, createdJpa, r,
155-
executorService);
170+
r = extensions.runPostInsert(ctx, makeAsyncExtensionContextFor(ctx), transaction.getManager(), json,
171+
mappedJpa, createdJpa, r, executorService);
156172

157173
transaction.end();
158174
ctx.attribute(Attribute.RESPONSE_OBJECT, r);
@@ -163,7 +179,7 @@ private void create(final Context ctx) throws IOException {
163179
}
164180

165181
private void fullUpdate(final Context ctx) throws IOException {
166-
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction();
182+
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction(ctx);
167183
P jpa = hu.getJpaById(ctx, transaction.getManager(), dao);
168184
try {
169185
J json = jsonMapper.fromStringTo(jsonType, ctx.body());
@@ -172,13 +188,13 @@ private void fullUpdate(final Context ctx) throws IOException {
172188
mappedJpa.setCreatedOn(jpa.getCreatedOn());
173189
mappedJpa.setEditedOn(jpa.getEditedOn());
174190

175-
mappedJpa = extensions.runPreModify(ctx, transaction.getManager(), jpa.getId(), json, jpa, mappedJpa,
176-
executorService);
191+
mappedJpa = extensions.runPreModify(ctx, makeAsyncExtensionContextFor(ctx), transaction.getManager(),
192+
jpa.getId(), json, jpa, mappedJpa, executorService);
177193
P persistedJpa = dao.update(transaction.getManager(), mappedJpa, hu.getReadTenantIdsFrom(ctx));
178194

179195
J r = orikaMapper.map(persistedJpa, jsonType);
180-
r = extensions.runPostModify(ctx, transaction.getManager(), jpa.getId(), json, jpa, mappedJpa, persistedJpa,
181-
r, executorService);
196+
r = extensions.runPostModify(ctx, makeAsyncExtensionContextFor(ctx), transaction.getManager(), jpa.getId(),
197+
json, jpa, mappedJpa, persistedJpa, r, executorService);
182198

183199
ctx.attribute(Attribute.RESPONSE_OBJECT, r);
184200

@@ -192,12 +208,13 @@ private void fullUpdate(final Context ctx) throws IOException {
192208
private void delete(final Context ctx) {
193209
ctx.attribute(Attribute.RESPONSE_OBJECT, null);
194210
Long id = hu.checkAndGetId(ctx);
195-
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction();
211+
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction(ctx);
196212

197-
id = extensions.runPreDelete(ctx, transaction.getManager(), id, executorService);
213+
id = extensions.runPreDelete(ctx, makeAsyncExtensionContextFor(ctx), transaction.getManager(), id,
214+
executorService);
198215
dao.delete(transaction.getManager(), id, hu.getReadTenantIdsFrom(ctx));
199216
ctx.status(204);
200-
extensions.runPostDelete(ctx, transaction.getManager(), id, executorService);
217+
extensions.runPostDelete(ctx, makeAsyncExtensionContextFor(ctx), transaction.getManager(), id, executorService);
201218

202219
transaction.end();
203220
}

src/main/java/info/unterrainer/commons/httpserver/GenericHandlerGroupBuilder.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import info.unterrainer.commons.httpserver.daos.CoreDao;
1010
import info.unterrainer.commons.httpserver.daos.ParamMap;
1111
import info.unterrainer.commons.httpserver.enums.Endpoint;
12+
import info.unterrainer.commons.httpserver.extensions.AsyncExtensionContextMapper;
1213
import info.unterrainer.commons.httpserver.interceptors.InterceptorData;
1314
import info.unterrainer.commons.httpserver.interceptors.InterceptorParamBuilder;
1415
import info.unterrainer.commons.httpserver.interceptors.delegates.GetListInterceptor;
@@ -35,6 +36,7 @@ public class GenericHandlerGroupBuilder<P extends BasicJpa, J extends BasicJson,
3536
private String path;
3637
private List<Endpoint> endpoints = new ArrayList<>();
3738
private List<GetListInterceptor> getListInterceptors = new ArrayList<>();
39+
private List<AsyncExtensionContextMapper> asyncExtensionContextMappers = new ArrayList<>();
3840
private ExecutorService executorService;
3941

4042
HandlerExtensions<P, J, E> extensions = new HandlerExtensions<>();
@@ -49,7 +51,7 @@ public HttpServer add() {
4951
executorService = server.executorService;
5052
GenericHandlerGroup<P, J, E> handlerGroupInstance = new GenericHandlerGroup<>(dao, jpaType, jsonType,
5153
jsonMapper, orikaFactory.getMapperFacade(), path, endpoints, getListInterceptors, extensions,
52-
accessRoles, executorService);
54+
asyncExtensionContextMappers, accessRoles, executorService);
5355
server.addHandlerGroup(handlerGroupInstance);
5456
return server;
5557
}
@@ -93,6 +95,20 @@ public GenericHandlerGroupBuilder<P, J, E> getListInterceptor(final GetListInter
9395
return this;
9496
}
9597

98+
/**
99+
* Here you may register {@link AsyncExtensionContextMapper}s that allow you to
100+
* map attributes located in the {@link Context} to an offline, asynchronous one
101+
* which you can address within asynchronous extension methods.
102+
*
103+
* @param asyncExtensionContextMapper
104+
* @return an instance of this object to asure a fluent interface
105+
*/
106+
public GenericHandlerGroupBuilder<P, J, E> asyncExtensionContextMapper(
107+
final AsyncExtensionContextMapper asyncExtensionContextMapper) {
108+
asyncExtensionContextMappers.add(asyncExtensionContextMapper);
109+
return this;
110+
}
111+
96112
/**
97113
* Gives you a {@link InterceptorParamBuilder} object that allows you to declare
98114
* an interceptor with minimal code.<br>

src/main/java/info/unterrainer/commons/httpserver/HandlerExtensions.java

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.concurrent.ExecutorService;
66

77
import info.unterrainer.commons.httpserver.exceptions.GracefulCancelationException;
8+
import info.unterrainer.commons.httpserver.extensions.AsyncExtensionContext;
89
import info.unterrainer.commons.httpserver.extensions.delegates.PostDeleteAsync;
910
import info.unterrainer.commons.httpserver.extensions.delegates.PostDeleteSync;
1011
import info.unterrainer.commons.httpserver.extensions.delegates.PostGetListAsync;
@@ -52,10 +53,10 @@ public class HandlerExtensions<P extends BasicJpa, J extends BasicJson, E> {
5253
private final List<PreModifyAsync<P, J>> preModifyAsync = new ArrayList<>();
5354
private final List<PreModifySync<P, J, E>> preModifySync = new ArrayList<>();
5455

55-
public J runPostGetSingle(final Context ctx, final E entityManager, final Long receivedId, final P readJpa,
56-
final J response, final ExecutorService executorService) {
56+
public J runPostGetSingle(final Context ctx, final AsyncExtensionContext asyncCtx, final E entityManager,
57+
final Long receivedId, final P readJpa, final J response, final ExecutorService executorService) {
5758
for (PostGetSingleAsync<P, J> h : postGetSingleAsync())
58-
executorService.execute(() -> h.handle(receivedId, readJpa, response));
59+
executorService.execute(() -> h.handle(asyncCtx, receivedId, readJpa, response));
5960

6061
J result = response;
6162
for (PostGetSingleSync<P, J, E> h : postGetSingleSync()) {
@@ -66,10 +67,11 @@ public J runPostGetSingle(final Context ctx, final E entityManager, final Long r
6667
return result;
6768
}
6869

69-
public ListJson<J> runPostGetList(final Context ctx, final E entityManager, final Long size, final Long offset,
70-
final ListJson<P> readList, final ListJson<J> response, final ExecutorService executorService) {
70+
public ListJson<J> runPostGetList(final Context ctx, final AsyncExtensionContext asyncCtx, final E entityManager,
71+
final Long size, final Long offset, final ListJson<P> readList, final ListJson<J> response,
72+
final ExecutorService executorService) {
7173
for (PostGetListAsync<P, J> h : postGetListAsync())
72-
executorService.execute(() -> h.handle(size, offset, readList, response));
74+
executorService.execute(() -> h.handle(asyncCtx, size, offset, readList, response));
7375

7476
ListJson<J> result = response;
7577
for (PostGetListSync<P, J, E> h : postGetListSync()) {
@@ -80,10 +82,10 @@ public ListJson<J> runPostGetList(final Context ctx, final E entityManager, fina
8082
return result;
8183
}
8284

83-
public P runPreInsert(final Context ctx, final E entityManager, final J receivedJson, final P resultJpa,
84-
final ExecutorService executorService) {
85+
public P runPreInsert(final Context ctx, final AsyncExtensionContext asyncCtx, final E entityManager,
86+
final J receivedJson, final P resultJpa, final ExecutorService executorService) {
8587
for (PreInsertAsync<P, J> h : preInsertAsync())
86-
executorService.execute(() -> h.handle(receivedJson, resultJpa));
88+
executorService.execute(() -> h.handle(asyncCtx, receivedJson, resultJpa));
8789

8890
P result = resultJpa;
8991
for (PreInsertSync<P, J, E> h : preInsertSync()) {
@@ -94,10 +96,11 @@ public P runPreInsert(final Context ctx, final E entityManager, final J received
9496
return result;
9597
}
9698

97-
public J runPostInsert(final Context ctx, final E entityManager, final J receivedJson, final P mappedJpa,
98-
final P createdJpa, final J response, final ExecutorService executorService) {
99+
public J runPostInsert(final Context ctx, final AsyncExtensionContext asyncCtx, final E entityManager,
100+
final J receivedJson, final P mappedJpa, final P createdJpa, final J response,
101+
final ExecutorService executorService) {
99102
for (PostInsertAsync<P, J> h : postInsertAsync())
100-
executorService.execute(() -> h.handle(receivedJson, mappedJpa, createdJpa, response));
103+
executorService.execute(() -> h.handle(asyncCtx, receivedJson, mappedJpa, createdJpa, response));
101104

102105
J result = response;
103106
for (PostInsertSync<P, J, E> h : postInsertSync()) {
@@ -108,10 +111,11 @@ public J runPostInsert(final Context ctx, final E entityManager, final J receive
108111
return result;
109112
}
110113

111-
public P runPreModify(final Context ctx, final E entityManager, final Long receivedId, final J receivedJson,
112-
final P readJpa, final P resultJpa, final ExecutorService executorService) {
114+
public P runPreModify(final Context ctx, final AsyncExtensionContext asyncCtx, final E entityManager,
115+
final Long receivedId, final J receivedJson, final P readJpa, final P resultJpa,
116+
final ExecutorService executorService) {
113117
for (PreModifyAsync<P, J> h : preModifyAsync())
114-
executorService.execute(() -> h.handle(receivedId, receivedJson, readJpa, resultJpa));
118+
executorService.execute(() -> h.handle(asyncCtx, receivedId, receivedJson, readJpa, resultJpa));
115119

116120
P result = resultJpa;
117121
for (PreModifySync<P, J, E> h : preModifySync()) {
@@ -122,12 +126,12 @@ public P runPreModify(final Context ctx, final E entityManager, final Long recei
122126
return result;
123127
}
124128

125-
public J runPostModify(final Context ctx, final E entityManager, final Long receivedId, final J receivedJson,
126-
final P readJpa, final P mappedJpa, final P persistedJpa, final J response,
127-
final ExecutorService executorService) {
129+
public J runPostModify(final Context ctx, final AsyncExtensionContext asyncCtx, final E entityManager,
130+
final Long receivedId, final J receivedJson, final P readJpa, final P mappedJpa, final P persistedJpa,
131+
final J response, final ExecutorService executorService) {
128132
for (PostModifyAsync<P, J> h : postModifyAsync())
129-
executorService
130-
.execute(() -> h.handle(receivedId, receivedJson, readJpa, mappedJpa, persistedJpa, response));
133+
executorService.execute(
134+
() -> h.handle(asyncCtx, receivedId, receivedJson, readJpa, mappedJpa, persistedJpa, response));
131135

132136
J result = response;
133137
for (PostModifySync<P, J, E> h : postModifySync()) {
@@ -138,10 +142,10 @@ public J runPostModify(final Context ctx, final E entityManager, final Long rece
138142
return result;
139143
}
140144

141-
public Long runPreDelete(final Context ctx, final E entityManager, final Long receivedId,
142-
final ExecutorService executorService) {
145+
public Long runPreDelete(final Context ctx, final AsyncExtensionContext asyncCtx, final E entityManager,
146+
final Long receivedId, final ExecutorService executorService) {
143147
for (PreDeleteAsync h : preDeleteAsync())
144-
executorService.execute(() -> h.handle(receivedId));
148+
executorService.execute(() -> h.handle(asyncCtx, receivedId));
145149

146150
Long result = receivedId;
147151
for (PreDeleteSync<E> h : preDeleteSync()) {
@@ -152,10 +156,10 @@ public Long runPreDelete(final Context ctx, final E entityManager, final Long re
152156
return result;
153157
}
154158

155-
public void runPostDelete(final Context ctx, final E entityManager, final Long receivedId,
156-
final ExecutorService executorService) {
159+
public void runPostDelete(final Context ctx, final AsyncExtensionContext asyncCtx, final E entityManager,
160+
final Long receivedId, final ExecutorService executorService) {
157161
for (PostDeleteAsync h : postDeleteAsync())
158-
executorService.execute(() -> h.handle(receivedId));
162+
executorService.execute(() -> h.handle(asyncCtx, receivedId));
159163

160164
for (PostDeleteSync<E> h : postDeleteSync())
161165
if (!h.handle(ctx, entityManager, receivedId))

src/main/java/info/unterrainer/commons/httpserver/HandlerUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public Set<Long> getWriteTenantIdsFrom(final Context ctx) {
4040

4141
public <P extends BasicJpa, E> P getJpaById(final Context ctx, final CoreDao<P, E> dao) {
4242
Long id = checkAndGetId(ctx);
43-
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction();
43+
DaoTransaction<E> transaction = dao.getTransactionManager().beginTransaction(ctx);
4444
try {
4545
P jpa = dao.getById(transaction.getManager(), id, getReadTenantIdsFrom(ctx));
4646
if (jpa == null)

src/main/java/info/unterrainer/commons/httpserver/daos/BasicJpqlDao.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
import java.util.List;
44
import java.util.Set;
5+
import java.util.function.Function;
56

67
import javax.persistence.EntityManager;
78
import javax.persistence.EntityManagerFactory;
89
import javax.persistence.TypedQuery;
910

1011
import info.unterrainer.commons.rdbutils.entities.BasicJpa;
12+
import io.javalin.http.Context;
1113
import lombok.Getter;
1214

1315
public class BasicJpqlDao<P extends BasicJpa> implements CoreDaoProvider<P, EntityManager> {
@@ -24,6 +26,14 @@ public BasicJpqlDao(final EntityManagerFactory emf, final Class<P> type) {
2426
coreDao = new JpqlCoreDao<>(emf, type);
2527
}
2628

29+
public BasicJpqlDao(final Function<Context, EntityManagerFactory> entityManagerFactorySupplier,
30+
final Class<P> type) {
31+
super();
32+
this.emf = null;
33+
this.type = type;
34+
coreDao = new JpqlCoreDao<>(entityManagerFactorySupplier, type);
35+
}
36+
2737
<T> List<T> getList(final EntityManager em, final TypedQuery<T> query, final long offset, final long size) {
2838
int s = Integer.MAX_VALUE;
2939
if (size < s)
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package info.unterrainer.commons.httpserver.daos;
22

3+
import io.javalin.http.Context;
4+
35
public interface DaoTransactionManager<E> {
46

57
/**
68
* Gets you a new transaction and starts it.
79
*
810
* @return a {@link JpqlTransaction}
911
*/
10-
DaoTransaction<E> beginTransaction();
12+
DaoTransaction<E> beginTransaction(Context ctx);
1113
}

0 commit comments

Comments
 (0)