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

davsclaus pushed a commit to branch CAMEL-26124-jt400-pgm-npe
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f1239bc5002dfc6f75317ca2885494e7f1e00c72
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Nov 2 16:34:57 2026 +0100

    CAMEL-26124: camel-jt400 - Fix program call without outputFieldsIdx and 
with a List body
    
    A program call without outputFieldsIdx failed with a NullPointerException,
    because isFieldIdxForOuput did a binary search on a null array. A missing
    outputFieldsIdx now means no output fields (all parameters are input).
    
    The producer cast the body to Object[], so a List body failed with a
    ClassCastException. It now uses getMandatoryBody(Object[].class): a List
    is converted, and other bodies fail with an InvalidPayloadException.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../apache/camel/catalog/docs/jt400-component.adoc |  6 +-
 .../camel-jt400/src/main/docs/jt400-component.adoc |  6 +-
 .../camel/component/jt400/Jt400Endpoint.java       |  4 +-
 .../camel/component/jt400/Jt400PgmProducer.java    | 10 ++-
 .../component/jt400/Jt400PgmProducerTest.java      | 84 ++++++++++++++++++++++
 5 files changed, 99 insertions(+), 11 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jt400-component.adoc
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jt400-component.adoc
index 047b2ba226e7..0ae32efb8cee 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jt400-component.adoc
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/jt400-component.adoc
@@ -93,12 +93,14 @@ on the endpoint.
 
 === Program call
 
-This endpoint expects the input to be an `Object[]`, whose object types are
+This endpoint expects the input to be an `Object[]` (a `List` is converted to 
an array), whose object types are
 `int`, `long`, `CharSequence` (such as `String`), or `byte[]`. All other
 data types in the input array will be converted to `String`. For character
 inputs, CCSID handling is performed through the native jt400 library
 mechanisms. A parameter can be _omitted_ by passing null as the value in
-its position (the program has to support it). After the program execution,
+its position (the program has to support it). The `outputFieldsIdx` option 
lists the
+output parameters; when it is not set, all parameters are input-only.
+After the program execution,
 the endpoint returns an `Object[]` in the message body. Depending on
 _format_, the returned array will be populated with `byte[]` or `String`
 objects representing the values as they were returned by the program.
diff --git a/components/camel-jt400/src/main/docs/jt400-component.adoc 
b/components/camel-jt400/src/main/docs/jt400-component.adoc
index 047b2ba226e7..0ae32efb8cee 100644
--- a/components/camel-jt400/src/main/docs/jt400-component.adoc
+++ b/components/camel-jt400/src/main/docs/jt400-component.adoc
@@ -93,12 +93,14 @@ on the endpoint.
 
 === Program call
 
-This endpoint expects the input to be an `Object[]`, whose object types are
+This endpoint expects the input to be an `Object[]` (a `List` is converted to 
an array), whose object types are
 `int`, `long`, `CharSequence` (such as `String`), or `byte[]`. All other
 data types in the input array will be converted to `String`. For character
 inputs, CCSID handling is performed through the native jt400 library
 mechanisms. A parameter can be _omitted_ by passing null as the value in
-its position (the program has to support it). After the program execution,
+its position (the program has to support it). The `outputFieldsIdx` option 
lists the
+output parameters; when it is not set, all parameters are input-only.
+After the program execution,
 the endpoint returns an `Object[]` in the message body. Depending on
 _format_, the returned array will be populated with `byte[]` or `String`
 objects representing the values as they were returned by the program.
diff --git 
a/components/camel-jt400/src/main/java/org/apache/camel/component/jt400/Jt400Endpoint.java
 
b/components/camel-jt400/src/main/java/org/apache/camel/component/jt400/Jt400Endpoint.java
index 45a58baee4d2..d7d34c4d16e1 100644
--- 
a/components/camel-jt400/src/main/java/org/apache/camel/component/jt400/Jt400Endpoint.java
+++ 
b/components/camel-jt400/src/main/java/org/apache/camel/component/jt400/Jt400Endpoint.java
@@ -266,7 +266,9 @@ public class Jt400Endpoint extends ScheduledPollEndpoint 
implements MultipleCons
     }
 
     public boolean isFieldIdxForOuput(int idx) {
-        return Arrays.binarySearch(getOutputFieldsIdxArray(), idx) >= 0;
+        Integer[] outputFieldsIdxArray = getOutputFieldsIdxArray();
+        // no outputFieldsIdx configured means no output fields
+        return outputFieldsIdxArray != null && 
Arrays.binarySearch(outputFieldsIdxArray, idx) >= 0;
     }
 
     public int getOutputFieldLength(int idx) {
diff --git 
a/components/camel-jt400/src/main/java/org/apache/camel/component/jt400/Jt400PgmProducer.java
 
b/components/camel-jt400/src/main/java/org/apache/camel/component/jt400/Jt400PgmProducer.java
index bd9a02f888aa..cd300f26a7b5 100644
--- 
a/components/camel-jt400/src/main/java/org/apache/camel/component/jt400/Jt400PgmProducer.java
+++ 
b/components/camel-jt400/src/main/java/org/apache/camel/component/jt400/Jt400PgmProducer.java
@@ -99,12 +99,11 @@ public class Jt400PgmProducer extends DefaultProducer {
         }
     }
 
-    private ProgramParameter[] getParameterList(Exchange exchange, AS400 
iSeries)
+    ProgramParameter[] getParameterList(Exchange exchange, AS400 iSeries)
             throws InvalidPayloadException, PropertyVetoException {
 
-        Object body = exchange.getIn().getMandatoryBody();
-
-        Object[] params = (Object[]) body;
+        // the body must be an array of parameters (a List is converted to an 
array)
+        Object[] params = exchange.getIn().getMandatoryBody(Object[].class);
 
         ProgramParameter[] parameterList = new ProgramParameter[params.length];
         for (int i = 0; i < params.length; i++) {
@@ -178,8 +177,7 @@ public class Jt400PgmProducer extends DefaultProducer {
     private void handlePGMOutput(Exchange exchange, ProgramCall pgmCall, AS400 
iSeries)
             throws InvalidPayloadException {
 
-        Object body = exchange.getIn().getMandatoryBody();
-        Object[] params = (Object[]) body;
+        Object[] params = exchange.getIn().getMandatoryBody(Object[].class);
 
         List<Object> results = new ArrayList<>();
 
diff --git 
a/components/camel-jt400/src/test/java/org/apache/camel/component/jt400/Jt400PgmProducerTest.java
 
b/components/camel-jt400/src/test/java/org/apache/camel/component/jt400/Jt400PgmProducerTest.java
new file mode 100644
index 000000000000..8e96aca14d0d
--- /dev/null
+++ 
b/components/camel-jt400/src/test/java/org/apache/camel/component/jt400/Jt400PgmProducerTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.jt400;
+
+import java.util.List;
+
+import com.ibm.as400.access.AS400;
+import com.ibm.as400.access.ProgramParameter;
+import org.apache.camel.Exchange;
+import org.apache.camel.InvalidPayloadException;
+import org.apache.camel.support.DefaultExchange;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * Builds the program parameter list of {@link Jt400PgmProducer} without 
connecting to an IBM i system.
+ */
+public class Jt400PgmProducerTest extends Jt400TestSupport {
+
+    private static final String PGM_URI = 
"jt400://USER:password@host/qsys.lib/library.lib/prog.pgm"
+                                          + 
"?connectionPool=#mockPool&fieldsLength=4,8";
+
+    private final AS400 iSeries = new AS400("host", "USER", "password");
+
+    @Test
+    public void testNoOutputFieldsIdxMeansInputOnly() throws Exception {
+        Jt400Endpoint endpoint = context.getEndpoint(PGM_URI, 
Jt400Endpoint.class);
+        assertNull(endpoint.getOutputFieldsIdxArray());
+        assertFalse(endpoint.isFieldIdxForOuput(0));
+
+        ProgramParameter[] parameters = createParameterList(endpoint, new 
Object[] { 1, 2L });
+
+        assertEquals(2, parameters.length);
+        assertArrayEquals(new byte[] { 0, 0, 0, 1 }, 
parameters[0].getInputData());
+        assertEquals(0, parameters[0].getOutputDataLength());
+        assertArrayEquals(new byte[] { 0, 0, 0, 0, 0, 0, 0, 2 }, 
parameters[1].getInputData());
+        assertEquals(0, parameters[1].getOutputDataLength());
+    }
+
+    @Test
+    public void testListBody() throws Exception {
+        Jt400Endpoint endpoint = context.getEndpoint(PGM_URI + 
"&outputFieldsIdx=1", Jt400Endpoint.class);
+
+        ProgramParameter[] parameters = createParameterList(endpoint, 
List.of(1, new byte[0]));
+
+        assertEquals(2, parameters.length);
+        assertArrayEquals(new byte[] { 0, 0, 0, 1 }, 
parameters[0].getInputData());
+        assertEquals(0, parameters[0].getOutputDataLength());
+        assertEquals(8, parameters[1].getOutputDataLength());
+    }
+
+    @Test
+    public void testInvalidBody() {
+        Jt400Endpoint endpoint = context.getEndpoint(PGM_URI, 
Jt400Endpoint.class);
+
+        assertThrows(InvalidPayloadException.class, () -> 
createParameterList(endpoint, new Object()));
+    }
+
+    private ProgramParameter[] createParameterList(Jt400Endpoint endpoint, 
Object body) throws Exception {
+        Exchange exchange = new DefaultExchange(context);
+        exchange.getIn().setBody(body);
+        return new Jt400PgmProducer(endpoint).getParameterList(exchange, 
iSeries);
+    }
+
+}

Reply via email to