From 8a04e3ed1b98bd3cf7a2a9233467b10b4562e7a5 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 2 Oct 2024 10:10:43 +0200 Subject: [PATCH 1/3] CAMEL-21300: camel-platform-http - Consumer should have option to control if writing response failing should cause Exchange to fail --- .../catalog/components/platform-http.json | 27 ++++++------- .../http/vertx/VertxPlatformHttpConsumer.java | 11 +++++- .../http/PlatformHttpEndpointConfigurer.java | 6 +++ .../http/PlatformHttpEndpointUriFactory.java | 3 +- .../platform/http/platform-http.json | 27 ++++++------- .../platform/http/PlatformHttpEndpoint.java | 20 +++++++--- .../PlatformHttpEndpointBuilderFactory.java | 38 +++++++++++++++++++ 7 files changed, 99 insertions(+), 33 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json index 5169f38a06378..ffca8a9a4311f 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json @@ -39,18 +39,19 @@ "cookiePath": { "index": 5, "kind": "parameter", "displayName": "Cookie Path", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "\/", "configurationClass": "org.apache.camel.component.platform.http.cookie.CookieConfiguration", "configurationField": "cookieConfiguration", "description": "Sets the URL path that must exist in the requested URL in order to send the Cookie." }, "cookieSameSite": { "index": 6, "kind": "parameter", "displayName": "Cookie Same Site", "group": "consumer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.cookie.CookieConfiguration.CookieSameSite", "enum": [ "STRICT", "LAX", "NONE" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Lax", "configurationClass": "org.apache.camel.component.platform.http.cookie.CookieConfiguration", "configurationField": "cookieConfiguration", "description": "Sets whether to prevent the browser from sending cookies along with cross-site requests." }, "cookieSecure": { "index": 7, "kind": "parameter", "displayName": "Cookie Secure", "group": "consumer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.platform.http.cookie.CookieConfiguration", "configurationField": "cookieConfiguration", "description": "Sets whether the cookie is only sent to the server with an encrypted request over HTTPS." }, - "httpMethodRestrict": { "index": 8, "kind": "parameter", "displayName": "Http Method Restrict", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "A comma separated list of HTTP methods to serve, e.g. GET,POST . If no methods are specified, all methods will be served." }, - "matchOnUriPrefix": { "index": 9, "kind": "parameter", "displayName": "Match On Uri Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether or not the consumer should try to find a target consumer by matching the URI prefix if no exact match is found." }, - "muteException": { "index": 10, "kind": "parameter", "displayName": "Mute Exception", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "If enabled and an Exchange failed processing on the consumer side the response's body won't contain the exception's stack trace." }, - "produces": { "index": 11, "kind": "parameter", "displayName": "Produces", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type this endpoint produces, such as application\/xml or application\/json." }, - "returnHttpRequestHeaders": { "index": 12, "kind": "parameter", "displayName": "Return Http Request Headers", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to include HTTP request headers (Accept, User-Agent, etc.) into HTTP response produced by this endpoint." }, - "useCookieHandler": { "index": 13, "kind": "parameter", "displayName": "Use Cookie Handler", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable the Cookie Handler that allows Cookie addition, expiry, and retrieval (currently only supported by camel-platform-http-vertx)" }, - "useStreaming": { "index": 14, "kind": "parameter", "displayName": "Use Streaming", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use streaming for large requests and responses (currently only supported by camel-platform-http-vertx)" }, - "bridgeErrorHandler": { "index": 15, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exceptionHandler": { "index": 16, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exchangePattern": { "index": 17, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, - "fileNameExtWhitelist": { "index": 18, "kind": "parameter", "displayName": "File Name Ext Whitelist", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "A comma or whitespace separated list of file extensions. Uploads having these extensions will be stored locally. Null value or asterisk () will allow all files." }, - "headerFilterStrategy": { "index": 19, "kind": "parameter", "displayName": "Header Filter Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HeaderFilterStrategy to filter headers to and from Camel message." }, - "platformHttpEngine": { "index": 20, "kind": "parameter", "displayName": "Platform Http Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.spi.PlatformHttpEngine", "deprecated": false, "autowired": false, "secret": false, "description": "An HTTP Server engine implementation to serve the requests of this endpoint." } + "handleWriteResponseError": { "index": 8, "kind": "parameter", "displayName": "Handle Write Response Error", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "When Camel is complete processing the message, and the HTTP server is writing response. This option controls whether Camel should catch any failure during writing response and store this on the Exchange, which allows onCompletion\/UnitOfWork to regard the Exchange as failed and have access to the caused exception from the HTTP server." }, + "httpMethodRestrict": { "index": 9, "kind": "parameter", "displayName": "Http Method Restrict", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "A comma separated list of HTTP methods to serve, e.g. GET,POST . If no methods are specified, all methods will be served." }, + "matchOnUriPrefix": { "index": 10, "kind": "parameter", "displayName": "Match On Uri Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether or not the consumer should try to find a target consumer by matching the URI prefix if no exact match is found." }, + "muteException": { "index": 11, "kind": "parameter", "displayName": "Mute Exception", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "If enabled and an Exchange failed processing on the consumer side the response's body won't contain the exception's stack trace." }, + "produces": { "index": 12, "kind": "parameter", "displayName": "Produces", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type this endpoint produces, such as application\/xml or application\/json." }, + "returnHttpRequestHeaders": { "index": 13, "kind": "parameter", "displayName": "Return Http Request Headers", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to include HTTP request headers (Accept, User-Agent, etc.) into HTTP response produced by this endpoint." }, + "useCookieHandler": { "index": 14, "kind": "parameter", "displayName": "Use Cookie Handler", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable the Cookie Handler that allows Cookie addition, expiry, and retrieval (currently only supported by camel-platform-http-vertx)" }, + "useStreaming": { "index": 15, "kind": "parameter", "displayName": "Use Streaming", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use streaming for large requests and responses (currently only supported by camel-platform-http-vertx)" }, + "bridgeErrorHandler": { "index": 16, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exceptionHandler": { "index": 17, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exchangePattern": { "index": 18, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "fileNameExtWhitelist": { "index": 19, "kind": "parameter", "displayName": "File Name Ext Whitelist", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "A comma or whitespace separated list of file extensions. Uploads having these extensions will be stored locally. Null value or asterisk () will allow all files." }, + "headerFilterStrategy": { "index": 20, "kind": "parameter", "displayName": "Header Filter Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HeaderFilterStrategy to filter headers to and from Camel message." }, + "platformHttpEngine": { "index": 21, "kind": "parameter", "displayName": "Platform Http Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.spi.PlatformHttpEngine", "deprecated": false, "autowired": false, "secret": false, "description": "An HTTP Server engine implementation to serve the requests of this endpoint." } } } diff --git a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java index 128885d8b43e5..1d8258632b25b 100644 --- a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java +++ b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java @@ -76,6 +76,7 @@ public class VertxPlatformHttpConsumer extends DefaultConsumer private final List> handlers; private final String fileNameExtWhitelist; private final boolean muteExceptions; + private final boolean handleWriteResponseError; private Set methods; private String path; private Route route; @@ -92,6 +93,7 @@ public VertxPlatformHttpConsumer(PlatformHttpEndpoint endpoint, this.fileNameExtWhitelist = endpoint.getFileNameExtWhitelist() == null ? null : endpoint.getFileNameExtWhitelist().toLowerCase(Locale.US); this.muteExceptions = endpoint.isMuteException(); + this.handleWriteResponseError = endpoint.isHandleWriteResponseError(); } @Override @@ -238,6 +240,13 @@ private void handleFailure(Exchange exchange, RoutingContext ctx, Throwable fail "Failed handling platform-http endpoint " + getEndpoint().getPath(), failure); ctx.fail(failure); + if (handleWriteResponseError && failure != null) { + Exception existing = exchange.getException(); + if (existing != null) { + failure.addSuppressed(existing); + } + exchange.setException(failure); + } handleExchangeComplete(exchange); } @@ -351,7 +360,7 @@ protected void populateAttachments(List uploads, Message message) { class VertxCookieHandler implements CookieHandler { - private RoutingContext routingContext; + private final RoutingContext routingContext; VertxCookieHandler(RoutingContext routingContext) { this.routingContext = routingContext; diff --git a/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpEndpointConfigurer.java b/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpEndpointConfigurer.java index 35052f63db2df..32e877f436752 100644 --- a/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpEndpointConfigurer.java +++ b/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpEndpointConfigurer.java @@ -44,6 +44,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj case "exchangePattern": target.setExchangePattern(property(camelContext, org.apache.camel.ExchangePattern.class, value)); return true; case "filenameextwhitelist": case "fileNameExtWhitelist": target.setFileNameExtWhitelist(property(camelContext, java.lang.String.class, value)); return true; + case "handlewriteresponseerror": + case "handleWriteResponseError": target.setHandleWriteResponseError(property(camelContext, boolean.class, value)); return true; case "headerfilterstrategy": case "headerFilterStrategy": target.setHeaderFilterStrategy(property(camelContext, org.apache.camel.spi.HeaderFilterStrategy.class, value)); return true; case "httpmethodrestrict": @@ -89,6 +91,8 @@ public Class getOptionType(String name, boolean ignoreCase) { case "exchangePattern": return org.apache.camel.ExchangePattern.class; case "filenameextwhitelist": case "fileNameExtWhitelist": return java.lang.String.class; + case "handlewriteresponseerror": + case "handleWriteResponseError": return boolean.class; case "headerfilterstrategy": case "headerFilterStrategy": return org.apache.camel.spi.HeaderFilterStrategy.class; case "httpmethodrestrict": @@ -135,6 +139,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) { case "exchangePattern": return target.getExchangePattern(); case "filenameextwhitelist": case "fileNameExtWhitelist": return target.getFileNameExtWhitelist(); + case "handlewriteresponseerror": + case "handleWriteResponseError": return target.isHandleWriteResponseError(); case "headerfilterstrategy": case "headerFilterStrategy": return target.getHeaderFilterStrategy(); case "httpmethodrestrict": diff --git a/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpEndpointUriFactory.java b/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpEndpointUriFactory.java index 481e5e0d895ba..0caa0f240ff92 100644 --- a/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpEndpointUriFactory.java +++ b/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpEndpointUriFactory.java @@ -23,7 +23,7 @@ public class PlatformHttpEndpointUriFactory extends org.apache.camel.support.com private static final Set SECRET_PROPERTY_NAMES; private static final Set MULTI_VALUE_PREFIXES; static { - Set props = new HashSet<>(21); + Set props = new HashSet<>(22); props.add("bridgeErrorHandler"); props.add("consumes"); props.add("cookieDomain"); @@ -35,6 +35,7 @@ public class PlatformHttpEndpointUriFactory extends org.apache.camel.support.com props.add("exceptionHandler"); props.add("exchangePattern"); props.add("fileNameExtWhitelist"); + props.add("handleWriteResponseError"); props.add("headerFilterStrategy"); props.add("httpMethodRestrict"); props.add("matchOnUriPrefix"); diff --git a/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json b/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json index 5169f38a06378..ffca8a9a4311f 100644 --- a/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json +++ b/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json @@ -39,18 +39,19 @@ "cookiePath": { "index": 5, "kind": "parameter", "displayName": "Cookie Path", "group": "consumer", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "\/", "configurationClass": "org.apache.camel.component.platform.http.cookie.CookieConfiguration", "configurationField": "cookieConfiguration", "description": "Sets the URL path that must exist in the requested URL in order to send the Cookie." }, "cookieSameSite": { "index": 6, "kind": "parameter", "displayName": "Cookie Same Site", "group": "consumer", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.cookie.CookieConfiguration.CookieSameSite", "enum": [ "STRICT", "LAX", "NONE" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "Lax", "configurationClass": "org.apache.camel.component.platform.http.cookie.CookieConfiguration", "configurationField": "cookieConfiguration", "description": "Sets whether to prevent the browser from sending cookies along with cross-site requests." }, "cookieSecure": { "index": 7, "kind": "parameter", "displayName": "Cookie Secure", "group": "consumer", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.platform.http.cookie.CookieConfiguration", "configurationField": "cookieConfiguration", "description": "Sets whether the cookie is only sent to the server with an encrypted request over HTTPS." }, - "httpMethodRestrict": { "index": 8, "kind": "parameter", "displayName": "Http Method Restrict", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "A comma separated list of HTTP methods to serve, e.g. GET,POST . If no methods are specified, all methods will be served." }, - "matchOnUriPrefix": { "index": 9, "kind": "parameter", "displayName": "Match On Uri Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether or not the consumer should try to find a target consumer by matching the URI prefix if no exact match is found." }, - "muteException": { "index": 10, "kind": "parameter", "displayName": "Mute Exception", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "If enabled and an Exchange failed processing on the consumer side the response's body won't contain the exception's stack trace." }, - "produces": { "index": 11, "kind": "parameter", "displayName": "Produces", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type this endpoint produces, such as application\/xml or application\/json." }, - "returnHttpRequestHeaders": { "index": 12, "kind": "parameter", "displayName": "Return Http Request Headers", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to include HTTP request headers (Accept, User-Agent, etc.) into HTTP response produced by this endpoint." }, - "useCookieHandler": { "index": 13, "kind": "parameter", "displayName": "Use Cookie Handler", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable the Cookie Handler that allows Cookie addition, expiry, and retrieval (currently only supported by camel-platform-http-vertx)" }, - "useStreaming": { "index": 14, "kind": "parameter", "displayName": "Use Streaming", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use streaming for large requests and responses (currently only supported by camel-platform-http-vertx)" }, - "bridgeErrorHandler": { "index": 15, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exceptionHandler": { "index": 16, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "exchangePattern": { "index": 17, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, - "fileNameExtWhitelist": { "index": 18, "kind": "parameter", "displayName": "File Name Ext Whitelist", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "A comma or whitespace separated list of file extensions. Uploads having these extensions will be stored locally. Null value or asterisk () will allow all files." }, - "headerFilterStrategy": { "index": 19, "kind": "parameter", "displayName": "Header Filter Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HeaderFilterStrategy to filter headers to and from Camel message." }, - "platformHttpEngine": { "index": 20, "kind": "parameter", "displayName": "Platform Http Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.spi.PlatformHttpEngine", "deprecated": false, "autowired": false, "secret": false, "description": "An HTTP Server engine implementation to serve the requests of this endpoint." } + "handleWriteResponseError": { "index": 8, "kind": "parameter", "displayName": "Handle Write Response Error", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "When Camel is complete processing the message, and the HTTP server is writing response. This option controls whether Camel should catch any failure during writing response and store this on the Exchange, which allows onCompletion\/UnitOfWork to regard the Exchange as failed and have access to the caused exception from the HTTP server." }, + "httpMethodRestrict": { "index": 9, "kind": "parameter", "displayName": "Http Method Restrict", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "A comma separated list of HTTP methods to serve, e.g. GET,POST . If no methods are specified, all methods will be served." }, + "matchOnUriPrefix": { "index": 10, "kind": "parameter", "displayName": "Match On Uri Prefix", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether or not the consumer should try to find a target consumer by matching the URI prefix if no exact match is found." }, + "muteException": { "index": 11, "kind": "parameter", "displayName": "Mute Exception", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "If enabled and an Exchange failed processing on the consumer side the response's body won't contain the exception's stack trace." }, + "produces": { "index": 12, "kind": "parameter", "displayName": "Produces", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The content type this endpoint produces, such as application\/xml or application\/json." }, + "returnHttpRequestHeaders": { "index": 13, "kind": "parameter", "displayName": "Return Http Request Headers", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to include HTTP request headers (Accept, User-Agent, etc.) into HTTP response produced by this endpoint." }, + "useCookieHandler": { "index": 14, "kind": "parameter", "displayName": "Use Cookie Handler", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to enable the Cookie Handler that allows Cookie addition, expiry, and retrieval (currently only supported by camel-platform-http-vertx)" }, + "useStreaming": { "index": 15, "kind": "parameter", "displayName": "Use Streaming", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Whether to use streaming for large requests and responses (currently only supported by camel-platform-http-vertx)" }, + "bridgeErrorHandler": { "index": 16, "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exceptionHandler": { "index": 17, "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "autowired": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, + "exchangePattern": { "index": 18, "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut" ], "deprecated": false, "autowired": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." }, + "fileNameExtWhitelist": { "index": 19, "kind": "parameter", "displayName": "File Name Ext Whitelist", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "A comma or whitespace separated list of file extensions. Uploads having these extensions will be stored locally. Null value or asterisk () will allow all files." }, + "headerFilterStrategy": { "index": 20, "kind": "parameter", "displayName": "Header Filter Strategy", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom HeaderFilterStrategy to filter headers to and from Camel message." }, + "platformHttpEngine": { "index": 21, "kind": "parameter", "displayName": "Platform Http Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.spi.PlatformHttpEngine", "deprecated": false, "autowired": false, "secret": false, "description": "An HTTP Server engine implementation to serve the requests of this endpoint." } } } diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java index 9f88649c322eb..063e0a1b1b431 100644 --- a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java +++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpEndpoint.java @@ -42,9 +42,7 @@ */ @UriEndpoint(firstVersion = "3.0.0", scheme = "platform-http", title = "Platform HTTP", syntax = "platform-http:path", category = { Category.HTTP }, consumerOnly = true) -@Metadata(annotations = { - "protocol=http", -}) +@Metadata(annotations = { "protocol=http" }) public class PlatformHttpEndpoint extends DefaultEndpoint implements AsyncEndpoint, HeaderFilterStrategyAware, EndpointServiceLocation { @@ -119,10 +117,14 @@ public class PlatformHttpEndpoint extends DefaultEndpoint description = "Whether to enable the Cookie Handler that allows Cookie addition, expiry, and retrieval" + " (currently only supported by camel-platform-http-vertx)") private boolean useCookieHandler; - @UriParam(label = "advanced,consumer", defaultValue = "false", description = "Whether to include HTTP request headers (Accept, User-Agent, etc.) into HTTP response produced by this endpoint.") - private boolean returnHttpRequestHeaders = false; + private boolean returnHttpRequestHeaders; + @UriParam(label = "advanced,consumer", defaultValue = "false", + description = "When Camel is complete processing the message, and the HTTP server is writing response. This option controls whether Camel" + + " should catch any failure during writing response and store this on the Exchange, which allows onCompletion/UnitOfWork to" + + " regard the Exchange as failed and have access to the caused exception from the HTTP server.") + private boolean handleWriteResponseError; public PlatformHttpEndpoint(String uri, String remaining, Component component) { super(uri, component); @@ -299,4 +301,12 @@ public boolean isReturnHttpRequestHeaders() { public void setReturnHttpRequestHeaders(boolean returnHttpRequestHeaders) { this.returnHttpRequestHeaders = returnHttpRequestHeaders; } + + public boolean isHandleWriteResponseError() { + return handleWriteResponseError; + } + + public void setHandleWriteResponseError(boolean handleWriteResponseError) { + this.handleWriteResponseError = handleWriteResponseError; + } } diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PlatformHttpEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PlatformHttpEndpointBuilderFactory.java index 0f2e4a9790b6c..ba1f9e1b71c8b 100644 --- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PlatformHttpEndpointBuilderFactory.java +++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/PlatformHttpEndpointBuilderFactory.java @@ -323,6 +323,44 @@ default PlatformHttpEndpointBuilder basic() { return (PlatformHttpEndpointBuilder) this; } + /** + * When Camel is complete processing the message, and the HTTP server is + * writing response. This option controls whether Camel should catch any + * failure during writing response and store this on the Exchange, which + * allows onCompletion/UnitOfWork to regard the Exchange as failed and + * have access to the caused exception from the HTTP server. + * + * The option is a: boolean type. + * + * Default: false + * Group: consumer + * + * @param handleWriteResponseError the value to set + * @return the dsl builder + */ + default AdvancedPlatformHttpEndpointBuilder handleWriteResponseError(boolean handleWriteResponseError) { + doSetProperty("handleWriteResponseError", handleWriteResponseError); + return this; + } + /** + * When Camel is complete processing the message, and the HTTP server is + * writing response. This option controls whether Camel should catch any + * failure during writing response and store this on the Exchange, which + * allows onCompletion/UnitOfWork to regard the Exchange as failed and + * have access to the caused exception from the HTTP server. + * + * The option will be converted to a boolean type. + * + * Default: false + * Group: consumer + * + * @param handleWriteResponseError the value to set + * @return the dsl builder + */ + default AdvancedPlatformHttpEndpointBuilder handleWriteResponseError(String handleWriteResponseError) { + doSetProperty("handleWriteResponseError", handleWriteResponseError); + return this; + } /** * Whether to include HTTP request headers (Accept, User-Agent, etc.) * into HTTP response produced by this endpoint. From 07c5ad3c1fe00ab7f42ab86d33ee39ca371b177d Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 2 Oct 2024 10:33:49 +0200 Subject: [PATCH 2/3] CAMEL-21300: camel-platform-http - Consumer should have option to control if writing response failing should cause Exchange to fail --- .../catalog/components/platform-http.json | 7 +++--- .../http/PlatformHttpComponentConfigurer.java | 6 +++++ .../platform/http/platform-http.json | 7 +++--- .../platform/http/PlatformHttpComponent.java | 17 +++++++++++--- .../PlatformHttpComponentBuilderFactory.java | 22 +++++++++++++++++++ 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json index ffca8a9a4311f..e38929d3a891a 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/platform-http.json @@ -26,9 +26,10 @@ }, "componentProperties": { "bridgeErrorHandler": { "index": 0, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "autowiredEnabled": { "index": 1, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." }, - "engine": { "index": 2, "kind": "property", "displayName": "Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.spi.PlatformHttpEngine", "deprecated": false, "autowired": false, "secret": false, "description": "An HTTP Server engine implementation to serve the requests" }, - "headerFilterStrategy": { "index": 3, "kind": "property", "displayName": "Header Filter Strategy", "group": "filter", "label": "filter", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message." } + "handleWriteResponseError": { "index": 1, "kind": "property", "displayName": "Handle Write Response Error", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "When Camel is complete processing the message, and the HTTP server is writing response. This option controls whether Camel should catch any failure during writing response and store this on the Exchange, which allows onCompletion\/UnitOfWork to regard the Exchange as failed and have access to the caused exception from the HTTP server." }, + "autowiredEnabled": { "index": 2, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." }, + "engine": { "index": 3, "kind": "property", "displayName": "Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.spi.PlatformHttpEngine", "deprecated": false, "autowired": false, "secret": false, "description": "An HTTP Server engine implementation to serve the requests" }, + "headerFilterStrategy": { "index": 4, "kind": "property", "displayName": "Header Filter Strategy", "group": "filter", "label": "filter", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message." } }, "properties": { "path": { "index": 0, "kind": "path", "displayName": "Path", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The path under which this endpoint serves the HTTP requests, for proxy use 'proxy'" }, diff --git a/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpComponentConfigurer.java b/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpComponentConfigurer.java index 1ecee2a087427..6bac3f77b8e9b 100644 --- a/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpComponentConfigurer.java +++ b/components/camel-platform-http/src/generated/java/org/apache/camel/component/platform/http/PlatformHttpComponentConfigurer.java @@ -28,6 +28,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj case "bridgeerrorhandler": case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true; case "engine": target.setEngine(property(camelContext, org.apache.camel.component.platform.http.spi.PlatformHttpEngine.class, value)); return true; + case "handlewriteresponseerror": + case "handleWriteResponseError": target.setHandleWriteResponseError(property(camelContext, boolean.class, value)); return true; case "headerfilterstrategy": case "headerFilterStrategy": target.setHeaderFilterStrategy(property(camelContext, org.apache.camel.spi.HeaderFilterStrategy.class, value)); return true; default: return false; @@ -42,6 +44,8 @@ public Class getOptionType(String name, boolean ignoreCase) { case "bridgeerrorhandler": case "bridgeErrorHandler": return boolean.class; case "engine": return org.apache.camel.component.platform.http.spi.PlatformHttpEngine.class; + case "handlewriteresponseerror": + case "handleWriteResponseError": return boolean.class; case "headerfilterstrategy": case "headerFilterStrategy": return org.apache.camel.spi.HeaderFilterStrategy.class; default: return null; @@ -57,6 +61,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) { case "bridgeerrorhandler": case "bridgeErrorHandler": return target.isBridgeErrorHandler(); case "engine": return target.getEngine(); + case "handlewriteresponseerror": + case "handleWriteResponseError": return target.isHandleWriteResponseError(); case "headerfilterstrategy": case "headerFilterStrategy": return target.getHeaderFilterStrategy(); default: return null; diff --git a/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json b/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json index ffca8a9a4311f..e38929d3a891a 100644 --- a/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json +++ b/components/camel-platform-http/src/generated/resources/META-INF/org/apache/camel/component/platform/http/platform-http.json @@ -26,9 +26,10 @@ }, "componentProperties": { "bridgeErrorHandler": { "index": 0, "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored." }, - "autowiredEnabled": { "index": 1, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." }, - "engine": { "index": 2, "kind": "property", "displayName": "Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.spi.PlatformHttpEngine", "deprecated": false, "autowired": false, "secret": false, "description": "An HTTP Server engine implementation to serve the requests" }, - "headerFilterStrategy": { "index": 3, "kind": "property", "displayName": "Header Filter Strategy", "group": "filter", "label": "filter", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message." } + "handleWriteResponseError": { "index": 1, "kind": "property", "displayName": "Handle Write Response Error", "group": "consumer", "label": "advanced,consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "When Camel is complete processing the message, and the HTTP server is writing response. This option controls whether Camel should catch any failure during writing response and store this on the Exchange, which allows onCompletion\/UnitOfWork to regard the Exchange as failed and have access to the caused exception from the HTTP server." }, + "autowiredEnabled": { "index": 2, "kind": "property", "displayName": "Autowired Enabled", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether autowiring is enabled. This is used for automatic autowiring options (the option must be marked as autowired) by looking up in the registry to find if there is a single instance of matching type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc." }, + "engine": { "index": 3, "kind": "property", "displayName": "Engine", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.platform.http.spi.PlatformHttpEngine", "deprecated": false, "autowired": false, "secret": false, "description": "An HTTP Server engine implementation to serve the requests" }, + "headerFilterStrategy": { "index": 4, "kind": "property", "displayName": "Header Filter Strategy", "group": "filter", "label": "filter", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom org.apache.camel.spi.HeaderFilterStrategy to filter header to and from Camel message." } }, "properties": { "path": { "index": 0, "kind": "path", "displayName": "Path", "group": "consumer", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": false, "secret": false, "description": "The path under which this endpoint serves the HTTP requests, for proxy use 'proxy'" }, diff --git a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java index 05fbb6f5d5508..7872688d9a006 100644 --- a/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java +++ b/components/camel-platform-http/src/main/java/org/apache/camel/component/platform/http/PlatformHttpComponent.java @@ -56,13 +56,15 @@ public class PlatformHttpComponent extends HeaderFilterStrategyComponent @Metadata(label = "advanced", description = "An HTTP Server engine implementation to serve the requests") private volatile PlatformHttpEngine engine; + @Metadata(label = "advanced,consumer", defaultValue = "false", + description = "When Camel is complete processing the message, and the HTTP server is writing response. This option controls whether Camel" + + " should catch any failure during writing response and store this on the Exchange, which allows onCompletion/UnitOfWork to" + + " regard the Exchange as failed and have access to the caused exception from the HTTP server.") + private boolean handleWriteResponseError; private final Set httpEndpoints = new TreeSet<>(); - private final List listeners = new ArrayList<>(); - private volatile boolean localEngine; - private final Object lock = new Object(); public PlatformHttpComponent() { @@ -77,6 +79,7 @@ public PlatformHttpComponent(CamelContext context) { protected Endpoint createEndpoint(String uri, String remaining, Map parameters) throws Exception { PlatformHttpEndpoint endpoint = new PlatformHttpEndpoint(uri, remaining, this); endpoint.setPlatformHttpEngine(engine); + endpoint.setHandleWriteResponseError(handleWriteResponseError); setEndpointHeaderFilterStrategy(endpoint); setProperties(endpoint, parameters); return endpoint; @@ -194,6 +197,14 @@ public void setEngine(PlatformHttpEngine engine) { this.engine = engine; } + public boolean isHandleWriteResponseError() { + return handleWriteResponseError; + } + + public void setHandleWriteResponseError(boolean handleWriteResponseError) { + this.handleWriteResponseError = handleWriteResponseError; + } + private Consumer doCreateConsumer( CamelContext camelContext, Processor processor, String verb, String basePath, String uriTemplate, diff --git a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PlatformHttpComponentBuilderFactory.java b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PlatformHttpComponentBuilderFactory.java index 9d7f71306223b..518054d750a27 100644 --- a/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PlatformHttpComponentBuilderFactory.java +++ b/dsl/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/PlatformHttpComponentBuilderFactory.java @@ -81,6 +81,27 @@ default PlatformHttpComponentBuilder bridgeErrorHandler(boolean bridgeErrorHandl } + /** + * When Camel is complete processing the message, and the HTTP server is + * writing response. This option controls whether Camel should catch any + * failure during writing response and store this on the Exchange, which + * allows onCompletion/UnitOfWork to regard the Exchange as failed and + * have access to the caused exception from the HTTP server. + * + * The option is a: <code>boolean</code> type. + * + * Default: false + * Group: consumer + * + * @param handleWriteResponseError the value to set + * @return the dsl builder + */ + default PlatformHttpComponentBuilder handleWriteResponseError(boolean handleWriteResponseError) { + doSetProperty("handleWriteResponseError", handleWriteResponseError); + return this; + } + + /** * Whether autowiring is enabled. This is used for automatic autowiring * options (the option must be marked as autowired) by looking up in the @@ -151,6 +172,7 @@ protected boolean setPropertyOnComponent( Object value) { switch (name) { case "bridgeErrorHandler": ((PlatformHttpComponent) component).setBridgeErrorHandler((boolean) value); return true; + case "handleWriteResponseError": ((PlatformHttpComponent) component).setHandleWriteResponseError((boolean) value); return true; case "autowiredEnabled": ((PlatformHttpComponent) component).setAutowiredEnabled((boolean) value); return true; case "engine": ((PlatformHttpComponent) component).setEngine((org.apache.camel.component.platform.http.spi.PlatformHttpEngine) value); return true; case "headerFilterStrategy": ((PlatformHttpComponent) component).setHeaderFilterStrategy((org.apache.camel.spi.HeaderFilterStrategy) value); return true; From c30b7d62af9c245e9b3f81e0efd3b8487affb4a9 Mon Sep 17 00:00:00 2001 From: Claus Ibsen Date: Wed, 2 Oct 2024 11:44:05 +0200 Subject: [PATCH 3/3] CAMEL-21300: camel-platform-http - Consumer should have option to control if writing response failing should cause Exchange to fail --- .../component/platform/http/vertx/VertxPlatformHttpConsumer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java index 1d8258632b25b..146ade30da7b5 100644 --- a/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java +++ b/components/camel-platform-http-vertx/src/main/java/org/apache/camel/component/platform/http/vertx/VertxPlatformHttpConsumer.java @@ -245,6 +245,7 @@ private void handleFailure(Exchange exchange, RoutingContext ctx, Throwable fail if (existing != null) { failure.addSuppressed(existing); } + exchange.setProperty(Exchange.EXCEPTION_CAUGHT, failure); exchange.setException(failure); } handleExchangeComplete(exchange);