List of usage examples for com.fasterxml.jackson.core JsonProcessingException toString
@Override
public String toString()
From source file:com.smartsheet.tin.filters.common.ORCFormatter.java
/** * Create the JSON entry for a row from a OneRowChange. * Whether the row_vals are ColumnVals or KeyVals depends on whether the * OneRowChange was for an INSERT/UPDATE (Column values) or a DELETE (Key * values).// ww w.j a v a 2 s.c o m * * @param msg_pojo The partially filled out object to add the key to. * @param tki Specifies which columns are keys. * @param pos2idx Mapping between key columns and the indexes of row_vals. * @param row_vals These can be the Column or Key values. * @return The JSON string representation of the msg_pojo. */ private String makeRowEntry(ORCPrimaryKeyInfo msg_pojo, TableKeyInfo tki, Position2Index pos2idx, ArrayList<ColumnVal> row_vals) { try { // Discard the key values for any previous row. msg_pojo.resetKey(); for (TableKeyInfo.KeyPair kp : tki.getKeys()) { int idx = kp.getIndex(); logger.debug(String.format("Key column '%s' at idx: %d pos2idx.get(%d)=%d", kp.getColumnName(), idx, idx, pos2idx.getIndex(idx))); msg_pojo.addKey(kp.getColumnName(), kp.getColumnType(), kp.getColumnTypeDesc(), row_vals.get(pos2idx.getIndex(idx)).getValue()); } try { return this.mapper.writeValueAsString(msg_pojo); } catch (JsonProcessingException e) { logger.error("Failed using mapper to write JSON:", e); return msg_pojo.toBasicJSON(); } } catch (Exception e) { logger.error("Failed creating JSON row entry", e); // NOTE: This might not be valid JSON, depends on the error msg. return "{\"ERROR\": \"" + e.toString() + "\" }"; } }
From source file:org.wikidata.wdtk.wikibaseapi.WikibaseDataFetcher.java
/** * Creates a map of identifiers or page titles to documents retrieved via * the API URL.//from w w w. j a v a 2 s. c om * * @param numOfEntities * number of entities that should be retrieved * @param url * the API URL (with parameters) * @param siteKey * null if the map keys should be document ids; siite key (e.g., * "enwiki") if the map should use page titles of a linked site * as keys * @return map of document identifiers or titles to documents retrieved via * the API URL */ Map<String, EntityDocument> getStringEntityDocumentMap(int numOfEntities, String url, String siteKey) { if (numOfEntities == 0 || url == null) { return Collections.<String, EntityDocument>emptyMap(); } Map<String, EntityDocument> result = new HashMap<>(numOfEntities); try (InputStream inStream = this.webResourceFetcher.getInputStreamForUrl(url)) { JsonNode root = mapper.readTree(inStream); if (root.has("error")) { JsonNode errorNode = root.path("error"); logger.error( "Error when reading data from API: " + errorNode.path("info").asText("DESCRIPTION MISSING") + " [" + errorNode.path("code").asText("UNKNOWN ERROR CODE") + "]"); } // fall through: maybe there are some entities anyway JsonNode entities = root.path("entities"); for (JsonNode entityNode : entities) { if (!entityNode.has("missing")) { try { JacksonTermedStatementDocument ed = mapper.treeToValue(entityNode, JacksonTermedStatementDocument.class); ed.setSiteIri(this.siteIri); if (siteKey == null) { result.put(ed.getEntityId().getId(), ed); } else { if (ed instanceof JacksonItemDocument && ((JacksonItemDocument) ed).getSiteLinks().containsKey(siteKey)) { result.put(((JacksonItemDocument) ed).getSiteLinks().get(siteKey).getPageTitle(), ed); } } } catch (JsonProcessingException e) { logger.error("Error when reading JSON for entity " + entityNode.path("id").asText("UNKNOWN") + ": " + e.toString()); } } } } catch (IOException e) { logger.error("Could not retrieve data from " + url + ". Error:\n" + e.toString()); } return result; }
From source file:io.github.retz.web.WebConsole.java
public WebConsole(ServerConfiguration config) { if (config.isTLS()) { LOG.info(// w ww.ja v a2s . c o m "HTTPS enabled. Keystore file={}, keystore pass={} chars, Truststore file={}, Truststorepass={} chars", config.getKeystoreFile(), config.getKeystorePass().length(), config.getTruststoreFile(), "(not printed)"); secure(config.getKeystoreFile(), config.getKeystorePass(), config.getTruststoreFile(), config.getTruststorePass()); } else { LOG.info("HTTPS disabled. Scheme: {}", config.getUri().getScheme()); } port(config.getUri().getPort()); ipAddress(config.getUri().getHost()); staticFileLocation("/public"); before((req, res) -> { res.header("Server", RetzScheduler.HTTP_SERVER_NAME); String resource; if (req.raw().getQueryString() != null) { resource = new StringBuilder().append(new URI(req.url()).getPath()).append("?") .append(req.raw().getQueryString()).toString(); } else { resource = new URI(req.url()).getPath(); } LOG.info("{} {} from {} {}", req.requestMethod(), resource, req.ip(), req.userAgent()); // TODO: authenticator must be per each user and single admin user Optional<Authenticator> adminAuthenticator = Optional.ofNullable(config.getAuthenticator()); if (!adminAuthenticator.isPresent()) { // No authentication required return; } String verb = req.requestMethod(); String md5 = req.headers("content-md5"); if (md5 == null) { md5 = ""; } String date = req.headers("date"); LOG.debug("req={}, res={}, resource=", req, res, resource); // These don't require authentication to simplify operation if (NO_AUTH_PAGES.contains(resource)) { return; } Optional<AuthHeader> authHeaderValue = getAuthInfo(req); if (!authHeaderValue.isPresent()) { halt(401, "Bad Authorization header: " + req.headers(AuthHeader.AUTHORIZATION)); } Authenticator authenticator; if (adminAuthenticator.get().getKey().equals(authHeaderValue.get().key())) { // Admin authenticator = adminAuthenticator.get(); } else { // Not admin Optional<User> u = Database.getInstance().getUser(authHeaderValue.get().key()); if (!u.isPresent()) { halt(403, "No such user"); } if (config.authenticationEnabled()) { authenticator = new HmacSHA256Authenticator(u.get().keyId(), u.get().secret()); } else { authenticator = new NoopAuthenticator(u.get().keyId()); } } if (!authenticator.authenticate(verb, md5, date, resource, authHeaderValue.get().key(), authHeaderValue.get().signature())) { String string2sign = authenticator.string2sign(verb, md5, date, resource); if (LOG.isDebugEnabled()) { LOG.debug("Auth failed. Calculated signature={}, Given signature={}", authenticator.signature(verb, md5, date, resource), authHeaderValue.get().signature()); } halt(401, "Authentication failed. String to sign: " + string2sign); } }); after((req, res) -> { LOG.debug("{} {} {} {} from {} {}", res.raw().getStatus(), req.requestMethod(), req.url(), req.raw().getQueryString(), req.ip(), req.userAgent()); }); exception(JobNotFoundException.class, (exception, request, response) -> { LOG.debug("Exception: {}", exception.toString(), exception); response.status(404); ErrorResponse errorResponse = new ErrorResponse(exception.toString()); try { response.body(MAPPER.writeValueAsString(errorResponse)); } catch (JsonProcessingException e) { LOG.error(e.toString(), e); response.body(e.toString()); } }); // APIs to be in vanilla HTTP get("/ping", (req, res) -> "OK"); get("/status", WebConsole::status); // TODO: XXX: validate application owner at ALL job-related APIs // /jobs GET -> list get(ListJobRequest.resourcePattern(), (req, res) -> { Optional<AuthHeader> authHeaderValue = getAuthInfo(req); LOG.debug("list jobs owned by {}", authHeaderValue.get().key()); ListJobResponse listJobResponse = WebConsole.list(authHeaderValue.get().key(), -1); listJobResponse.ok(); res.status(200); res.type("application/json"); return MAPPER.writeValueAsString(listJobResponse); }); // /job PUT -> schedule, GET -> get-job, DELETE -> kill get(GetJobRequest.resourcePattern(), JobRequestRouter::getJob); // Get a file get(GetFileRequest.resourcePattern(), JobRequestRouter::getFile); // Get file list get(ListFilesRequest.resourcePattern(), JobRequestRouter::getDir); post(ScheduleRequest.resourcePattern(), WebConsole::schedule); delete(KillRequest.resourcePattern(), (req, res) -> { LOG.debug("kill", req.params(":id")); int id = Integer.parseInt(req.params(":id")); // or 400 when failed? WebConsole.kill(id); res.status(200); KillResponse response = new KillResponse(); response.ok(); return MAPPER.writeValueAsString(response); }); // /apps GET -> list-app get(ListAppRequest.resourcePattern(), (req, res) -> { Optional<AuthHeader> authHeaderValue = getAuthInfo(req); LOG.info("Listing all apps owned by {}", authHeaderValue.get().key()); ListAppResponse response = new ListAppResponse(Applications.getAll(authHeaderValue.get().key())); response.ok(); return MAPPER.writeValueAsString(response); }); // /app PUT -> load, GET -> get-app, DELETE -> unload-app put(LoadAppRequest.resourcePattern(), (req, res) -> { LOG.debug(LoadAppRequest.resourcePattern()); Optional<AuthHeader> authHeaderValue = getAuthInfo(req); res.type("application/json"); // TODO: check key from Authorization header matches a key in Application object LoadAppRequest loadAppRequest = MAPPER.readValue(req.bodyAsBytes(), LoadAppRequest.class); LOG.debug("app (id={}, owner={}), requested by {}", loadAppRequest.application().getAppid(), loadAppRequest.application().getOwner(), authHeaderValue.get().key()); // Compare application owner and requester validateOwner(req, loadAppRequest.application()); if (!(loadAppRequest.application().container() instanceof DockerContainer)) { if (loadAppRequest.application().getUser().isPresent() && loadAppRequest.application().getUser().get().equals("root")) { res.status(400); return MAPPER.writeValueAsString( new ErrorResponse("root user is only allowed with Docker container")); } } Application app = loadAppRequest.application(); LOG.info("Registering application name={} owner={}", app.getAppid(), app.getOwner()); boolean result = Applications.load(app); if (result) { res.status(200); LoadAppResponse response = new LoadAppResponse(); response.ok(); return MAPPER.writeValueAsString(response); } else { res.status(400); return MAPPER.writeValueAsString(new ErrorResponse("cannot load application")); } }); get(GetAppRequest.resourcePattern(), (req, res) -> { LOG.debug(LoadAppRequest.resourcePattern()); Optional<AuthHeader> authHeaderValue = getAuthInfo(req); String appname = req.params(":name"); LOG.debug("deleting app {} requested by {}", appname, authHeaderValue.get().key()); Optional<Application> maybeApp = Applications.get(appname); res.type("application/json"); if (maybeApp.isPresent()) { // Compare application owner and requester validateOwner(req, maybeApp.get()); res.status(200); GetAppResponse getAppResponse = new GetAppResponse(maybeApp.get()); getAppResponse.ok(); return MAPPER.writeValueAsString(getAppResponse); } else { ErrorResponse response = new ErrorResponse("No such application: " + appname); res.status(404); return MAPPER.writeValueAsString(response); } }); delete(UnloadAppRequest.resourcePattern(), (req, res) -> { String appname = req.params(":name"); LOG.warn("deleting app {} (This API is deprecated)", appname); WebConsole.unload(appname); UnloadAppResponse response = new UnloadAppResponse(); response.ok(); return MAPPER.writeValueAsString(response); }); init(); }
From source file:com.streamsets.datacollector.event.handler.remote.RemoteDataCollector.java
private String getSourceOffset(String pipelineId, Map<String, String> offset) { SourceOffset sourceOffset = new SourceOffset(SourceOffset.CURRENT_VERSION, offset); try {//from w w w.j av a 2s . co m return ObjectMapperFactory.get().writeValueAsString(new SourceOffsetJson(sourceOffset)); } catch (JsonProcessingException e) { throw new IllegalStateException( Utils.format("Failed to fetch source offset for pipeline: {} due to error: {}", pipelineId, e.toString()), e); } }
From source file:com.rusticisoftware.tincan.RemoteLRS.java
@Override public StatementsResultLRSResponse saveStatements(List<Statement> statements) { StatementsResultLRSResponse lrsResponse = new StatementsResultLRSResponse(); if (statements.size() == 0) { lrsResponse.setSuccess(true);//from w ww. j a v a 2 s. c o m return lrsResponse; } ArrayNode rootNode = Mapper.getInstance().createArrayNode(); for (Statement statement : statements) { rootNode.add(statement.toJSONNode(version)); } lrsResponse.setRequest(new HTTPRequest()); lrsResponse.getRequest().setResource("statements"); lrsResponse.getRequest().setMethod(HttpMethods.POST); lrsResponse.getRequest().setContentType("application/json"); try { lrsResponse.getRequest().setContent(Mapper.getWriter(this.usePrettyJSON()).writeValueAsBytes(rootNode)); } catch (JsonProcessingException ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); return lrsResponse; } HTTPResponse response = makeSyncRequest(lrsResponse.getRequest()); int status = response.getStatus(); lrsResponse.setResponse(response); if (status == 200) { lrsResponse.setSuccess(true); lrsResponse.setContent(new StatementsResult()); try { Iterator it = Mapper.getInstance().readValue(response.getContent(), ArrayNode.class).elements(); for (int i = 0; it.hasNext(); ++i) { lrsResponse.getContent().getStatements().add(statements.get(i)); lrsResponse.getContent().getStatements().get(i) .setId(UUID.fromString(((JsonNode) it.next()).textValue())); } } catch (Exception ex) { lrsResponse.setErrMsg("Exception: " + ex.toString()); lrsResponse.setSuccess(false); } } else { lrsResponse.setSuccess(false); } return lrsResponse; }
From source file:io.github.retz.db.Database.java
public void updateJobs(List<Job> list) { try (Connection conn = dataSource.getConnection()) { conn.setAutoCommit(false);/* ww w .j a v a 2s . c o m*/ Jobs jobs = new Jobs(conn, MAPPER); for (Job job : list) { jobs.updateJob(job); } conn.commit(); } catch (JsonProcessingException e) { LOG.error(e.toString()); } catch (SQLException e) { LOG.error(e.toString()); } }
From source file:com.streamsets.datacollector.execution.runner.cluster.ClusterRunner.java
@VisibleForTesting void validateAndSetStateTransition(PipelineStatus toStatus, String message, Map<String, Object> attributes) throws PipelineStoreException, PipelineRunnerException { Utils.checkState(attributes != null, "Attributes cannot be set to null"); PipelineState fromState = getState(); if (fromState.getStatus() == toStatus && toStatus != PipelineStatus.STARTING) { LOG.debug(//from w ww . j a va2s . c o m Utils.format("Ignoring status '{}' as this is same as current status", fromState.getStatus())); } else { PipelineState pipelineState; synchronized (this) { fromState = getState(); checkState(VALID_TRANSITIONS.get(fromState.getStatus()).contains(toStatus), ContainerError.CONTAINER_0102, fromState.getStatus(), toStatus); long nextRetryTimeStamp = fromState.getNextRetryTimeStamp(); int retryAttempt = fromState.getRetryAttempt(); if (toStatus == PipelineStatus.RUN_ERROR && shouldRetry) { toStatus = PipelineStatus.RETRY; checkState(VALID_TRANSITIONS.get(fromState.getStatus()).contains(toStatus), ContainerError.CONTAINER_0102, fromState.getStatus(), toStatus); } if (toStatus == PipelineStatus.RETRY && fromState.getStatus() != PipelineStatus.CONNECTING) { retryAttempt = fromState.getRetryAttempt() + 1; if (retryAttempt > maxRetries && maxRetries != -1) { LOG.info("Retry attempt '{}' is greater than max no of retries '{}'", retryAttempt, maxRetries); toStatus = PipelineStatus.RUN_ERROR; retryAttempt = 0; nextRetryTimeStamp = 0; } else { nextRetryTimeStamp = RetryUtils.getNextRetryTimeStamp(retryAttempt, getState().getTimeStamp()); long delay = 0; long currentTime = System.currentTimeMillis(); if (nextRetryTimeStamp > currentTime) { delay = nextRetryTimeStamp - currentTime; } retryFuture = scheduleForRetries(runnerExecutor, delay); } } else if (!toStatus.isActive()) { retryAttempt = 0; nextRetryTimeStamp = 0; } ObjectMapper objectMapper = ObjectMapperFactory.get(); String metricsJSONStr = null; if (!toStatus.isActive() || toStatus == PipelineStatus.DISCONNECTED) { Object metrics = getMetrics(); if (metrics != null) { try { metricsJSONStr = objectMapper.writer().writeValueAsString(metrics); } catch (JsonProcessingException e) { throw new PipelineStoreException(ContainerError.CONTAINER_0210, e.toString(), e); } } if (metricsJSONStr == null) { metricsJSONStr = getState().getMetrics(); } } pipelineState = pipelineStateStore.saveState(user, name, rev, toStatus, message, attributes, getState().getExecutionMode(), metricsJSONStr, retryAttempt, nextRetryTimeStamp); } // This should be out of sync block if (eventListenerManager != null) { eventListenerManager.broadcastStateChange(fromState, pipelineState, ThreadUsage.CLUSTER); } } }
From source file:org.metis.sql.SqlJob.java
/** * Polls the DB and notifies clients of a change in the DB or a fatal error. * //w ww.j av a 2s. c om * @return * @throws Exception */ private String pollDB() throws Exception { SqlResult sqlResult = null; try { // execute the sql statement. if a sqlResult was not returned, // then an error occurred and this job must be considered // defunct. if ((sqlResult = sqlStmnt.execute(getlParams())) == null) { // execute will have logged the necessary debug/error info. // notify all subscribed clients, that an error has occurred // and that this job is being stopped LOG.error(getThreadName() + ":ERROR, execute did not return a sqlResult object"); sendInternalServerError(""); throw new Exception("execute returns null sqlResult"); } // sqlResult was returned, but it may not contain a result set List<Map<String, Object>> listMap = sqlResult.getResultSet(); String jsonOutput = null; if (listMap == null || listMap.isEmpty()) { LOG.trace(getThreadName() + ":sqlResult did not contain a result set"); } else { // convert the result set to a json object jsonOutput = Utils.generateJson(listMap); if (LOG.isTraceEnabled()) { if (jsonOutput.length() > 100) { LOG.trace(getThreadName() + ": first 100 bytes of acquired result set = " + jsonOutput.substring(0, 100)); } else { LOG.trace(getThreadName() + ": acquired this result set - " + jsonOutput); } } } // get the digital signature of the json object (if any) that // represents the result set String dSign = (jsonOutput != null) ? getHashOf(jsonOutput) : WS_DFLT_SIGNATURE; LOG.trace(getThreadName() + ": acquired digital signature = " + dSign); LOG.trace(getThreadName() + ": current digital signature = " + getDigitalSignature()); // determine if a change has occurred if (getDigitalSignature() == null) { // first time, so just update the current digital signature setDigitalSignature(dSign); } else if (!dSign.equals(getDigitalSignature())) { // update the current digital signature setDigitalSignature(dSign); // ... and send the notification LOG.debug(getThreadName() + ": sending notification"); sendChangeNotification(dSign); return getDigitalSignature(); } } catch (JsonProcessingException exc) { LOG.error(getThreadName() + ":ERROR, caught this " + "JsonProcessingException while trying to gen json " + "message: " + exc.toString()); LOG.error(getThreadName() + ": exception stack trace follows:"); dumpStackTrace(exc.getStackTrace()); if (exc.getCause() != null) { LOG.error(getThreadName() + ": Caused by " + exc.getCause().toString()); LOG.error(getThreadName() + ": causing exception stack trace follows:"); dumpStackTrace(exc.getCause().getStackTrace()); } sendInternalServerError(""); throw exc; } catch (Exception exc) { LOG.error(getThreadName() + ":ERROR, caught this " + "Exception while trying to gen json " + "message: " + exc.toString()); LOG.error(getThreadName() + ": exception stack trace follows:"); dumpStackTrace(exc.getStackTrace()); if (exc.getCause() != null) { LOG.error(getThreadName() + ": Caused by " + exc.getCause().toString()); LOG.error(getThreadName() + ": causing exception stack trace follows:"); dumpStackTrace(exc.getCause().getStackTrace()); } sendInternalServerError(""); throw exc; } finally { if (sqlResult != null) { SqlResult.enqueue(sqlResult); } } return null; }
From source file:com.dnanexus.DXHTTPRequest.java
/** * Issues a request against the specified resource and returns either the text of the response * or the parsed JSON of the response (depending on whether parseResponse is set). * * @throws DXAPIException If the server returns a complete response with an HTTP status code * other than 200 (OK).//www.j a v a 2s . co m * @throws DXHTTPException If an error occurs while making the HTTP request or obtaining the * response (includes HTTP protocol errors). * @throws InternalError If the server returns an HTTP status code 500 and the environment * specifies that retries are disabled. * @throws ServiceUnavailableException If the server returns an HTTP status code 503 and * indicates that the client should retry the request at a later time, and the * environment specifies that retries are disabled. */ private ParsedResponse requestImpl(String resource, String data, boolean parseResponse, RetryStrategy retryStrategy) { HttpPost request = new HttpPost(apiserver + resource); if (securityContext == null || securityContext.isNull()) { throw new DXHTTPException(new IOException("No security context was set")); } request.setHeader("Content-Type", "application/json"); request.setHeader("Connection", "close"); request.setHeader("Authorization", securityContext.get("auth_token_type").textValue() + " " + securityContext.get("auth_token").textValue()); request.setEntity(new StringEntity(data, Charset.forName("UTF-8"))); // Retry with exponential backoff int timeoutSeconds = 1; int attempts = 0; while (true) { Integer statusCode = null; String requestId = ""; // This guarantees that we get at least one iteration around this loop before running // out of retries, so we can check at the bottom of the loop instead of the top. assert NUM_RETRIES > 0; // By default, our conservative strategy is to retry if the route permits it. Later we // may update this to unconditionally retry if we can definitely determine that the // server never saw the request. boolean retryRequest = (retryStrategy == RetryStrategy.SAFE_TO_RETRY); int retryAfterSeconds = 60; try { // In this block, any IOException will cause the request to be retried (up to a // total of NUM_RETRIES retries). RuntimeException (including DXAPIException) // instances are not caught and will immediately return control to the caller. // TODO: distinguish between errors during connection init and socket errors while // sending or receiving data. The former can always be retried, but the latter can // only be retried if the request is idempotent. HttpResponse response = httpclient.execute(request); statusCode = response.getStatusLine().getStatusCode(); requestId = getHeader(response, "X-Request-ID"); HttpEntity entity = response.getEntity(); if (statusCode == null) { throw new DXHTTPException(); } else if (statusCode == HttpStatus.SC_OK) { // 200 OK byte[] value = EntityUtils.toByteArray(entity); int realLength = value.length; if (entity.getContentLength() >= 0 && realLength != entity.getContentLength()) { // Content length mismatch. Retry is possible (if the route permits it). throw new IOException("Received response of " + realLength + " bytes but Content-Length was " + entity.getContentLength()); } else if (parseResponse) { JsonNode responseJson = null; try { responseJson = DXJSON.parseJson(new String(value, "UTF-8")); } catch (JsonProcessingException e) { if (entity.getContentLength() < 0) { // content-length was not provided, and the JSON could not be // parsed. Retry (if the route permits it) since this is probably // just a streaming request that encountered a transient error. throw new IOException( "Content-length was not provided and the response JSON could not be parsed."); } // This is probably a real problem (the request // is complete but doesn't parse), so avoid // masking it as an IOException (which is // rethrown as DXHTTPException below). If it // comes up frequently we can revisit how these // should be handled. throw new RuntimeException("Request is of the correct length but is unparseable", e); } catch (IOException e) { // TODO: characterize what kinds of errors // DXJSON.parseJson can emit, determine how we can // get here and what to do about it. throw new RuntimeException(e); } return new ParsedResponse(null, responseJson); } else { return new ParsedResponse(new String(value, Charset.forName("UTF-8")), null); } } else if (statusCode < 500) { // 4xx errors should be considered not recoverable. String responseStr = EntityUtils.toString(entity); String errorType = null; String errorMessage = responseStr; try { JsonNode responseJson = DXJSON.parseJson(responseStr); JsonNode errorField = responseJson.get("error"); if (errorField != null) { JsonNode typeField = errorField.get("type"); if (typeField != null) { errorType = typeField.asText(); } JsonNode messageField = errorField.get("message"); if (messageField != null) { errorMessage = messageField.asText(); } } } catch (IOException e) { // Just fall back to reproducing the entire response // body. } logError(errorType + ": " + errorMessage + ". Code: " + Integer.toString(statusCode) + " Request ID: " + requestId); throw DXAPIException.getInstance(errorType, errorMessage, statusCode); } else { // Propagate 500 error to caller if (this.disableRetry && statusCode != 503) { logError("POST " + resource + ": " + statusCode + " Internal Server Error, try " + String.valueOf(attempts + 1) + "/" + NUM_RETRIES + " Request ID: " + requestId); throw new InternalErrorException("Internal Server Error", statusCode); } // If retries enabled, 500 InternalError should get retried unconditionally retryRequest = true; if (statusCode == 503) { Header retryAfterHeader = response.getFirstHeader("retry-after"); // Consume the response to avoid leaking resources EntityUtils.consume(entity); if (retryAfterHeader != null) { try { retryAfterSeconds = Integer.parseInt(retryAfterHeader.getValue()); } catch (NumberFormatException e) { // Just fall back to the default } } throw new ServiceUnavailableException("503 Service Unavailable", statusCode, retryAfterSeconds); } throw new IOException(EntityUtils.toString(entity)); } } catch (ServiceUnavailableException e) { int secondsToWait = retryAfterSeconds; if (this.disableRetry) { logError("POST " + resource + ": 503 Service Unavailable, suggested wait " + secondsToWait + " seconds" + ". Request ID: " + requestId); throw e; } // Retries due to 503 Service Unavailable and Retry-After do NOT count against the // allowed number of retries. logError("POST " + resource + ": 503 Service Unavailable, waiting for " + Integer.toString(secondsToWait) + " seconds" + " Request ID: " + requestId); sleep(secondsToWait); continue; } catch (IOException e) { // Note, this catches both exceptions directly thrown from httpclient.execute (e.g. // no connectivity to server) and exceptions thrown by our code above after parsing // the response. logError(errorMessage("POST", resource, e.toString(), timeoutSeconds, attempts + 1, NUM_RETRIES)); if (attempts == NUM_RETRIES || !retryRequest) { if (statusCode == null) { throw new DXHTTPException(); } throw new InternalErrorException("Maximum number of retries reached, or unsafe to retry", statusCode); } } assert attempts < NUM_RETRIES; assert retryRequest; attempts++; // The number of failed attempts is now no more than NUM_RETRIES, and the total number // of attempts allowed is NUM_RETRIES + 1 (the first attempt, plus up to NUM_RETRIES // retries). So there is at least one more retry left; sleep before we retry. assert attempts <= NUM_RETRIES; sleep(timeoutSeconds); timeoutSeconds *= 2; } }