use of org.apache.camel.AsyncCallback in project camel by apache.
the class AbstractRestProcessor method processApproval.
final void processApproval(final Exchange exchange, final AsyncCallback callback) throws SalesforceException {
final TypeConverter converter = exchange.getContext().getTypeConverter();
final ApprovalRequest approvalRequestFromHeader = getParameter(SalesforceEndpointConfig.APPROVAL, exchange, IGNORE_BODY, IS_OPTIONAL, ApprovalRequest.class);
final boolean requestGivenInHeader = approvalRequestFromHeader != null;
// find if there is a ApprovalRequest as `approval` in the message header
final ApprovalRequest approvalHeader = Optional.ofNullable(approvalRequestFromHeader).orElse(new ApprovalRequest());
final Message incomingMessage = exchange.getIn();
final Map<String, Object> incomingHeaders = incomingMessage.getHeaders();
final boolean requestGivenInParametersInHeader = processApprovalHeaderValues(approvalHeader, incomingHeaders);
final boolean nothingInheader = !requestGivenInHeader && !requestGivenInParametersInHeader;
final Object approvalBody = incomingMessage.getBody();
final boolean bodyIsIterable = approvalBody instanceof Iterable;
final boolean bodyIsIterableButEmpty = bodyIsIterable && !((Iterable) approvalBody).iterator().hasNext();
// body contains nothing of interest if it's null, holds an empty iterable or cannot be converted to
// ApprovalRequest
final boolean nothingInBody = !(approvalBody != null && !bodyIsIterableButEmpty);
// we found nothing in the headers or the body
if (nothingInheader && nothingInBody) {
throw new SalesforceException("Missing " + SalesforceEndpointConfig.APPROVAL + " parameter in header or ApprovalRequest or List of ApprovalRequests body", 0);
}
// let's try to resolve the request body to send
final ApprovalRequests requestsBody;
if (nothingInBody) {
// nothing in body use the header values only
requestsBody = new ApprovalRequests(approvalHeader);
} else if (bodyIsIterable) {
// multiple ApprovalRequests are found
final Iterable<?> approvalRequests = (Iterable<?>) approvalBody;
// use header values as template and apply them to the body
final List<ApprovalRequest> requests = StreamSupport.stream(approvalRequests.spliterator(), false).map(value -> converter.convertTo(ApprovalRequest.class, value)).map(request -> request.applyTemplate(approvalHeader)).collect(Collectors.toList());
requestsBody = new ApprovalRequests(requests);
} else {
// we've looked at the body, and are expecting to see something resembling ApprovalRequest in there
// but lets see if that is so
final ApprovalRequest given = converter.tryConvertTo(ApprovalRequest.class, approvalBody);
final ApprovalRequest request = Optional.ofNullable(given).orElse(new ApprovalRequest()).applyTemplate(approvalHeader);
requestsBody = new ApprovalRequests(request);
}
final InputStream request = getRequestStream(requestsBody);
restClient.approval(request, (response, exception) -> processResponse(exchange, response, exception, callback));
}
use of org.apache.camel.AsyncCallback in project camel by apache.
the class NettyProducer method processWithConnectedChannel.
public void processWithConnectedChannel(final Exchange exchange, final BodyReleaseCallback callback, final ChannelFuture channelFuture, final Object body) {
// remember channel so we can reuse it
final Channel channel = channelFuture.channel();
if (getConfiguration().isReuseChannel() && exchange.getProperty(NettyConstants.NETTY_CHANNEL) == null) {
exchange.setProperty(NettyConstants.NETTY_CHANNEL, channel);
// and defer closing the channel until we are done routing the exchange
exchange.addOnCompletion(new SynchronizationAdapter() {
@Override
public void onComplete(Exchange exchange) {
// should channel be closed after complete?
Boolean close;
if (ExchangeHelper.isOutCapable(exchange)) {
close = exchange.getOut().getHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class);
} else {
close = exchange.getIn().getHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class);
}
// should we disconnect, the header can override the configuration
boolean disconnect = getConfiguration().isDisconnect();
if (close != null) {
disconnect = close;
}
if (disconnect) {
LOG.trace("Closing channel {} as routing the Exchange is done", channel);
NettyHelper.close(channel);
}
releaseChannel(channelFuture);
}
});
}
if (exchange.getIn().getHeader(NettyConstants.NETTY_REQUEST_TIMEOUT) != null) {
long timeoutInMs = exchange.getIn().getHeader(NettyConstants.NETTY_REQUEST_TIMEOUT, Long.class);
ChannelHandler oldHandler = channel.pipeline().get("timeout");
ReadTimeoutHandler newHandler = new ReadTimeoutHandler(timeoutInMs, TimeUnit.MILLISECONDS);
if (oldHandler == null) {
channel.pipeline().addBefore("handler", "timeout", newHandler);
} else {
channel.pipeline().replace(oldHandler, "timeout", newHandler);
}
}
//This will refer to original callback since netty will release body by itself
final AsyncCallback producerCallback;
if (configuration.isReuseChannel()) {
// use callback as-is because we should not put it back in the pool as NettyProducerCallback would do
// as when reuse channel is enabled it will put the channel back in the pool when exchange is done using on completion
producerCallback = callback.getOriginalCallback();
} else {
producerCallback = new NettyProducerCallback(channelFuture, callback.getOriginalCallback());
}
// setup state as attachment on the channel, so we can access the state later when needed
putState(channel, new NettyCamelState(producerCallback, exchange));
// here we need to setup the remote address information here
InetSocketAddress remoteAddress = null;
if (!isTcp()) {
remoteAddress = new InetSocketAddress(configuration.getHost(), configuration.getPort());
}
// write body
NettyHelper.writeBodyAsync(LOG, channel, remoteAddress, body, exchange, new ChannelFutureListener() {
public void operationComplete(ChannelFuture channelFuture) throws Exception {
LOG.trace("Operation complete {}", channelFuture);
if (!channelFuture.isSuccess()) {
// no success then exit, (any exception has been handled by ClientChannelHandler#exceptionCaught)
return;
}
// if we do not expect any reply then signal callback to continue routing
if (!configuration.isSync()) {
try {
// should channel be closed after complete?
Boolean close;
if (ExchangeHelper.isOutCapable(exchange)) {
close = exchange.getOut().getHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class);
} else {
close = exchange.getIn().getHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class);
}
// should we disconnect, the header can override the configuration
boolean disconnect = getConfiguration().isDisconnect();
if (close != null) {
disconnect = close;
}
// we should not close if we are reusing the channel
if (!configuration.isReuseChannel() && disconnect) {
if (LOG.isTraceEnabled()) {
LOG.trace("Closing channel when complete at address: {}", getEndpoint().getConfiguration().getAddress());
}
NettyHelper.close(channel);
}
} finally {
// signal callback to continue routing
producerCallback.done(false);
}
}
}
});
}
use of org.apache.camel.AsyncCallback in project camel by apache.
the class ClientChannelHandler method exceptionCaught.
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (LOG.isTraceEnabled()) {
LOG.trace("Exception caught at Channel: " + ctx.channel(), cause);
}
if (exceptionHandled) {
// ignore subsequent exceptions being thrown
return;
}
exceptionHandled = true;
if (LOG.isDebugEnabled()) {
LOG.debug("Closing channel as an exception was thrown from Netty", cause);
}
Exchange exchange = getExchange(ctx);
AsyncCallback callback = getAsyncCallback(ctx);
// the state may not be set
if (exchange != null && callback != null) {
Throwable initialCause = exchange.getException();
if (initialCause != null && initialCause.getCause() == null) {
initialCause.initCause(cause);
} else {
// set the cause on the exchange
exchange.setException(cause);
}
// close channel in case an exception was thrown
NettyHelper.close(ctx.channel());
// signal callback
callback.done(false);
}
}
use of org.apache.camel.AsyncCallback in project camel by apache.
the class ClientChannelHandler method channelInactive.
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
if (LOG.isTraceEnabled()) {
LOG.trace("Channel closed: {}", ctx.channel());
}
Exchange exchange = getExchange(ctx);
AsyncCallback callback = getAsyncCallback(ctx);
// remove state
producer.removeState(ctx.channel());
// to keep track of open sockets
producer.getAllChannels().remove(ctx.channel());
// this channel is maybe closing graceful and the exchange is already done
// and if so we should not trigger an exception
boolean doneUoW = exchange.getUnitOfWork() == null;
NettyConfiguration configuration = producer.getConfiguration();
if (configuration.isSync() && !doneUoW && !messageReceived && !exceptionHandled) {
// To avoid call the callback.done twice
exceptionHandled = true;
// session was closed but no message received. This could be because the remote server had an internal error
// and could not return a response. We should count down to stop waiting for a response
String address = configuration != null ? configuration.getAddress() : "";
if (LOG.isDebugEnabled()) {
LOG.debug("Channel closed but no message received from address: {}", address);
}
// don't fail the exchange if we actually specify to disconnect
if (!configuration.isDisconnect()) {
exchange.setException(new CamelExchangeException("No response received from remote server: " + address, exchange));
}
// signal callback
callback.done(false);
}
// make sure the event can be processed by other handlers
super.channelInactive(ctx);
}
use of org.apache.camel.AsyncCallback in project camel by apache.
the class ClientChannelHandler method channelRead0.
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
messageReceived = true;
if (LOG.isTraceEnabled()) {
LOG.trace("Message received: {}", msg);
}
ChannelHandler handler = ctx.pipeline().get("timeout");
if (handler != null) {
LOG.trace("Removing timeout channel as we received message");
ctx.pipeline().remove(handler);
}
Exchange exchange = getExchange(ctx);
if (exchange == null) {
// we just ignore the received message as the channel is closed
return;
}
AsyncCallback callback = getAsyncCallback(ctx);
Message message;
try {
message = getResponseMessage(exchange, ctx, msg);
} catch (Exception e) {
exchange.setException(e);
callback.done(false);
return;
}
// set the result on either IN or OUT on the original exchange depending on its pattern
if (ExchangeHelper.isOutCapable(exchange)) {
exchange.setOut(message);
} else {
exchange.setIn(message);
}
try {
// should channel be closed after complete?
Boolean close;
if (ExchangeHelper.isOutCapable(exchange)) {
close = exchange.getOut().getHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class);
} else {
close = exchange.getIn().getHeader(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class);
}
// check the setting on the exchange property
if (close == null) {
close = exchange.getProperty(NettyConstants.NETTY_CLOSE_CHANNEL_WHEN_COMPLETE, Boolean.class);
}
// should we disconnect, the header can override the configuration
boolean disconnect = producer.getConfiguration().isDisconnect();
if (close != null) {
disconnect = close;
}
// we should not close if we are reusing the channel
if (!producer.getConfiguration().isReuseChannel() && disconnect) {
if (LOG.isTraceEnabled()) {
LOG.trace("Closing channel when complete at address: {}", producer.getConfiguration().getAddress());
}
NettyHelper.close(ctx.channel());
}
} finally {
// signal callback
callback.done(false);
}
}
Aggregations