This is an automated email from the ASF dual-hosted git repository.

davsclaus 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 b9266cee86f0 CAMEL-24348: camel-google-bigquery - report unusable 
bodies and missing jobs properly
b9266cee86f0 is described below

commit b9266cee86f0de4be08bfcf10f9e826309b11492
Author: Andrea Cosentino <[email protected]>
AuthorDate: Wed Aug 12 07:15:36 2026 +0200

    CAMEL-24348: camel-google-bigquery - report unusable bodies and missing 
jobs properly
    
    Fix NullPointerException when the message body is null in 
GoogleBigQueryProducer,
    and when getJob/waitFor returns null for an expired or unknown job in
    GoogleBigQuerySQLProducer. Replace raw Exception throws with 
RuntimeCamelException
    so routes receive a proper Camel exception type.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 .../google/bigquery/GoogleBigQueryProducer.java    |  8 +++-
 .../bigquery/sql/GoogleBigQuerySQLProducer.java    | 15 +++++--
 .../unit/GoogleBigQueryProducerBodyTypeTest.java   | 48 ++++++++++++++++++++++
 3 files changed, 66 insertions(+), 5 deletions(-)

diff --git 
a/components/camel-google/camel-google-bigquery/src/main/java/org/apache/camel/component/google/bigquery/GoogleBigQueryProducer.java
 
b/components/camel-google/camel-google-bigquery/src/main/java/org/apache/camel/component/google/bigquery/GoogleBigQueryProducer.java
index 4693d7c920c3..6a80d9848944 100644
--- 
a/components/camel-google/camel-google-bigquery/src/main/java/org/apache/camel/component/google/bigquery/GoogleBigQueryProducer.java
+++ 
b/components/camel-google/camel-google-bigquery/src/main/java/org/apache/camel/component/google/bigquery/GoogleBigQueryProducer.java
@@ -26,6 +26,7 @@ import com.google.cloud.bigquery.InsertAllRequest;
 import com.google.cloud.bigquery.InsertAllResponse;
 import org.apache.camel.Exchange;
 import org.apache.camel.ExchangePropertyKey;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.support.DefaultProducer;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
@@ -129,13 +130,16 @@ public class GoogleBigQueryProducer extends 
DefaultProducer {
         for (Exchange ex : exchanges) {
             Object entryObject = ex.getIn().getBody();
             if (entryObject instanceof List) {
+                // the insert id header identifies one row, so it is not 
applied to the rows of a list: BigQuery
+                // would treat them as duplicates of each other and keep only 
one. Use useAsInsertId for those
                 for (Map<String, Object> entry : (List<Map<String, Object>>) 
entryObject) {
                     apiRequestRows.add(createRowRequest(null, entry));
                 }
             } else if (entryObject instanceof Map) {
                 apiRequestRows.add(createRowRequest(ex, (Map<String, Object>) 
entryObject));
             } else {
-                ex.setException(new IllegalArgumentException("Cannot handle 
body type " + entryObject.getClass()));
+                ex.setException(new IllegalArgumentException(
+                        "Cannot handle body type " + (entryObject == null ? 
"null" : entryObject.getClass().getName())));
             }
         }
 
@@ -160,7 +164,7 @@ public class GoogleBigQueryProducer extends DefaultProducer 
{
         InsertAllResponse apiResponse = bigquery.insertAll(insertAllRequest);
 
         if (apiResponse.getInsertErrors() != null && 
!apiResponse.getInsertErrors().isEmpty()) {
-            throw new Exception("InsertAll into " + tableId + " failed: " + 
apiResponse.getInsertErrors());
+            throw new RuntimeCamelException("InsertAll into " + tableId + " 
failed: " + apiResponse.getInsertErrors());
         }
 
         if (LOG.isTraceEnabled()) {
diff --git 
a/components/camel-google/camel-google-bigquery/src/main/java/org/apache/camel/component/google/bigquery/sql/GoogleBigQuerySQLProducer.java
 
b/components/camel-google/camel-google-bigquery/src/main/java/org/apache/camel/component/google/bigquery/sql/GoogleBigQuerySQLProducer.java
index f8589defc9ef..c17dada760a6 100644
--- 
a/components/camel-google/camel-google-bigquery/src/main/java/org/apache/camel/component/google/bigquery/sql/GoogleBigQuerySQLProducer.java
+++ 
b/components/camel-google/camel-google-bigquery/src/main/java/org/apache/camel/component/google/bigquery/sql/GoogleBigQuerySQLProducer.java
@@ -37,6 +37,7 @@ import com.google.cloud.bigquery.StandardSQLTypeName;
 import com.google.cloud.bigquery.TableResult;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.RuntimeExchangeException;
 import org.apache.camel.component.google.bigquery.GoogleBigQueryConstants;
 import org.apache.camel.support.DefaultProducer;
@@ -157,10 +158,18 @@ public class GoogleBigQuerySQLProducer extends 
DefaultProducer {
             var job = ObjectHelper.isNotEmpty(jobId)
                     ? bigquery.getJob(jobId)
                     : bigquery.create(getJobInfo(queryJobConfiguration));
+            if (job == null) {
+                throw new RuntimeCamelException("BigQuery job " + jobId + " 
does not exist");
+            }
 
-            return job.waitFor();
+            Job completed = job.waitFor();
+            if (completed == null) {
+                // waitFor returns null when the job does not exist any more, 
for example when it expired
+                throw new RuntimeCamelException("BigQuery job " + 
job.getJobId() + " is no longer available");
+            }
+            return completed;
         } catch (BigQueryException e) {
-            throw new Exception("Query " + translatedQuery + " failed: " + 
e.getError(), e);
+            throw new RuntimeCamelException("Query " + translatedQuery + " 
failed: " + e.getError(), e);
         }
     }
 
@@ -186,7 +195,7 @@ public class GoogleBigQuerySQLProducer extends 
DefaultProducer {
             QueryResultsOption[] queryResultsOptions = 
getQueryResultsOptions(pageSize, pageToken);
             return job.getQueryResults(queryResultsOptions);
         } catch (BigQueryException e) {
-            throw new Exception("Query " + translatedQuery + " failed: " + 
e.getError(), e);
+            throw new RuntimeCamelException("Query " + translatedQuery + " 
failed: " + e.getError(), e);
         }
     }
 
diff --git 
a/components/camel-google/camel-google-bigquery/src/test/java/org/apache/camel/component/google/bigquery/unit/GoogleBigQueryProducerBodyTypeTest.java
 
b/components/camel-google/camel-google-bigquery/src/test/java/org/apache/camel/component/google/bigquery/unit/GoogleBigQueryProducerBodyTypeTest.java
new file mode 100644
index 000000000000..341b9954c6f1
--- /dev/null
+++ 
b/components/camel-google/camel-google-bigquery/src/test/java/org/apache/camel/component/google/bigquery/unit/GoogleBigQueryProducerBodyTypeTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.bigquery.unit;
+
+import org.apache.camel.Exchange;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Verifies what the producer reports for a body it cannot turn into rows.
+ */
+class GoogleBigQueryProducerBodyTypeTest extends BaseBigQueryTest {
+
+    @Test
+    void aBodyThatIsNotAMapOrAListIsReported() throws Exception {
+        Exchange exchange = createExchangeWithBody("not a row");
+        producer.process(exchange);
+
+        assertThat(exchange.getException())
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessage("Cannot handle body type java.lang.String");
+    }
+
+    @Test
+    void aMissingBodyIsReportedInsteadOfFailingWithANullPointer() throws 
Exception {
+        Exchange exchange = createExchangeWithBody(null);
+        producer.process(exchange);
+
+        assertThat(exchange.getException())
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessage("Cannot handle body type null");
+    }
+}

Reply via email to