Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,10 @@

## Breaking Changes

* X behavior was changed ([#X](https://github.com/apache/beam/issues/X)).
* (Go) The row coder now encodes `int16` and `uint16` struct fields as 2 byte big endian INT16 values, matching the Java and Python SDKs. This is an update incompatible change for streaming pipelines that use rows with `int16` or `uint16` fields ([#40151](https://github.com/apache/beam/issues/40151)).
* (Java) JmsIO migrated to `jakarta.jms` (JMS 3.1) and ActiveMQ 6.2.5. User code implementing `JmsIO.MessageMapper`,
`valueMapper`, `topicNameMapper`, or providing a `ConnectionFactory` must update imports from `javax.jms.*` to
`jakarta.jms.*`. The module now requires Java 17 at runtime ([#38729](https://github.com/apache/beam/issues/38729)).

## Deprecations

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ class BeamModulePlugin implements Plugin<Project> {
//
// There are a few versions are determined by the BOMs by running scripts/tools/bomupgrader.py
// marked as [bomupgrader]. See the documentation of that script for detail.
def activemq_version = "5.19.5"
def activemq_version = "6.2.5"
def autovalue_version = "1.9"
def autoservice_version = "1.0.1"
def aws_java_sdk2_version = "2.20.162"
Expand Down Expand Up @@ -650,7 +650,7 @@ class BeamModulePlugin implements Plugin<Project> {
def postgres_version = "42.6.2"
// [bomupgrader] determined by: com.google.protobuf:protobuf-java, consistent with: google_cloud_platform_libraries_bom
def protobuf_version = "4.33.6"
def qpid_jms_client_version = "0.61.0"
def qpid_jms_client_version = "2.10.0"
Comment thread
derrickaw marked this conversation as resolved.
def quickcheck_version = "1.0"
def sbe_tool_version = "1.25.1"
def singlestore_jdbc_version = "1.1.4"
Expand Down
16 changes: 16 additions & 0 deletions sdks/java/io/amqp/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@
plugins { id 'org.apache.beam.module' }
applyJavaNature( automaticModuleName: 'org.apache.beam.sdk.io.amqp')

// The JMS IO module pulls ActiveMQ 6.2.5 (Java 17) into the shared dependency
// map. Because the global resolution strategy forces every mapped version,
// that 6.2.5 would otherwise be forced onto this Java 11 module via the shared
// org.apache.activemq coordinates. AMQP IO only needs ActiveMQ as an embedded
// test broker, so pin it back to the Java 11-compatible 5.x line.
def activemq5_version = '5.19.5'
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute module('org.apache.activemq:activemq-broker') using module("org.apache.activemq:activemq-broker:${activemq5_version}")
substitute module('org.apache.activemq:activemq-amqp') using module("org.apache.activemq:activemq-amqp:${activemq5_version}")
substitute module('org.apache.activemq:activemq-client') using module("org.apache.activemq:activemq-client:${activemq5_version}")
substitute module('org.apache.activemq:activemq-kahadb-store') using module("org.apache.activemq:activemq-kahadb-store:${activemq5_version}")
substitute module('org.apache.activemq.tooling:activemq-junit') using module("org.apache.activemq.tooling:activemq-junit:${activemq5_version}")
}
}

description = "Apache Beam :: SDKs :: Java :: IO :: AMQP"
ext.summary = "IO to read and write using AMQP 1.0 protocol (http://www.amqp.org)."

Expand Down
8 changes: 3 additions & 5 deletions sdks/java/io/jms/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
plugins { id 'org.apache.beam.module' }
applyJavaNature(
automaticModuleName: 'org.apache.beam.sdk.io.jms',
requireJavaVersion: JavaVersion.VERSION_17,
)
provideIntegrationTestingDependencies()
enableJavaPerformanceTesting()
Expand All @@ -32,13 +33,10 @@ dependencies {
implementation project(path: ":sdks:java:core", configuration: "shadow")
implementation library.java.slf4j_api
implementation library.java.joda_time
implementation "org.apache.geronimo.specs:geronimo-jms_2.0_spec:1.0-alpha-2"
// Don't put proprietary licensed ibm mq client into runtimeClasspath
// (affects expansion service shadow jar)
compileOnly("com.ibm.mq:com.ibm.mq.allclient:9.3.0.25") {
// duplicating geronimo-jms_2.0_spec
exclude group: "javax.jms", module: "javax.jms-api"
}
compileOnly "com.ibm.mq:com.ibm.mq.jakarta.client:9.3.0.25"
implementation "jakarta.jms:jakarta.jms-api:3.1.0"
Comment thread
derrickaw marked this conversation as resolved.
testImplementation library.java.activemq_amqp
testImplementation library.java.activemq_broker
testImplementation library.java.activemq_jaas
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
*/
package org.apache.beam.sdk.io.jms;

import jakarta.jms.ConnectionFactory;
import java.io.Serializable;
import javax.jms.ConnectionFactory;

/**
* An interface for creating custom JMS {@link ConnectionFactory} instances.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@
import static org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.base.Preconditions.checkArgument;

import com.google.auto.value.AutoValue;
import com.ibm.mq.jms.MQConnectionFactory;
import com.ibm.msg.client.wmq.WMQConstants;
import com.ibm.mq.jakarta.jms.MQConnectionFactory;
import com.ibm.msg.client.jakarta.wmq.WMQConstants;
import jakarta.jms.ConnectionFactory;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.List;
import javax.jms.ConnectionFactory;
import org.apache.beam.sdk.schemas.AutoValueSchema;
import org.apache.beam.sdk.schemas.annotations.DefaultSchema;
import org.apache.beam.sdk.schemas.annotations.SchemaFieldDescription;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
*/
package org.apache.beam.sdk.io.jms;

import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.MessageConsumer;
import jakarta.jms.Session;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import org.apache.beam.sdk.io.UnboundedSource;
import org.apache.beam.sdk.io.jms.JmsIO.AcknowledgeMode;
import org.apache.beam.vendor.guava.v32_1_2_jre.com.google.common.annotations.VisibleForTesting;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@

import com.google.auto.value.AutoValue;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.jms.Connection;
import jakarta.jms.ConnectionFactory;
import jakarta.jms.Destination;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.MessageConsumer;
import jakarta.jms.MessageProducer;
import jakarta.jms.Session;
import jakarta.jms.TextMessage;
import java.io.IOException;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
Expand All @@ -37,15 +46,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Stream;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.beam.sdk.coders.Coder;
import org.apache.beam.sdk.coders.SerializableCoder;
import org.apache.beam.sdk.io.Read.Unbounded;
Expand Down Expand Up @@ -87,9 +87,9 @@
*
* <p>JmsIO source returns unbounded collection of JMS records as {@code PCollection<JmsRecord>}. A
* {@link JmsRecord} includes JMS headers and properties, along with the JMS {@link
* javax.jms.TextMessage} payload.
* jakarta.jms.TextMessage} payload.
*
* <p>To configure a JMS source, you have to provide a {@link javax.jms.ConnectionFactory} and the
* <p>To configure a JMS source, you have to provide a {@link jakarta.jms.ConnectionFactory} and the
* destination (queue or topic) where to consume. The following example illustrates various options
* for configuring the source:
*
Expand All @@ -103,8 +103,8 @@
*
* }</pre>
*
* <p>It is possible to read any type of JMS {@link javax.jms.Message} into a custom POJO using the
* following configuration:
* <p>It is possible to read any type of JMS {@link jakarta.jms.Message} into a custom POJO using
* the following configuration:
*
* <pre>{@code
* pipeline.apply(JmsIO.<T>readMessage()
Expand All @@ -122,10 +122,10 @@
* <h4>Acknowledgment Modes and Client Prefetch Configuration</h4>
*
* <p>By default, {@link JmsIO} consumes messages using {@link AcknowledgeMode#CLIENT_ACKNOWLEDGE}
* where a new {@link javax.jms.Session} is created for each checkpoint to prevent premature
* where a new {@link jakarta.jms.Session} is created for each checkpoint to prevent premature
* acknowledgments across bundles. When using {@link AcknowledgeMode#CLIENT_ACKNOWLEDGE}, if your
* JMS broker or client library utilizes client-side message prefetch buffers (such as Apache
* ActiveMQ), you should configure {@code prefetch=0} on your {@link javax.jms.ConnectionFactory}
* ActiveMQ), you should configure {@code prefetch=0} on your {@link jakarta.jms.ConnectionFactory}
* (e.g., via {@code ?jms.prefetchPolicy.all=0} in the broker URL or {@code
* ActiveMQPrefetchPolicy.setAll(0)}). Otherwise, unconsumed messages could be held inside old
* consumers in low throughput scenario and could lead to message backlog.
Expand All @@ -138,8 +138,8 @@
* <h3>Writing to a JMS destination</h3>
*
* <p>JmsIO sink supports writing text messages to a JMS destination on a broker. To configure a JMS
* sink, you must specify a {@link javax.jms.ConnectionFactory} and a {@link javax.jms.Destination}
* name. For instance:
* sink, you must specify a {@link jakarta.jms.ConnectionFactory} and a {@link
* jakarta.jms.Destination} name. For instance:
*
* <pre>{@code
* pipeline
Expand Down Expand Up @@ -1223,7 +1223,7 @@ public Write<EventT> withTopicNameMapper(SerializableFunction<EventT, String> to
}

/**
* Map the {@code EventT} object to a {@link javax.jms.Message}.
* Map the {@code EventT} object to a {@link jakarta.jms.Message}.
*
* <p>For instance:
*
Expand All @@ -1245,7 +1245,7 @@ public Write<EventT> withTopicNameMapper(SerializableFunction<EventT, String> to
* .apply(JmsIO.write().withValueMapper(valueNapper)
* }</pre>
*
* @param valueMapper The function returning the {@link javax.jms.Message}
* @param valueMapper The function returning the {@link jakarta.jms.Message}
* @return The corresponding {@link JmsIO.Write}.
*/
public Write<EventT> withValueMapper(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
package org.apache.beam.sdk.io.jms;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import jakarta.jms.Destination;
import java.io.Serializable;
import java.util.Map;
import java.util.Objects;
import javax.jms.Destination;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
*/
package org.apache.beam.sdk.io.jms;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.Session;
import jakarta.jms.TextMessage;
import org.apache.beam.sdk.transforms.SerializableBiFunction;

/**
* The TextMessageMapper takes a {@link String} value, a {@link javax.jms.Session} and returns a
* {@link javax.jms.TextMessage}.
* The TextMessageMapper takes a {@link String} value, a {@link jakarta.jms.Session} and returns a
* {@link jakarta.jms.TextMessage}.
*/
public class TextMessageMapper implements SerializableBiFunction<String, Session, Message> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
*/
package org.apache.beam.sdk.io.jms;

import jakarta.jms.BytesMessage;
import jakarta.jms.ConnectionFactory;
import jakarta.jms.Message;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import javax.jms.BytesMessage;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import org.apache.activemq.broker.BrokerPlugin;
import org.apache.activemq.broker.BrokerService;
import org.apache.activemq.security.AuthenticationUser;
Expand Down Expand Up @@ -160,7 +160,7 @@ Class<? extends ConnectionFactory> getConnectionFactoryClass() {
return this.connectionFactoryClass;
}

/** A test class that maps a {@link javax.jms.BytesMessage} into a {@link String}. */
/** A test class that maps a {@link jakarta.jms.BytesMessage} into a {@link String}. */
public static class BytesMessageToStringMessageMapper implements JmsIO.MessageMapper<String> {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import jakarta.jms.Connection;
import jakarta.jms.ConnectionFactory;
import jakarta.jms.JMSException;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.qpid.jms.JmsConnectionFactory;
import org.checkerframework.checker.nullness.qual.Nullable;
Expand Down Expand Up @@ -79,22 +79,22 @@ public Connection createConnection(String username, String password) throws JMSE
}

@Override
public javax.jms.JMSContext createContext() {
public jakarta.jms.JMSContext createContext() {
return null;
}

@Override
public javax.jms.JMSContext createContext(int sessionMode) {
public jakarta.jms.JMSContext createContext(int sessionMode) {
return null;
}

@Override
public javax.jms.JMSContext createContext(String username, String password) {
public jakarta.jms.JMSContext createContext(String username, String password) {
return null;
}

@Override
public javax.jms.JMSContext createContext(String username, String password, int sessionMode) {
public jakarta.jms.JMSContext createContext(String username, String password, int sessionMode) {
return null;
}
}
Expand Down Expand Up @@ -137,11 +137,12 @@ public void testCustomBeamGenericJmsConnectionFactory() {
public void testClientsNotSlippedIntoRuntimeDependencies() {
// Verify IBM MQ client is not present on runtime classpath
assertThrows(
ClassNotFoundException.class, () -> Class.forName("com.ibm.mq.jms.MQConnectionFactory"));
ClassNotFoundException.class,
() -> Class.forName("com.ibm.mq.jakarta.jms.MQConnectionFactory"));

ConnectionConfiguration config =
ConnectionConfiguration.create("tcp://localhost:1414")
.withConnectionFactoryClassName("com.ibm.mq.jms.MQConnectionFactory");
.withConnectionFactoryClassName("com.ibm.mq.jakarta.jms.MQConnectionFactory");
IllegalArgumentException exception =
assertThrows(IllegalArgumentException.class, config::createConnectionFactory);
assertTrue(exception.getCause() instanceof ClassNotFoundException);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;

import jakarta.jms.Connection;
import jakarta.jms.ConnectionFactory;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.QueueBrowser;
import jakarta.jms.Session;
import jakarta.jms.TextMessage;
import java.io.IOException;
import java.io.Serializable;
import java.time.Instant;
Expand All @@ -34,13 +41,6 @@
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.QueueBrowser;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQTextMessage;
import org.apache.beam.sdk.PipelineResult;
Expand Down
Loading
Loading