This is an automated email from the ASF dual-hosted git repository.
oscerd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new bdebd92f8d67 CAMEL-24349: camel-google-functions - name the header
createFunction is missing (#25563)
bdebd92f8d67 is described below
commit bdebd92f8d67d0cb1ce132f4c20f71bd2344ef9f
Author: Andrea Cosentino <[email protected]>
AuthorDate: Fri Aug 21 19:42:54 2026 +0200
CAMEL-24349: camel-google-functions - name the header createFunction is
missing (#25563)
createFunction passed the entryPoint, runtime and sourceArchiveUrl headers
straight into the protobuf setters, which reject null, so a request missing
any
of them failed with a bare NullPointerException instead of saying which
header
the operation needs.
listFunctions also asked for a page size of Integer.MAX_VALUE while
iterating
with iterateAll, which follows the pages by itself; the oversized page size
is
dropped.
Signed-off-by: Andrea Cosentino <[email protected]>
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
.../camel-google/camel-google-functions/pom.xml | 5 ++
.../functions/GoogleCloudFunctionsProducer.java | 25 ++++++--
...CloudFunctionsCreateFunctionValidationTest.java | 74 ++++++++++++++++++++++
3 files changed, 98 insertions(+), 6 deletions(-)
diff --git a/components/camel-google/camel-google-functions/pom.xml
b/components/camel-google/camel-google-functions/pom.xml
index 1c6d2df74f14..3e4784449bb5 100644
--- a/components/camel-google/camel-google-functions/pom.xml
+++ b/components/camel-google/camel-google-functions/pom.xml
@@ -89,5 +89,10 @@
<artifactId>camel-test-junit6</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git
a/components/camel-google/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsProducer.java
b/components/camel-google/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsProducer.java
index 74b3f94f665d..c821e205b326 100644
---
a/components/camel-google/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsProducer.java
+++
b/components/camel-google/camel-google-functions/src/main/java/org/apache/camel/component/google/functions/GoogleCloudFunctionsProducer.java
@@ -41,6 +41,7 @@ import org.apache.camel.Exchange;
import org.apache.camel.InvalidPayloadException;
import org.apache.camel.Message;
import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.ObjectHelper;
/**
* The GoogleCloudFunctions producer.
@@ -93,10 +94,12 @@ public class GoogleCloudFunctionsProducer extends
DefaultProducer {
ListFunctionsPagedResponse pagedListResponse =
client.listFunctions(request);
response = Lists.newArrayList(pagedListResponse.iterateAll());
} else {
+ // no page size: iterateAll below follows the pages itself, and
the service rejects an
+ // oversized one
ListFunctionsRequest request = ListFunctionsRequest
.newBuilder().setParent(LocationName
.of(getConfiguration().getProject(),
getConfiguration().getLocation()).toString())
- .setPageSize(Integer.MAX_VALUE).build();
+ .build();
ListFunctionsPagedResponse pagedListResponse =
client.listFunctions(request);
response = Lists.newArrayList(pagedListResponse.iterateAll());
}
@@ -182,11 +185,9 @@ public class GoogleCloudFunctionsProducer extends
DefaultProducer {
final String project = getConfiguration().getProject();
final String location = getConfiguration().getLocation();
final String functionName = getConfiguration().getFunctionName();
- final String entryPoint =
exchange.getIn().getHeader(GoogleCloudFunctionsConstants.ENTRY_POINT,
- String.class);
- final String runtime =
exchange.getIn().getHeader(GoogleCloudFunctionsConstants.RUNTIME, String.class);
- final String sourceArchiveUrl =
exchange.getIn().getHeader(GoogleCloudFunctionsConstants.SOURCE_ARCHIVE_URL,
- String.class);
+ final String entryPoint = mandatoryHeader(exchange,
GoogleCloudFunctionsConstants.ENTRY_POINT);
+ final String runtime = mandatoryHeader(exchange,
GoogleCloudFunctionsConstants.RUNTIME);
+ final String sourceArchiveUrl = mandatoryHeader(exchange,
GoogleCloudFunctionsConstants.SOURCE_ARCHIVE_URL);
CloudFunction function = CloudFunction.newBuilder()
.setName(CloudFunctionName.of(project, location,
functionName).toString()).setEntryPoint(entryPoint)
.setRuntime(runtime).setHttpsTrigger(HttpsTrigger.getDefaultInstance())
@@ -228,6 +229,18 @@ public class GoogleCloudFunctionsProducer extends
DefaultProducer {
message.setBody(response);
}
+ /**
+ * A header the request cannot be built without. The protobuf setters
reject null, so without this the missing
+ * header surfaces as a bare NullPointerException instead of naming what
is missing.
+ */
+ private static String mandatoryHeader(Exchange exchange, String header) {
+ String value = exchange.getIn().getHeader(header, String.class);
+ if (ObjectHelper.isEmpty(value)) {
+ throw new IllegalArgumentException("The " + header + " header must
be set for this operation");
+ }
+ return value;
+ }
+
private GoogleCloudFunctionsOperations determineOperation(Exchange
exchange) {
GoogleCloudFunctionsOperations operation =
exchange.getIn().getHeader(GoogleCloudFunctionsConstants.OPERATION,
GoogleCloudFunctionsOperations.class);
diff --git
a/components/camel-google/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/unit/GoogleCloudFunctionsCreateFunctionValidationTest.java
b/components/camel-google/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/unit/GoogleCloudFunctionsCreateFunctionValidationTest.java
new file mode 100644
index 000000000000..910d7ac35335
--- /dev/null
+++
b/components/camel-google/camel-google-functions/src/test/java/org/apache/camel/component/google/functions/unit/GoogleCloudFunctionsCreateFunctionValidationTest.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.google.functions.unit;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import
org.apache.camel.component.google.functions.GoogleCloudFunctionsConstants;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Verifies that createFunction reports the header it is missing instead of
failing inside protobuf.
+ */
+class GoogleCloudFunctionsCreateFunctionValidationTest extends
GoogleCloudFunctionsBaseTest {
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ public void configure() {
+ from("direct:createFunction")
+
.to("google-functions://myCamelFunction?project=project123&location=location123"
+ + "&operation=createFunction");
+ }
+ };
+ }
+
+ @Test
+ void aMissingEntryPointIsReported() {
+ Exchange exchange = template.request("direct:createFunction", e -> {
+ });
+
+ assertThat(exchange.getException())
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("The " + GoogleCloudFunctionsConstants.ENTRY_POINT
+ " header must be set for this operation");
+ }
+
+ @Test
+ void aMissingRuntimeIsReported() {
+ Exchange exchange = template.request("direct:createFunction",
+ e ->
e.getIn().setHeader(GoogleCloudFunctionsConstants.ENTRY_POINT, "myEntryPoint"));
+
+ assertThat(exchange.getException())
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("The " + GoogleCloudFunctionsConstants.RUNTIME + "
header must be set for this operation");
+ }
+
+ @Test
+ void aMissingSourceArchiveUrlIsReported() {
+ Exchange exchange = template.request("direct:createFunction", e -> {
+ e.getIn().setHeader(GoogleCloudFunctionsConstants.ENTRY_POINT,
"myEntryPoint");
+ e.getIn().setHeader(GoogleCloudFunctionsConstants.RUNTIME,
"java17");
+ });
+
+ assertThat(exchange.getException())
+ .isInstanceOf(IllegalArgumentException.class)
+ .hasMessage("The " +
GoogleCloudFunctionsConstants.SOURCE_ARCHIVE_URL
+ + " header must be set for this operation");
+ }
+}