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

damccorm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new 88b3ee7b488 JmsIO yaml (#39818)
88b3ee7b488 is described below

commit 88b3ee7b488aa8a3e85e8dd04b64349384818d16
Author: Vitaly Terentyev <[email protected]>
AuthorDate: Fri Aug 21 18:46:38 2026 +0400

    JmsIO yaml (#39818)
    
    * Add JmsIO YAML test
    
    * Fix depends
    
    * Add IBM MQ
---
 sdks/python/apache_beam/yaml/integration_tests.py | 49 ++++++++++++++++++
 sdks/python/apache_beam/yaml/standard_io.yaml     | 58 +++++++++++++++++++++
 sdks/python/apache_beam/yaml/tests/ibm_mq.yaml    | 62 +++++++++++++++++++++++
 sdks/python/apache_beam/yaml/tests/jms.yaml       | 56 ++++++++++++++++++++
 sdks/python/apache_beam/yaml/yaml_provider.py     |  6 ++-
 sdks/python/build.gradle                          |  1 +
 6 files changed, 230 insertions(+), 2 deletions(-)

diff --git a/sdks/python/apache_beam/yaml/integration_tests.py 
b/sdks/python/apache_beam/yaml/integration_tests.py
index c6e33f8c6de..f4329205855 100644
--- a/sdks/python/apache_beam/yaml/integration_tests.py
+++ b/sdks/python/apache_beam/yaml/integration_tests.py
@@ -804,6 +804,55 @@ def temp_kinesis_localstack():
     _LOGGER.info('LocalStack Kinesis fixture stopped.')
 
 
[email protected]
+def temp_jms_activemq_server():
+  """Context manager to provide a temporary ActiveMQ broker for JMS tests."""
+
+  broker = 
DockerContainer('apache/activemq-classic:5.18.3').with_exposed_ports(
+      61616)
+
+  try:
+    broker.start()
+    wait_for_logs(broker, '.*ActiveMQ .* started.*', timeout=30)
+
+    host = broker.get_container_host_ip()
+    port = broker.get_exposed_port(61616)
+
+    yield {
+        'SERVER_URI': f'tcp://{host}:{port}',
+        'CONNECTION_FACTORY_CLASS_NAME': 
'org.apache.activemq.ActiveMQConnectionFactory',
+    }
+  finally:
+    broker.stop()
+
+
[email protected]
+def temp_ibm_mq_server():
+  container = (
+      DockerContainer('icr.io/ibm-messaging/mq:9.3.0.25-r1').with_env(
+          'LICENSE', 'accept').with_env('MQ_QMGR_NAME', 'QM1').with_env(
+              'MQ_APP_PASSWORD', 'admin123').with_exposed_ports(1414))
+
+  try:
+    container.start()
+    wait_for_logs(container, '.*(MQQMNAME|Started queue manager).*', 
timeout=45)
+
+    host = container.get_container_host_ip()
+    port = container.get_exposed_port(1414)
+
+    yield {
+        'SERVER_URI': 
f'tcp://{host}:{port}?channel=DEV.APP.SVRCONN&queueManager=QM1',
+        'CONNECTION_FACTORY_CLASS_NAME': 'com.ibm.mq.jms.MQConnectionFactory',
+        'USERNAME': 'app',
+        'PASSWORD': 'admin123',
+        'SOURCE_QUEUE': 'DEV.QUEUE.1',
+        'SINK_QUEUE': 'DEV.QUEUE.2',
+    }
+
+  finally:
+    container.stop()
+
+
 @contextlib.contextmanager
 def temp_kafka_server():
   """Context manager to provide a temporary Kafka server for testing.
diff --git a/sdks/python/apache_beam/yaml/standard_io.yaml 
b/sdks/python/apache_beam/yaml/standard_io.yaml
index b14db7bbec1..81fd62b0501 100644
--- a/sdks/python/apache_beam/yaml/standard_io.yaml
+++ b/sdks/python/apache_beam/yaml/standard_io.yaml
@@ -183,6 +183,64 @@
   config:
     gradle_target: 'sdks:java:extensions:schemaio-expansion-service:shadowJar'
 
+# JMS
+- type: renaming
+  transforms:
+    'ReadFromJms': 'ReadFromJms'
+    'WriteToJms': 'WriteToJms'
+  config:
+    mappings:
+      'ReadFromJms':
+        connection_configuration: 'connection_configuration'
+        queue: 'queue'
+        topic: 'topic'
+        max_num_records: 'max_num_records'
+        max_read_time_seconds: 'max_read_time_seconds'
+        close_timeout_seconds: 'close_timeout_seconds'
+        acknowledge_mode: 'acknowledge_mode'
+        individual_acknowledge_mode_code: 'individual_acknowledge_mode_code'
+      'WriteToJms':
+        connection_configuration: 'connection_configuration'
+        queue: 'queue'
+        topic: 'topic'
+    underlying_provider:
+      type: beamJar
+      transforms:
+        'ReadFromJms': 'beam:schematransform:org.apache.beam:jms_read:v1'
+        'WriteToJms': 'beam:schematransform:org.apache.beam:jms_write:v1'
+      config:
+        gradle_target: 'sdks:java:io:messaging-expansion-service:shadowJar'
+- type: renaming
+  transforms:
+    'ReadFromIbmMQ': 'ReadFromIbmMQ'
+    'WriteToIbmMQ': 'WriteToIbmMQ'
+  config:
+    mappings:
+      'ReadFromIbmMQ':
+        connection_configuration: 'connection_configuration'
+        queue: 'queue'
+        topic: 'topic'
+        max_num_records: 'max_num_records'
+        max_read_time_seconds: 'max_read_time_seconds'
+        close_timeout_seconds: 'close_timeout_seconds'
+        acknowledge_mode: 'acknowledge_mode'
+        individual_acknowledge_mode_code: 'individual_acknowledge_mode_code'
+      'WriteToIbmMQ':
+        connection_configuration: 'connection_configuration'
+        queue: 'queue'
+        topic: 'topic'
+    underlying_provider:
+      type: beamJar
+      transforms:
+        'ReadFromIbmMQ': 'beam:schematransform:org.apache.beam:jms_read:v1'
+        'WriteToIbmMQ': 'beam:schematransform:org.apache.beam:jms_write:v1'
+      config:
+        gradle_target: 'sdks:java:io:messaging-expansion-service:shadowJar'
+        classpath:
+          - 'com.ibm.mq:com.ibm.mq.allclient:9.3.0.25'
+          - 'org.json:json:20251224'
+
+
 # Debezium
 - type: renaming
   transforms:
diff --git a/sdks/python/apache_beam/yaml/tests/ibm_mq.yaml 
b/sdks/python/apache_beam/yaml/tests/ibm_mq.yaml
new file mode 100644
index 00000000000..b621e293cc7
--- /dev/null
+++ b/sdks/python/apache_beam/yaml/tests/ibm_mq.yaml
@@ -0,0 +1,62 @@
+#
+# 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.
+#
+
+fixtures:
+  - name: IBM_MQ
+    type: apache_beam.yaml.integration_tests.temp_ibm_mq_server
+
+pipelines:
+  - pipeline:
+      type: chain
+      transforms:
+        - type: Create
+          config:
+            elements:
+              - payload: message-1
+              - payload: message-2
+              - payload: message-3
+
+        - type: WriteToIbmMQ
+          config:
+            connection_configuration:
+              server_uri: "{IBM_MQ[SERVER_URI]}"
+              connection_factory_class_name:
+                "{IBM_MQ[CONNECTION_FACTORY_CLASS_NAME]}"
+              username: "{IBM_MQ[USERNAME]}"
+              password: "{IBM_MQ[PASSWORD]}"
+            queue: "{IBM_MQ[SOURCE_QUEUE]}"
+
+  - pipeline:
+      type: chain
+      transforms:
+        - type: ReadFromIbmMQ
+          config:
+            connection_configuration:
+              server_uri: "{IBM_MQ[SERVER_URI]}"
+              connection_factory_class_name:
+                "{IBM_MQ[CONNECTION_FACTORY_CLASS_NAME]}"
+              username: "{IBM_MQ[USERNAME]}"
+              password: "{IBM_MQ[PASSWORD]}"
+            queue: "{IBM_MQ[SOURCE_QUEUE]}"
+            max_num_records: 3
+
+        - type: AssertEqual
+          config:
+            elements:
+              - payload: message-1
+              - payload: message-2
+              - payload: message-3
diff --git a/sdks/python/apache_beam/yaml/tests/jms.yaml 
b/sdks/python/apache_beam/yaml/tests/jms.yaml
new file mode 100644
index 00000000000..60070dd2d45
--- /dev/null
+++ b/sdks/python/apache_beam/yaml/tests/jms.yaml
@@ -0,0 +1,56 @@
+#
+# 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.
+#
+
+fixtures:
+  - name: JMS
+    type: "apache_beam.yaml.integration_tests.temp_jms_activemq_server"
+
+pipelines:
+  - pipeline:
+      type: chain
+      transforms:
+        - type: Create
+          config:
+            elements:
+              - payload: message-1
+              - payload: message-2
+              - payload: message-3
+
+        - type: WriteToJms
+          config:
+            connection_configuration:
+              server_uri: "{JMS[SERVER_URI]}"
+              connection_factory_class_name: 
"{JMS[CONNECTION_FACTORY_CLASS_NAME]}"
+            queue: yaml-jms-test
+
+  - pipeline:
+      type: chain
+      transforms:
+        - type: ReadFromJms
+          config:
+            connection_configuration:
+              server_uri: "{JMS[SERVER_URI]}"
+              connection_factory_class_name: 
"{JMS[CONNECTION_FACTORY_CLASS_NAME]}"
+            queue: yaml-jms-test
+            max_num_records: 3
+
+        - type: AssertEqual
+          config:
+            elements:
+              - payload: message-1
+              - payload: message-2
+              - payload: message-3
diff --git a/sdks/python/apache_beam/yaml/yaml_provider.py 
b/sdks/python/apache_beam/yaml/yaml_provider.py
index 324ae0c2e73..6dd7a502eba 100755
--- a/sdks/python/apache_beam/yaml/yaml_provider.py
+++ b/sdks/python/apache_beam/yaml/yaml_provider.py
@@ -339,12 +339,14 @@ def beam_jar(
     managed_replacement=None,
     appendix=None,
     version=beam_version,
-    artifact_id=None):
+    artifact_id=None,
+    classpath=None):
   return ExternalJavaProvider(
       urns, lambda: subprocess_server.JavaJarServer.path_to_beam_jar(
           gradle_target=gradle_target, version=version, artifact_id=artifact_id
       ),
-      managed_replacement=managed_replacement)
+      managed_replacement=managed_replacement,
+      classpath=classpath)
 
 
 @ExternalProvider.register_provider_type('docker')
diff --git a/sdks/python/build.gradle b/sdks/python/build.gradle
index 1a93983da66..a15d4719ff7 100644
--- a/sdks/python/build.gradle
+++ b/sdks/python/build.gradle
@@ -152,6 +152,7 @@ tasks.register("yamlIntegrationTests") {
   dependsOn ":sdks:java:io:expansion-service:build"
   dependsOn ":sdks:java:io:google-cloud-platform:expansion-service:build"
   dependsOn ":sdks:java:io:debezium:expansion-service:shadowJar"
+  dependsOn ":sdks:java:io:messaging-expansion-service:shadowJar"
 
   doLast {
     exec {

Reply via email to