Skip to content

Commit be31ee7

Browse files
committed
RetryingInvocationBuilder
New subclasses of `GraphStoreClient` and `SPARQLClient` that use the `RetryingInvocationBuilder`
1 parent 938d687 commit be31ee7

6 files changed

Lines changed: 503 additions & 19 deletions

File tree

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/**
2+
* Copyright 2025 Martynas Jusevičius <martynas@atomgraph.com>
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 com.atomgraph.linkeddatahub.client;
18+
19+
import com.atomgraph.core.MediaTypes;
20+
import com.atomgraph.linkeddatahub.client.util.RetryingInvocationBuilder;
21+
import jakarta.ws.rs.NotFoundException;
22+
import jakarta.ws.rs.client.Entity;
23+
import jakarta.ws.rs.client.WebTarget;
24+
import jakarta.ws.rs.core.MultivaluedHashMap;
25+
import jakarta.ws.rs.core.MultivaluedMap;
26+
import jakarta.ws.rs.core.Response;
27+
import jakarta.ws.rs.core.Response.Status;
28+
import org.apache.jena.rdf.model.Model;
29+
import org.slf4j.Logger;
30+
import org.slf4j.LoggerFactory;
31+
32+
/**
33+
*
34+
* @author Martynas.Jusevicius
35+
*/
36+
public class GraphStoreClient extends com.atomgraph.core.client.GraphStoreClient {
37+
38+
private static final Logger log = LoggerFactory.getLogger(GraphStoreClient.class);
39+
40+
private final long defaultDelayMillis = 5000L;
41+
private final int maxRetryCount = 3;
42+
43+
protected GraphStoreClient(MediaTypes mediaTypes, WebTarget endpoint) {
44+
super(mediaTypes, endpoint);
45+
}
46+
47+
protected GraphStoreClient(WebTarget endpoint) {
48+
this(new MediaTypes(), endpoint);
49+
}
50+
51+
public static GraphStoreClient create(MediaTypes mediaTypes, WebTarget endpoint) {
52+
return new GraphStoreClient(mediaTypes, endpoint);
53+
}
54+
55+
public static GraphStoreClient create(WebTarget endpoint) {
56+
return new GraphStoreClient(endpoint);
57+
}
58+
59+
@Override
60+
public boolean containsModel(String uri) {
61+
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
62+
params.putSingle(GRAPH_PARAM_NAME, uri);
63+
64+
try (Response cr = new RetryingInvocationBuilder(
65+
applyParams(params).request(getReadableMediaTypes(Model.class)),
66+
defaultDelayMillis,
67+
maxRetryCount
68+
).head()) {
69+
return cr.getStatusInfo().getFamily().equals(Response.Status.Family.SUCCESSFUL);
70+
}
71+
}
72+
73+
@Override
74+
public Model getModel() {
75+
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
76+
params.putSingle(DEFAULT_PARAM_NAME, Boolean.TRUE.toString());
77+
78+
try (Response cr = new RetryingInvocationBuilder(
79+
applyParams(params).request(getReadableMediaTypes(Model.class)),
80+
defaultDelayMillis,
81+
maxRetryCount
82+
).get()) {
83+
if (cr.getStatus() == Status.NOT_FOUND.getStatusCode()) {
84+
throw new NotFoundException();
85+
}
86+
return cr.readEntity(Model.class);
87+
}
88+
}
89+
90+
@Override
91+
public Model getModel(String uri) {
92+
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
93+
params.putSingle(GRAPH_PARAM_NAME, uri);
94+
95+
try (Response cr = new RetryingInvocationBuilder(
96+
applyParams(params).request(getReadableMediaTypes(Model.class)),
97+
defaultDelayMillis,
98+
maxRetryCount
99+
).get()) {
100+
if (cr.getStatus() == Status.NOT_FOUND.getStatusCode()) {
101+
throw new NotFoundException();
102+
}
103+
return cr.readEntity(Model.class);
104+
}
105+
}
106+
107+
@Override
108+
public void add(Model model) {
109+
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
110+
params.putSingle(DEFAULT_PARAM_NAME, Boolean.TRUE.toString());
111+
112+
try (Response cr = new RetryingInvocationBuilder(
113+
applyParams(params).request(),
114+
defaultDelayMillis,
115+
maxRetryCount
116+
).post(Entity.entity(model, getDefaultMediaType()))) {
117+
if (cr.getStatus() == Status.NOT_FOUND.getStatusCode()) {
118+
throw new NotFoundException();
119+
}
120+
}
121+
}
122+
123+
@Override
124+
public void add(String uri, Model model) {
125+
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
126+
params.putSingle(GRAPH_PARAM_NAME, uri);
127+
128+
try (Response cr = new RetryingInvocationBuilder(
129+
applyParams(params).request(),
130+
defaultDelayMillis,
131+
maxRetryCount
132+
).post(Entity.entity(model, getDefaultMediaType()))) {
133+
if (cr.getStatus() == Status.NOT_FOUND.getStatusCode()) {
134+
throw new NotFoundException();
135+
}
136+
}
137+
}
138+
139+
@Override
140+
public void putModel(Model model) {
141+
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
142+
params.putSingle(DEFAULT_PARAM_NAME, Boolean.TRUE.toString());
143+
144+
try (Response cr = new RetryingInvocationBuilder(
145+
applyParams(params).request(),
146+
defaultDelayMillis,
147+
maxRetryCount
148+
).put(Entity.entity(model, getDefaultMediaType()))) {
149+
if (cr.getStatus() == Status.NOT_FOUND.getStatusCode()) {
150+
throw new NotFoundException();
151+
}
152+
}
153+
}
154+
155+
@Override
156+
public void putModel(String uri, Model model) {
157+
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
158+
params.putSingle(GRAPH_PARAM_NAME, uri);
159+
160+
try (Response cr = new RetryingInvocationBuilder(
161+
applyParams(params).request(),
162+
defaultDelayMillis,
163+
maxRetryCount
164+
).put(Entity.entity(model, getDefaultMediaType()))) {
165+
if (cr.getStatus() == Status.NOT_FOUND.getStatusCode()) {
166+
throw new NotFoundException();
167+
}
168+
}
169+
}
170+
171+
@Override
172+
public void deleteDefault() {
173+
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
174+
params.putSingle(DEFAULT_PARAM_NAME, Boolean.TRUE.toString());
175+
176+
try (Response cr = new RetryingInvocationBuilder(
177+
applyParams(params).request(),
178+
defaultDelayMillis,
179+
maxRetryCount
180+
).delete()) {
181+
if (cr.getStatus() == Status.NOT_FOUND.getStatusCode()) {
182+
throw new NotFoundException();
183+
}
184+
}
185+
}
186+
187+
@Override
188+
public void deleteModel(String uri) {
189+
MultivaluedMap<String, String> params = new MultivaluedHashMap<>();
190+
params.putSingle(GRAPH_PARAM_NAME, uri);
191+
192+
try (Response cr = new RetryingInvocationBuilder(
193+
applyParams(params).request(),
194+
defaultDelayMillis,
195+
maxRetryCount
196+
).delete()) {
197+
if (cr.getStatus() == Status.NOT_FOUND.getStatusCode()) {
198+
throw new NotFoundException();
199+
}
200+
}
201+
}
202+
203+
}

src/main/java/com/atomgraph/linkeddatahub/client/LinkedDataClient.java

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,13 @@
1919
import com.atomgraph.core.MediaTypes;
2020
import com.atomgraph.linkeddatahub.client.filter.auth.IDTokenDelegationFilter;
2121
import com.atomgraph.linkeddatahub.client.filter.auth.WebIDDelegationFilter;
22-
import com.atomgraph.linkeddatahub.client.util.RetryAfterHelper;
22+
import com.atomgraph.linkeddatahub.client.util.RetryingInvocationBuilder;
2323
import com.atomgraph.linkeddatahub.server.security.AgentContext;
2424
import com.atomgraph.linkeddatahub.server.security.IDTokenSecurityContext;
2525
import com.atomgraph.linkeddatahub.server.security.WebIDSecurityContext;
2626
import java.net.URI;
2727
import jakarta.ws.rs.client.Client;
2828
import jakarta.ws.rs.client.Entity;
29-
import static jakarta.ws.rs.client.Entity.entity;
3029
import jakarta.ws.rs.client.WebTarget;
3130
import jakarta.ws.rs.core.HttpHeaders;
3231
import jakarta.ws.rs.core.MediaType;
@@ -160,43 +159,60 @@ protected WebTarget getWebTarget(URI uri)
160159
public Response get(URI uri, jakarta.ws.rs.core.MediaType[] acceptedTypes)
161160
{
162161
WebTarget webTarget = getWebTarget(uri);
163-
return new RetryAfterHelper(getDefaultDelayMillis(), getMaxRetryCount()).invokeWithRetry(() ->
164-
webTarget.request(acceptedTypes)
165-
.header(HttpHeaders.USER_AGENT, getUserAgentHeaderValue())
166-
.get());
162+
163+
return new RetryingInvocationBuilder(
164+
webTarget.
165+
request(acceptedTypes).
166+
header(HttpHeaders.USER_AGENT, getUserAgentHeaderValue()), getDefaultDelayMillis(), getMaxRetryCount()).
167+
get();
167168
}
168169

169170
@Override
170171
public Response post(URI uri, MediaType[] acceptedTypes, Entity entity)
171172
{
172173
WebTarget webTarget = getWebTarget(uri);
173-
return new RetryAfterHelper(getDefaultDelayMillis(), getMaxRetryCount()).invokeWithRetry(() ->
174-
webTarget.request(acceptedTypes).post(entity));
174+
175+
return new RetryingInvocationBuilder(
176+
webTarget.request(acceptedTypes),
177+
getDefaultDelayMillis(),
178+
getMaxRetryCount()).
179+
post(entity);
175180
}
176-
177181
@Override
178182
public Response put(URI uri, MediaType[] acceptedTypes, Entity entity)
179183
{
180184
WebTarget webTarget = getWebTarget(uri);
181-
return new RetryAfterHelper(getDefaultDelayMillis(), getMaxRetryCount()).invokeWithRetry(() ->
182-
webTarget.request(acceptedTypes).put(entity));
185+
186+
return new RetryingInvocationBuilder(
187+
webTarget.request(acceptedTypes),
188+
getDefaultDelayMillis(),
189+
getMaxRetryCount()
190+
).
191+
put(entity);
183192
}
184193

185194
public Response put(URI uri, Model model, MultivaluedMap<String, Object> headers)
186195
{
187196
WebTarget webTarget = getWebTarget(uri);
188-
return new RetryAfterHelper(getDefaultDelayMillis(), getMaxRetryCount()).invokeWithRetry(() ->
189-
webTarget.request(getReadableMediaTypes(Model.class)).
190-
headers(headers).
191-
put(Entity.entity(model, getDefaultMediaType())));
197+
198+
return new RetryingInvocationBuilder(
199+
webTarget.request(getReadableMediaTypes(Model.class)).headers(headers),
200+
getDefaultDelayMillis(),
201+
getMaxRetryCount()
202+
).
203+
put(Entity.entity(model, getDefaultMediaType()));
192204
}
193205

194206
@Override
195207
public Response delete(URI uri)
196208
{
197209
WebTarget webTarget = getWebTarget(uri);
198-
return new RetryAfterHelper(getDefaultDelayMillis(), getMaxRetryCount()).invokeWithRetry(() ->
199-
webTarget.request().delete());
210+
211+
return new RetryingInvocationBuilder(
212+
webTarget.request(),
213+
getDefaultDelayMillis(),
214+
getMaxRetryCount()
215+
).delete();
200216
}
201217

202218
/**

0 commit comments

Comments
 (0)