use of javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR in project nakadi by zalando.
the class EventStreamController method streamEvents.
@RequestMapping(value = "/event-types/{name}/events", method = RequestMethod.GET)
public StreamingResponseBody streamEvents(@PathVariable("name") final String eventTypeName, @Nullable @RequestParam(value = "batch_limit", required = false) final Integer batchLimit, @Nullable @RequestParam(value = "stream_limit", required = false) final Integer streamLimit, @Nullable @RequestParam(value = "batch_flush_timeout", required = false) final Integer batchTimeout, @Nullable @RequestParam(value = "stream_timeout", required = false) final Integer streamTimeout, @Nullable @RequestParam(value = "stream_keep_alive_limit", required = false) final Integer streamKeepAliveLimit, @Nullable @RequestHeader(name = "X-nakadi-cursors", required = false) final String cursorsStr, final HttpServletRequest request, final HttpServletResponse response, final Client client) {
final String flowId = FlowIdUtils.peek();
return outputStream -> {
FlowIdUtils.push(flowId);
if (blacklistService.isConsumptionBlocked(eventTypeName, client.getClientId())) {
writeProblemResponse(response, outputStream, Problem.valueOf(Response.Status.FORBIDDEN, "Application or event type is blocked"));
return;
}
final AtomicBoolean connectionReady = closedConnectionsCrutch.listenForConnectionClose(request);
Counter consumerCounter = null;
EventStream eventStream = null;
List<ConnectionSlot> connectionSlots = ImmutableList.of();
final AtomicBoolean needCheckAuthorization = new AtomicBoolean(false);
LOG.info("[X-NAKADI-CURSORS] \"{}\" {}", eventTypeName, Optional.ofNullable(cursorsStr).orElse("-"));
try (Closeable ignore = eventTypeChangeListener.registerListener(et -> needCheckAuthorization.set(true), Collections.singletonList(eventTypeName))) {
final EventType eventType = eventTypeRepository.findByName(eventTypeName);
authorizeStreamRead(eventTypeName);
// validate parameters
final EventStreamConfig streamConfig = EventStreamConfig.builder().withBatchLimit(batchLimit).withStreamLimit(streamLimit).withBatchTimeout(batchTimeout).withStreamTimeout(streamTimeout).withStreamKeepAliveLimit(streamKeepAliveLimit).withEtName(eventTypeName).withConsumingClient(client).withCursors(getStreamingStart(eventType, cursorsStr)).withMaxMemoryUsageBytes(maxMemoryUsageBytes).build();
// acquire connection slots to limit the number of simultaneous connections from one client
if (featureToggleService.isFeatureEnabled(LIMIT_CONSUMERS_NUMBER)) {
final List<String> partitions = streamConfig.getCursors().stream().map(NakadiCursor::getPartition).collect(Collectors.toList());
connectionSlots = consumerLimitingService.acquireConnectionSlots(client.getClientId(), eventTypeName, partitions);
}
consumerCounter = metricRegistry.counter(metricNameFor(eventTypeName, CONSUMERS_COUNT_METRIC_NAME));
consumerCounter.inc();
final String kafkaQuotaClientId = getKafkaQuotaClientId(eventTypeName, client);
response.setStatus(HttpStatus.OK.value());
response.setHeader("Warning", "299 - nakadi - the Low-level API is deprecated and will " + "be removed from a future release. Please consider migrating to the Subscriptions API.");
response.setContentType("application/x-json-stream");
final EventConsumer eventConsumer = timelineService.createEventConsumer(kafkaQuotaClientId, streamConfig.getCursors());
final String bytesFlushedMetricName = MetricUtils.metricNameForLoLAStream(client.getClientId(), eventTypeName);
final Meter bytesFlushedMeter = this.streamMetrics.meter(bytesFlushedMetricName);
eventStream = eventStreamFactory.createEventStream(outputStream, eventConsumer, streamConfig, bytesFlushedMeter);
// Flush status code to client
outputStream.flush();
eventStream.streamEvents(connectionReady, () -> {
if (needCheckAuthorization.getAndSet(false)) {
authorizeStreamRead(eventTypeName);
}
});
} catch (final UnparseableCursorException e) {
LOG.debug("Incorrect syntax of X-nakadi-cursors header: {}. Respond with BAD_REQUEST.", e.getCursors(), e);
writeProblemResponse(response, outputStream, BAD_REQUEST, e.getMessage());
} catch (final NoSuchEventTypeException e) {
writeProblemResponse(response, outputStream, NOT_FOUND, "topic not found");
} catch (final NoConnectionSlotsException e) {
LOG.debug("Connection creation failed due to exceeding max connection count");
writeProblemResponse(response, outputStream, e.asProblem());
} catch (final NakadiException e) {
LOG.error("Error while trying to stream events.", e);
writeProblemResponse(response, outputStream, e.asProblem());
} catch (final InvalidCursorException e) {
writeProblemResponse(response, outputStream, PRECONDITION_FAILED, e.getMessage());
} catch (final AccessDeniedException e) {
writeProblemResponse(response, outputStream, FORBIDDEN, e.explain());
} catch (final Exception e) {
LOG.error("Error while trying to stream events. Respond with INTERNAL_SERVER_ERROR.", e);
writeProblemResponse(response, outputStream, INTERNAL_SERVER_ERROR, e.getMessage());
} finally {
connectionReady.set(false);
consumerLimitingService.releaseConnectionSlots(connectionSlots);
if (consumerCounter != null) {
consumerCounter.dec();
}
if (eventStream != null) {
eventStream.close();
}
try {
outputStream.flush();
} finally {
outputStream.close();
}
}
};
}
use of javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR in project component-runtime by Talend.
the class DocumentationResource method getDocumentation.
/**
* Returns an asciidoctor version of the documentation for the component represented by its identifier `id`.
*
* Format can be either asciidoc or html - if not it will fallback on asciidoc - and if html is selected you get
* a partial document.
*
* IMPORTANT: it is recommended to use asciidoc format and handle the conversion on your side if you can,
* the html flavor handles a limited set of the asciidoc syntax only like plain arrays, paragraph and titles.
*
* The documentation will likely be the family documentation but you can use anchors to access a particular
* component (_componentname_inlowercase).
*
* @param id the component identifier.
* @param language the expected language for the documentation (default to en if not found).
* @param format the expected format (asciidoc or html).
* @return the documentation for that component.
*/
@GET
@Path("component/{id}")
@Produces(MediaType.APPLICATION_JSON)
public DocumentationContent getDocumentation(@PathParam("id") final String id, @QueryParam("language") @DefaultValue("en") final String language, @QueryParam("format") @DefaultValue("asciidoc") final String format) {
final Locale locale = localeMapper.mapLocale(language);
final Container container = ofNullable(componentDao.findById(id)).map(meta -> manager.findPlugin(meta.getParent().getPlugin()).orElseThrow(() -> new WebApplicationException(Response.status(NOT_FOUND).entity(new ErrorPayload(ErrorDictionary.PLUGIN_MISSING, "No plugin '" + meta.getParent().getPlugin() + "'")).build()))).orElseThrow(() -> new WebApplicationException(Response.status(NOT_FOUND).entity(new ErrorPayload(ErrorDictionary.COMPONENT_MISSING, "No component '" + id + "'")).build()));
// rendering to html can be slow so do it lazily and once
DocumentationCache cache = container.get(DocumentationCache.class);
if (cache == null) {
synchronized (container) {
cache = container.get(DocumentationCache.class);
if (cache == null) {
cache = new DocumentationCache();
container.set(DocumentationCache.class, cache);
}
}
}
return cache.documentations.computeIfAbsent(new DocKey(id, language, format), key -> {
// todo: handle i18n properly, for now just fallback on not suffixed version and assume the dev put it
// in the comp
final String content = Stream.of("documentation_" + locale.getLanguage() + ".adoc", "documentation_" + language + ".adoc", "documentation.adoc").map(name -> container.getLoader().getResource("TALEND-INF/" + name)).filter(Objects::nonNull).findFirst().map(url -> {
try (final BufferedReader stream = new BufferedReader(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8))) {
return stream.lines().collect(joining("\n"));
} catch (final IOException e) {
throw new WebApplicationException(Response.status(INTERNAL_SERVER_ERROR).entity(new ErrorPayload(ErrorDictionary.UNEXPECTED, e.getMessage())).build());
}
}).map(value -> {
switch(format) {
case "html":
case "html5":
return adoc.toHtml(value);
case "asciidoc":
case "adoc":
default:
return value;
}
}).orElseThrow(() -> new WebApplicationException(Response.status(NOT_FOUND).entity(new ErrorPayload(ErrorDictionary.COMPONENT_MISSING, "No component '" + id + "'")).build()));
return new DocumentationContent(format, content);
});
}
Aggregations