Skip to content

Commit 410132c

Browse files
committed
Small refactoring of APIRequest. Common functionality like open connections, parse response or exception handling have been relocated into the abstract super-class. Specific request implementations are still able to apply different object behaviour by overwriting the super-class' "prepareRequest" and "getResponse" methods.
1 parent 95b9c80 commit 410132c

File tree

1 file changed

+61
-114
lines changed

1 file changed

+61
-114
lines changed

src/main/java/com/github/m0nk3y2k4/thetvdb/internal/connection/APIConnection.java

Lines changed: 61 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.util.Map.Entry;
1515
import java.util.Optional;
1616

17+
import javax.annotation.CheckForNull;
1718
import javax.annotation.Nonnull;
1819
import javax.net.ssl.HttpsURLConnection;
1920

@@ -131,6 +132,7 @@ abstract class APIRequest {
131132

132133
/** Messages for error/exception handling */
133134
private static final String ERR_UNEXPECTED_RESPONSE = "Receiver returned an unexpected error: HTTP-%d \nOriginal API error message: %s";
135+
private static final String ERR_SEND = "An exception occurred while sending %s request to API";
134136

135137
/** Constants for API error handling */
136138
private static final String API_ERROR = "Error";
@@ -144,25 +146,45 @@ abstract class APIRequest {
144146
/** Session for remote API authentication */
145147
private APISession session;
146148

147-
/** HTTPS connection for this API request */
148-
HttpsURLConnection con;
149-
150149
/** Resource/Route to be called on remote service */
151-
final String resource;
150+
private final String resource;
151+
152+
/** HTTP request method to be used for this request*/
153+
private final String requestMethod;
152154

153-
APIRequest(@Nonnull String resource) {
155+
APIRequest(@Nonnull String resource, @Nonnull String requestMethod) {
154156
this.resource = resource;
157+
this.requestMethod = requestMethod;
155158
}
156159

157160
void setSession(@Nonnull APISession session) {
158161
this.session = session;
159162
}
160163

161-
void openConnection(@Nonnull String resource, @Nonnull String requestMethod) throws IOException {
164+
final JsonNode send() throws APIException {
165+
HttpsURLConnection con = null;
166+
167+
try {
168+
// Create new HTTP connection to the remove service
169+
con = openConnection();
170+
171+
// Special preparations for the request to send, e.g. specific connection settings, body for POST request,...
172+
prepareRequest(con);
173+
174+
// Parse response from HTTP connection
175+
return getResponse(con);
176+
} catch (IOException ex) {
177+
throw new APICommunicationException(String.format(ERR_SEND, requestMethod), ex);
178+
} finally {
179+
disconnect(con);
180+
}
181+
}
182+
183+
private HttpsURLConnection openConnection() throws IOException {
162184
ConnectionValidator.validateResource(resource);
163185
ConnectionValidator.validateRequestMethod(requestMethod);
164186

165-
con = (HttpsURLConnection) new URL(API_URL + resource).openConnection();
187+
HttpsURLConnection con = (HttpsURLConnection) new URL(API_URL + resource).openConnection();
166188

167189
// POST, GET, DELETE, PUT,...
168190
con.setRequestMethod(requestMethod.toUpperCase());
@@ -176,103 +198,74 @@ void openConnection(@Nonnull String resource, @Nonnull String requestMethod) thr
176198
con.setRequestProperty("Authorization", "Bearer " + session.getToken().get());
177199
con.setRequestProperty("Accept-Language", session.getLanguage());
178200
}
201+
202+
return con;
179203
}
180204

181-
void disconnect() {
205+
private void disconnect(@CheckForNull HttpsURLConnection con) {
182206
if (con != null) {
183207
con.disconnect();
184208
}
185209
}
186210

187-
JsonNode getResponse() throws APIException, IOException {
211+
void prepareRequest(@Nonnull HttpsURLConnection con) throws IOException {
212+
// No default preparation. Overwrite this method in any sub-class to add type specific request preparations.
213+
}
214+
215+
JsonNode getResponse(@Nonnull HttpsURLConnection con) throws APIException, IOException {
188216
int responseCode = con.getResponseCode();
189217

190218
switch (responseCode) {
191219
case HttpsURLConnection.HTTP_OK:
192-
return parseResponse();
220+
return parseResponse(con);
193221
case HttpsURLConnection.HTTP_UNAUTHORIZED:
194-
throw new APINotAuthorizedException(getError());
222+
throw new APINotAuthorizedException(getError(con));
195223
case HttpsURLConnection.HTTP_NOT_FOUND:
196-
throw new APIException(API_NOT_FOUND_ERROR, getError());
224+
throw new APIException(API_NOT_FOUND_ERROR, getError(con));
197225
case HttpsURLConnection.HTTP_CONFLICT:
198-
throw new APIException(API_CONFLICT_ERROR, getError());
226+
throw new APIException(API_CONFLICT_ERROR, getError(con));
199227
case HttpsURLConnection.HTTP_UNAVAILABLE:
200228
throw new APIException(API_SERVICE_UNAVAILABLE);
201229
default:
202-
throw new APICommunicationException(String.format(ERR_UNEXPECTED_RESPONSE, responseCode, getError()));
203-
}
204-
}
205-
206-
private JsonNode parseResponse(InputStream inputStream) throws IOException {
207-
ObjectMapper mapper = new ObjectMapper();
208-
try (JsonParser parser = mapper.getFactory().createParser(inputStream)) {
209-
return mapper.readTree(parser);
230+
throw new APICommunicationException(String.format(ERR_UNEXPECTED_RESPONSE, responseCode, getError(con)));
210231
}
211232
}
212233

213-
private JsonNode parseResponse() throws IOException {
234+
private JsonNode parseResponse(@Nonnull HttpsURLConnection con) throws IOException {
214235
return parseResponse(con.getInputStream());
215236
}
216237

217-
private String getError() throws IOException {
238+
private String getError(@Nonnull HttpsURLConnection con) throws IOException {
218239
return parseResponse(con.getErrorStream()).get(API_ERROR).asText("");
219240
}
220241

221-
abstract JsonNode send() throws APIException;
242+
private JsonNode parseResponse(@Nonnull InputStream inputStream) throws IOException {
243+
ObjectMapper mapper = new ObjectMapper();
244+
try (JsonParser parser = mapper.getFactory().createParser(inputStream)) {
245+
return mapper.readTree(parser);
246+
}
247+
}
222248
}
223249

224250
final class GetRequest extends APIRequest {
225251

226-
/** Messages for error/exception handling */
227-
private static final String ERR_GET = "An exception occurred while sending GET request to API";
228-
229252
GetRequest(@Nonnull String resource) {
230-
super(resource);
231-
}
232-
233-
@Override
234-
JsonNode send() throws APIException {
235-
try {
236-
openConnection(resource, "GET");
237-
238-
return getResponse();
239-
} catch (IOException ex) {
240-
throw new APICommunicationException(ERR_GET, ex);
241-
} finally {
242-
disconnect();
243-
}
253+
super(resource, "GET");
244254
}
245255
}
246256

247257
final class PostRequest extends APIRequest {
248258

249-
/** Messages for error/exception handling */
250-
private static final String ERR_POST = "An exception occurred while sending POST request to API";
251-
252259
private final String data;
253260

254261
PostRequest(@Nonnull String resource, @Nonnull String data) {
255-
super(resource);
262+
super(resource, "POST");
256263
this.data = data;
257264
}
258265

259266
@Override
260-
JsonNode send() throws APIException {
261-
try {
262-
openConnection(resource, "POST");
263-
264-
// POST data
265-
writeRequestBody(data);
266-
267-
return getResponse();
268-
} catch (IOException ex) {
269-
throw new APICommunicationException(ERR_POST, ex);
270-
} finally {
271-
disconnect();
272-
}
273-
}
274-
275-
private void writeRequestBody(@Nonnull String data) throws IOException {
267+
void prepareRequest(@Nonnull HttpsURLConnection con) throws IOException {
268+
// Write request body (payload) for POST request
276269
ConnectionValidator.validatePayload(data);
277270

278271
con.setDoOutput(true);
@@ -286,27 +279,13 @@ private void writeRequestBody(@Nonnull String data) throws IOException {
286279

287280
final class HeadRequest extends APIRequest {
288281

289-
/** Messages for error/exception handling */
290-
private static final String ERR_HEAD = "An exception occurred while sending HEAD request to API";
291-
292282
HeadRequest(@Nonnull String resource) {
293-
super(resource);
283+
super(resource, "HEAD");
294284
}
295285

296286
@Override
297-
JsonNode send() throws APIException {
298-
try {
299-
openConnection(resource, "HEAD");
300-
301-
return createJsonFromHeaderFields();
302-
} catch (IOException ex) {
303-
throw new APICommunicationException(ERR_HEAD, ex);
304-
} finally {
305-
disconnect();
306-
}
307-
}
308-
309-
private JsonNode createJsonFromHeaderFields() {
287+
JsonNode getResponse(@Nonnull HttpsURLConnection con) {
288+
// Create JSON object from response header fields
310289
JsonNodeFactory factory = new ObjectMapper().getNodeFactory();
311290
ObjectNode root = factory.objectNode();
312291

@@ -335,46 +314,14 @@ private JsonNode createJsonFromHeaderFields() {
335314

336315
final class DeleteRequest extends APIRequest {
337316

338-
/** Messages for error/exception handling */
339-
private static final String ERR_DELETE = "An exception occurred while sending DELETE request to API";
340-
341-
DeleteRequest(@Nonnull String resource) {
342-
super(resource);
343-
}
344-
345-
@Override
346-
JsonNode send() throws APIException {
347-
try {
348-
openConnection(resource, "DELETE");
349-
350-
return getResponse();
351-
} catch (IOException ex) {
352-
throw new APICommunicationException(ERR_DELETE, ex);
353-
} finally {
354-
disconnect();
355-
}
356-
}
317+
DeleteRequest(@Nonnull String resource) {
318+
super(resource, "DELETE");
319+
}
357320
}
358321

359322
final class PutRequest extends APIRequest {
360323

361-
/** Messages for error/exception handling */
362-
private static final String ERR_PUT = "An exception occurred while sending PUT request to API";
363-
364324
PutRequest(@Nonnull String resource) {
365-
super(resource);
366-
}
367-
368-
@Override
369-
JsonNode send() throws APIException {
370-
try {
371-
openConnection(resource, "PUT");
372-
373-
return getResponse();
374-
} catch (IOException ex) {
375-
throw new APICommunicationException(ERR_PUT, ex);
376-
} finally {
377-
disconnect();
378-
}
325+
super(resource, "PUT");
379326
}
380327
}

0 commit comments

Comments
 (0)