From 6e895f2290c7b9791fc34d303676bd5a3bd07e04 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 15 Jun 2020 14:53:26 -0700 Subject: [PATCH 01/29] create draft PR --- .../azure-messaging-eventhubs/pom.xml | 6 + .../com/azure/messaging/eventhubs/Batch.java | 226 +++++++++++++++++ .../azure/messaging/eventhubs/EventData.java | 1 + .../eventhubs/EventHubAsyncClient.java | 29 ++- .../eventhubs/EventHubClientBuilder.java | 26 +- .../EventHubConsumerAsyncClient.java | 23 +- .../EventHubPartitionAsyncConsumer.java | 24 +- .../EventHubProducerAsyncClient.java | 65 ++++- .../eventhubs/EventHubProducerClient.java | 6 +- .../messaging/eventhubs/ObjectBatch.java | 228 ++++++++++++++++++ .../eventhubs/models/PartitionEvent.java | 17 +- .../src/main/java/module-info.java | 1 + .../EventDataBatchIntegrationTest.java | 8 +- .../eventhubs/EventDataBatchTest.java | 8 +- .../EventHubConsumerAsyncClientTest.java | 18 +- .../eventhubs/EventHubConsumerClientTest.java | 6 +- .../EventHubPartitionAsyncConsumerTest.java | 6 +- .../EventHubProducerAsyncClientTest.java | 22 +- .../eventhubs/EventHubProducerClientTest.java | 10 +- ...EventProcessorClientErrorHandlingTest.java | 2 +- .../eventhubs/EventProcessorClientTest.java | 2 +- .../PartitionBasedLoadBalancerTest.java | 12 +- .../SchemaRegistryAvroAsyncDeserializer.java | 3 +- .../SchemaRegistryAvroAsyncSerializer.java | 4 +- .../SchemaRegistryDataDeserializer.java | 18 ++ .../SchemaRegistryDataSerializer.java | 21 ++ 26 files changed, 698 insertions(+), 94 deletions(-) create mode 100644 sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java create mode 100644 sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java create mode 100644 sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataDeserializer.java create mode 100644 sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataSerializer.java diff --git a/sdk/eventhubs/azure-messaging-eventhubs/pom.xml b/sdk/eventhubs/azure-messaging-eventhubs/pom.xml index df8bd06596a48..ad3864a455a86 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/pom.xml +++ b/sdk/eventhubs/azure-messaging-eventhubs/pom.xml @@ -45,6 +45,12 @@ 1.2.0 + + com.azure + azure-data-schemaregistry + 1.0.0-beta.2 + + com.azure diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java new file mode 100644 index 0000000000000..87b0377258858 --- /dev/null +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java @@ -0,0 +1,226 @@ +package com.azure.messaging.eventhubs; + +import com.azure.core.amqp.AmqpMessageConstant; +import com.azure.core.amqp.implementation.AmqpConstants; +import com.azure.core.amqp.implementation.ErrorContextProvider; +import com.azure.core.amqp.implementation.TracerProvider; +import com.azure.core.util.Context; +import com.azure.core.util.logging.ClientLogger; +import com.azure.core.util.tracing.ProcessKind; +import org.apache.qpid.proton.Proton; +import org.apache.qpid.proton.amqp.Binary; +import org.apache.qpid.proton.amqp.Symbol; +import org.apache.qpid.proton.amqp.messaging.ApplicationProperties; +import org.apache.qpid.proton.amqp.messaging.Data; +import org.apache.qpid.proton.amqp.messaging.MessageAnnotations; +import org.apache.qpid.proton.message.Message; +import reactor.core.publisher.Signal; + +import java.util.*; + +import static com.azure.core.util.tracing.Tracer.*; +import static com.azure.messaging.eventhubs.implementation.ClientConstants.AZ_NAMESPACE_VALUE; + +public abstract class Batch { + private final ClientLogger logger = new ClientLogger(this.getClass()); + private final Object lock = new Object(); + private final int maxMessageSize; + private final String partitionKey; + private final ErrorContextProvider contextProvider; + private final List events; + private final byte[] eventBytes; + private final String partitionId; + private int sizeInBytes; + protected final TracerProvider tracerProvider; + private final String entityPath; + private final String hostname; + + Batch(int maxMessageSize, String partitionId, String partitionKey, ErrorContextProvider contextProvider, + TracerProvider tracerProvider, String entityPath, String hostname) { + this.maxMessageSize = maxMessageSize; + this.partitionKey = partitionKey; + this.partitionId = partitionId; + this.contextProvider = contextProvider; + this.events = new LinkedList<>(); + this.sizeInBytes = (maxMessageSize / 65536) * 1024; // reserve 1KB for every 64KB + this.eventBytes = new byte[maxMessageSize]; + this.tracerProvider = tracerProvider; + this.entityPath = entityPath; + this.hostname = hostname; + } + + /** + * Gets the number of {@link EventData events} in the batch. + * + * @return The number of {@link EventData events} in the batch. + */ + public int getCount() { + return events.size(); + } + + /** + * Gets the maximum size, in bytes, of the {@link EventDataBatch}. + * + * @return The maximum size, in bytes, of the {@link EventDataBatch}. + */ + public int getMaxSizeInBytes() { + return maxMessageSize; + } + + /** + * Gets the size of the {@link EventDataBatch} in bytes. + * + * @return the size of the {@link EventDataBatch} in bytes. + */ + public int getSizeInBytes() { + return this.sizeInBytes; + } + + + /** + * Method to start and end a "Azure.EventHubs.message" span and add the "DiagnosticId" as a property of the message. + * + * @param eventData The Event to add tracing span for. + * @return the updated event data object. + */ + private EventData traceMessageSpan(EventData eventData) { + Optional eventContextData = eventData.getContext().getData(SPAN_CONTEXT_KEY); + if (eventContextData.isPresent()) { + // if message has context (in case of retries), don't start a message span or add a new context + return eventData; + } else { + // Starting the span makes the sampling decision (nothing is logged at this time) + Context eventContext = eventData.getContext() + .addData(AZ_TRACING_NAMESPACE_KEY, AZ_NAMESPACE_VALUE) + .addData(ENTITY_PATH_KEY, this.entityPath) + .addData(HOST_NAME_KEY, this.hostname); + Context eventSpanContext = tracerProvider.startSpan(eventContext, ProcessKind.MESSAGE); + Optional eventDiagnosticIdOptional = eventSpanContext.getData(DIAGNOSTIC_ID_KEY); + if (eventDiagnosticIdOptional.isPresent()) { + eventData.getProperties().put(DIAGNOSTIC_ID_KEY, eventDiagnosticIdOptional.get().toString()); + tracerProvider.endSpan(eventSpanContext, Signal.complete()); + eventData.addContext(SPAN_CONTEXT_KEY, eventSpanContext); + } + } + + return eventData; + } + + List getEvents() { + return events; + } + + String getPartitionKey() { + return partitionKey; + } + + String getPartitionId() { + return partitionId; + } + + private int getSize(final EventData eventData, final boolean isFirst) { + Objects.requireNonNull(eventData, "'eventData' cannot be null."); + + final Message amqpMessage = createAmqpMessage(eventData, partitionKey); + int eventSize = amqpMessage.encode(this.eventBytes, 0, maxMessageSize); // actual encoded bytes size + eventSize += 16; // data section overhead + + if (isFirst) { + amqpMessage.setBody(null); + amqpMessage.setApplicationProperties(null); + amqpMessage.setProperties(null); + amqpMessage.setDeliveryAnnotations(null); + + eventSize += amqpMessage.encode(this.eventBytes, 0, maxMessageSize); + } + + return eventSize; + } + + /* + * Creates the AMQP message represented by the event data + */ + private Message createAmqpMessage(EventData event, String partitionKey) { + final Message message = Proton.message(); + + if (event.getProperties() != null && !event.getProperties().isEmpty()) { + final ApplicationProperties applicationProperties = new ApplicationProperties(event.getProperties()); + message.setApplicationProperties(applicationProperties); + } + + if (event.getSystemProperties() != null) { + event.getSystemProperties().forEach((key, value) -> { + if (EventData.RESERVED_SYSTEM_PROPERTIES.contains(key)) { + return; + } + + final AmqpMessageConstant constant = AmqpMessageConstant.fromString(key); + + if (constant != null) { + switch (constant) { + case MESSAGE_ID: + message.setMessageId(value); + break; + case USER_ID: + message.setUserId((byte[]) value); + break; + case TO: + message.setAddress((String) value); + break; + case SUBJECT: + message.setSubject((String) value); + break; + case REPLY_TO: + message.setReplyTo((String) value); + break; + case CORRELATION_ID: + message.setCorrelationId(value); + break; + case CONTENT_TYPE: + message.setContentType((String) value); + break; + case CONTENT_ENCODING: + message.setContentEncoding((String) value); + break; + case ABSOLUTE_EXPIRY_TIME: + message.setExpiryTime((long) value); + break; + case CREATION_TIME: + message.setCreationTime((long) value); + break; + case GROUP_ID: + message.setGroupId((String) value); + break; + case GROUP_SEQUENCE: + message.setGroupSequence((long) value); + break; + case REPLY_TO_GROUP_ID: + message.setReplyToGroupId((String) value); + break; + default: + throw logger.logExceptionAsWarning(new IllegalArgumentException(String.format(Locale.US, + "Property is not a recognized reserved property name: %s", key))); + } + } else { + final MessageAnnotations messageAnnotations = (message.getMessageAnnotations() == null) + ? new MessageAnnotations(new HashMap<>()) + : message.getMessageAnnotations(); + messageAnnotations.getValue().put(Symbol.getSymbol(key), value); + message.setMessageAnnotations(messageAnnotations); + } + }); + } + + if (partitionKey != null) { + final MessageAnnotations messageAnnotations = (message.getMessageAnnotations() == null) + ? new MessageAnnotations(new HashMap<>()) + : message.getMessageAnnotations(); + messageAnnotations.getValue().put(AmqpConstants.PARTITION_KEY, partitionKey); + message.setMessageAnnotations(messageAnnotations); + } + + message.setBody(new Data(new Binary(event.getBody()))); + + return message; + } +} diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventData.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventData.java index bcf8f0d101fbb..0a02323cdfd22 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventData.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventData.java @@ -4,6 +4,7 @@ package com.azure.messaging.eventhubs; import com.azure.core.util.Context; +import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; import java.nio.ByteBuffer; import java.time.Instant; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java index 3a0598a08da51..301b98bcc9afa 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java @@ -6,6 +6,8 @@ import com.azure.core.amqp.implementation.MessageSerializer; import com.azure.core.amqp.implementation.TracerProvider; import com.azure.core.util.logging.ClientLogger; +import com.azure.data.schemaregistry.SchemaRegistryDataDeserializer; +import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; import com.azure.messaging.eventhubs.implementation.EventHubConnectionProcessor; import com.azure.messaging.eventhubs.implementation.EventHubManagementNode; import reactor.core.publisher.Flux; @@ -24,7 +26,7 @@ * @see EventHubClient See EventHubClient to communicate with an Event Hub using a synchronous client. * @see About Azure Event Hubs */ -class EventHubAsyncClient implements Closeable { +class EventHubAsyncClient implements Closeable { private final ClientLogger logger = new ClientLogger(EventHubAsyncClient.class); private final MessageSerializer messageSerializer; private final EventHubConnectionProcessor connectionProcessor; @@ -32,17 +34,24 @@ class EventHubAsyncClient implements Closeable { private final boolean isSharedConnection; private final Runnable onClientClose; private final TracerProvider tracerProvider; + private final SchemaRegistryDataSerializer registrySerializer; + private final SchemaRegistryDataDeserializer registryDeserializer; EventHubAsyncClient(EventHubConnectionProcessor connectionProcessor, TracerProvider tracerProvider, - MessageSerializer messageSerializer, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose) { + MessageSerializer messageSerializer, Scheduler scheduler, boolean isSharedConnection, + Runnable onClientClose, SchemaRegistryDataSerializer registrySerializer, + SchemaRegistryDataDeserializer registryDeserializer) { this.tracerProvider = Objects.requireNonNull(tracerProvider, "'tracerProvider' cannot be null."); - this.messageSerializer = Objects.requireNonNull(messageSerializer, "'messageSerializer' cannot be null."); + this.messageSerializer = + Objects.requireNonNull(messageSerializer, "'messageSerializer' cannot be null."); this.connectionProcessor = Objects.requireNonNull(connectionProcessor, "'connectionProcessor' cannot be null."); this.scheduler = Objects.requireNonNull(scheduler, "'scheduler' cannot be null"); this.onClientClose = Objects.requireNonNull(onClientClose, "'onClientClose' cannot be null."); this.isSharedConnection = isSharedConnection; + this.registrySerializer = registrySerializer; + this.registryDeserializer = registryDeserializer; } /** @@ -102,9 +111,10 @@ Mono getPartitionProperties(String partitionId) { * * @return A new {@link EventHubProducerAsyncClient}. */ - EventHubProducerAsyncClient createProducer() { - return new EventHubProducerAsyncClient(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), - connectionProcessor, connectionProcessor.getRetryOptions(), tracerProvider, messageSerializer, scheduler, + EventHubProducerAsyncClient createProducer() { + return new EventHubProducerAsyncClient<>(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), + connectionProcessor, connectionProcessor.getRetryOptions(), tracerProvider, messageSerializer, + registrySerializer, scheduler, isSharedConnection, onClientClose); } @@ -120,7 +130,7 @@ EventHubProducerAsyncClient createProducer() { * @throws NullPointerException If {@code consumerGroup} is {@code null}. * @throws IllegalArgumentException If {@code consumerGroup} is an empty string. */ - EventHubConsumerAsyncClient createConsumer(String consumerGroup, int prefetchCount) { + EventHubConsumerAsyncClient createConsumer(String consumerGroup, int prefetchCount) { Objects.requireNonNull(consumerGroup, "'consumerGroup' cannot be null."); if (consumerGroup.isEmpty()) { @@ -128,8 +138,9 @@ EventHubConsumerAsyncClient createConsumer(String consumerGroup, int prefetchCou new IllegalArgumentException("'consumerGroup' cannot be an empty string.")); } - return new EventHubConsumerAsyncClient(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), - connectionProcessor, messageSerializer, consumerGroup, prefetchCount, scheduler, isSharedConnection, + return new EventHubConsumerAsyncClient<>(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), + connectionProcessor, messageSerializer, consumerGroup, registryDeserializer, + prefetchCount, scheduler, isSharedConnection, onClientClose); } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java index 009168ce8e933..225111b7e6305 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java @@ -24,6 +24,8 @@ import com.azure.core.util.CoreUtils; import com.azure.core.util.logging.ClientLogger; import com.azure.core.util.tracing.Tracer; +import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; +import com.azure.data.schemaregistry.SchemaRegistryDataDeserializer; import com.azure.messaging.eventhubs.implementation.ClientConstants; import com.azure.messaging.eventhubs.implementation.EventHubAmqpConnection; import com.azure.messaging.eventhubs.implementation.EventHubConnectionProcessor; @@ -93,7 +95,7 @@ */ @ServiceClientBuilder(serviceClients = {EventHubProducerAsyncClient.class, EventHubProducerClient.class, EventHubConsumerAsyncClient.class, EventHubConsumerClient.class}) -public class EventHubClientBuilder { +public class EventHubClientBuilder { // Default number of events to fetch when creating the consumer. static final int DEFAULT_PREFETCH_COUNT = 500; @@ -135,6 +137,8 @@ public class EventHubClientBuilder { private String consumerGroup; private EventHubConnectionProcessor eventHubConnectionProcessor; private int prefetchCount; + private SchemaRegistryDataSerializer registrySerializer; + private SchemaRegistryDataDeserializer registryDeserializer; /** * Keeps track of the open clients that were created from this builder when there is a shared connection. @@ -361,6 +365,16 @@ public EventHubClientBuilder prefetchCount(int prefetchCount) { return this; } + /** + * Set registry serializer + * @param serializer serializer + * @return update builder instance + */ + public EventHubClientBuilder registrySerializer(Serializer serializer) { // could be avro, json, schema registry + this.registrySerializer = registrySerializer; + return this; + } + /** * Package-private method that sets the scheduler for the created Event Hub client. * @@ -383,7 +397,7 @@ EventHubClientBuilder scheduler(Scheduler scheduler) { * {@link #consumerGroup(String)} have not been set. And if a proxy is specified but the transport type is not * {@link AmqpTransportType#AMQP_WEB_SOCKETS web sockets}. */ - public EventHubConsumerAsyncClient buildAsyncConsumerClient() { + public EventHubConsumerAsyncClient buildAsyncConsumerClient() { if (CoreUtils.isNullOrEmpty(consumerGroup)) { throw logger.logExceptionAsError(new IllegalArgumentException("'consumerGroup' cannot be null or an empty " + "string. using EventHubClientBuilder.consumerGroup(String)")); @@ -402,7 +416,7 @@ public EventHubConsumerAsyncClient buildAsyncConsumerClient() { * {@link #consumerGroup(String)} have not been set. And if a proxy is specified but the transport type is not * {@link AmqpTransportType#AMQP_WEB_SOCKETS web sockets}. */ - public EventHubConsumerClient buildConsumerClient() { + public EventHubConsumerClient buildConsumerClient() { return buildClient().createConsumer(consumerGroup, prefetchCount); } @@ -415,7 +429,7 @@ public EventHubConsumerClient buildConsumerClient() { * either {@link #connectionString(String)} or {@link #credential(String, String, TokenCredential)}. Or, if a * proxy is specified but the transport type is not {@link AmqpTransportType#AMQP_WEB_SOCKETS web sockets}. */ - public EventHubProducerAsyncClient buildAsyncProducerClient() { + public EventHubProducerAsyncClient buildAsyncProducerClient() { return buildAsyncClient().createProducer(); } @@ -428,7 +442,7 @@ public EventHubProducerAsyncClient buildAsyncProducerClient() { * either {@link #connectionString(String)} or {@link #credential(String, String, TokenCredential)}. Or, if a * proxy is specified but the transport type is not {@link AmqpTransportType#AMQP_WEB_SOCKETS web sockets}. */ - public EventHubProducerClient buildProducerClient() { + public EventHubProducerClient buildProducerClient() { return buildClient().createProducer(); } @@ -486,7 +500,7 @@ EventHubAsyncClient buildAsyncClient() { final TracerProvider tracerProvider = new TracerProvider(ServiceLoader.load(Tracer.class)); return new EventHubAsyncClient(processor, tracerProvider, messageSerializer, scheduler, - isSharedConnection.get(), this::onClientClose); + isSharedConnection.get(), this::onClientClose, registrySerializer, registryDeserializer); } /** diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java index 335fc7d3a9735..3dd18b8713c5f 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java @@ -12,6 +12,7 @@ import com.azure.core.annotation.ServiceClient; import com.azure.core.annotation.ServiceMethod; import com.azure.core.util.logging.ClientLogger; +import com.azure.data.schemaregistry.SchemaRegistryDataDeserializer; import com.azure.messaging.eventhubs.implementation.AmqpReceiveLinkProcessor; import com.azure.messaging.eventhubs.implementation.EventHubConnectionProcessor; import com.azure.messaging.eventhubs.implementation.EventHubManagementNode; @@ -71,6 +72,7 @@ public class EventHubConsumerAsyncClient implements Closeable { private final EventHubConnectionProcessor connectionProcessor; private final MessageSerializer messageSerializer; private final String consumerGroup; + private final SchemaRegistryDataDeserializer registryDeserializer; private final int prefetchCount; private final Scheduler scheduler; private final boolean isSharedConnection; @@ -83,8 +85,10 @@ public class EventHubConsumerAsyncClient implements Closeable { new ConcurrentHashMap<>(); EventHubConsumerAsyncClient(String fullyQualifiedNamespace, String eventHubName, - EventHubConnectionProcessor connectionProcessor, MessageSerializer messageSerializer, String consumerGroup, - int prefetchCount, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClosed) { + EventHubConnectionProcessor connectionProcessor, MessageSerializer messageSerializer, + String consumerGroup, + SchemaRegistryDataDeserializer registryDeserializer, int prefetchCount, + Scheduler scheduler, boolean isSharedConnection, Runnable onClientClosed) { this.fullyQualifiedNamespace = fullyQualifiedNamespace; this.eventHubName = eventHubName; this.connectionProcessor = connectionProcessor; @@ -94,6 +98,7 @@ public class EventHubConsumerAsyncClient implements Closeable { this.scheduler = scheduler; this.isSharedConnection = isSharedConnection; this.onClientClosed = onClientClosed; + this.registryDeserializer = registryDeserializer; } /** @@ -177,7 +182,7 @@ public Mono getPartitionProperties(String partitionId) { * @throws NullPointerException if {@code partitionId}, or {@code startingPosition} is null. * @throws IllegalArgumentException if {@code partitionId} is an empty string. */ - public Flux receiveFromPartition(String partitionId, EventPosition startingPosition) { + public Flux> receiveFromPartition(String partitionId, EventPosition startingPosition) { return receiveFromPartition(partitionId, startingPosition, defaultReceiveOptions); } @@ -205,7 +210,7 @@ public Flux receiveFromPartition(String partitionId, EventPositi * null. * @throws IllegalArgumentException if {@code partitionId} is an empty string. */ - public Flux receiveFromPartition(String partitionId, EventPosition startingPosition, + public Flux> receiveFromPartition(String partitionId, EventPosition startingPosition, ReceiveOptions receiveOptions) { if (Objects.isNull(partitionId)) { return fluxError(logger, new NullPointerException("'partitionId' cannot be null.")); @@ -235,7 +240,7 @@ public Flux receiveFromPartition(String partitionId, EventPositi * * @return A stream of events for every partition in the Event Hub starting from the beginning of each partition. */ - public Flux receive() { + public Flux> receive() { return receive(true, defaultReceiveOptions); } @@ -256,7 +261,7 @@ public Flux receive() { * * @return A stream of events for every partition in the Event Hub. */ - public Flux receive(boolean startReadingAtEarliestEvent) { + public Flux> receive(boolean startReadingAtEarliestEvent) { return receive(startReadingAtEarliestEvent, defaultReceiveOptions); } @@ -289,7 +294,7 @@ public Flux receive(boolean startReadingAtEarliestEvent) { * * @throws NullPointerException if {@code receiveOptions} is null. */ - public Flux receive(boolean startReadingAtEarliestEvent, ReceiveOptions receiveOptions) { + public Flux> receive(boolean startReadingAtEarliestEvent, ReceiveOptions receiveOptions) { if (Objects.isNull(receiveOptions)) { return fluxError(logger, new NullPointerException("'receiveOptions' cannot be null.")); } @@ -325,7 +330,7 @@ public void close() { } } - private Flux createConsumer(String linkName, String partitionId, EventPosition startingPosition, + private Flux> createConsumer(String linkName, String partitionId, EventPosition startingPosition, ReceiveOptions receiveOptions) { return openPartitionConsumers .computeIfAbsent(linkName, @@ -365,6 +370,6 @@ private EventHubPartitionAsyncConsumer createPartitionConsumer(String linkName, return new EventHubPartitionAsyncConsumer(linkMessageProcessor, messageSerializer, getFullyQualifiedNamespace(), getEventHubName(), consumerGroup, partitionId, initialPosition, - receiveOptions.getTrackLastEnqueuedEventProperties(), scheduler); + receiveOptions.getTrackLastEnqueuedEventProperties(), scheduler, registryDeserializer); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java index d0b070343d4d6..728da49c954cc 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java @@ -5,6 +5,7 @@ import com.azure.core.amqp.implementation.MessageSerializer; import com.azure.core.util.logging.ClientLogger; +import com.azure.data.schemaregistry.SchemaRegistryDataDeserializer; import com.azure.messaging.eventhubs.implementation.AmqpReceiveLinkProcessor; import com.azure.messaging.eventhubs.models.EventPosition; import com.azure.messaging.eventhubs.models.LastEnqueuedEventProperties; @@ -25,7 +26,7 @@ * A package-private consumer responsible for reading {@link EventData} from a specific Event Hub partition in the * context of a specific consumer group. */ -class EventHubPartitionAsyncConsumer implements AutoCloseable { +class EventHubPartitionAsyncConsumer implements AutoCloseable { private final ClientLogger logger = new ClientLogger(EventHubPartitionAsyncConsumer.class); private final AtomicBoolean isDisposed = new AtomicBoolean(); private final AtomicReference lastEnqueuedEventProperties = new AtomicReference<>(); @@ -39,13 +40,16 @@ class EventHubPartitionAsyncConsumer implements AutoCloseable { private final Scheduler scheduler; private final EmitterProcessor emitterProcessor; private final EventPosition initialPosition; + private final SchemaRegistryDataDeserializer registryDeserializer; private volatile Long currentOffset; EventHubPartitionAsyncConsumer(AmqpReceiveLinkProcessor amqpReceiveLinkProcessor, - MessageSerializer messageSerializer, String fullyQualifiedNamespace, String eventHubName, String consumerGroup, - String partitionId, AtomicReference> currentEventPosition, - boolean trackLastEnqueuedEventProperties, Scheduler scheduler) { + MessageSerializer messageSerializer, String fullyQualifiedNamespace, + String eventHubName, String consumerGroup, + String partitionId, AtomicReference> currentEventPosition, + boolean trackLastEnqueuedEventProperties, Scheduler scheduler, + SchemaRegistryDataDeserializer registryDeserializer) { this.initialPosition = Objects.requireNonNull(currentEventPosition.get().get(), "'currentEventPosition.get().get()' cannot be null."); this.amqpReceiveLinkProcessor = amqpReceiveLinkProcessor; @@ -56,6 +60,7 @@ class EventHubPartitionAsyncConsumer implements AutoCloseable { this.partitionId = partitionId; this.trackLastEnqueuedEventProperties = trackLastEnqueuedEventProperties; this.scheduler = Objects.requireNonNull(scheduler, "'scheduler' cannot be null."); + this.registryDeserializer = registryDeserializer; if (trackLastEnqueuedEventProperties) { lastEnqueuedEventProperties.set(new LastEnqueuedEventProperties(null, null, null, null)); @@ -105,7 +110,7 @@ public void close() { * * @return A stream of events received from the partition. */ - Flux receive() { + Flux> receive() { return emitterProcessor.publishOn(this.scheduler); } @@ -138,6 +143,13 @@ private PartitionEvent onMessageReceived(Message message) { final PartitionContext partitionContext = new PartitionContext(fullyQualifiedNamespace, eventHubName, consumerGroup, partitionId); - return new PartitionEvent(partitionContext, event, lastEnqueuedEventProperties.get()); + + if (registryDeserializer == null) { + return new PartitionEvent(partitionContext, event, lastEnqueuedEventProperties.get(), ); + } + + return new PartitionEvent(partitionContext, event, lastEnqueuedEventProperties.get(), + registryDeserializer.deserialize(event.getBody()).block()); + } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java index f2a81b0ba5bd5..05fbab84ca1e4 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java @@ -19,6 +19,7 @@ import com.azure.core.util.CoreUtils; import com.azure.core.util.logging.ClientLogger; import com.azure.core.util.tracing.ProcessKind; +import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; import com.azure.messaging.eventhubs.implementation.EventHubConnectionProcessor; import com.azure.messaging.eventhubs.implementation.EventHubManagementNode; import com.azure.messaging.eventhubs.models.CreateBatchOptions; @@ -107,6 +108,7 @@ public class EventHubProducerAsyncClient implements Closeable { private final AmqpRetryPolicy retryPolicy; private final TracerProvider tracerProvider; private final MessageSerializer messageSerializer; + private final SchemaRegistryDataSerializer registrySerializer; private final Scheduler scheduler; private final boolean isSharedConnection; private final Runnable onClientClose; @@ -117,8 +119,10 @@ public class EventHubProducerAsyncClient implements Closeable { * load balance the messages amongst available partitions. */ EventHubProducerAsyncClient(String fullyQualifiedNamespace, String eventHubName, - EventHubConnectionProcessor connectionProcessor, AmqpRetryOptions retryOptions, TracerProvider tracerProvider, - MessageSerializer messageSerializer, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose) { + EventHubConnectionProcessor connectionProcessor, AmqpRetryOptions retryOptions, + TracerProvider tracerProvider, + MessageSerializer messageSerializer, SchemaRegistryDataSerializer registrySerializer, + Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose) { this.fullyQualifiedNamespace = Objects.requireNonNull(fullyQualifiedNamespace, "'fullyQualifiedNamespace' cannot be null."); this.eventHubName = Objects.requireNonNull(eventHubName, "'eventHubName' cannot be null."); @@ -127,6 +131,7 @@ public class EventHubProducerAsyncClient implements Closeable { this.retryOptions = Objects.requireNonNull(retryOptions, "'retryOptions' cannot be null."); this.tracerProvider = Objects.requireNonNull(tracerProvider, "'tracerProvider' cannot be null."); this.messageSerializer = Objects.requireNonNull(messageSerializer, "'messageSerializer' cannot be null."); + this.registrySerializer = registrySerializer; this.onClientClose = Objects.requireNonNull(onClientClose, "'onClientClose' cannot be null."); this.retryPolicy = getRetryPolicy(retryOptions); @@ -192,7 +197,7 @@ public Mono getPartitionProperties(String partitionId) { * * @return A new {@link EventDataBatch} that can fit as many events as the transport allows. */ - public Mono createBatch() { + public Mono> createBatch() { return createBatch(DEFAULT_BATCH_OPTIONS); } @@ -203,7 +208,7 @@ public Mono createBatch() { * @return A new {@link EventDataBatch} that can fit as many events as the transport allows. * @throws NullPointerException if {@code options} is null. */ - public Mono createBatch(CreateBatchOptions options) { + public Mono> createBatch(Class objectClass1, CreateBatchOptions options) { if (options == null) { return monoError(logger, new NullPointerException("'options' cannot be null.")); } @@ -244,10 +249,42 @@ public Mono createBatch(CreateBatchOptions options) { : maximumLinkSize; return Mono.just(new EventDataBatch(batchSize, partitionId, partitionKey, link::getErrorContext, - tracerProvider, link.getEntityPath(), link.getHostname())); + tracerProvider, registrySerializer, link.getEntityPath(), link.getHostname())); })); } + /** + * Sends single object, serialized by the stored serializer, + * @param object object + * @return mono that completes when event is pushed to the service + */ + Mono send(T object) { + if (registrySerializer == null) { + return monoError(logger, new NullPointerException("Registry serializer not initialized")); + } + byte[] body = registrySerializer.serialize(object).block(); + if (body == null) { + throw logger.logExceptionAsError(new IllegalArgumentException("Payload cannot be null")); + } + return send(Flux.just(new EventData(body))); + } + + /** + * send object + * @param object object + * @return mono that completes when event is pushed to the service + */ + Mono send(T object, SendOptions options) { + if (registrySerializer == null) { + return monoError(logger, new NullPointerException("Registry serializer not initialized")); + } + byte[] body = registrySerializer.serialize(object).block(); + if (body == null) { + throw logger.logExceptionAsError(new IllegalArgumentException("Payload cannot be null")); + } + return send(Flux.just(new EventData(body))); + } + /** * Sends a single event to the associated Event Hub. If the size of the single event exceeds the maximum size * allowed, an exception will be triggered and the send will fail. @@ -284,6 +321,9 @@ Mono send(EventData event) { * @return A {@link Mono} that completes when the event is pushed to the service. */ Mono send(EventData event, SendOptions options) { + if (registrySerializer != null) { + // fail this path + } if (event == null) { return monoError(logger, new NullPointerException("'event' cannot be null.")); } else if (options == null) { @@ -462,6 +502,11 @@ public Mono send(EventDataBatch batch) { } private Mono sendInternal(Flux events, SendOptions options) { + if (registrySerializer != null) { + throw logger.logExceptionAsError( + new IllegalArgumentException("Serializer mode - sending EventData is not permitted")); + } + final String partitionKey = options.getPartitionKey(); final String partitionId = options.getPartitionId(); @@ -481,7 +526,8 @@ private Mono sendInternal(Flux events, SendOptions options) { .setPartitionKey(options.getPartitionKey()) .setPartitionId(options.getPartitionId()) .setMaximumSizeInBytes(batchSize); - return events.collect(new EventDataCollector(batchOptions, 1, link::getErrorContext, + return events.collect(new EventDataCollector(batchOptions, 1, + link::getErrorContext, tracerProvider, link.getEntityPath(), link.getHostname())); }) .flatMap(list -> sendInternal(Flux.fromIterable(list)))); @@ -547,7 +593,8 @@ private static class EventDataCollector implements Collector 0 ? options.getMaximumSizeInBytes() @@ -560,7 +607,7 @@ private static class EventDataCollector implements Collector, EventData> accumulator() { } currentBatch = new EventDataBatch(maxMessageSize, partitionId, partitionKey, contextProvider, - tracerProvider, entityPath, hostname); + tracerProvider, null, entityPath, hostname); currentBatch.tryAdd(event); list.add(batch); }; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerClient.java index 700fd8d9c648b..0a61cde976fd9 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerClient.java @@ -52,8 +52,8 @@ * @see EventHubProducerAsyncClient To asynchronously generate events to an Event Hub, see EventHubProducerAsyncClient. */ @ServiceClient(builder = EventHubClientBuilder.class) -public class EventHubProducerClient implements Closeable { - private final EventHubProducerAsyncClient producer; +public class EventHubProducerClient implements Closeable { + private final EventHubProducerAsyncClient producer; private final Duration tryTimeout; /** @@ -61,7 +61,7 @@ public class EventHubProducerClient implements Closeable { * * @throws NullPointerException if {@code producer} or {@code tryTimeout} is null. */ - EventHubProducerClient(EventHubProducerAsyncClient producer, Duration tryTimeout) { + EventHubProducerClient(EventHubProducerAsyncClient producer, Duration tryTimeout) { this.producer = Objects.requireNonNull(producer, "'producer' cannot be null."); this.tryTimeout = Objects.requireNonNull(tryTimeout, "'tryTimeout' cannot be null."); } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java new file mode 100644 index 0000000000000..8b421cb8f13c6 --- /dev/null +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -0,0 +1,228 @@ +package com.azure.messaging.eventhubs; + +import com.azure.core.amqp.AmqpMessageConstant; +import com.azure.core.amqp.exception.AmqpErrorCondition; +import com.azure.core.amqp.exception.AmqpException; +import com.azure.core.amqp.implementation.AmqpConstants; +import com.azure.core.amqp.implementation.ErrorContextProvider; +import com.azure.core.amqp.implementation.TracerProvider; +import com.azure.core.util.Context; +import com.azure.core.util.logging.ClientLogger; +import com.azure.core.util.tracing.ProcessKind; +import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; +import org.apache.qpid.proton.Proton; +import org.apache.qpid.proton.amqp.Binary; +import org.apache.qpid.proton.amqp.Symbol; +import org.apache.qpid.proton.amqp.messaging.ApplicationProperties; +import org.apache.qpid.proton.amqp.messaging.Data; +import org.apache.qpid.proton.amqp.messaging.MessageAnnotations; +import org.apache.qpid.proton.message.Message; +import reactor.core.publisher.Signal; + +import java.nio.BufferOverflowException; +import java.util.*; + +import static com.azure.core.util.tracing.Tracer.*; +import static com.azure.messaging.eventhubs.implementation.ClientConstants.AZ_NAMESPACE_VALUE; + +public final class ObjectBatch extends Batch { + private final ClientLogger logger = new ClientLogger(ObjectBatch.class)); + private final Object lock = new Object(); + private final Class batchType; + private final SchemaRegistryDataSerializer registrySerializer; + + ObjectBatch(int maxMessageSize, String partitionId, String partitionKey, Class batchType, + ErrorContextProvider contextProvider, TracerProvider tracerProvider, + SchemaRegistryDataSerializer registrySerializer, String entityPath, String hostname) { + super(maxMessageSize, partitionId, partitionKey, contextProvider, tracerProvider, entityPath, + hostname, new ClientLogger(ObjectBatch.class)); + this.batchType = batchType; + this.registrySerializer = registrySerializer; + } + + /** + * Tries to add an {@link EventData event} to the batch. + * + * @param object The {@link EventData} to add to the batch. + * @return {@code true} if the event could be added to the batch; {@code false} if the event was too large to fit in + * the batch. + * @throws IllegalArgumentException if {@code eventData} is {@code null}. + * @throws AmqpException if {@code eventData} is larger than the maximum size of the {@link EventDataBatch}. + */ + public boolean tryAdd(final T object) { + if (object == null) { + throw logger.logExceptionAsWarning(new IllegalArgumentException("object cannot be null")); + } + + EventData eventData = new EventData(registrySerializer.serialize(object).block()); + EventData event = tracerProvider.isEnabled() ? traceMessageSpan(eventData) : eventData; + + final int size; + try { + size = getSize(event, events.isEmpty()); + } catch (BufferOverflowException exception) { + throw logger.logExceptionAsWarning(new AmqpException(false, AmqpErrorCondition.LINK_PAYLOAD_SIZE_EXCEEDED, + String.format(Locale.US, "Size of the payload exceeded maximum message size: %s kb", + maxMessageSize / 1024), + contextProvider.getErrorContext())); + } + + synchronized (lock) { + if (this.sizeInBytes + size > this.maxMessageSize) { + return false; + } + + this.sizeInBytes += size; + } + + this.events.add(event); + return true; + } + + /** + * Method to start and end a "Azure.EventHubs.message" span and add the "DiagnosticId" as a property of the message. + * + * @param eventData The Event to add tracing span for. + * @return the updated event data object. + */ + private EventData traceMessageSpan(EventData eventData) { + Optional eventContextData = eventData.getContext().getData(SPAN_CONTEXT_KEY); + if (eventContextData.isPresent()) { + // if message has context (in case of retries), don't start a message span or add a new context + return eventData; + } else { + // Starting the span makes the sampling decision (nothing is logged at this time) + Context eventContext = eventData.getContext() + .addData(AZ_TRACING_NAMESPACE_KEY, AZ_NAMESPACE_VALUE) + .addData(ENTITY_PATH_KEY, this.entityPath) + .addData(HOST_NAME_KEY, this.hostname); + Context eventSpanContext = tracerProvider.startSpan(eventContext, ProcessKind.MESSAGE); + Optional eventDiagnosticIdOptional = eventSpanContext.getData(DIAGNOSTIC_ID_KEY); + if (eventDiagnosticIdOptional.isPresent()) { + eventData.getProperties().put(DIAGNOSTIC_ID_KEY, eventDiagnosticIdOptional.get().toString()); + tracerProvider.endSpan(eventSpanContext, Signal.complete()); + eventData.addContext(SPAN_CONTEXT_KEY, eventSpanContext); + } + } + + return eventData; + } + + List getEvents() { + return events; + } + + String getPartitionKey() { + return partitionKey; + } + + String getPartitionId() { + return partitionId; + } + + private int getSize(final EventData eventData, final boolean isFirst) { + Objects.requireNonNull(eventData, "'eventData' cannot be null."); + + final Message amqpMessage = createAmqpMessage(eventData, partitionKey); + int eventSize = amqpMessage.encode(this.eventBytes, 0, maxMessageSize); // actual encoded bytes size + eventSize += 16; // data section overhead + + if (isFirst) { + amqpMessage.setBody(null); + amqpMessage.setApplicationProperties(null); + amqpMessage.setProperties(null); + amqpMessage.setDeliveryAnnotations(null); + + eventSize += amqpMessage.encode(this.eventBytes, 0, maxMessageSize); + } + + return eventSize; + } + + /* + * Creates the AMQP message represented by the event data + */ + private Message createAmqpMessage(EventData event, String partitionKey) { + final Message message = Proton.message(); + + if (event.getProperties() != null && !event.getProperties().isEmpty()) { + final ApplicationProperties applicationProperties = new ApplicationProperties(event.getProperties()); + message.setApplicationProperties(applicationProperties); + } + + if (event.getSystemProperties() != null) { + event.getSystemProperties().forEach((key, value) -> { + if (EventData.RESERVED_SYSTEM_PROPERTIES.contains(key)) { + return; + } + + final AmqpMessageConstant constant = AmqpMessageConstant.fromString(key); + + if (constant != null) { + switch (constant) { + case MESSAGE_ID: + message.setMessageId(value); + break; + case USER_ID: + message.setUserId((byte[]) value); + break; + case TO: + message.setAddress((String) value); + break; + case SUBJECT: + message.setSubject((String) value); + break; + case REPLY_TO: + message.setReplyTo((String) value); + break; + case CORRELATION_ID: + message.setCorrelationId(value); + break; + case CONTENT_TYPE: + message.setContentType((String) value); + break; + case CONTENT_ENCODING: + message.setContentEncoding((String) value); + break; + case ABSOLUTE_EXPIRY_TIME: + message.setExpiryTime((long) value); + break; + case CREATION_TIME: + message.setCreationTime((long) value); + break; + case GROUP_ID: + message.setGroupId((String) value); + break; + case GROUP_SEQUENCE: + message.setGroupSequence((long) value); + break; + case REPLY_TO_GROUP_ID: + message.setReplyToGroupId((String) value); + break; + default: + throw logger.logExceptionAsWarning(new IllegalArgumentException(String.format(Locale.US, + "Property is not a recognized reserved property name: %s", key))); + } + } else { + final MessageAnnotations messageAnnotations = (message.getMessageAnnotations() == null) + ? new MessageAnnotations(new HashMap<>()) + : message.getMessageAnnotations(); + messageAnnotations.getValue().put(Symbol.getSymbol(key), value); + message.setMessageAnnotations(messageAnnotations); + } + }); + } + + if (partitionKey != null) { + final MessageAnnotations messageAnnotations = (message.getMessageAnnotations() == null) + ? new MessageAnnotations(new HashMap<>()) + : message.getMessageAnnotations(); + messageAnnotations.getValue().put(AmqpConstants.PARTITION_KEY, partitionKey); + message.setMessageAnnotations(messageAnnotations); + } + + message.setBody(new Data(new Binary(event.getBody()))); + + return message; + } +} diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java index 838025b1eff4e..a465e57f9447f 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java @@ -12,11 +12,12 @@ * A container for {@link EventData} along with the partition information for this event data. */ @Immutable -public class PartitionEvent { +public class PartitionEvent { private final PartitionContext partitionContext; private final EventData eventData; private final LastEnqueuedEventProperties lastEnqueuedEventProperties; + private final Object deserialized; /** * Creates an instance of PartitionEvent. @@ -24,13 +25,16 @@ public class PartitionEvent { * @param partitionContext The partition information associated with the event data. * @param eventData The event data received from the Event Hub. * @param lastEnqueuedEventProperties The properties of the last enqueued event in the partition. + * @param deserialized object deserialized by deserializer. Set to eventData byte array payload if no deserializer + * has been set. * @throws NullPointerException if {@code partitionContext} or {@code eventData} is {@code null}. */ public PartitionEvent(final PartitionContext partitionContext, final EventData eventData, - LastEnqueuedEventProperties lastEnqueuedEventProperties) { + LastEnqueuedEventProperties lastEnqueuedEventProperties, T deserialized) { this.partitionContext = Objects.requireNonNull(partitionContext, "'partitionContext' cannot be null"); this.eventData = Objects.requireNonNull(eventData, "'eventData' cannot be null"); this.lastEnqueuedEventProperties = lastEnqueuedEventProperties; + this.deserialized = deserialized; } /** @@ -59,4 +63,13 @@ public EventData getData() { public LastEnqueuedEventProperties getLastEnqueuedEventProperties() { return lastEnqueuedEventProperties; } + + /** + * Gets deserialized object from EventData byte payload + * @return deserialized object + */ + public T getDeserializedObject() { + Objects.requireNonNull(this.deserialized); + return (T) this.deserialized; + } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java index 0386dee075a72..86ce6f72469c8 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java @@ -6,6 +6,7 @@ requires transitive com.azure.core.amqp; requires com.microsoft.azure.qpid.protonj.extensions; + requires azure.data.schemaregistry; exports com.azure.messaging.eventhubs; exports com.azure.messaging.eventhubs.models; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchIntegrationTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchIntegrationTest.java index fa8afad99b1bc..34558f868d668 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchIntegrationTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchIntegrationTest.java @@ -67,7 +67,7 @@ protected void afterTest() { public void sendSmallEventsFullBatch() { // Arrange final EventDataBatch batch = new EventDataBatch(ClientConstants.MAX_MESSAGE_LENGTH_BYTES, null, null, contextProvider, - new TracerProvider(Collections.emptyList()), getFullyQualifiedDomainName(), getEventHubName()); + new TracerProvider(Collections.emptyList()), null, getFullyQualifiedDomainName(), getEventHubName()); int count = 0; while (batch.tryAdd(createData())) { // We only print every 100th item or it'll be really spammy. @@ -90,7 +90,7 @@ public void sendSmallEventsFullBatch() { public void sendSmallEventsFullBatchPartitionKey() { // Arrange final EventDataBatch batch = new EventDataBatch(ClientConstants.MAX_MESSAGE_LENGTH_BYTES, null, - PARTITION_KEY, contextProvider, tracerProvider, getFullyQualifiedDomainName(), getEventHubName()); + PARTITION_KEY, contextProvider, tracerProvider, null, getFullyQualifiedDomainName(), getEventHubName()); int count = 0; while (batch.tryAdd(createData())) { // We only print every 100th item or it'll be really spammy. @@ -116,7 +116,7 @@ public void sendBatchPartitionKeyValidate() throws InterruptedException { final SendOptions sendOptions = new SendOptions().setPartitionKey(PARTITION_KEY); final EventDataBatch batch = new EventDataBatch(ClientConstants.MAX_MESSAGE_LENGTH_BYTES, null, - PARTITION_KEY, contextProvider, tracerProvider, getFullyQualifiedDomainName(), getEventHubName()); + PARTITION_KEY, contextProvider, tracerProvider, null, getFullyQualifiedDomainName(), getEventHubName()); int count = 0; while (count < 10) { final EventData data = createData(); @@ -183,7 +183,7 @@ public void sendEventsFullBatchWithPartitionKey() { // Arrange final int maxMessageSize = 1024; final EventDataBatch batch = new EventDataBatch(maxMessageSize, null, PARTITION_KEY, contextProvider, - tracerProvider, getFullyQualifiedDomainName(), getEventHubName()); + tracerProvider, null, getFullyQualifiedDomainName(), getEventHubName()); final Random random = new Random(); final SendOptions sendOptions = new SendOptions().setPartitionKey(PARTITION_KEY); int count = 0; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchTest.java index ea85afedd71f0..42c1edfe2e781 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchTest.java @@ -34,7 +34,7 @@ public void setup() { @Test public void nullEventData() { assertThrows(IllegalArgumentException.class, () -> { - final EventDataBatch batch = new EventDataBatch(1024, null, PARTITION_KEY, null, null, null, null); + final EventDataBatch batch = new EventDataBatch(1024, null, PARTITION_KEY, null, null, null, null, null); batch.tryAdd(null); }); } @@ -47,7 +47,7 @@ public void payloadExceededException() { when(errorContextProvider.getErrorContext()).thenReturn(new AmqpErrorContext("test-namespace")); final EventDataBatch batch = new EventDataBatch(1024, null, PARTITION_KEY, errorContextProvider, - new TracerProvider(Collections.emptyList()), null, null); + new TracerProvider(Collections.emptyList()), null, null, null); final EventData tooBig = new EventData(new byte[1024 * 1024 * 2]); try { batch.tryAdd(tooBig); @@ -65,7 +65,7 @@ public void payloadExceededException() { public void withinPayloadSize() { final int maxSize = ClientConstants.MAX_MESSAGE_LENGTH_BYTES; final EventDataBatch batch = new EventDataBatch(ClientConstants.MAX_MESSAGE_LENGTH_BYTES, null, PARTITION_KEY, - null, new TracerProvider(Collections.emptyList()), null, null); + null, new TracerProvider(Collections.emptyList()), null, null, null); final EventData within = new EventData(new byte[1024]); Assertions.assertEquals(maxSize, batch.getMaxSizeInBytes()); @@ -83,7 +83,7 @@ public void setsPartitionId() { // Act final EventDataBatch batch = new EventDataBatch(ClientConstants.MAX_MESSAGE_LENGTH_BYTES, partitionId, - PARTITION_KEY, null, null, null, null); + PARTITION_KEY, null, null, null, null, null); // Assert Assertions.assertEquals(PARTITION_KEY, batch.getPartitionKey()); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java index c37f1686c710d..40dc4288b312d 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java @@ -137,7 +137,7 @@ CbsAuthorizationType.SHARED_ACCESS_SIGNATURE, AmqpTransportType.AMQP_WEB_SOCKETS "event-hub-name", connectionOptions.getRetry())); consumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, - CONSUMER_GROUP, PREFETCH, parallelScheduler, false, onClientClosed); + CONSUMER_GROUP, null, PREFETCH, parallelScheduler, false, onClientClosed); } @AfterEach @@ -156,7 +156,7 @@ void teardown() { @Test void lastEnqueuedEventInformationIsNull() { final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, DEFAULT_PREFETCH_COUNT, parallelScheduler, false, onClientClosed); + connectionProcessor, messageSerializer, CONSUMER_GROUP, null, DEFAULT_PREFETCH_COUNT, parallelScheduler, false, onClientClosed); final int numberOfEvents = 10; when(amqpReceiveLink.getCredits()).thenReturn(numberOfEvents); final int numberToReceive = 3; @@ -179,7 +179,7 @@ void lastEnqueuedEventInformationIsNull() { void lastEnqueuedEventInformationCreated() { // Arrange final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, DEFAULT_PREFETCH_COUNT, Schedulers.parallel(), false, onClientClosed); + connectionProcessor, messageSerializer, CONSUMER_GROUP, null, DEFAULT_PREFETCH_COUNT, Schedulers.parallel(), false, onClientClosed); final int numberOfEvents = 10; final ReceiveOptions receiveOptions = new ReceiveOptions().setTrackLastEnqueuedEventProperties(true); when(amqpReceiveLink.getCredits()).thenReturn(numberOfEvents); @@ -232,7 +232,7 @@ void receivesNumberOfEventsAllowsBlock() throws InterruptedException { // Scheduling on elastic to simulate a user passed in scheduler (this is the default in EventHubClientBuilder). final EventHubConsumerAsyncClient myConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.elastic(), false, onClientClosed); + connectionProcessor, messageSerializer, CONSUMER_GROUP, null, PREFETCH, Schedulers.elastic(), false, onClientClosed); final Flux eventsFlux = myConsumer.receiveFromPartition(PARTITION_ID, EventPosition.earliest()) .take(numberOfEvents); @@ -294,7 +294,7 @@ void returnsNewListener() { any(ReceiveOptions.class))).thenReturn(Mono.just(link2), Mono.just(link3)); EventHubConsumerAsyncClient asyncClient = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, testScheduler, false, onClientClosed); + eventHubConnection, messageSerializer, CONSUMER_GROUP, null, PREFETCH, testScheduler, false, onClientClosed); // Act & Assert StepVerifier.create(asyncClient.receiveFromPartition(PARTITION_ID, EventPosition.earliest()).take(numberOfEvents)) @@ -517,7 +517,7 @@ void receivesMultiplePartitions() { .thenReturn(Mono.just(new EventHubProperties(EVENT_HUB_NAME, Instant.EPOCH, partitions))); EventHubConsumerAsyncClient asyncClient = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, parallelScheduler, false, onClientClosed); + eventHubConnection, messageSerializer, CONSUMER_GROUP, null, PREFETCH, parallelScheduler, false, onClientClosed); EmitterProcessor processor2 = EmitterProcessor.create(); FluxSink processor2sink = processor2.sink(); @@ -592,7 +592,7 @@ void receivesMultiplePartitionsWhenOneCloses() { .thenReturn(Mono.just(new EventHubProperties(EVENT_HUB_NAME, Instant.EPOCH, partitions))); EventHubConsumerAsyncClient asyncClient = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); + eventHubConnection, messageSerializer, CONSUMER_GROUP, null, PREFETCH, Schedulers.parallel(), false, onClientClosed); EmitterProcessor processor2 = EmitterProcessor.create(); FluxSink processor2sink = processor2.sink(); @@ -652,7 +652,7 @@ void doesNotCloseSharedConnection() { EventHubConnectionProcessor eventHubConnection = Flux.create(sink -> sink.next(connection1)) .subscribeWith(new EventHubConnectionProcessor(HOSTNAME, EVENT_HUB_NAME, retryOptions)); EventHubConsumerAsyncClient sharedConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), true, onClientClosed); + eventHubConnection, messageSerializer, CONSUMER_GROUP, null, PREFETCH, Schedulers.parallel(), true, onClientClosed); // Act sharedConsumer.close(); @@ -672,7 +672,7 @@ void closesDedicatedConnection() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubConsumerAsyncClient dedicatedConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); + hubConnection, messageSerializer, CONSUMER_GROUP, null, PREFETCH, Schedulers.parallel(), false, onClientClosed); // Act dedicatedConsumer.close(); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java index b05a875f23617..fe955ad0af7df 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java @@ -118,7 +118,7 @@ CbsAuthorizationType.SHARED_ACCESS_SIGNATURE, AmqpTransportType.AMQP_WEB_SOCKETS })); asyncConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); + connectionProcessor, messageSerializer, CONSUMER_GROUP, null, PREFETCH, Schedulers.parallel(), false, onClientClosed); consumer = new EventHubConsumerClient(asyncConsumer, Duration.ofSeconds(10)); } @@ -143,7 +143,7 @@ public void lastEnqueuedEventInformationIsNull() { // Arrange final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient( HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, CONSUMER_GROUP, - PREFETCH, Schedulers.parallel(), false, onClientClosed); + null, PREFETCH, Schedulers.parallel(), false, onClientClosed); final EventHubConsumerClient consumer = new EventHubConsumerClient(runtimeConsumer, Duration.ofSeconds(5)); final int numberOfEvents = 10; sendMessages(sink, numberOfEvents, PARTITION_ID); @@ -172,7 +172,7 @@ public void lastEnqueuedEventInformationCreated() { // Arrange final ReceiveOptions options = new ReceiveOptions().setTrackLastEnqueuedEventProperties(true); final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient( - HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, CONSUMER_GROUP, PREFETCH, + HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, CONSUMER_GROUP, null, PREFETCH, Schedulers.parallel(), false, onClientClosed); final EventHubConsumerClient consumer = new EventHubConsumerClient(runtimeConsumer, Duration.ofSeconds(5)); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java index 3510200950493..748aaa1328592 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java @@ -117,7 +117,7 @@ void receivesMessages(boolean trackLastEnqueuedProperties) { // Arrange linkProcessor = createSink(link1, link2).subscribeWith(new AmqpReceiveLinkProcessor(PREFETCH, retryPolicy, parentConnection)); consumer = new EventHubPartitionAsyncConsumer(linkProcessor, messageSerializer, HOSTNAME, EVENT_HUB_NAME, - CONSUMER_GROUP, PARTITION_ID, currentPosition, trackLastEnqueuedProperties, Schedulers.parallel()); + CONSUMER_GROUP, PARTITION_ID, currentPosition, trackLastEnqueuedProperties, Schedulers.parallel(), null); final EventData event1 = new EventData("Foo"); final EventData event2 = new EventData("Bar"); @@ -165,7 +165,7 @@ void receiveMultipleTimes() { // Arrange linkProcessor = createSink(link1, link2).subscribeWith(new AmqpReceiveLinkProcessor(PREFETCH, retryPolicy, parentConnection)); consumer = new EventHubPartitionAsyncConsumer(linkProcessor, messageSerializer, HOSTNAME, EVENT_HUB_NAME, - CONSUMER_GROUP, PARTITION_ID, currentPosition, false, Schedulers.parallel()); + CONSUMER_GROUP, PARTITION_ID, currentPosition, false, Schedulers.parallel(), null); final Message message3 = mock(Message.class); final String secondOffset = "54"; @@ -233,7 +233,7 @@ void listensToShutdownSignals() throws InterruptedException { // Arrange linkProcessor = createSink(link1, link2).subscribeWith(new AmqpReceiveLinkProcessor(PREFETCH, retryPolicy, parentConnection)); consumer = new EventHubPartitionAsyncConsumer(linkProcessor, messageSerializer, HOSTNAME, EVENT_HUB_NAME, - CONSUMER_GROUP, PARTITION_ID, currentPosition, false, Schedulers.parallel()); + CONSUMER_GROUP, PARTITION_ID, currentPosition, false, Schedulers.parallel(), null); final Message message3 = mock(Message.class); final String secondOffset = "54"; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java index 85eaacce57ff4..6ab8b2d20f3a9 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java @@ -146,7 +146,7 @@ void setup(TestInfo testInfo) { new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), "event-hub-path", connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, testScheduler, false, onClientClosed); + tracerProvider, messageSerializer, null, testScheduler, false, onClientClosed); when(sendLink.getLinkSize()).thenReturn(Mono.just(ClientConstants.MAX_MESSAGE_LENGTH_BYTES)); when(sendLink2.getLinkSize()).thenReturn(Mono.just(ClientConstants.MAX_MESSAGE_LENGTH_BYTES)); @@ -238,7 +238,7 @@ void sendSingleMessageWithBlock() throws InterruptedException { final Semaphore semaphore = new Semaphore(1); // In our actual client builder, we allow this. final EventHubProducerAsyncClient flexibleProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, testScheduler, + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, testScheduler, false, onClientClosed); // EC is the prefix they use when creating a link that sends to the service round-robin. @@ -319,7 +319,7 @@ void sendStartSpanSingleMessage() { final SendOptions sendOptions = new SendOptions() .setPartitionId(partitionId); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); when(connection.createSendLink( @@ -377,7 +377,7 @@ void sendMessageRetrySpanTest() { TracerProvider tracerProvider = new TracerProvider(tracers); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed); + tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final String failureKey = "fail"; final EventData testData = new EventData("test"); @@ -516,7 +516,7 @@ void startMessageSpansOnCreateBatch() { final List tracers = Collections.singletonList(tracer1); TracerProvider tracerProvider = new TracerProvider(tracers); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final AmqpSendLink link = mock(AmqpSendLink.class); @@ -822,7 +822,7 @@ void doesNotCloseSharedConnection() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubProducerAsyncClient sharedProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + hubConnection, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), true, onClientClosed); // Act @@ -841,7 +841,7 @@ void closesDedicatedConnection() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubProducerAsyncClient dedicatedProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + hubConnection, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); // Act @@ -860,7 +860,7 @@ void closesDedicatedConnectionOnlyOnce() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubProducerAsyncClient dedicatedProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + hubConnection, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); // Act @@ -897,7 +897,7 @@ void reopensOnFailure() { new EventHubConnectionProcessor(EVENT_HUB_NAME, connectionOptions.getFullyQualifiedNamespace(), connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed); + tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final int count = 4; final byte[] contents = TEST_CONTENTS.getBytes(UTF_8); @@ -972,7 +972,7 @@ void closesOnNonTransientFailure() { new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), EVENT_HUB_NAME, connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed); + tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final int count = 4; final byte[] contents = TEST_CONTENTS.getBytes(UTF_8); @@ -1048,7 +1048,7 @@ void resendMessageOnTransientLinkFailure() { new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), EVENT_HUB_NAME, connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed); + tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final int count = 4; final byte[] contents = TEST_CONTENTS.getBytes(UTF_8); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java index 9e0455d89957b..02ec09aaeb2c1 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java @@ -105,7 +105,7 @@ public void setup() { .subscribeWith(new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), "event-hub-path", connectionOptions.getRetry())); asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed); + tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); when(connection.getEndpointStates()).thenReturn(Flux.create(sink -> sink.next(AmqpEndpointState.ACTIVE))); } @@ -157,7 +157,7 @@ public void sendStartSpanSingleMessage() { final List tracers = Collections.singletonList(tracer1); final TracerProvider tracerProvider = new TracerProvider(tracers); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); final EventData eventData = new EventData("hello-world".getBytes(UTF_8)); @@ -219,7 +219,7 @@ public void sendMessageRetrySpanTest() { .thenReturn(Mono.just(sendLink)); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); final EventData eventData = new EventData("hello-world".getBytes(UTF_8)) .addContext(SPAN_CONTEXT_KEY, Context.NONE); @@ -267,7 +267,7 @@ public void sendEventsExceedsBatchSize() { when(sendLink.getLinkSize()).thenReturn(Mono.just(1024)); TracerProvider tracerProvider = new TracerProvider(Collections.emptyList()); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); //Act & Assert @@ -369,7 +369,7 @@ public void startsMessageSpanOnEventBatch() { final List tracers = Collections.singletonList(tracer1); final TracerProvider tracerProvider = new TracerProvider(tracers); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java index a79be245862d5..5dc5079bde4fd 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java @@ -139,7 +139,7 @@ private static Stream checkpointStoreSupplier() { private PartitionEvent getEvent(EventData event) { PartitionContext context = new PartitionContext("ns", "foo", "bar", "baz"); - return new PartitionEvent(context, event, null); + return new PartitionEvent(context, event, null, deserialized); } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java index 05888a75f6cb4..567d199b0ce6d 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java @@ -474,7 +474,7 @@ public void testSingleEventReceiveHeartBeat() throws InterruptedException { private PartitionEvent getEvent(EventData event) { PartitionContext context = new PartitionContext("test-ns", "foo", "bar", "baz"); - return new PartitionEvent(context, event, null); + return new PartitionEvent(context, event, null, deserialized); } private static final class TestPartitionProcessor extends PartitionProcessor { diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java index 698aee42498ea..b0fb91a29ce65 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java @@ -113,7 +113,7 @@ public void testSingleEventProcessor() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); })); PartitionBasedLoadBalancer partitionBasedLoadBalancer = createPartitionLoadBalancer("owner1"); @@ -149,7 +149,7 @@ public void testTwoEventProcessors() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); })); PartitionBasedLoadBalancer partitionBasedLoadBalancer1 = createPartitionLoadBalancer("owner1"); @@ -185,7 +185,7 @@ public void testPartitionStealing() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); })); PartitionBasedLoadBalancer partitionBasedLoadBalancer1 = createPartitionLoadBalancer("owner1"); @@ -225,7 +225,7 @@ public void testMoreEventProcessorsThanPartitions() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); })); List loadBalancers = new ArrayList<>(); @@ -263,7 +263,7 @@ public void testEventProcessorInactive() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); final int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); })); List loadBalancers = new ArrayList<>(); @@ -422,7 +422,7 @@ public void testEmptyOwnerId() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); final int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); })); String ownerName = "owner1"; diff --git a/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncDeserializer.java b/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncDeserializer.java index e43ab1de10f51..20227a9c1b629 100644 --- a/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncDeserializer.java +++ b/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncDeserializer.java @@ -3,6 +3,7 @@ package com.azure.data.schemaregistry.avro; +import com.azure.data.schemaregistry.SchemaRegistryDataDeserializer; import com.azure.data.schemaregistry.SerializationException; import reactor.core.publisher.Mono; import reactor.core.scheduler.Scheduler; @@ -13,7 +14,7 @@ /** * Asynchronous registry-based deserializer implementation. */ -public class SchemaRegistryAvroAsyncDeserializer { +public class SchemaRegistryAvroAsyncDeserializer implements SchemaRegistryDataDeserializer { private static final int DEFAULT_THREAD_POOL_SIZE = 8; private final SchemaRegistryAvroDeserializer deserializer; diff --git a/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncSerializer.java b/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncSerializer.java index 7d8edfb020bac..e004ea98bb083 100644 --- a/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncSerializer.java +++ b/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncSerializer.java @@ -3,7 +3,7 @@ package com.azure.data.schemaregistry.avro; -import com.azure.data.schemaregistry.AbstractDataSerializer; +import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; import com.azure.data.schemaregistry.SerializationException; import reactor.core.publisher.Mono; import reactor.core.scheduler.Scheduler; @@ -14,7 +14,7 @@ /** * Asynchronous registry-based serializer implementation. */ -public class SchemaRegistryAvroAsyncSerializer extends AbstractDataSerializer { +public class SchemaRegistryAvroAsyncSerializer implements SchemaRegistryDataSerializer { private static final int DEFAULT_THREAD_POOL_SIZE = 8; private final SchemaRegistryAvroSerializer serializer; diff --git a/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataDeserializer.java b/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataDeserializer.java new file mode 100644 index 0000000000000..79a9400cdcf0d --- /dev/null +++ b/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataDeserializer.java @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.schemaregistry; + +import reactor.core.publisher.Mono; + +/** + * deserializer implementation + */ +public interface SchemaRegistryDataDeserializer { + /** + * deserialize SR client produced bytes + * @param data to be deserialized + * @return deserialized object + */ + Mono deserialize(byte[] data); +} diff --git a/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataSerializer.java b/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataSerializer.java new file mode 100644 index 0000000000000..ebbf495305664 --- /dev/null +++ b/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataSerializer.java @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.data.schemaregistry; + +import reactor.core.publisher.Mono; + +/** + * serializer interface + */ +public interface SchemaRegistryDataSerializer { + + Mono prefetchSchema(Class objectClass); + + /** + * serializer method + * @param object to be serialized + * @return Mono of serialized byte array + */ + byte[] serialize(Object object); +} From 544a6e77b9e7c8754801e645fa8924eed96f4c56 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Tue, 16 Jun 2020 16:27:07 -0700 Subject: [PATCH 02/29] fix object batch --- .../com/azure/messaging/eventhubs/Batch.java | 44 ++- .../messaging/eventhubs/EventDataBatch.java | 255 +----------------- .../eventhubs/EventHubAsyncClient.java | 30 +-- .../eventhubs/EventHubClientBuilder.java | 16 +- .../EventHubConsumerAsyncClient.java | 19 +- .../EventHubPartitionAsyncConsumer.java | 24 +- .../EventHubProducerAsyncClient.java | 148 ++++++---- .../eventhubs/EventHubProducerClient.java | 6 +- .../messaging/eventhubs/ObjectBatch.java | 217 ++------------- .../eventhubs/models/PartitionEvent.java | 17 +- .../EventDataBatchIntegrationTest.java | 8 +- .../eventhubs/EventDataBatchTest.java | 8 +- .../EventHubConsumerAsyncClientTest.java | 18 +- .../eventhubs/EventHubConsumerClientTest.java | 6 +- .../EventHubPartitionAsyncConsumerTest.java | 6 +- .../EventHubProducerAsyncClientTest.java | 34 +-- .../eventhubs/EventHubProducerClientTest.java | 14 +- ...EventProcessorClientErrorHandlingTest.java | 2 +- .../eventhubs/EventProcessorClientTest.java | 2 +- .../PartitionBasedLoadBalancerTest.java | 12 +- 20 files changed, 263 insertions(+), 623 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java index 87b0377258858..cbe4da3466f0f 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java @@ -1,6 +1,8 @@ package com.azure.messaging.eventhubs; import com.azure.core.amqp.AmqpMessageConstant; +import com.azure.core.amqp.exception.AmqpErrorCondition; +import com.azure.core.amqp.exception.AmqpException; import com.azure.core.amqp.implementation.AmqpConstants; import com.azure.core.amqp.implementation.ErrorContextProvider; import com.azure.core.amqp.implementation.TracerProvider; @@ -16,6 +18,7 @@ import org.apache.qpid.proton.message.Message; import reactor.core.publisher.Signal; +import java.nio.BufferOverflowException; import java.util.*; import static com.azure.core.util.tracing.Tracer.*; @@ -76,6 +79,43 @@ public int getSizeInBytes() { return this.sizeInBytes; } + /** + * Tries to add an {@link EventData event} to the batch. + * + * @param eventData The {@link EventData} to add to the batch. + * @return {@code true} if the event could be added to the batch; {@code false} if the event was too large to fit in + * the batch. + * @throws IllegalArgumentException if {@code eventData} is {@code null}. + * @throws AmqpException if {@code eventData} is larger than the maximum size of the {@link EventDataBatch}. + */ + public boolean tryAdd(final EventData eventData) { + if (eventData == null) { + throw logger.logExceptionAsWarning(new IllegalArgumentException("eventData cannot be null")); + } + EventData event = tracerProvider.isEnabled() ? traceMessageSpan(eventData) : eventData; + + final int size; + try { + size = getSize(event, events.isEmpty()); + } catch (BufferOverflowException exception) { + throw logger.logExceptionAsWarning(new AmqpException(false, AmqpErrorCondition.LINK_PAYLOAD_SIZE_EXCEEDED, + String.format(Locale.US, "Size of the payload exceeded maximum message size: %s kb", + maxMessageSize / 1024), + contextProvider.getErrorContext())); + } + + synchronized (lock) { + if (this.sizeInBytes + size > this.maxMessageSize) { + return false; + } + + this.sizeInBytes += size; + } + + this.events.add(event); + return true; + } + /** * Method to start and end a "Azure.EventHubs.message" span and add the "DiagnosticId" as a property of the message. @@ -83,7 +123,7 @@ public int getSizeInBytes() { * @param eventData The Event to add tracing span for. * @return the updated event data object. */ - private EventData traceMessageSpan(EventData eventData) { + EventData traceMessageSpan(EventData eventData) { Optional eventContextData = eventData.getContext().getData(SPAN_CONTEXT_KEY); if (eventContextData.isPresent()) { // if message has context (in case of retries), don't start a message span or add a new context @@ -118,7 +158,7 @@ String getPartitionId() { return partitionId; } - private int getSize(final EventData eventData, final boolean isFirst) { + int getSize(final EventData eventData, final boolean isFirst) { Objects.requireNonNull(eventData, "'eventData' cannot be null."); final Message amqpMessage = createAmqpMessage(eventData, partitionKey); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatch.java index 5656e9e588bc9..4ea3673f47f2e 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatch.java @@ -3,38 +3,9 @@ package com.azure.messaging.eventhubs; -import com.azure.core.amqp.AmqpMessageConstant; -import com.azure.core.amqp.exception.AmqpErrorCondition; import com.azure.core.amqp.exception.AmqpException; -import com.azure.core.amqp.implementation.AmqpConstants; import com.azure.core.amqp.implementation.ErrorContextProvider; import com.azure.core.amqp.implementation.TracerProvider; -import com.azure.core.util.Context; -import com.azure.core.util.logging.ClientLogger; -import com.azure.core.util.tracing.ProcessKind; -import org.apache.qpid.proton.Proton; -import org.apache.qpid.proton.amqp.Binary; -import org.apache.qpid.proton.amqp.Symbol; -import org.apache.qpid.proton.amqp.messaging.ApplicationProperties; -import org.apache.qpid.proton.amqp.messaging.Data; -import org.apache.qpid.proton.amqp.messaging.MessageAnnotations; -import org.apache.qpid.proton.message.Message; -import reactor.core.publisher.Signal; - -import java.nio.BufferOverflowException; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Objects; -import java.util.Optional; - -import static com.azure.core.util.tracing.Tracer.AZ_TRACING_NAMESPACE_KEY; -import static com.azure.core.util.tracing.Tracer.DIAGNOSTIC_ID_KEY; -import static com.azure.core.util.tracing.Tracer.ENTITY_PATH_KEY; -import static com.azure.core.util.tracing.Tracer.HOST_NAME_KEY; -import static com.azure.core.util.tracing.Tracer.SPAN_CONTEXT_KEY; -import static com.azure.messaging.eventhubs.implementation.ClientConstants.AZ_NAMESPACE_VALUE; /** * A class for aggregating {@link EventData} into a single, size-limited, batch. It is treated as a single message when @@ -45,59 +16,10 @@ * @see EventHubClientBuilder See EventHubClientBuilder for examples of building an asynchronous or synchronous * producer. */ -public final class EventDataBatch { - private final ClientLogger logger = new ClientLogger(EventDataBatch.class); - private final Object lock = new Object(); - private final int maxMessageSize; - private final String partitionKey; - private final ErrorContextProvider contextProvider; - private final List events; - private final byte[] eventBytes; - private final String partitionId; - private int sizeInBytes; - private final TracerProvider tracerProvider; - private final String entityPath; - private final String hostname; - +public final class EventDataBatch extends Batch { EventDataBatch(int maxMessageSize, String partitionId, String partitionKey, ErrorContextProvider contextProvider, TracerProvider tracerProvider, String entityPath, String hostname) { - this.maxMessageSize = maxMessageSize; - this.partitionKey = partitionKey; - this.partitionId = partitionId; - this.contextProvider = contextProvider; - this.events = new LinkedList<>(); - this.sizeInBytes = (maxMessageSize / 65536) * 1024; // reserve 1KB for every 64KB - this.eventBytes = new byte[maxMessageSize]; - this.tracerProvider = tracerProvider; - this.entityPath = entityPath; - this.hostname = hostname; - } - - /** - * Gets the number of {@link EventData events} in the batch. - * - * @return The number of {@link EventData events} in the batch. - */ - public int getCount() { - return events.size(); - } - - /** - * Gets the maximum size, in bytes, of the {@link EventDataBatch}. - * - * @return The maximum size, in bytes, of the {@link EventDataBatch}. - */ - public int getMaxSizeInBytes() { - return maxMessageSize; - } - - /** - * Gets the size of the {@link EventDataBatch} in bytes. - * - * @return the size of the {@link EventDataBatch} in bytes. - */ - public int getSizeInBytes() { - return this.sizeInBytes; + super(maxMessageSize, partitionId, partitionKey, contextProvider, tracerProvider, entityPath, hostname); } /** @@ -110,177 +32,6 @@ public int getSizeInBytes() { * @throws AmqpException if {@code eventData} is larger than the maximum size of the {@link EventDataBatch}. */ public boolean tryAdd(final EventData eventData) { - if (eventData == null) { - throw logger.logExceptionAsWarning(new IllegalArgumentException("eventData cannot be null")); - } - EventData event = tracerProvider.isEnabled() ? traceMessageSpan(eventData) : eventData; - - final int size; - try { - size = getSize(event, events.isEmpty()); - } catch (BufferOverflowException exception) { - throw logger.logExceptionAsWarning(new AmqpException(false, AmqpErrorCondition.LINK_PAYLOAD_SIZE_EXCEEDED, - String.format(Locale.US, "Size of the payload exceeded maximum message size: %s kb", - maxMessageSize / 1024), - contextProvider.getErrorContext())); - } - - synchronized (lock) { - if (this.sizeInBytes + size > this.maxMessageSize) { - return false; - } - - this.sizeInBytes += size; - } - - this.events.add(event); - return true; - } - - /** - * Method to start and end a "Azure.EventHubs.message" span and add the "DiagnosticId" as a property of the message. - * - * @param eventData The Event to add tracing span for. - * @return the updated event data object. - */ - private EventData traceMessageSpan(EventData eventData) { - Optional eventContextData = eventData.getContext().getData(SPAN_CONTEXT_KEY); - if (eventContextData.isPresent()) { - // if message has context (in case of retries), don't start a message span or add a new context - return eventData; - } else { - // Starting the span makes the sampling decision (nothing is logged at this time) - Context eventContext = eventData.getContext() - .addData(AZ_TRACING_NAMESPACE_KEY, AZ_NAMESPACE_VALUE) - .addData(ENTITY_PATH_KEY, this.entityPath) - .addData(HOST_NAME_KEY, this.hostname); - Context eventSpanContext = tracerProvider.startSpan(eventContext, ProcessKind.MESSAGE); - Optional eventDiagnosticIdOptional = eventSpanContext.getData(DIAGNOSTIC_ID_KEY); - if (eventDiagnosticIdOptional.isPresent()) { - eventData.getProperties().put(DIAGNOSTIC_ID_KEY, eventDiagnosticIdOptional.get().toString()); - tracerProvider.endSpan(eventSpanContext, Signal.complete()); - eventData.addContext(SPAN_CONTEXT_KEY, eventSpanContext); - } - } - - return eventData; - } - - List getEvents() { - return events; - } - - String getPartitionKey() { - return partitionKey; - } - - String getPartitionId() { - return partitionId; - } - - private int getSize(final EventData eventData, final boolean isFirst) { - Objects.requireNonNull(eventData, "'eventData' cannot be null."); - - final Message amqpMessage = createAmqpMessage(eventData, partitionKey); - int eventSize = amqpMessage.encode(this.eventBytes, 0, maxMessageSize); // actual encoded bytes size - eventSize += 16; // data section overhead - - if (isFirst) { - amqpMessage.setBody(null); - amqpMessage.setApplicationProperties(null); - amqpMessage.setProperties(null); - amqpMessage.setDeliveryAnnotations(null); - - eventSize += amqpMessage.encode(this.eventBytes, 0, maxMessageSize); - } - - return eventSize; - } - - /* - * Creates the AMQP message represented by the event data - */ - private Message createAmqpMessage(EventData event, String partitionKey) { - final Message message = Proton.message(); - - if (event.getProperties() != null && !event.getProperties().isEmpty()) { - final ApplicationProperties applicationProperties = new ApplicationProperties(event.getProperties()); - message.setApplicationProperties(applicationProperties); - } - - if (event.getSystemProperties() != null) { - event.getSystemProperties().forEach((key, value) -> { - if (EventData.RESERVED_SYSTEM_PROPERTIES.contains(key)) { - return; - } - - final AmqpMessageConstant constant = AmqpMessageConstant.fromString(key); - - if (constant != null) { - switch (constant) { - case MESSAGE_ID: - message.setMessageId(value); - break; - case USER_ID: - message.setUserId((byte[]) value); - break; - case TO: - message.setAddress((String) value); - break; - case SUBJECT: - message.setSubject((String) value); - break; - case REPLY_TO: - message.setReplyTo((String) value); - break; - case CORRELATION_ID: - message.setCorrelationId(value); - break; - case CONTENT_TYPE: - message.setContentType((String) value); - break; - case CONTENT_ENCODING: - message.setContentEncoding((String) value); - break; - case ABSOLUTE_EXPIRY_TIME: - message.setExpiryTime((long) value); - break; - case CREATION_TIME: - message.setCreationTime((long) value); - break; - case GROUP_ID: - message.setGroupId((String) value); - break; - case GROUP_SEQUENCE: - message.setGroupSequence((long) value); - break; - case REPLY_TO_GROUP_ID: - message.setReplyToGroupId((String) value); - break; - default: - throw logger.logExceptionAsWarning(new IllegalArgumentException(String.format(Locale.US, - "Property is not a recognized reserved property name: %s", key))); - } - } else { - final MessageAnnotations messageAnnotations = (message.getMessageAnnotations() == null) - ? new MessageAnnotations(new HashMap<>()) - : message.getMessageAnnotations(); - messageAnnotations.getValue().put(Symbol.getSymbol(key), value); - message.setMessageAnnotations(messageAnnotations); - } - }); - } - - if (partitionKey != null) { - final MessageAnnotations messageAnnotations = (message.getMessageAnnotations() == null) - ? new MessageAnnotations(new HashMap<>()) - : message.getMessageAnnotations(); - messageAnnotations.getValue().put(AmqpConstants.PARTITION_KEY, partitionKey); - message.setMessageAnnotations(messageAnnotations); - } - - message.setBody(new Data(new Binary(event.getBody()))); - - return message; + return super.tryAdd(eventData); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java index 301b98bcc9afa..f0efe1cac39c4 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java @@ -6,7 +6,6 @@ import com.azure.core.amqp.implementation.MessageSerializer; import com.azure.core.amqp.implementation.TracerProvider; import com.azure.core.util.logging.ClientLogger; -import com.azure.data.schemaregistry.SchemaRegistryDataDeserializer; import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; import com.azure.messaging.eventhubs.implementation.EventHubConnectionProcessor; import com.azure.messaging.eventhubs.implementation.EventHubManagementNode; @@ -26,7 +25,7 @@ * @see EventHubClient See EventHubClient to communicate with an Event Hub using a synchronous client. * @see About Azure Event Hubs */ -class EventHubAsyncClient implements Closeable { +class EventHubAsyncClient implements Closeable { private final ClientLogger logger = new ClientLogger(EventHubAsyncClient.class); private final MessageSerializer messageSerializer; private final EventHubConnectionProcessor connectionProcessor; @@ -34,16 +33,12 @@ class EventHubAsyncClient implements Closeable { private final boolean isSharedConnection; private final Runnable onClientClose; private final TracerProvider tracerProvider; - private final SchemaRegistryDataSerializer registrySerializer; - private final SchemaRegistryDataDeserializer registryDeserializer; + private final SchemaRegistryDataSerializer registrySerializer; EventHubAsyncClient(EventHubConnectionProcessor connectionProcessor, TracerProvider tracerProvider, - MessageSerializer messageSerializer, Scheduler scheduler, boolean isSharedConnection, - Runnable onClientClose, SchemaRegistryDataSerializer registrySerializer, - SchemaRegistryDataDeserializer registryDeserializer) { + MessageSerializer messageSerializer, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose, SchemaRegistryDataSerializer registrySerializer) { this.tracerProvider = Objects.requireNonNull(tracerProvider, "'tracerProvider' cannot be null."); - this.messageSerializer = - Objects.requireNonNull(messageSerializer, "'messageSerializer' cannot be null."); + this.messageSerializer = Objects.requireNonNull(messageSerializer, "'messageSerializer' cannot be null."); this.connectionProcessor = Objects.requireNonNull(connectionProcessor, "'connectionProcessor' cannot be null."); this.scheduler = Objects.requireNonNull(scheduler, "'scheduler' cannot be null"); @@ -51,7 +46,6 @@ class EventHubAsyncClient implements Closeable { this.isSharedConnection = isSharedConnection; this.registrySerializer = registrySerializer; - this.registryDeserializer = registryDeserializer; } /** @@ -111,11 +105,10 @@ Mono getPartitionProperties(String partitionId) { * * @return A new {@link EventHubProducerAsyncClient}. */ - EventHubProducerAsyncClient createProducer() { - return new EventHubProducerAsyncClient<>(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), - connectionProcessor, connectionProcessor.getRetryOptions(), tracerProvider, messageSerializer, - registrySerializer, scheduler, - isSharedConnection, onClientClose); + EventHubProducerAsyncClient createProducer() { + return new EventHubProducerAsyncClient(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), + connectionProcessor, connectionProcessor.getRetryOptions(), tracerProvider, messageSerializer, scheduler, + isSharedConnection, onClientClose, registrySerializer); } /** @@ -130,7 +123,7 @@ EventHubProducerAsyncClient createProducer() { * @throws NullPointerException If {@code consumerGroup} is {@code null}. * @throws IllegalArgumentException If {@code consumerGroup} is an empty string. */ - EventHubConsumerAsyncClient createConsumer(String consumerGroup, int prefetchCount) { + EventHubConsumerAsyncClient createConsumer(String consumerGroup, int prefetchCount) { Objects.requireNonNull(consumerGroup, "'consumerGroup' cannot be null."); if (consumerGroup.isEmpty()) { @@ -138,9 +131,8 @@ EventHubConsumerAsyncClient createConsumer(String consumerGroup, int prefetch new IllegalArgumentException("'consumerGroup' cannot be an empty string.")); } - return new EventHubConsumerAsyncClient<>(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), - connectionProcessor, messageSerializer, consumerGroup, registryDeserializer, - prefetchCount, scheduler, isSharedConnection, + return new EventHubConsumerAsyncClient(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), + connectionProcessor, messageSerializer, consumerGroup, prefetchCount, scheduler, isSharedConnection, onClientClose); } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java index 225111b7e6305..a520529adba03 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java @@ -137,8 +137,8 @@ public class EventHubClientBuilder { private String consumerGroup; private EventHubConnectionProcessor eventHubConnectionProcessor; private int prefetchCount; - private SchemaRegistryDataSerializer registrySerializer; - private SchemaRegistryDataDeserializer registryDeserializer; + private SchemaRegistryDataSerializer registrySerializer; + private SchemaRegistryDataDeserializer registryDeserializer; /** * Keeps track of the open clients that were created from this builder when there is a shared connection. @@ -370,7 +370,7 @@ public EventHubClientBuilder prefetchCount(int prefetchCount) { * @param serializer serializer * @return update builder instance */ - public EventHubClientBuilder registrySerializer(Serializer serializer) { // could be avro, json, schema registry + public EventHubClientBuilder registrySerializer(SchemaRegistryDataSerializer serializer) { this.registrySerializer = registrySerializer; return this; } @@ -397,7 +397,7 @@ EventHubClientBuilder scheduler(Scheduler scheduler) { * {@link #consumerGroup(String)} have not been set. And if a proxy is specified but the transport type is not * {@link AmqpTransportType#AMQP_WEB_SOCKETS web sockets}. */ - public EventHubConsumerAsyncClient buildAsyncConsumerClient() { + public EventHubConsumerAsyncClient buildAsyncConsumerClient() { if (CoreUtils.isNullOrEmpty(consumerGroup)) { throw logger.logExceptionAsError(new IllegalArgumentException("'consumerGroup' cannot be null or an empty " + "string. using EventHubClientBuilder.consumerGroup(String)")); @@ -416,7 +416,7 @@ public EventHubConsumerAsyncClient buildAsyncConsumerClient() { * {@link #consumerGroup(String)} have not been set. And if a proxy is specified but the transport type is not * {@link AmqpTransportType#AMQP_WEB_SOCKETS web sockets}. */ - public EventHubConsumerClient buildConsumerClient() { + public EventHubConsumerClient buildConsumerClient() { return buildClient().createConsumer(consumerGroup, prefetchCount); } @@ -429,7 +429,7 @@ public EventHubConsumerClient buildConsumerClient() { * either {@link #connectionString(String)} or {@link #credential(String, String, TokenCredential)}. Or, if a * proxy is specified but the transport type is not {@link AmqpTransportType#AMQP_WEB_SOCKETS web sockets}. */ - public EventHubProducerAsyncClient buildAsyncProducerClient() { + public EventHubProducerAsyncClient buildAsyncProducerClient() { return buildAsyncClient().createProducer(); } @@ -442,7 +442,7 @@ public EventHubProducerAsyncClient buildAsyncProducerClient() { * either {@link #connectionString(String)} or {@link #credential(String, String, TokenCredential)}. Or, if a * proxy is specified but the transport type is not {@link AmqpTransportType#AMQP_WEB_SOCKETS web sockets}. */ - public EventHubProducerClient buildProducerClient() { + public EventHubProducerClient buildProducerClient() { return buildClient().createProducer(); } @@ -500,7 +500,7 @@ EventHubAsyncClient buildAsyncClient() { final TracerProvider tracerProvider = new TracerProvider(ServiceLoader.load(Tracer.class)); return new EventHubAsyncClient(processor, tracerProvider, messageSerializer, scheduler, - isSharedConnection.get(), this::onClientClose, registrySerializer, registryDeserializer); + isSharedConnection.get(), this::onClientClose, registrySerializer); } /** diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java index 3dd18b8713c5f..82f97bd2f024e 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java @@ -72,7 +72,6 @@ public class EventHubConsumerAsyncClient implements Closeable { private final EventHubConnectionProcessor connectionProcessor; private final MessageSerializer messageSerializer; private final String consumerGroup; - private final SchemaRegistryDataDeserializer registryDeserializer; private final int prefetchCount; private final Scheduler scheduler; private final boolean isSharedConnection; @@ -86,8 +85,7 @@ public class EventHubConsumerAsyncClient implements Closeable { EventHubConsumerAsyncClient(String fullyQualifiedNamespace, String eventHubName, EventHubConnectionProcessor connectionProcessor, MessageSerializer messageSerializer, - String consumerGroup, - SchemaRegistryDataDeserializer registryDeserializer, int prefetchCount, + String consumerGroup, int prefetchCount, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClosed) { this.fullyQualifiedNamespace = fullyQualifiedNamespace; this.eventHubName = eventHubName; @@ -98,7 +96,6 @@ public class EventHubConsumerAsyncClient implements Closeable { this.scheduler = scheduler; this.isSharedConnection = isSharedConnection; this.onClientClosed = onClientClosed; - this.registryDeserializer = registryDeserializer; } /** @@ -182,7 +179,7 @@ public Mono getPartitionProperties(String partitionId) { * @throws NullPointerException if {@code partitionId}, or {@code startingPosition} is null. * @throws IllegalArgumentException if {@code partitionId} is an empty string. */ - public Flux> receiveFromPartition(String partitionId, EventPosition startingPosition) { + public Flux receiveFromPartition(String partitionId, EventPosition startingPosition) { return receiveFromPartition(partitionId, startingPosition, defaultReceiveOptions); } @@ -210,7 +207,7 @@ public Flux> receiveFromPartition(String partitionId, EventPos * null. * @throws IllegalArgumentException if {@code partitionId} is an empty string. */ - public Flux> receiveFromPartition(String partitionId, EventPosition startingPosition, + public Flux receiveFromPartition(String partitionId, EventPosition startingPosition, ReceiveOptions receiveOptions) { if (Objects.isNull(partitionId)) { return fluxError(logger, new NullPointerException("'partitionId' cannot be null.")); @@ -240,7 +237,7 @@ public Flux> receiveFromPartition(String partitionId, EventPos * * @return A stream of events for every partition in the Event Hub starting from the beginning of each partition. */ - public Flux> receive() { + public Flux receive() { return receive(true, defaultReceiveOptions); } @@ -261,7 +258,7 @@ public Flux> receive() { * * @return A stream of events for every partition in the Event Hub. */ - public Flux> receive(boolean startReadingAtEarliestEvent) { + public Flux receive(boolean startReadingAtEarliestEvent) { return receive(startReadingAtEarliestEvent, defaultReceiveOptions); } @@ -294,7 +291,7 @@ public Flux> receive(boolean startReadingAtEarliestEvent) { * * @throws NullPointerException if {@code receiveOptions} is null. */ - public Flux> receive(boolean startReadingAtEarliestEvent, ReceiveOptions receiveOptions) { + public Flux receive(boolean startReadingAtEarliestEvent, ReceiveOptions receiveOptions) { if (Objects.isNull(receiveOptions)) { return fluxError(logger, new NullPointerException("'receiveOptions' cannot be null.")); } @@ -330,7 +327,7 @@ public void close() { } } - private Flux> createConsumer(String linkName, String partitionId, EventPosition startingPosition, + private Flux createConsumer(String linkName, String partitionId, EventPosition startingPosition, ReceiveOptions receiveOptions) { return openPartitionConsumers .computeIfAbsent(linkName, @@ -370,6 +367,6 @@ private EventHubPartitionAsyncConsumer createPartitionConsumer(String linkName, return new EventHubPartitionAsyncConsumer(linkMessageProcessor, messageSerializer, getFullyQualifiedNamespace(), getEventHubName(), consumerGroup, partitionId, initialPosition, - receiveOptions.getTrackLastEnqueuedEventProperties(), scheduler, registryDeserializer); + receiveOptions.getTrackLastEnqueuedEventProperties(), scheduler); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java index 728da49c954cc..d0b070343d4d6 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java @@ -5,7 +5,6 @@ import com.azure.core.amqp.implementation.MessageSerializer; import com.azure.core.util.logging.ClientLogger; -import com.azure.data.schemaregistry.SchemaRegistryDataDeserializer; import com.azure.messaging.eventhubs.implementation.AmqpReceiveLinkProcessor; import com.azure.messaging.eventhubs.models.EventPosition; import com.azure.messaging.eventhubs.models.LastEnqueuedEventProperties; @@ -26,7 +25,7 @@ * A package-private consumer responsible for reading {@link EventData} from a specific Event Hub partition in the * context of a specific consumer group. */ -class EventHubPartitionAsyncConsumer implements AutoCloseable { +class EventHubPartitionAsyncConsumer implements AutoCloseable { private final ClientLogger logger = new ClientLogger(EventHubPartitionAsyncConsumer.class); private final AtomicBoolean isDisposed = new AtomicBoolean(); private final AtomicReference lastEnqueuedEventProperties = new AtomicReference<>(); @@ -40,16 +39,13 @@ class EventHubPartitionAsyncConsumer implements AutoCloseable { private final Scheduler scheduler; private final EmitterProcessor emitterProcessor; private final EventPosition initialPosition; - private final SchemaRegistryDataDeserializer registryDeserializer; private volatile Long currentOffset; EventHubPartitionAsyncConsumer(AmqpReceiveLinkProcessor amqpReceiveLinkProcessor, - MessageSerializer messageSerializer, String fullyQualifiedNamespace, - String eventHubName, String consumerGroup, - String partitionId, AtomicReference> currentEventPosition, - boolean trackLastEnqueuedEventProperties, Scheduler scheduler, - SchemaRegistryDataDeserializer registryDeserializer) { + MessageSerializer messageSerializer, String fullyQualifiedNamespace, String eventHubName, String consumerGroup, + String partitionId, AtomicReference> currentEventPosition, + boolean trackLastEnqueuedEventProperties, Scheduler scheduler) { this.initialPosition = Objects.requireNonNull(currentEventPosition.get().get(), "'currentEventPosition.get().get()' cannot be null."); this.amqpReceiveLinkProcessor = amqpReceiveLinkProcessor; @@ -60,7 +56,6 @@ class EventHubPartitionAsyncConsumer implements AutoCloseable { this.partitionId = partitionId; this.trackLastEnqueuedEventProperties = trackLastEnqueuedEventProperties; this.scheduler = Objects.requireNonNull(scheduler, "'scheduler' cannot be null."); - this.registryDeserializer = registryDeserializer; if (trackLastEnqueuedEventProperties) { lastEnqueuedEventProperties.set(new LastEnqueuedEventProperties(null, null, null, null)); @@ -110,7 +105,7 @@ public void close() { * * @return A stream of events received from the partition. */ - Flux> receive() { + Flux receive() { return emitterProcessor.publishOn(this.scheduler); } @@ -143,13 +138,6 @@ private PartitionEvent onMessageReceived(Message message) { final PartitionContext partitionContext = new PartitionContext(fullyQualifiedNamespace, eventHubName, consumerGroup, partitionId); - - if (registryDeserializer == null) { - return new PartitionEvent(partitionContext, event, lastEnqueuedEventProperties.get(), ); - } - - return new PartitionEvent(partitionContext, event, lastEnqueuedEventProperties.get(), - registryDeserializer.deserialize(event.getBody()).block()); - + return new PartitionEvent(partitionContext, event, lastEnqueuedEventProperties.get()); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java index 05fbab84ca1e4..eeb8b4abf7df2 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java @@ -108,10 +108,15 @@ public class EventHubProducerAsyncClient implements Closeable { private final AmqpRetryPolicy retryPolicy; private final TracerProvider tracerProvider; private final MessageSerializer messageSerializer; - private final SchemaRegistryDataSerializer registrySerializer; private final Scheduler scheduler; private final boolean isSharedConnection; private final Runnable onClientClose; + private final SchemaRegistryDataSerializer registrySerializer; + + private enum SendMode { + EVENT_DATA, + OBJECT + } /** * Creates a new instance of this {@link EventHubProducerAsyncClient} that can send messages to a single partition @@ -119,10 +124,8 @@ public class EventHubProducerAsyncClient implements Closeable { * load balance the messages amongst available partitions. */ EventHubProducerAsyncClient(String fullyQualifiedNamespace, String eventHubName, - EventHubConnectionProcessor connectionProcessor, AmqpRetryOptions retryOptions, - TracerProvider tracerProvider, - MessageSerializer messageSerializer, SchemaRegistryDataSerializer registrySerializer, - Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose) { + EventHubConnectionProcessor connectionProcessor, AmqpRetryOptions retryOptions, TracerProvider tracerProvider, + MessageSerializer messageSerializer, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose, SchemaRegistryDataSerializer registrySerializer) { this.fullyQualifiedNamespace = Objects.requireNonNull(fullyQualifiedNamespace, "'fullyQualifiedNamespace' cannot be null."); this.eventHubName = Objects.requireNonNull(eventHubName, "'eventHubName' cannot be null."); @@ -131,12 +134,12 @@ public class EventHubProducerAsyncClient implements Closeable { this.retryOptions = Objects.requireNonNull(retryOptions, "'retryOptions' cannot be null."); this.tracerProvider = Objects.requireNonNull(tracerProvider, "'tracerProvider' cannot be null."); this.messageSerializer = Objects.requireNonNull(messageSerializer, "'messageSerializer' cannot be null."); - this.registrySerializer = registrySerializer; this.onClientClose = Objects.requireNonNull(onClientClose, "'onClientClose' cannot be null."); this.retryPolicy = getRetryPolicy(retryOptions); this.scheduler = scheduler; this.isSharedConnection = isSharedConnection; + this.registrySerializer = registrySerializer; } /** @@ -197,7 +200,7 @@ public Mono getPartitionProperties(String partitionId) { * * @return A new {@link EventDataBatch} that can fit as many events as the transport allows. */ - public Mono> createBatch() { + public Mono createBatch() { return createBatch(DEFAULT_BATCH_OPTIONS); } @@ -208,7 +211,7 @@ public Mono> createBatch() { * @return A new {@link EventDataBatch} that can fit as many events as the transport allows. * @throws NullPointerException if {@code options} is null. */ - public Mono> createBatch(Class objectClass1, CreateBatchOptions options) { + public Mono createBatch(CreateBatchOptions options) { if (options == null) { return monoError(logger, new NullPointerException("'options' cannot be null.")); } @@ -249,40 +252,70 @@ public Mono> createBatch(Class objectClass1, CreateBatchOpt : maximumLinkSize; return Mono.just(new EventDataBatch(batchSize, partitionId, partitionKey, link::getErrorContext, - tracerProvider, registrySerializer, link.getEntityPath(), link.getHostname())); + tracerProvider, link.getEntityPath(), link.getHostname())); })); } /** - * Sends single object, serialized by the stored serializer, - * @param object object - * @return mono that completes when event is pushed to the service + * Creates an {@link ObjectBatch} that can fit as many serialized objects as events as the transport allows. + * + * @return A new {@link ObjectBatch} that can fit as many serialized objects as events as the transport allows. */ - Mono send(T object) { - if (registrySerializer == null) { - return monoError(logger, new NullPointerException("Registry serializer not initialized")); - } - byte[] body = registrySerializer.serialize(object).block(); - if (body == null) { - throw logger.logExceptionAsError(new IllegalArgumentException("Payload cannot be null")); - } - return send(Flux.just(new EventData(body))); + public Mono> createBatch(Class objectType) { + return createBatch(objectType, DEFAULT_BATCH_OPTIONS); } /** - * send object - * @param object object - * @return mono that completes when event is pushed to the service + * Creates an {@link ObjectBatch} configured with the options specified. + * + * @param options A set of options used to configure the {@link ObjectBatch}. + * @return A new {@link ObjectBatch} that can fit as many events as the transport allows. + * @throws NullPointerException if {@code options} is null. */ - Mono send(T object, SendOptions options) { - if (registrySerializer == null) { - return monoError(logger, new NullPointerException("Registry serializer not initialized")); + public Mono> createBatch(Class objectType, CreateBatchOptions options) { + if (objectType == null) { + return monoError(logger, new NullPointerException("'objectType' cannot be null.")); } - byte[] body = registrySerializer.serialize(object).block(); - if (body == null) { - throw logger.logExceptionAsError(new IllegalArgumentException("Payload cannot be null")); + if (options == null) { + return monoError(logger, new NullPointerException("'options' cannot be null.")); } - return send(Flux.just(new EventData(body))); + + Mono> sendModeError = verifySendMode(SendMode.OBJECT); + if (sendModeError != null) { + return sendModeError; + } + + Mono> optionsError = validateBatchOptions(options); + if (optionsError != null) { + return optionsError; + } + + final String partitionKey = options.getPartitionKey(); + final String partitionId = options.getPartitionId(); + final int batchMaxSize = options.getMaximumSizeInBytes(); + + return getSendLink(partitionId) + .flatMap(link -> link.getLinkSize() + .flatMap(size -> { + final int maximumLinkSize = size > 0 + ? size + : MAX_MESSAGE_LENGTH_BYTES; + + if (batchMaxSize > maximumLinkSize) { + return monoError(logger, + new IllegalArgumentException(String.format(Locale.US, + "BatchOptions.maximumSizeInBytes (%s bytes) is larger than the link size (%s bytes).", + batchMaxSize, maximumLinkSize))); + } + + final int batchSize = batchMaxSize > 0 + ? batchMaxSize + : maximumLinkSize; + + return Mono.just(new ObjectBatch<>(batchSize, partitionId, partitionKey, objectType, + link::getErrorContext, tracerProvider, registrySerializer, + link.getEntityPath(), link.getHostname())); + })); } /** @@ -321,9 +354,6 @@ Mono send(EventData event) { * @return A {@link Mono} that completes when the event is pushed to the service. */ Mono send(EventData event, SendOptions options) { - if (registrySerializer != null) { - // fail this path - } if (event == null) { return monoError(logger, new NullPointerException("'event' cannot be null.")); } else if (options == null) { @@ -502,11 +532,6 @@ public Mono send(EventDataBatch batch) { } private Mono sendInternal(Flux events, SendOptions options) { - if (registrySerializer != null) { - throw logger.logExceptionAsError( - new IllegalArgumentException("Serializer mode - sending EventData is not permitted")); - } - final String partitionKey = options.getPartitionKey(); final String partitionId = options.getPartitionId(); @@ -526,8 +551,7 @@ private Mono sendInternal(Flux events, SendOptions options) { .setPartitionKey(options.getPartitionKey()) .setPartitionId(options.getPartitionId()) .setMaximumSizeInBytes(batchSize); - return events.collect(new EventDataCollector(batchOptions, 1, - link::getErrorContext, + return events.collect(new EventDataCollector(batchOptions, 1, link::getErrorContext, tracerProvider, link.getEntityPath(), link.getHostname())); }) .flatMap(list -> sendInternal(Flux.fromIterable(list)))); @@ -556,6 +580,41 @@ private Mono getSendLink(String partitionId) { .flatMap(connection -> connection.createSendLink(linkName, entityPath, retryOptions)); } + private Mono verifySendMode(SendMode mode) { + switch (mode) { + case EVENT_DATA: + if (registrySerializer != null) { + return monoError(logger, new IllegalStateException()); + } + break; + case OBJECT: + if (registrySerializer == null) { + return monoError(logger, new IllegalStateException()); + } + break; + default: + break; + } + + return null; + } + + private Mono validateBatchOptions(CreateBatchOptions options) { + if (!CoreUtils.isNullOrEmpty(options.getPartitionKey()) + && !CoreUtils.isNullOrEmpty(options.getPartitionId())) { + return monoError(logger, new IllegalArgumentException(String.format(Locale.US, + "CreateBatchOptions.getPartitionKey() and CreateBatchOptions.getPartitionId() are both set. " + + "Only one or the other can be used. partitionKey: '%s'. partitionId: '%s'", + options.getPartitionKey(), options.getPartitionId()))); + } else if (!CoreUtils.isNullOrEmpty(options.getPartitionKey()) + && options.getPartitionKey().length() > MAX_PARTITION_KEY_LENGTH) { + return monoError(logger, new IllegalArgumentException(String.format(Locale.US, + "Partition key '%s' exceeds the maximum allowed length: '%s'.", options.getPartitionKey(), + MAX_PARTITION_KEY_LENGTH))); + } + return null; + } + /** * Disposes of the {@link EventHubProducerAsyncClient}. If the client had a dedicated connection, the underlying * connection is also closed. @@ -593,8 +652,7 @@ private static class EventDataCollector implements Collector 0 ? options.getMaximumSizeInBytes() @@ -607,7 +665,7 @@ private static class EventDataCollector implements Collector, EventData> accumulator() { } currentBatch = new EventDataBatch(maxMessageSize, partitionId, partitionKey, contextProvider, - tracerProvider, null, entityPath, hostname); + tracerProvider, entityPath, hostname); currentBatch.tryAdd(event); list.add(batch); }; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerClient.java index 0a61cde976fd9..700fd8d9c648b 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerClient.java @@ -52,8 +52,8 @@ * @see EventHubProducerAsyncClient To asynchronously generate events to an Event Hub, see EventHubProducerAsyncClient. */ @ServiceClient(builder = EventHubClientBuilder.class) -public class EventHubProducerClient implements Closeable { - private final EventHubProducerAsyncClient producer; +public class EventHubProducerClient implements Closeable { + private final EventHubProducerAsyncClient producer; private final Duration tryTimeout; /** @@ -61,7 +61,7 @@ public class EventHubProducerClient implements Closeable { * * @throws NullPointerException if {@code producer} or {@code tryTimeout} is null. */ - EventHubProducerClient(EventHubProducerAsyncClient producer, Duration tryTimeout) { + EventHubProducerClient(EventHubProducerAsyncClient producer, Duration tryTimeout) { this.producer = Objects.requireNonNull(producer, "'producer' cannot be null."); this.tryTimeout = Objects.requireNonNull(tryTimeout, "'tryTimeout' cannot be null."); } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index 8b421cb8f13c6..c4c7e677e8a38 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -1,53 +1,46 @@ package com.azure.messaging.eventhubs; -import com.azure.core.amqp.AmqpMessageConstant; -import com.azure.core.amqp.exception.AmqpErrorCondition; import com.azure.core.amqp.exception.AmqpException; -import com.azure.core.amqp.implementation.AmqpConstants; import com.azure.core.amqp.implementation.ErrorContextProvider; import com.azure.core.amqp.implementation.TracerProvider; -import com.azure.core.util.Context; import com.azure.core.util.logging.ClientLogger; -import com.azure.core.util.tracing.ProcessKind; import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; -import org.apache.qpid.proton.Proton; -import org.apache.qpid.proton.amqp.Binary; -import org.apache.qpid.proton.amqp.Symbol; -import org.apache.qpid.proton.amqp.messaging.ApplicationProperties; -import org.apache.qpid.proton.amqp.messaging.Data; -import org.apache.qpid.proton.amqp.messaging.MessageAnnotations; -import org.apache.qpid.proton.message.Message; -import reactor.core.publisher.Signal; - -import java.nio.BufferOverflowException; -import java.util.*; - -import static com.azure.core.util.tracing.Tracer.*; -import static com.azure.messaging.eventhubs.implementation.ClientConstants.AZ_NAMESPACE_VALUE; public final class ObjectBatch extends Batch { - private final ClientLogger logger = new ClientLogger(ObjectBatch.class)); + private final ClientLogger logger = new ClientLogger(ObjectBatch.class); private final Object lock = new Object(); private final Class batchType; private final SchemaRegistryDataSerializer registrySerializer; + /** + * + * @param maxMessageSize + * @param partitionId + * @param partitionKey + * @param batchType + * @param contextProvider + * @param tracerProvider + * @param registrySerializer + * @param entityPath + * @param hostname + */ ObjectBatch(int maxMessageSize, String partitionId, String partitionKey, Class batchType, ErrorContextProvider contextProvider, TracerProvider tracerProvider, SchemaRegistryDataSerializer registrySerializer, String entityPath, String hostname) { - super(maxMessageSize, partitionId, partitionKey, contextProvider, tracerProvider, entityPath, - hostname, new ClientLogger(ObjectBatch.class)); + super(maxMessageSize, partitionId, partitionKey, contextProvider, tracerProvider, entityPath, hostname); this.batchType = batchType; this.registrySerializer = registrySerializer; } /** - * Tries to add an {@link EventData event} to the batch. + * Tries to add an object to the batch. * - * @param object The {@link EventData} to add to the batch. - * @return {@code true} if the event could be added to the batch; {@code false} if the event was too large to fit in - * the batch. - * @throws IllegalArgumentException if {@code eventData} is {@code null}. - * @throws AmqpException if {@code eventData} is larger than the maximum size of the {@link EventDataBatch}. + * @param object The object to add to the batch. + * @return {@code true} if the object could be added to the batch; {@code false} if the serialized object + * was too large to fit in the batch. + * @throws IllegalArgumentException if object is {@code null}. + * @throws AmqpException if serialized object as {@link EventData} is larger than the maximum size + * of the {@link EventDataBatch}. */ public boolean tryAdd(final T object) { if (object == null) { @@ -57,172 +50,6 @@ public boolean tryAdd(final T object) { EventData eventData = new EventData(registrySerializer.serialize(object).block()); EventData event = tracerProvider.isEnabled() ? traceMessageSpan(eventData) : eventData; - final int size; - try { - size = getSize(event, events.isEmpty()); - } catch (BufferOverflowException exception) { - throw logger.logExceptionAsWarning(new AmqpException(false, AmqpErrorCondition.LINK_PAYLOAD_SIZE_EXCEEDED, - String.format(Locale.US, "Size of the payload exceeded maximum message size: %s kb", - maxMessageSize / 1024), - contextProvider.getErrorContext())); - } - - synchronized (lock) { - if (this.sizeInBytes + size > this.maxMessageSize) { - return false; - } - - this.sizeInBytes += size; - } - - this.events.add(event); - return true; - } - - /** - * Method to start and end a "Azure.EventHubs.message" span and add the "DiagnosticId" as a property of the message. - * - * @param eventData The Event to add tracing span for. - * @return the updated event data object. - */ - private EventData traceMessageSpan(EventData eventData) { - Optional eventContextData = eventData.getContext().getData(SPAN_CONTEXT_KEY); - if (eventContextData.isPresent()) { - // if message has context (in case of retries), don't start a message span or add a new context - return eventData; - } else { - // Starting the span makes the sampling decision (nothing is logged at this time) - Context eventContext = eventData.getContext() - .addData(AZ_TRACING_NAMESPACE_KEY, AZ_NAMESPACE_VALUE) - .addData(ENTITY_PATH_KEY, this.entityPath) - .addData(HOST_NAME_KEY, this.hostname); - Context eventSpanContext = tracerProvider.startSpan(eventContext, ProcessKind.MESSAGE); - Optional eventDiagnosticIdOptional = eventSpanContext.getData(DIAGNOSTIC_ID_KEY); - if (eventDiagnosticIdOptional.isPresent()) { - eventData.getProperties().put(DIAGNOSTIC_ID_KEY, eventDiagnosticIdOptional.get().toString()); - tracerProvider.endSpan(eventSpanContext, Signal.complete()); - eventData.addContext(SPAN_CONTEXT_KEY, eventSpanContext); - } - } - - return eventData; - } - - List getEvents() { - return events; - } - - String getPartitionKey() { - return partitionKey; - } - - String getPartitionId() { - return partitionId; - } - - private int getSize(final EventData eventData, final boolean isFirst) { - Objects.requireNonNull(eventData, "'eventData' cannot be null."); - - final Message amqpMessage = createAmqpMessage(eventData, partitionKey); - int eventSize = amqpMessage.encode(this.eventBytes, 0, maxMessageSize); // actual encoded bytes size - eventSize += 16; // data section overhead - - if (isFirst) { - amqpMessage.setBody(null); - amqpMessage.setApplicationProperties(null); - amqpMessage.setProperties(null); - amqpMessage.setDeliveryAnnotations(null); - - eventSize += amqpMessage.encode(this.eventBytes, 0, maxMessageSize); - } - - return eventSize; - } - - /* - * Creates the AMQP message represented by the event data - */ - private Message createAmqpMessage(EventData event, String partitionKey) { - final Message message = Proton.message(); - - if (event.getProperties() != null && !event.getProperties().isEmpty()) { - final ApplicationProperties applicationProperties = new ApplicationProperties(event.getProperties()); - message.setApplicationProperties(applicationProperties); - } - - if (event.getSystemProperties() != null) { - event.getSystemProperties().forEach((key, value) -> { - if (EventData.RESERVED_SYSTEM_PROPERTIES.contains(key)) { - return; - } - - final AmqpMessageConstant constant = AmqpMessageConstant.fromString(key); - - if (constant != null) { - switch (constant) { - case MESSAGE_ID: - message.setMessageId(value); - break; - case USER_ID: - message.setUserId((byte[]) value); - break; - case TO: - message.setAddress((String) value); - break; - case SUBJECT: - message.setSubject((String) value); - break; - case REPLY_TO: - message.setReplyTo((String) value); - break; - case CORRELATION_ID: - message.setCorrelationId(value); - break; - case CONTENT_TYPE: - message.setContentType((String) value); - break; - case CONTENT_ENCODING: - message.setContentEncoding((String) value); - break; - case ABSOLUTE_EXPIRY_TIME: - message.setExpiryTime((long) value); - break; - case CREATION_TIME: - message.setCreationTime((long) value); - break; - case GROUP_ID: - message.setGroupId((String) value); - break; - case GROUP_SEQUENCE: - message.setGroupSequence((long) value); - break; - case REPLY_TO_GROUP_ID: - message.setReplyToGroupId((String) value); - break; - default: - throw logger.logExceptionAsWarning(new IllegalArgumentException(String.format(Locale.US, - "Property is not a recognized reserved property name: %s", key))); - } - } else { - final MessageAnnotations messageAnnotations = (message.getMessageAnnotations() == null) - ? new MessageAnnotations(new HashMap<>()) - : message.getMessageAnnotations(); - messageAnnotations.getValue().put(Symbol.getSymbol(key), value); - message.setMessageAnnotations(messageAnnotations); - } - }); - } - - if (partitionKey != null) { - final MessageAnnotations messageAnnotations = (message.getMessageAnnotations() == null) - ? new MessageAnnotations(new HashMap<>()) - : message.getMessageAnnotations(); - messageAnnotations.getValue().put(AmqpConstants.PARTITION_KEY, partitionKey); - message.setMessageAnnotations(messageAnnotations); - } - - message.setBody(new Data(new Binary(event.getBody()))); - - return message; + return tryAdd(event); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java index a465e57f9447f..838025b1eff4e 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java @@ -12,12 +12,11 @@ * A container for {@link EventData} along with the partition information for this event data. */ @Immutable -public class PartitionEvent { +public class PartitionEvent { private final PartitionContext partitionContext; private final EventData eventData; private final LastEnqueuedEventProperties lastEnqueuedEventProperties; - private final Object deserialized; /** * Creates an instance of PartitionEvent. @@ -25,16 +24,13 @@ public class PartitionEvent { * @param partitionContext The partition information associated with the event data. * @param eventData The event data received from the Event Hub. * @param lastEnqueuedEventProperties The properties of the last enqueued event in the partition. - * @param deserialized object deserialized by deserializer. Set to eventData byte array payload if no deserializer - * has been set. * @throws NullPointerException if {@code partitionContext} or {@code eventData} is {@code null}. */ public PartitionEvent(final PartitionContext partitionContext, final EventData eventData, - LastEnqueuedEventProperties lastEnqueuedEventProperties, T deserialized) { + LastEnqueuedEventProperties lastEnqueuedEventProperties) { this.partitionContext = Objects.requireNonNull(partitionContext, "'partitionContext' cannot be null"); this.eventData = Objects.requireNonNull(eventData, "'eventData' cannot be null"); this.lastEnqueuedEventProperties = lastEnqueuedEventProperties; - this.deserialized = deserialized; } /** @@ -63,13 +59,4 @@ public EventData getData() { public LastEnqueuedEventProperties getLastEnqueuedEventProperties() { return lastEnqueuedEventProperties; } - - /** - * Gets deserialized object from EventData byte payload - * @return deserialized object - */ - public T getDeserializedObject() { - Objects.requireNonNull(this.deserialized); - return (T) this.deserialized; - } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchIntegrationTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchIntegrationTest.java index 34558f868d668..fa8afad99b1bc 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchIntegrationTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchIntegrationTest.java @@ -67,7 +67,7 @@ protected void afterTest() { public void sendSmallEventsFullBatch() { // Arrange final EventDataBatch batch = new EventDataBatch(ClientConstants.MAX_MESSAGE_LENGTH_BYTES, null, null, contextProvider, - new TracerProvider(Collections.emptyList()), null, getFullyQualifiedDomainName(), getEventHubName()); + new TracerProvider(Collections.emptyList()), getFullyQualifiedDomainName(), getEventHubName()); int count = 0; while (batch.tryAdd(createData())) { // We only print every 100th item or it'll be really spammy. @@ -90,7 +90,7 @@ public void sendSmallEventsFullBatch() { public void sendSmallEventsFullBatchPartitionKey() { // Arrange final EventDataBatch batch = new EventDataBatch(ClientConstants.MAX_MESSAGE_LENGTH_BYTES, null, - PARTITION_KEY, contextProvider, tracerProvider, null, getFullyQualifiedDomainName(), getEventHubName()); + PARTITION_KEY, contextProvider, tracerProvider, getFullyQualifiedDomainName(), getEventHubName()); int count = 0; while (batch.tryAdd(createData())) { // We only print every 100th item or it'll be really spammy. @@ -116,7 +116,7 @@ public void sendBatchPartitionKeyValidate() throws InterruptedException { final SendOptions sendOptions = new SendOptions().setPartitionKey(PARTITION_KEY); final EventDataBatch batch = new EventDataBatch(ClientConstants.MAX_MESSAGE_LENGTH_BYTES, null, - PARTITION_KEY, contextProvider, tracerProvider, null, getFullyQualifiedDomainName(), getEventHubName()); + PARTITION_KEY, contextProvider, tracerProvider, getFullyQualifiedDomainName(), getEventHubName()); int count = 0; while (count < 10) { final EventData data = createData(); @@ -183,7 +183,7 @@ public void sendEventsFullBatchWithPartitionKey() { // Arrange final int maxMessageSize = 1024; final EventDataBatch batch = new EventDataBatch(maxMessageSize, null, PARTITION_KEY, contextProvider, - tracerProvider, null, getFullyQualifiedDomainName(), getEventHubName()); + tracerProvider, getFullyQualifiedDomainName(), getEventHubName()); final Random random = new Random(); final SendOptions sendOptions = new SendOptions().setPartitionKey(PARTITION_KEY); int count = 0; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchTest.java index 42c1edfe2e781..ea85afedd71f0 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchTest.java @@ -34,7 +34,7 @@ public void setup() { @Test public void nullEventData() { assertThrows(IllegalArgumentException.class, () -> { - final EventDataBatch batch = new EventDataBatch(1024, null, PARTITION_KEY, null, null, null, null, null); + final EventDataBatch batch = new EventDataBatch(1024, null, PARTITION_KEY, null, null, null, null); batch.tryAdd(null); }); } @@ -47,7 +47,7 @@ public void payloadExceededException() { when(errorContextProvider.getErrorContext()).thenReturn(new AmqpErrorContext("test-namespace")); final EventDataBatch batch = new EventDataBatch(1024, null, PARTITION_KEY, errorContextProvider, - new TracerProvider(Collections.emptyList()), null, null, null); + new TracerProvider(Collections.emptyList()), null, null); final EventData tooBig = new EventData(new byte[1024 * 1024 * 2]); try { batch.tryAdd(tooBig); @@ -65,7 +65,7 @@ public void payloadExceededException() { public void withinPayloadSize() { final int maxSize = ClientConstants.MAX_MESSAGE_LENGTH_BYTES; final EventDataBatch batch = new EventDataBatch(ClientConstants.MAX_MESSAGE_LENGTH_BYTES, null, PARTITION_KEY, - null, new TracerProvider(Collections.emptyList()), null, null, null); + null, new TracerProvider(Collections.emptyList()), null, null); final EventData within = new EventData(new byte[1024]); Assertions.assertEquals(maxSize, batch.getMaxSizeInBytes()); @@ -83,7 +83,7 @@ public void setsPartitionId() { // Act final EventDataBatch batch = new EventDataBatch(ClientConstants.MAX_MESSAGE_LENGTH_BYTES, partitionId, - PARTITION_KEY, null, null, null, null, null); + PARTITION_KEY, null, null, null, null); // Assert Assertions.assertEquals(PARTITION_KEY, batch.getPartitionKey()); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java index 40dc4288b312d..c37f1686c710d 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java @@ -137,7 +137,7 @@ CbsAuthorizationType.SHARED_ACCESS_SIGNATURE, AmqpTransportType.AMQP_WEB_SOCKETS "event-hub-name", connectionOptions.getRetry())); consumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, - CONSUMER_GROUP, null, PREFETCH, parallelScheduler, false, onClientClosed); + CONSUMER_GROUP, PREFETCH, parallelScheduler, false, onClientClosed); } @AfterEach @@ -156,7 +156,7 @@ void teardown() { @Test void lastEnqueuedEventInformationIsNull() { final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, null, DEFAULT_PREFETCH_COUNT, parallelScheduler, false, onClientClosed); + connectionProcessor, messageSerializer, CONSUMER_GROUP, DEFAULT_PREFETCH_COUNT, parallelScheduler, false, onClientClosed); final int numberOfEvents = 10; when(amqpReceiveLink.getCredits()).thenReturn(numberOfEvents); final int numberToReceive = 3; @@ -179,7 +179,7 @@ void lastEnqueuedEventInformationIsNull() { void lastEnqueuedEventInformationCreated() { // Arrange final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, null, DEFAULT_PREFETCH_COUNT, Schedulers.parallel(), false, onClientClosed); + connectionProcessor, messageSerializer, CONSUMER_GROUP, DEFAULT_PREFETCH_COUNT, Schedulers.parallel(), false, onClientClosed); final int numberOfEvents = 10; final ReceiveOptions receiveOptions = new ReceiveOptions().setTrackLastEnqueuedEventProperties(true); when(amqpReceiveLink.getCredits()).thenReturn(numberOfEvents); @@ -232,7 +232,7 @@ void receivesNumberOfEventsAllowsBlock() throws InterruptedException { // Scheduling on elastic to simulate a user passed in scheduler (this is the default in EventHubClientBuilder). final EventHubConsumerAsyncClient myConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, null, PREFETCH, Schedulers.elastic(), false, onClientClosed); + connectionProcessor, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.elastic(), false, onClientClosed); final Flux eventsFlux = myConsumer.receiveFromPartition(PARTITION_ID, EventPosition.earliest()) .take(numberOfEvents); @@ -294,7 +294,7 @@ void returnsNewListener() { any(ReceiveOptions.class))).thenReturn(Mono.just(link2), Mono.just(link3)); EventHubConsumerAsyncClient asyncClient = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, null, PREFETCH, testScheduler, false, onClientClosed); + eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, testScheduler, false, onClientClosed); // Act & Assert StepVerifier.create(asyncClient.receiveFromPartition(PARTITION_ID, EventPosition.earliest()).take(numberOfEvents)) @@ -517,7 +517,7 @@ void receivesMultiplePartitions() { .thenReturn(Mono.just(new EventHubProperties(EVENT_HUB_NAME, Instant.EPOCH, partitions))); EventHubConsumerAsyncClient asyncClient = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, null, PREFETCH, parallelScheduler, false, onClientClosed); + eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, parallelScheduler, false, onClientClosed); EmitterProcessor processor2 = EmitterProcessor.create(); FluxSink processor2sink = processor2.sink(); @@ -592,7 +592,7 @@ void receivesMultiplePartitionsWhenOneCloses() { .thenReturn(Mono.just(new EventHubProperties(EVENT_HUB_NAME, Instant.EPOCH, partitions))); EventHubConsumerAsyncClient asyncClient = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, null, PREFETCH, Schedulers.parallel(), false, onClientClosed); + eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); EmitterProcessor processor2 = EmitterProcessor.create(); FluxSink processor2sink = processor2.sink(); @@ -652,7 +652,7 @@ void doesNotCloseSharedConnection() { EventHubConnectionProcessor eventHubConnection = Flux.create(sink -> sink.next(connection1)) .subscribeWith(new EventHubConnectionProcessor(HOSTNAME, EVENT_HUB_NAME, retryOptions)); EventHubConsumerAsyncClient sharedConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, null, PREFETCH, Schedulers.parallel(), true, onClientClosed); + eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), true, onClientClosed); // Act sharedConsumer.close(); @@ -672,7 +672,7 @@ void closesDedicatedConnection() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubConsumerAsyncClient dedicatedConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, messageSerializer, CONSUMER_GROUP, null, PREFETCH, Schedulers.parallel(), false, onClientClosed); + hubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); // Act dedicatedConsumer.close(); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java index fe955ad0af7df..b05a875f23617 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java @@ -118,7 +118,7 @@ CbsAuthorizationType.SHARED_ACCESS_SIGNATURE, AmqpTransportType.AMQP_WEB_SOCKETS })); asyncConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, null, PREFETCH, Schedulers.parallel(), false, onClientClosed); + connectionProcessor, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); consumer = new EventHubConsumerClient(asyncConsumer, Duration.ofSeconds(10)); } @@ -143,7 +143,7 @@ public void lastEnqueuedEventInformationIsNull() { // Arrange final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient( HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, CONSUMER_GROUP, - null, PREFETCH, Schedulers.parallel(), false, onClientClosed); + PREFETCH, Schedulers.parallel(), false, onClientClosed); final EventHubConsumerClient consumer = new EventHubConsumerClient(runtimeConsumer, Duration.ofSeconds(5)); final int numberOfEvents = 10; sendMessages(sink, numberOfEvents, PARTITION_ID); @@ -172,7 +172,7 @@ public void lastEnqueuedEventInformationCreated() { // Arrange final ReceiveOptions options = new ReceiveOptions().setTrackLastEnqueuedEventProperties(true); final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient( - HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, CONSUMER_GROUP, null, PREFETCH, + HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); final EventHubConsumerClient consumer = new EventHubConsumerClient(runtimeConsumer, Duration.ofSeconds(5)); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java index 748aaa1328592..3510200950493 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java @@ -117,7 +117,7 @@ void receivesMessages(boolean trackLastEnqueuedProperties) { // Arrange linkProcessor = createSink(link1, link2).subscribeWith(new AmqpReceiveLinkProcessor(PREFETCH, retryPolicy, parentConnection)); consumer = new EventHubPartitionAsyncConsumer(linkProcessor, messageSerializer, HOSTNAME, EVENT_HUB_NAME, - CONSUMER_GROUP, PARTITION_ID, currentPosition, trackLastEnqueuedProperties, Schedulers.parallel(), null); + CONSUMER_GROUP, PARTITION_ID, currentPosition, trackLastEnqueuedProperties, Schedulers.parallel()); final EventData event1 = new EventData("Foo"); final EventData event2 = new EventData("Bar"); @@ -165,7 +165,7 @@ void receiveMultipleTimes() { // Arrange linkProcessor = createSink(link1, link2).subscribeWith(new AmqpReceiveLinkProcessor(PREFETCH, retryPolicy, parentConnection)); consumer = new EventHubPartitionAsyncConsumer(linkProcessor, messageSerializer, HOSTNAME, EVENT_HUB_NAME, - CONSUMER_GROUP, PARTITION_ID, currentPosition, false, Schedulers.parallel(), null); + CONSUMER_GROUP, PARTITION_ID, currentPosition, false, Schedulers.parallel()); final Message message3 = mock(Message.class); final String secondOffset = "54"; @@ -233,7 +233,7 @@ void listensToShutdownSignals() throws InterruptedException { // Arrange linkProcessor = createSink(link1, link2).subscribeWith(new AmqpReceiveLinkProcessor(PREFETCH, retryPolicy, parentConnection)); consumer = new EventHubPartitionAsyncConsumer(linkProcessor, messageSerializer, HOSTNAME, EVENT_HUB_NAME, - CONSUMER_GROUP, PARTITION_ID, currentPosition, false, Schedulers.parallel(), null); + CONSUMER_GROUP, PARTITION_ID, currentPosition, false, Schedulers.parallel()); final Message message3 = mock(Message.class); final String secondOffset = "54"; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java index 6ab8b2d20f3a9..fbc8af492f9c8 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java @@ -146,7 +146,7 @@ void setup(TestInfo testInfo) { new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), "event-hub-path", connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, null, testScheduler, false, onClientClosed); + tracerProvider, messageSerializer, testScheduler, false, onClientClosed, registrySerializer); when(sendLink.getLinkSize()).thenReturn(Mono.just(ClientConstants.MAX_MESSAGE_LENGTH_BYTES)); when(sendLink2.getLinkSize()).thenReturn(Mono.just(ClientConstants.MAX_MESSAGE_LENGTH_BYTES)); @@ -238,8 +238,8 @@ void sendSingleMessageWithBlock() throws InterruptedException { final Semaphore semaphore = new Semaphore(1); // In our actual client builder, we allow this. final EventHubProducerAsyncClient flexibleProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, testScheduler, - false, onClientClosed); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, testScheduler, + false, onClientClosed, registrySerializer); // EC is the prefix they use when creating a link that sends to the service round-robin. when(connection.createSendLink(eq(EVENT_HUB_NAME), eq(EVENT_HUB_NAME), eq(retryOptions))) @@ -319,8 +319,8 @@ void sendStartSpanSingleMessage() { final SendOptions sendOptions = new SendOptions() .setPartitionId(partitionId); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), - false, onClientClosed); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + false, onClientClosed, registrySerializer); when(connection.createSendLink( argThat(name -> name.endsWith(partitionId)), argThat(name -> name.endsWith(partitionId)), eq(retryOptions))) @@ -377,7 +377,7 @@ void sendMessageRetrySpanTest() { TracerProvider tracerProvider = new TracerProvider(tracers); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); + tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); final String failureKey = "fail"; final EventData testData = new EventData("test"); @@ -516,8 +516,8 @@ void startMessageSpansOnCreateBatch() { final List tracers = Collections.singletonList(tracer1); TracerProvider tracerProvider = new TracerProvider(tracers); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), - false, onClientClosed); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + false, onClientClosed, registrySerializer); final AmqpSendLink link = mock(AmqpSendLink.class); when(link.getLinkSize()).thenReturn(Mono.just(ClientConstants.MAX_MESSAGE_LENGTH_BYTES)); @@ -822,8 +822,8 @@ void doesNotCloseSharedConnection() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubProducerAsyncClient sharedProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), - true, onClientClosed); + hubConnection, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + true, onClientClosed, registrySerializer); // Act sharedProducer.close(); @@ -841,8 +841,8 @@ void closesDedicatedConnection() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubProducerAsyncClient dedicatedProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), - false, onClientClosed); + hubConnection, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + false, onClientClosed, registrySerializer); // Act dedicatedProducer.close(); @@ -860,8 +860,8 @@ void closesDedicatedConnectionOnlyOnce() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubProducerAsyncClient dedicatedProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), - false, onClientClosed); + hubConnection, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + false, onClientClosed, registrySerializer); // Act dedicatedProducer.close(); @@ -897,7 +897,7 @@ void reopensOnFailure() { new EventHubConnectionProcessor(EVENT_HUB_NAME, connectionOptions.getFullyQualifiedNamespace(), connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); + tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); final int count = 4; final byte[] contents = TEST_CONTENTS.getBytes(UTF_8); @@ -972,7 +972,7 @@ void closesOnNonTransientFailure() { new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), EVENT_HUB_NAME, connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); + tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); final int count = 4; final byte[] contents = TEST_CONTENTS.getBytes(UTF_8); @@ -1048,7 +1048,7 @@ void resendMessageOnTransientLinkFailure() { new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), EVENT_HUB_NAME, connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); + tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); final int count = 4; final byte[] contents = TEST_CONTENTS.getBytes(UTF_8); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java index 02ec09aaeb2c1..ef06765753c56 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java @@ -105,7 +105,7 @@ public void setup() { .subscribeWith(new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), "event-hub-path", connectionOptions.getRetry())); asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); + tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); when(connection.getEndpointStates()).thenReturn(Flux.create(sink -> sink.next(AmqpEndpointState.ACTIVE))); } @@ -157,8 +157,8 @@ public void sendStartSpanSingleMessage() { final List tracers = Collections.singletonList(tracer1); final TracerProvider tracerProvider = new TracerProvider(tracers); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), - false, onClientClosed); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + false, onClientClosed, registrySerializer); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); final EventData eventData = new EventData("hello-world".getBytes(UTF_8)); @@ -219,7 +219,7 @@ public void sendMessageRetrySpanTest() { .thenReturn(Mono.just(sendLink)); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); final EventData eventData = new EventData("hello-world".getBytes(UTF_8)) .addContext(SPAN_CONTEXT_KEY, Context.NONE); @@ -267,7 +267,7 @@ public void sendEventsExceedsBatchSize() { when(sendLink.getLinkSize()).thenReturn(Mono.just(1024)); TracerProvider tracerProvider = new TracerProvider(Collections.emptyList()); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); //Act & Assert @@ -369,8 +369,8 @@ public void startsMessageSpanOnEventBatch() { final List tracers = Collections.singletonList(tracer1); final TracerProvider tracerProvider = new TracerProvider(tracers); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), - false, onClientClosed); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), + false, onClientClosed, registrySerializer); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); final AmqpSendLink link = mock(AmqpSendLink.class); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java index 5dc5079bde4fd..a79be245862d5 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java @@ -139,7 +139,7 @@ private static Stream checkpointStoreSupplier() { private PartitionEvent getEvent(EventData event) { PartitionContext context = new PartitionContext("ns", "foo", "bar", "baz"); - return new PartitionEvent(context, event, null, deserialized); + return new PartitionEvent(context, event, null); } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java index 567d199b0ce6d..05888a75f6cb4 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java @@ -474,7 +474,7 @@ public void testSingleEventReceiveHeartBeat() throws InterruptedException { private PartitionEvent getEvent(EventData event) { PartitionContext context = new PartitionContext("test-ns", "foo", "bar", "baz"); - return new PartitionEvent(context, event, null, deserialized); + return new PartitionEvent(context, event, null); } private static final class TestPartitionProcessor extends PartitionProcessor { diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java index b0fb91a29ce65..698aee42498ea 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java @@ -113,7 +113,7 @@ public void testSingleEventProcessor() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); + return new PartitionEvent(partitionContext, eventDataList.get(i), null); })); PartitionBasedLoadBalancer partitionBasedLoadBalancer = createPartitionLoadBalancer("owner1"); @@ -149,7 +149,7 @@ public void testTwoEventProcessors() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); + return new PartitionEvent(partitionContext, eventDataList.get(i), null); })); PartitionBasedLoadBalancer partitionBasedLoadBalancer1 = createPartitionLoadBalancer("owner1"); @@ -185,7 +185,7 @@ public void testPartitionStealing() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); + return new PartitionEvent(partitionContext, eventDataList.get(i), null); })); PartitionBasedLoadBalancer partitionBasedLoadBalancer1 = createPartitionLoadBalancer("owner1"); @@ -225,7 +225,7 @@ public void testMoreEventProcessorsThanPartitions() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); + return new PartitionEvent(partitionContext, eventDataList.get(i), null); })); List loadBalancers = new ArrayList<>(); @@ -263,7 +263,7 @@ public void testEventProcessorInactive() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); final int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); + return new PartitionEvent(partitionContext, eventDataList.get(i), null); })); List loadBalancers = new ArrayList<>(); @@ -422,7 +422,7 @@ public void testEmptyOwnerId() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); final int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null, deserialized); + return new PartitionEvent(partitionContext, eventDataList.get(i), null); })); String ownerName = "owner1"; From 7e9ae15ea7c91c2aeb39ccab38021312240aebfe Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Wed, 1 Jul 2020 15:29:24 -0700 Subject: [PATCH 03/29] temp object serializer --- .../eventhubs/EventHubProducerAsyncClient.java | 13 ++++++------- .../com/azure/messaging/eventhubs/ObjectBatch.java | 11 +++++------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java index eeb8b4abf7df2..3f6935fc2522a 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java @@ -19,7 +19,6 @@ import com.azure.core.util.CoreUtils; import com.azure.core.util.logging.ClientLogger; import com.azure.core.util.tracing.ProcessKind; -import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; import com.azure.messaging.eventhubs.implementation.EventHubConnectionProcessor; import com.azure.messaging.eventhubs.implementation.EventHubManagementNode; import com.azure.messaging.eventhubs.models.CreateBatchOptions; @@ -111,7 +110,7 @@ public class EventHubProducerAsyncClient implements Closeable { private final Scheduler scheduler; private final boolean isSharedConnection; private final Runnable onClientClose; - private final SchemaRegistryDataSerializer registrySerializer; + private final ObjectSerializer serializer; private enum SendMode { EVENT_DATA, @@ -125,7 +124,7 @@ private enum SendMode { */ EventHubProducerAsyncClient(String fullyQualifiedNamespace, String eventHubName, EventHubConnectionProcessor connectionProcessor, AmqpRetryOptions retryOptions, TracerProvider tracerProvider, - MessageSerializer messageSerializer, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose, SchemaRegistryDataSerializer registrySerializer) { + MessageSerializer messageSerializer, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose, ObjectSerializer serializer) { this.fullyQualifiedNamespace = Objects.requireNonNull(fullyQualifiedNamespace, "'fullyQualifiedNamespace' cannot be null."); this.eventHubName = Objects.requireNonNull(eventHubName, "'eventHubName' cannot be null."); @@ -139,7 +138,7 @@ private enum SendMode { this.retryPolicy = getRetryPolicy(retryOptions); this.scheduler = scheduler; this.isSharedConnection = isSharedConnection; - this.registrySerializer = registrySerializer; + this.serializer = serializer; } /** @@ -313,7 +312,7 @@ public Mono> createBatch(Class objectType, CreateBatchOpti : maximumLinkSize; return Mono.just(new ObjectBatch<>(batchSize, partitionId, partitionKey, objectType, - link::getErrorContext, tracerProvider, registrySerializer, + link::getErrorContext, tracerProvider, serializer, link.getEntityPath(), link.getHostname())); })); } @@ -583,12 +582,12 @@ private Mono getSendLink(String partitionId) { private Mono verifySendMode(SendMode mode) { switch (mode) { case EVENT_DATA: - if (registrySerializer != null) { + if (serializer != null) { return monoError(logger, new IllegalStateException()); } break; case OBJECT: - if (registrySerializer == null) { + if (serializer == null) { return monoError(logger, new IllegalStateException()); } break; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index c4c7e677e8a38..1d08f69750d45 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -4,13 +4,12 @@ import com.azure.core.amqp.implementation.ErrorContextProvider; import com.azure.core.amqp.implementation.TracerProvider; import com.azure.core.util.logging.ClientLogger; -import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; public final class ObjectBatch extends Batch { private final ClientLogger logger = new ClientLogger(ObjectBatch.class); private final Object lock = new Object(); private final Class batchType; - private final SchemaRegistryDataSerializer registrySerializer; + private final ObjectSerializer serializer; /** * @@ -20,16 +19,16 @@ public final class ObjectBatch extends Batch { * @param batchType * @param contextProvider * @param tracerProvider - * @param registrySerializer + * @param serializer * @param entityPath * @param hostname */ ObjectBatch(int maxMessageSize, String partitionId, String partitionKey, Class batchType, ErrorContextProvider contextProvider, TracerProvider tracerProvider, - SchemaRegistryDataSerializer registrySerializer, String entityPath, String hostname) { + ObjectSerializer serializer, String entityPath, String hostname) { super(maxMessageSize, partitionId, partitionKey, contextProvider, tracerProvider, entityPath, hostname); this.batchType = batchType; - this.registrySerializer = registrySerializer; + this.serializer = serializer; } /** @@ -47,7 +46,7 @@ public boolean tryAdd(final T object) { throw logger.logExceptionAsWarning(new IllegalArgumentException("object cannot be null")); } - EventData eventData = new EventData(registrySerializer.serialize(object).block()); + EventData eventData = new EventData(serializer.serialize(object).block()); EventData event = tracerProvider.isEnabled() ? traceMessageSpan(eventData) : eventData; return tryAdd(event); From 82eb0ff7a1cdf791fd4fa447e85400c0557b167d Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Wed, 1 Jul 2020 16:34:25 -0700 Subject: [PATCH 04/29] dep on core experimental --- sdk/eventhubs/azure-messaging-eventhubs/pom.xml | 4 ++-- .../azure-messaging-eventhubs/src/main/java/module-info.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/pom.xml b/sdk/eventhubs/azure-messaging-eventhubs/pom.xml index a2439f655028b..d5c76c3524923 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/pom.xml +++ b/sdk/eventhubs/azure-messaging-eventhubs/pom.xml @@ -36,8 +36,8 @@ com.azure - azure-core - 1.5.1 + azure-core-experimental + 1.0.0-beta.1 com.azure diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java index 86ce6f72469c8..3929be5ca9f3d 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java @@ -2,7 +2,8 @@ // Licensed under the MIT License. module com.azure.messaging.eventhubs { - requires transitive com.azure.core; +// requires transitive com.azure.core; + requires com.azure.core.experimental; requires transitive com.azure.core.amqp; requires com.microsoft.azure.qpid.protonj.extensions; From eda212d0dda4351f68162b7eb70f984f945f3168 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Wed, 1 Jul 2020 16:36:02 -0700 Subject: [PATCH 05/29] temp --- .../com/azure/messaging/eventhubs/ObjectBatch.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index 1d08f69750d45..ee526c930798a 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -4,6 +4,11 @@ import com.azure.core.amqp.implementation.ErrorContextProvider; import com.azure.core.amqp.implementation.TracerProvider; import com.azure.core.util.logging.ClientLogger; +import com.azure.core.experimental.serializer.ObjectSerializer; +import reactor.core.publisher.Mono; + +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; public final class ObjectBatch extends Batch { private final ClientLogger logger = new ClientLogger(ObjectBatch.class); @@ -46,9 +51,15 @@ public boolean tryAdd(final T object) { throw logger.logExceptionAsWarning(new IllegalArgumentException("object cannot be null")); } - EventData eventData = new EventData(serializer.serialize(object).block()); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + serializer.serialize(outputStream, object).block(); + EventData eventData = new EventData(outputStream.toByteArray()); EventData event = tracerProvider.isEnabled() ? traceMessageSpan(eventData) : eventData; return tryAdd(event); } + + Mono serialize(S stream, Object value) { + return null; + } } From 6a1d7e7baf571d41a767c003a268bd4d65fc1640 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Thu, 2 Jul 2020 10:48:34 -0700 Subject: [PATCH 06/29] getDeserializedObject() --- .../azure/messaging/eventhubs/EventData.java | 1 - .../eventhubs/EventHubAsyncClient.java | 17 +++++----- .../eventhubs/EventHubClientBuilder.java | 20 +++++------ .../EventHubConsumerAsyncClient.java | 10 +++--- .../EventHubPartitionAsyncConsumer.java | 11 +++--- .../EventHubProducerAsyncClient.java | 7 +++- .../messaging/eventhubs/ObjectBatch.java | 16 ++++----- .../eventhubs/models/PartitionEvent.java | 24 ++++++++++++- .../EventHubConsumerAsyncClientTest.java | 18 +++++----- .../eventhubs/EventHubConsumerClientTest.java | 10 +++--- .../EventHubPartitionAsyncConsumerTest.java | 6 ++-- .../EventHubProducerAsyncClientTest.java | 34 +++++++++---------- .../eventhubs/EventHubProducerClientTest.java | 14 ++++---- ...EventProcessorClientErrorHandlingTest.java | 2 +- .../eventhubs/EventProcessorClientTest.java | 2 +- .../PartitionBasedLoadBalancerTest.java | 12 +++---- 16 files changed, 115 insertions(+), 89 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventData.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventData.java index 0a02323cdfd22..bcf8f0d101fbb 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventData.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventData.java @@ -4,7 +4,6 @@ package com.azure.messaging.eventhubs; import com.azure.core.util.Context; -import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; import java.nio.ByteBuffer; import java.time.Instant; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java index f0efe1cac39c4..1df8f1ee5cac4 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java @@ -5,8 +5,8 @@ import com.azure.core.amqp.implementation.MessageSerializer; import com.azure.core.amqp.implementation.TracerProvider; +import com.azure.core.experimental.serializer.ObjectSerializer; import com.azure.core.util.logging.ClientLogger; -import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; import com.azure.messaging.eventhubs.implementation.EventHubConnectionProcessor; import com.azure.messaging.eventhubs.implementation.EventHubManagementNode; import reactor.core.publisher.Flux; @@ -33,10 +33,11 @@ class EventHubAsyncClient implements Closeable { private final boolean isSharedConnection; private final Runnable onClientClose; private final TracerProvider tracerProvider; - private final SchemaRegistryDataSerializer registrySerializer; + private final ObjectSerializer objectSerializer; EventHubAsyncClient(EventHubConnectionProcessor connectionProcessor, TracerProvider tracerProvider, - MessageSerializer messageSerializer, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose, SchemaRegistryDataSerializer registrySerializer) { + MessageSerializer messageSerializer, ObjectSerializer objectSerializer, Scheduler scheduler, boolean isSharedConnection, + Runnable onClientClose) { this.tracerProvider = Objects.requireNonNull(tracerProvider, "'tracerProvider' cannot be null."); this.messageSerializer = Objects.requireNonNull(messageSerializer, "'messageSerializer' cannot be null."); this.connectionProcessor = Objects.requireNonNull(connectionProcessor, @@ -45,7 +46,7 @@ class EventHubAsyncClient implements Closeable { this.onClientClose = Objects.requireNonNull(onClientClose, "'onClientClose' cannot be null."); this.isSharedConnection = isSharedConnection; - this.registrySerializer = registrySerializer; + this.objectSerializer = objectSerializer; } /** @@ -107,8 +108,8 @@ Mono getPartitionProperties(String partitionId) { */ EventHubProducerAsyncClient createProducer() { return new EventHubProducerAsyncClient(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), - connectionProcessor, connectionProcessor.getRetryOptions(), tracerProvider, messageSerializer, scheduler, - isSharedConnection, onClientClose, registrySerializer); + connectionProcessor, connectionProcessor.getRetryOptions(), tracerProvider, messageSerializer, + objectSerializer, scheduler, isSharedConnection, onClientClose); } /** @@ -132,8 +133,8 @@ EventHubConsumerAsyncClient createConsumer(String consumerGroup, int prefetchCou } return new EventHubConsumerAsyncClient(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), - connectionProcessor, messageSerializer, consumerGroup, prefetchCount, scheduler, isSharedConnection, - onClientClose); + connectionProcessor, messageSerializer, objectSerializer, consumerGroup, prefetchCount, scheduler, + isSharedConnection, onClientClose); } /** diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java index a520529adba03..a221b9e188caa 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java @@ -20,12 +20,11 @@ import com.azure.core.annotation.ServiceClientBuilder; import com.azure.core.credential.TokenCredential; import com.azure.core.exception.AzureException; +import com.azure.core.experimental.serializer.ObjectSerializer; import com.azure.core.util.Configuration; import com.azure.core.util.CoreUtils; import com.azure.core.util.logging.ClientLogger; import com.azure.core.util.tracing.Tracer; -import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; -import com.azure.data.schemaregistry.SchemaRegistryDataDeserializer; import com.azure.messaging.eventhubs.implementation.ClientConstants; import com.azure.messaging.eventhubs.implementation.EventHubAmqpConnection; import com.azure.messaging.eventhubs.implementation.EventHubConnectionProcessor; @@ -95,7 +94,7 @@ */ @ServiceClientBuilder(serviceClients = {EventHubProducerAsyncClient.class, EventHubProducerClient.class, EventHubConsumerAsyncClient.class, EventHubConsumerClient.class}) -public class EventHubClientBuilder { +public class EventHubClientBuilder { // Default number of events to fetch when creating the consumer. static final int DEFAULT_PREFETCH_COUNT = 500; @@ -137,8 +136,7 @@ public class EventHubClientBuilder { private String consumerGroup; private EventHubConnectionProcessor eventHubConnectionProcessor; private int prefetchCount; - private SchemaRegistryDataSerializer registrySerializer; - private SchemaRegistryDataDeserializer registryDeserializer; + private ObjectSerializer objectSerializer; /** * Keeps track of the open clients that were created from this builder when there is a shared connection. @@ -367,11 +365,11 @@ public EventHubClientBuilder prefetchCount(int prefetchCount) { /** * Set registry serializer - * @param serializer serializer - * @return update builder instance + * @param objectSerializer serializer + * @return updated builder instance */ - public EventHubClientBuilder registrySerializer(SchemaRegistryDataSerializer serializer) { - this.registrySerializer = registrySerializer; + public EventHubClientBuilder objectSerializer(ObjectSerializer objectSerializer) { + this.objectSerializer = objectSerializer; return this; } @@ -499,8 +497,8 @@ EventHubAsyncClient buildAsyncClient() { final TracerProvider tracerProvider = new TracerProvider(ServiceLoader.load(Tracer.class)); - return new EventHubAsyncClient(processor, tracerProvider, messageSerializer, scheduler, - isSharedConnection.get(), this::onClientClose, registrySerializer); + return new EventHubAsyncClient(processor, tracerProvider, messageSerializer, objectSerializer, scheduler, + isSharedConnection.get(), this::onClientClose); } /** diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java index 82f97bd2f024e..31ab2f7aed91a 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java @@ -11,8 +11,8 @@ import com.azure.core.annotation.ReturnType; import com.azure.core.annotation.ServiceClient; import com.azure.core.annotation.ServiceMethod; +import com.azure.core.experimental.serializer.ObjectSerializer; import com.azure.core.util.logging.ClientLogger; -import com.azure.data.schemaregistry.SchemaRegistryDataDeserializer; import com.azure.messaging.eventhubs.implementation.AmqpReceiveLinkProcessor; import com.azure.messaging.eventhubs.implementation.EventHubConnectionProcessor; import com.azure.messaging.eventhubs.implementation.EventHubManagementNode; @@ -71,6 +71,7 @@ public class EventHubConsumerAsyncClient implements Closeable { private final String eventHubName; private final EventHubConnectionProcessor connectionProcessor; private final MessageSerializer messageSerializer; + private final ObjectSerializer objectSerializer; private final String consumerGroup; private final int prefetchCount; private final Scheduler scheduler; @@ -85,12 +86,13 @@ public class EventHubConsumerAsyncClient implements Closeable { EventHubConsumerAsyncClient(String fullyQualifiedNamespace, String eventHubName, EventHubConnectionProcessor connectionProcessor, MessageSerializer messageSerializer, - String consumerGroup, int prefetchCount, + ObjectSerializer objectSerializer, String consumerGroup, int prefetchCount, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClosed) { this.fullyQualifiedNamespace = fullyQualifiedNamespace; this.eventHubName = eventHubName; this.connectionProcessor = connectionProcessor; this.messageSerializer = messageSerializer; + this.objectSerializer = objectSerializer; this.consumerGroup = consumerGroup; this.prefetchCount = prefetchCount; this.scheduler = scheduler; @@ -366,7 +368,7 @@ private EventHubPartitionAsyncConsumer createPartitionConsumer(String linkName, new AmqpReceiveLinkProcessor(prefetchCount, retryPolicy, connectionProcessor)); return new EventHubPartitionAsyncConsumer(linkMessageProcessor, messageSerializer, getFullyQualifiedNamespace(), - getEventHubName(), consumerGroup, partitionId, initialPosition, - receiveOptions.getTrackLastEnqueuedEventProperties(), scheduler); + getEventHubName(), consumerGroup, partitionId, objectSerializer, + initialPosition, receiveOptions.getTrackLastEnqueuedEventProperties(), scheduler); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java index d0b070343d4d6..e63775e87fd42 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java @@ -4,6 +4,7 @@ package com.azure.messaging.eventhubs; import com.azure.core.amqp.implementation.MessageSerializer; +import com.azure.core.experimental.serializer.ObjectSerializer; import com.azure.core.util.logging.ClientLogger; import com.azure.messaging.eventhubs.implementation.AmqpReceiveLinkProcessor; import com.azure.messaging.eventhubs.models.EventPosition; @@ -39,13 +40,14 @@ class EventHubPartitionAsyncConsumer implements AutoCloseable { private final Scheduler scheduler; private final EmitterProcessor emitterProcessor; private final EventPosition initialPosition; + private final ObjectSerializer objectSerializer; private volatile Long currentOffset; EventHubPartitionAsyncConsumer(AmqpReceiveLinkProcessor amqpReceiveLinkProcessor, - MessageSerializer messageSerializer, String fullyQualifiedNamespace, String eventHubName, String consumerGroup, - String partitionId, AtomicReference> currentEventPosition, - boolean trackLastEnqueuedEventProperties, Scheduler scheduler) { + MessageSerializer messageSerializer, String fullyQualifiedNamespace, String eventHubName, String consumerGroup, + String partitionId, ObjectSerializer objectSerializer, AtomicReference> currentEventPosition, + boolean trackLastEnqueuedEventProperties, Scheduler scheduler) { this.initialPosition = Objects.requireNonNull(currentEventPosition.get().get(), "'currentEventPosition.get().get()' cannot be null."); this.amqpReceiveLinkProcessor = amqpReceiveLinkProcessor; @@ -54,6 +56,7 @@ class EventHubPartitionAsyncConsumer implements AutoCloseable { this.eventHubName = eventHubName; this.consumerGroup = consumerGroup; this.partitionId = partitionId; + this.objectSerializer = objectSerializer; this.trackLastEnqueuedEventProperties = trackLastEnqueuedEventProperties; this.scheduler = Objects.requireNonNull(scheduler, "'scheduler' cannot be null."); @@ -138,6 +141,6 @@ private PartitionEvent onMessageReceived(Message message) { final PartitionContext partitionContext = new PartitionContext(fullyQualifiedNamespace, eventHubName, consumerGroup, partitionId); - return new PartitionEvent(partitionContext, event, lastEnqueuedEventProperties.get()); + return new PartitionEvent(partitionContext, event, lastEnqueuedEventProperties.get(), this.objectSerializer); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java index 3f6935fc2522a..47776a6511ba1 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java @@ -15,6 +15,7 @@ import com.azure.core.annotation.ReturnType; import com.azure.core.annotation.ServiceClient; import com.azure.core.annotation.ServiceMethod; +import com.azure.core.experimental.serializer.ObjectSerializer; import com.azure.core.util.Context; import com.azure.core.util.CoreUtils; import com.azure.core.util.logging.ClientLogger; @@ -124,7 +125,7 @@ private enum SendMode { */ EventHubProducerAsyncClient(String fullyQualifiedNamespace, String eventHubName, EventHubConnectionProcessor connectionProcessor, AmqpRetryOptions retryOptions, TracerProvider tracerProvider, - MessageSerializer messageSerializer, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose, ObjectSerializer serializer) { + MessageSerializer messageSerializer, ObjectSerializer serializer, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose) { this.fullyQualifiedNamespace = Objects.requireNonNull(fullyQualifiedNamespace, "'fullyQualifiedNamespace' cannot be null."); this.eventHubName = Objects.requireNonNull(eventHubName, "'eventHubName' cannot be null."); @@ -257,6 +258,8 @@ public Mono createBatch(CreateBatchOptions options) { /** * Creates an {@link ObjectBatch} that can fit as many serialized objects as events as the transport allows. + * @param objectType type of object in the batch + * @param object type * * @return A new {@link ObjectBatch} that can fit as many serialized objects as events as the transport allows. */ @@ -267,6 +270,8 @@ public Mono> createBatch(Class objectType) { /** * Creates an {@link ObjectBatch} configured with the options specified. * + * @param objectType type of object in the batch + * @param object type * @param options A set of options used to configure the {@link ObjectBatch}. * @return A new {@link ObjectBatch} that can fit as many events as the transport allows. * @throws NullPointerException if {@code options} is null. diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index ee526c930798a..b8fe14217435a 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -46,20 +46,16 @@ public final class ObjectBatch extends Batch { * @throws AmqpException if serialized object as {@link EventData} is larger than the maximum size * of the {@link EventDataBatch}. */ - public boolean tryAdd(final T object) { + public Boolean tryAdd(final T object) { if (object == null) { throw logger.logExceptionAsWarning(new IllegalArgumentException("object cannot be null")); } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - serializer.serialize(outputStream, object).block(); - EventData eventData = new EventData(outputStream.toByteArray()); - EventData event = tracerProvider.isEnabled() ? traceMessageSpan(eventData) : eventData; - - return tryAdd(event); - } - - Mono serialize(S stream, Object value) { - return null; + return serializer.serialize(outputStream, object).map(s -> { + EventData eventData = new EventData(s.toByteArray()); + EventData event = tracerProvider.isEnabled() ? traceMessageSpan(eventData) : eventData; + return tryAdd(event); + }).block(); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java index 838025b1eff4e..a4c272b798af4 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java @@ -4,8 +4,10 @@ package com.azure.messaging.eventhubs.models; import com.azure.core.annotation.Immutable; +import com.azure.core.experimental.serializer.ObjectSerializer; import com.azure.messaging.eventhubs.EventData; +import java.io.ByteArrayInputStream; import java.util.Objects; /** @@ -17,6 +19,9 @@ public class PartitionEvent { private final PartitionContext partitionContext; private final EventData eventData; private final LastEnqueuedEventProperties lastEnqueuedEventProperties; + private final ObjectSerializer objectSerializer; + + private Object deserialized; /** * Creates an instance of PartitionEvent. @@ -24,13 +29,15 @@ public class PartitionEvent { * @param partitionContext The partition information associated with the event data. * @param eventData The event data received from the Event Hub. * @param lastEnqueuedEventProperties The properties of the last enqueued event in the partition. + * @param objectSerializer ObjectSerializer implementation for deserializing event data payload. May be null. * @throws NullPointerException if {@code partitionContext} or {@code eventData} is {@code null}. */ public PartitionEvent(final PartitionContext partitionContext, final EventData eventData, - LastEnqueuedEventProperties lastEnqueuedEventProperties) { + LastEnqueuedEventProperties lastEnqueuedEventProperties, ObjectSerializer objectSerializer) { this.partitionContext = Objects.requireNonNull(partitionContext, "'partitionContext' cannot be null"); this.eventData = Objects.requireNonNull(eventData, "'eventData' cannot be null"); this.lastEnqueuedEventProperties = lastEnqueuedEventProperties; + this.objectSerializer = objectSerializer; } /** @@ -59,4 +66,19 @@ public EventData getData() { public LastEnqueuedEventProperties getLastEnqueuedEventProperties() { return lastEnqueuedEventProperties; } + + public T getDeserializedObject(Class objectType) { + Objects.requireNonNull(objectSerializer, "No serializer set for deserializing event data payload."); + + if (deserialized != null) { + if (objectType.isInstance(deserialized)) { + return objectType.cast(deserialized); + }; + } + + T typedDeserializedObject = + objectSerializer.deserialize(new ByteArrayInputStream(eventData.getBody()), objectType).block(); + deserialized = typedDeserializedObject; + return typedDeserializedObject; + } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java index c37f1686c710d..ce9461c31e179 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClientTest.java @@ -136,7 +136,7 @@ CbsAuthorizationType.SHARED_ACCESS_SIGNATURE, AmqpTransportType.AMQP_WEB_SOCKETS .subscribeWith(new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), "event-hub-name", connectionOptions.getRetry())); - consumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, + consumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, null, CONSUMER_GROUP, PREFETCH, parallelScheduler, false, onClientClosed); } @@ -156,7 +156,7 @@ void teardown() { @Test void lastEnqueuedEventInformationIsNull() { final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, DEFAULT_PREFETCH_COUNT, parallelScheduler, false, onClientClosed); + connectionProcessor, messageSerializer, null, CONSUMER_GROUP, DEFAULT_PREFETCH_COUNT, parallelScheduler, false, onClientClosed); final int numberOfEvents = 10; when(amqpReceiveLink.getCredits()).thenReturn(numberOfEvents); final int numberToReceive = 3; @@ -179,7 +179,7 @@ void lastEnqueuedEventInformationIsNull() { void lastEnqueuedEventInformationCreated() { // Arrange final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, DEFAULT_PREFETCH_COUNT, Schedulers.parallel(), false, onClientClosed); + connectionProcessor, messageSerializer, null, CONSUMER_GROUP, DEFAULT_PREFETCH_COUNT, Schedulers.parallel(), false, onClientClosed); final int numberOfEvents = 10; final ReceiveOptions receiveOptions = new ReceiveOptions().setTrackLastEnqueuedEventProperties(true); when(amqpReceiveLink.getCredits()).thenReturn(numberOfEvents); @@ -232,7 +232,7 @@ void receivesNumberOfEventsAllowsBlock() throws InterruptedException { // Scheduling on elastic to simulate a user passed in scheduler (this is the default in EventHubClientBuilder). final EventHubConsumerAsyncClient myConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.elastic(), false, onClientClosed); + connectionProcessor, messageSerializer, null, CONSUMER_GROUP, PREFETCH, Schedulers.elastic(), false, onClientClosed); final Flux eventsFlux = myConsumer.receiveFromPartition(PARTITION_ID, EventPosition.earliest()) .take(numberOfEvents); @@ -294,7 +294,7 @@ void returnsNewListener() { any(ReceiveOptions.class))).thenReturn(Mono.just(link2), Mono.just(link3)); EventHubConsumerAsyncClient asyncClient = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, testScheduler, false, onClientClosed); + eventHubConnection, messageSerializer, null, CONSUMER_GROUP, PREFETCH, testScheduler, false, onClientClosed); // Act & Assert StepVerifier.create(asyncClient.receiveFromPartition(PARTITION_ID, EventPosition.earliest()).take(numberOfEvents)) @@ -517,7 +517,7 @@ void receivesMultiplePartitions() { .thenReturn(Mono.just(new EventHubProperties(EVENT_HUB_NAME, Instant.EPOCH, partitions))); EventHubConsumerAsyncClient asyncClient = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, parallelScheduler, false, onClientClosed); + eventHubConnection, messageSerializer, null, CONSUMER_GROUP, PREFETCH, parallelScheduler, false, onClientClosed); EmitterProcessor processor2 = EmitterProcessor.create(); FluxSink processor2sink = processor2.sink(); @@ -592,7 +592,7 @@ void receivesMultiplePartitionsWhenOneCloses() { .thenReturn(Mono.just(new EventHubProperties(EVENT_HUB_NAME, Instant.EPOCH, partitions))); EventHubConsumerAsyncClient asyncClient = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); + eventHubConnection, messageSerializer, null, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); EmitterProcessor processor2 = EmitterProcessor.create(); FluxSink processor2sink = processor2.sink(); @@ -652,7 +652,7 @@ void doesNotCloseSharedConnection() { EventHubConnectionProcessor eventHubConnection = Flux.create(sink -> sink.next(connection1)) .subscribeWith(new EventHubConnectionProcessor(HOSTNAME, EVENT_HUB_NAME, retryOptions)); EventHubConsumerAsyncClient sharedConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - eventHubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), true, onClientClosed); + eventHubConnection, messageSerializer, null, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), true, onClientClosed); // Act sharedConsumer.close(); @@ -672,7 +672,7 @@ void closesDedicatedConnection() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubConsumerAsyncClient dedicatedConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); + hubConnection, messageSerializer, null, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); // Act dedicatedConsumer.close(); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java index b05a875f23617..6aa9c9cb85fdb 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubConsumerClientTest.java @@ -118,7 +118,7 @@ CbsAuthorizationType.SHARED_ACCESS_SIGNATURE, AmqpTransportType.AMQP_WEB_SOCKETS })); asyncConsumer = new EventHubConsumerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, messageSerializer, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); + connectionProcessor, messageSerializer, null, CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); consumer = new EventHubConsumerClient(asyncConsumer, Duration.ofSeconds(10)); } @@ -142,8 +142,8 @@ public static void dispose() { public void lastEnqueuedEventInformationIsNull() { // Arrange final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient( - HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, CONSUMER_GROUP, - PREFETCH, Schedulers.parallel(), false, onClientClosed); + HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, null, + CONSUMER_GROUP, PREFETCH, Schedulers.parallel(), false, onClientClosed); final EventHubConsumerClient consumer = new EventHubConsumerClient(runtimeConsumer, Duration.ofSeconds(5)); final int numberOfEvents = 10; sendMessages(sink, numberOfEvents, PARTITION_ID); @@ -172,8 +172,8 @@ public void lastEnqueuedEventInformationCreated() { // Arrange final ReceiveOptions options = new ReceiveOptions().setTrackLastEnqueuedEventProperties(true); final EventHubConsumerAsyncClient runtimeConsumer = new EventHubConsumerAsyncClient( - HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, CONSUMER_GROUP, PREFETCH, - Schedulers.parallel(), false, onClientClosed); + HOSTNAME, EVENT_HUB_NAME, connectionProcessor, messageSerializer, null, CONSUMER_GROUP, + PREFETCH, Schedulers.parallel(), false, onClientClosed); final EventHubConsumerClient consumer = new EventHubConsumerClient(runtimeConsumer, Duration.ofSeconds(5)); final int numberOfEvents = 10; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java index 3510200950493..0d95457f03d35 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java @@ -117,7 +117,7 @@ void receivesMessages(boolean trackLastEnqueuedProperties) { // Arrange linkProcessor = createSink(link1, link2).subscribeWith(new AmqpReceiveLinkProcessor(PREFETCH, retryPolicy, parentConnection)); consumer = new EventHubPartitionAsyncConsumer(linkProcessor, messageSerializer, HOSTNAME, EVENT_HUB_NAME, - CONSUMER_GROUP, PARTITION_ID, currentPosition, trackLastEnqueuedProperties, Schedulers.parallel()); + CONSUMER_GROUP, PARTITION_ID, null, currentPosition, trackLastEnqueuedProperties, Schedulers.parallel()); final EventData event1 = new EventData("Foo"); final EventData event2 = new EventData("Bar"); @@ -165,7 +165,7 @@ void receiveMultipleTimes() { // Arrange linkProcessor = createSink(link1, link2).subscribeWith(new AmqpReceiveLinkProcessor(PREFETCH, retryPolicy, parentConnection)); consumer = new EventHubPartitionAsyncConsumer(linkProcessor, messageSerializer, HOSTNAME, EVENT_HUB_NAME, - CONSUMER_GROUP, PARTITION_ID, currentPosition, false, Schedulers.parallel()); + CONSUMER_GROUP, PARTITION_ID, null, currentPosition, false, Schedulers.parallel()); final Message message3 = mock(Message.class); final String secondOffset = "54"; @@ -233,7 +233,7 @@ void listensToShutdownSignals() throws InterruptedException { // Arrange linkProcessor = createSink(link1, link2).subscribeWith(new AmqpReceiveLinkProcessor(PREFETCH, retryPolicy, parentConnection)); consumer = new EventHubPartitionAsyncConsumer(linkProcessor, messageSerializer, HOSTNAME, EVENT_HUB_NAME, - CONSUMER_GROUP, PARTITION_ID, currentPosition, false, Schedulers.parallel()); + CONSUMER_GROUP, PARTITION_ID, null, currentPosition, false, Schedulers.parallel()); final Message message3 = mock(Message.class); final String secondOffset = "54"; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java index fbc8af492f9c8..6ab8b2d20f3a9 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClientTest.java @@ -146,7 +146,7 @@ void setup(TestInfo testInfo) { new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), "event-hub-path", connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, testScheduler, false, onClientClosed, registrySerializer); + tracerProvider, messageSerializer, null, testScheduler, false, onClientClosed); when(sendLink.getLinkSize()).thenReturn(Mono.just(ClientConstants.MAX_MESSAGE_LENGTH_BYTES)); when(sendLink2.getLinkSize()).thenReturn(Mono.just(ClientConstants.MAX_MESSAGE_LENGTH_BYTES)); @@ -238,8 +238,8 @@ void sendSingleMessageWithBlock() throws InterruptedException { final Semaphore semaphore = new Semaphore(1); // In our actual client builder, we allow this. final EventHubProducerAsyncClient flexibleProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, testScheduler, - false, onClientClosed, registrySerializer); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, testScheduler, + false, onClientClosed); // EC is the prefix they use when creating a link that sends to the service round-robin. when(connection.createSendLink(eq(EVENT_HUB_NAME), eq(EVENT_HUB_NAME), eq(retryOptions))) @@ -319,8 +319,8 @@ void sendStartSpanSingleMessage() { final SendOptions sendOptions = new SendOptions() .setPartitionId(partitionId); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), - false, onClientClosed, registrySerializer); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), + false, onClientClosed); when(connection.createSendLink( argThat(name -> name.endsWith(partitionId)), argThat(name -> name.endsWith(partitionId)), eq(retryOptions))) @@ -377,7 +377,7 @@ void sendMessageRetrySpanTest() { TracerProvider tracerProvider = new TracerProvider(tracers); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); + tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final String failureKey = "fail"; final EventData testData = new EventData("test"); @@ -516,8 +516,8 @@ void startMessageSpansOnCreateBatch() { final List tracers = Collections.singletonList(tracer1); TracerProvider tracerProvider = new TracerProvider(tracers); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), - false, onClientClosed, registrySerializer); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), + false, onClientClosed); final AmqpSendLink link = mock(AmqpSendLink.class); when(link.getLinkSize()).thenReturn(Mono.just(ClientConstants.MAX_MESSAGE_LENGTH_BYTES)); @@ -822,8 +822,8 @@ void doesNotCloseSharedConnection() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubProducerAsyncClient sharedProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), - true, onClientClosed, registrySerializer); + hubConnection, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), + true, onClientClosed); // Act sharedProducer.close(); @@ -841,8 +841,8 @@ void closesDedicatedConnection() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubProducerAsyncClient dedicatedProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), - false, onClientClosed, registrySerializer); + hubConnection, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), + false, onClientClosed); // Act dedicatedProducer.close(); @@ -860,8 +860,8 @@ void closesDedicatedConnectionOnlyOnce() { // Arrange EventHubConnectionProcessor hubConnection = mock(EventHubConnectionProcessor.class); EventHubProducerAsyncClient dedicatedProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - hubConnection, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), - false, onClientClosed, registrySerializer); + hubConnection, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), + false, onClientClosed); // Act dedicatedProducer.close(); @@ -897,7 +897,7 @@ void reopensOnFailure() { new EventHubConnectionProcessor(EVENT_HUB_NAME, connectionOptions.getFullyQualifiedNamespace(), connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); + tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final int count = 4; final byte[] contents = TEST_CONTENTS.getBytes(UTF_8); @@ -972,7 +972,7 @@ void closesOnNonTransientFailure() { new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), EVENT_HUB_NAME, connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); + tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final int count = 4; final byte[] contents = TEST_CONTENTS.getBytes(UTF_8); @@ -1048,7 +1048,7 @@ void resendMessageOnTransientLinkFailure() { new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), EVENT_HUB_NAME, connectionOptions.getRetry())); producer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); + tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final int count = 4; final byte[] contents = TEST_CONTENTS.getBytes(UTF_8); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java index ef06765753c56..02ec09aaeb2c1 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubProducerClientTest.java @@ -105,7 +105,7 @@ public void setup() { .subscribeWith(new EventHubConnectionProcessor(connectionOptions.getFullyQualifiedNamespace(), "event-hub-path", connectionOptions.getRetry())); asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, connectionProcessor, retryOptions, - tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); + tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); when(connection.getEndpointStates()).thenReturn(Flux.create(sink -> sink.next(AmqpEndpointState.ACTIVE))); } @@ -157,8 +157,8 @@ public void sendStartSpanSingleMessage() { final List tracers = Collections.singletonList(tracer1); final TracerProvider tracerProvider = new TracerProvider(tracers); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), - false, onClientClosed, registrySerializer); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), + false, onClientClosed); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); final EventData eventData = new EventData("hello-world".getBytes(UTF_8)); @@ -219,7 +219,7 @@ public void sendMessageRetrySpanTest() { .thenReturn(Mono.just(sendLink)); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); final EventData eventData = new EventData("hello-world".getBytes(UTF_8)) .addContext(SPAN_CONTEXT_KEY, Context.NONE); @@ -267,7 +267,7 @@ public void sendEventsExceedsBatchSize() { when(sendLink.getLinkSize()).thenReturn(Mono.just(1024)); TracerProvider tracerProvider = new TracerProvider(Collections.emptyList()); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), false, onClientClosed, registrySerializer); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), false, onClientClosed); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); //Act & Assert @@ -369,8 +369,8 @@ public void startsMessageSpanOnEventBatch() { final List tracers = Collections.singletonList(tracer1); final TracerProvider tracerProvider = new TracerProvider(tracers); final EventHubProducerAsyncClient asyncProducer = new EventHubProducerAsyncClient(HOSTNAME, EVENT_HUB_NAME, - connectionProcessor, retryOptions, tracerProvider, messageSerializer, Schedulers.parallel(), - false, onClientClosed, registrySerializer); + connectionProcessor, retryOptions, tracerProvider, messageSerializer, null, Schedulers.parallel(), + false, onClientClosed); final EventHubProducerClient producer = new EventHubProducerClient(asyncProducer, retryOptions.getTryTimeout()); final AmqpSendLink link = mock(AmqpSendLink.class); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java index a79be245862d5..86941734582ba 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientErrorHandlingTest.java @@ -139,7 +139,7 @@ private static Stream checkpointStoreSupplier() { private PartitionEvent getEvent(EventData event) { PartitionContext context = new PartitionContext("ns", "foo", "bar", "baz"); - return new PartitionEvent(context, event, null); + return new PartitionEvent(context, event, null, null); } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java index 05888a75f6cb4..ae309f330f9e2 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventProcessorClientTest.java @@ -474,7 +474,7 @@ public void testSingleEventReceiveHeartBeat() throws InterruptedException { private PartitionEvent getEvent(EventData event) { PartitionContext context = new PartitionContext("test-ns", "foo", "bar", "baz"); - return new PartitionEvent(context, event, null); + return new PartitionEvent(context, event, null, null); } private static final class TestPartitionProcessor extends PartitionProcessor { diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java index 698aee42498ea..4e5c09b72b313 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/PartitionBasedLoadBalancerTest.java @@ -113,7 +113,7 @@ public void testSingleEventProcessor() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, null); })); PartitionBasedLoadBalancer partitionBasedLoadBalancer = createPartitionLoadBalancer("owner1"); @@ -149,7 +149,7 @@ public void testTwoEventProcessors() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, null); })); PartitionBasedLoadBalancer partitionBasedLoadBalancer1 = createPartitionLoadBalancer("owner1"); @@ -185,7 +185,7 @@ public void testPartitionStealing() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, null); })); PartitionBasedLoadBalancer partitionBasedLoadBalancer1 = createPartitionLoadBalancer("owner1"); @@ -225,7 +225,7 @@ public void testMoreEventProcessorsThanPartitions() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, null); })); List loadBalancers = new ArrayList<>(); @@ -263,7 +263,7 @@ public void testEventProcessorInactive() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); final int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, null); })); List loadBalancers = new ArrayList<>(); @@ -422,7 +422,7 @@ public void testEmptyOwnerId() { .thenReturn(Flux.interval(Duration.ofSeconds(1)).map(index -> { final PartitionContext partitionContext = new PartitionContext("ns", "foo", "bar", "bazz"); final int i = index.intValue() % eventDataList.size(); - return new PartitionEvent(partitionContext, eventDataList.get(i), null); + return new PartitionEvent(partitionContext, eventDataList.get(i), null, null); })); String ownerName = "owner1"; From 3560da282ad74b25adccbc15ef768975cffa6935 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Thu, 2 Jul 2020 14:46:32 -0700 Subject: [PATCH 07/29] null object in object batch test --- .../messaging/eventhubs/ObjectBatch.java | 13 ++--- ...EventDataBatchTest.java => BatchTest.java} | 2 +- .../messaging/eventhubs/ObjectBatchTest.java | 52 +++++++++++++++++++ 3 files changed, 60 insertions(+), 7 deletions(-) rename sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/{EventDataBatchTest.java => BatchTest.java} (99%) create mode 100644 sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/ObjectBatchTest.java diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index b8fe14217435a..73015e6c8965d 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -9,12 +9,13 @@ import java.io.ByteArrayOutputStream; import java.io.OutputStream; +import java.util.Objects; public final class ObjectBatch extends Batch { private final ClientLogger logger = new ClientLogger(ObjectBatch.class); private final Object lock = new Object(); private final Class batchType; - private final ObjectSerializer serializer; + private final ObjectSerializer objectSerializer; /** * @@ -24,16 +25,16 @@ public final class ObjectBatch extends Batch { * @param batchType * @param contextProvider * @param tracerProvider - * @param serializer + * @param objectSerializer * @param entityPath * @param hostname */ ObjectBatch(int maxMessageSize, String partitionId, String partitionKey, Class batchType, ErrorContextProvider contextProvider, TracerProvider tracerProvider, - ObjectSerializer serializer, String entityPath, String hostname) { + ObjectSerializer objectSerializer, String entityPath, String hostname) { super(maxMessageSize, partitionId, partitionKey, contextProvider, tracerProvider, entityPath, hostname); - this.batchType = batchType; - this.serializer = serializer; + this.batchType = Objects.requireNonNull(batchType, "'batchType' cannot be null."); + this.objectSerializer = Objects.requireNonNull(objectSerializer, "'objectSerializer' cannot be null."); } /** @@ -52,7 +53,7 @@ public Boolean tryAdd(final T object) { } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - return serializer.serialize(outputStream, object).map(s -> { + return objectSerializer.serialize(outputStream, object).map(s -> { EventData eventData = new EventData(s.toByteArray()); EventData event = tracerProvider.isEnabled() ? traceMessageSpan(eventData) : eventData; return tryAdd(event); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/BatchTest.java similarity index 99% rename from sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchTest.java rename to sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/BatchTest.java index ea85afedd71f0..1833d24ece7df 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/BatchTest.java @@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; -public class EventDataBatchTest { +public class BatchTest { private static final String PARTITION_KEY = "PartitionIDCopyFromProducerOption"; @Mock diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/ObjectBatchTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/ObjectBatchTest.java new file mode 100644 index 0000000000000..26b7012402502 --- /dev/null +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/ObjectBatchTest.java @@ -0,0 +1,52 @@ +package com.azure.messaging.eventhubs; + +import com.azure.core.amqp.implementation.ErrorContextProvider; +import com.azure.core.experimental.serializer.ObjectSerializer; +import net.bytebuddy.pool.TypePool; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import reactor.core.publisher.Mono; + +import java.io.InputStream; +import java.io.OutputStream; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class ObjectBatchTest { + @Mock + private ErrorContextProvider errorContextProvider; + + @BeforeEach + public void setup() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void nullObject() { + assertThrows(IllegalArgumentException.class, () -> { + final ObjectBatch batch = new ObjectBatch<>( + 1024, + null, + null, + Object.class, + errorContextProvider, + null, + new ObjectSerializer() { + @Override + public Mono deserialize(InputStream stream, Class clazz) { + return null; + } + + @Override + public Mono serialize(S stream, Object value) { + return null; + } + }, + null, + null); + batch.tryAdd(null); + }); + } +} From 7a7bce3ba6747454325b9acc56cf474a5f9cd635 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Thu, 2 Jul 2020 14:52:01 -0700 Subject: [PATCH 08/29] remove old SR dep --- sdk/eventhubs/azure-messaging-eventhubs/pom.xml | 8 +------- .../src/main/java/module-info.java | 1 - 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/pom.xml b/sdk/eventhubs/azure-messaging-eventhubs/pom.xml index d5c76c3524923..ab4cabcfb35bc 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/pom.xml +++ b/sdk/eventhubs/azure-messaging-eventhubs/pom.xml @@ -37,7 +37,7 @@ com.azure azure-core-experimental - 1.0.0-beta.1 + 1.0.0-beta.1 com.azure @@ -45,12 +45,6 @@ 1.2.0 - - com.azure - azure-data-schemaregistry - 1.0.0-beta.2 - - com.azure diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java index 3929be5ca9f3d..7a942988e3c46 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java @@ -7,7 +7,6 @@ requires transitive com.azure.core.amqp; requires com.microsoft.azure.qpid.protonj.extensions; - requires azure.data.schemaregistry; exports com.azure.messaging.eventhubs; exports com.azure.messaging.eventhubs.models; From 89e6cca3ba0110beb5707ce6d69d55fb8dcf9fc3 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 09:55:59 -0700 Subject: [PATCH 09/29] remove temporary interfaces --- .../SchemaRegistryDataDeserializer.java | 18 ---------------- .../SchemaRegistryDataSerializer.java | 21 ------------------- 2 files changed, 39 deletions(-) delete mode 100644 sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataDeserializer.java delete mode 100644 sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataSerializer.java diff --git a/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataDeserializer.java b/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataDeserializer.java deleted file mode 100644 index 79a9400cdcf0d..0000000000000 --- a/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataDeserializer.java +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.data.schemaregistry; - -import reactor.core.publisher.Mono; - -/** - * deserializer implementation - */ -public interface SchemaRegistryDataDeserializer { - /** - * deserialize SR client produced bytes - * @param data to be deserialized - * @return deserialized object - */ - Mono deserialize(byte[] data); -} diff --git a/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataSerializer.java b/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataSerializer.java deleted file mode 100644 index ebbf495305664..0000000000000 --- a/sdk/schemaregistry/azure-data-schemaregistry/src/main/java/com/azure/data/schemaregistry/SchemaRegistryDataSerializer.java +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.azure.data.schemaregistry; - -import reactor.core.publisher.Mono; - -/** - * serializer interface - */ -public interface SchemaRegistryDataSerializer { - - Mono prefetchSchema(Class objectClass); - - /** - * serializer method - * @param object to be serialized - * @return Mono of serialized byte array - */ - byte[] serialize(Object object); -} From f3acc8c9f72a0becbede6bae614c11e926c67803 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 10:12:28 -0700 Subject: [PATCH 10/29] rename objectSerializer builder method to serializer --- .../messaging/eventhubs/EventHubClientBuilder.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java index a221b9e188caa..7e10cdb0a56cb 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java @@ -136,7 +136,7 @@ public class EventHubClientBuilder { private String consumerGroup; private EventHubConnectionProcessor eventHubConnectionProcessor; private int prefetchCount; - private ObjectSerializer objectSerializer; + private ObjectSerializer serializer; /** * Keeps track of the open clients that were created from this builder when there is a shared connection. @@ -365,11 +365,11 @@ public EventHubClientBuilder prefetchCount(int prefetchCount) { /** * Set registry serializer - * @param objectSerializer serializer + * @param serializer ObjectSerializer implementation * @return updated builder instance */ - public EventHubClientBuilder objectSerializer(ObjectSerializer objectSerializer) { - this.objectSerializer = objectSerializer; + public EventHubClientBuilder serializer(ObjectSerializer serializer) { + this.serializer = serializer; return this; } @@ -497,7 +497,7 @@ EventHubAsyncClient buildAsyncClient() { final TracerProvider tracerProvider = new TracerProvider(ServiceLoader.load(Tracer.class)); - return new EventHubAsyncClient(processor, tracerProvider, messageSerializer, objectSerializer, scheduler, + return new EventHubAsyncClient(processor, tracerProvider, messageSerializer, serializer, scheduler, isSharedConnection.get(), this::onClientClose); } From c95145c0b1ead9c81139164bb9d95ba673cc294d Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 13:19:53 -0700 Subject: [PATCH 11/29] single class imports --- .../src/main/java/com/azure/messaging/eventhubs/Batch.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java index cbe4da3466f0f..3938a304061a4 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java @@ -19,7 +19,12 @@ import reactor.core.publisher.Signal; import java.nio.BufferOverflowException; -import java.util.*; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.Optional; import static com.azure.core.util.tracing.Tracer.*; import static com.azure.messaging.eventhubs.implementation.ClientConstants.AZ_NAMESPACE_VALUE; From 4eed6e03208926dd9a2b78502ccb5929f06399a6 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 13:20:17 -0700 Subject: [PATCH 12/29] fix serializer builder javadoc --- .../com/azure/messaging/eventhubs/EventHubClientBuilder.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java index 7e10cdb0a56cb..76b66e4b5f17e 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubClientBuilder.java @@ -364,8 +364,10 @@ public EventHubClientBuilder prefetchCount(int prefetchCount) { } /** - * Set registry serializer + * Set ObjectSerializer implementation to be used for creating ObjectBatch. + * * @param serializer ObjectSerializer implementation + * * @return updated builder instance */ public EventHubClientBuilder serializer(ObjectSerializer serializer) { From f78469a45f76e6d58afa3d3f18aadde64e6a6f25 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 13:23:06 -0700 Subject: [PATCH 13/29] rename abstract batch impl --- .../java/com/azure/messaging/eventhubs/EventDataBatch.java | 2 +- .../eventhubs/{Batch.java => EventDataBatchBase.java} | 6 +++--- .../java/com/azure/messaging/eventhubs/ObjectBatch.java | 4 +--- .../{BatchTest.java => EventDataBatchBaseTest.java} | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) rename sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/{Batch.java => EventDataBatchBase.java} (97%) rename sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/{BatchTest.java => EventDataBatchBaseTest.java} (98%) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatch.java index 4ea3673f47f2e..0c00c696453e3 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatch.java @@ -16,7 +16,7 @@ * @see EventHubClientBuilder See EventHubClientBuilder for examples of building an asynchronous or synchronous * producer. */ -public final class EventDataBatch extends Batch { +public final class EventDataBatch extends EventDataBatchBase { EventDataBatch(int maxMessageSize, String partitionId, String partitionKey, ErrorContextProvider contextProvider, TracerProvider tracerProvider, String entityPath, String hostname) { super(maxMessageSize, partitionId, partitionKey, contextProvider, tracerProvider, entityPath, hostname); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java similarity index 97% rename from sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java rename to sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java index 3938a304061a4..3955589f1cf9c 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/Batch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java @@ -29,7 +29,7 @@ import static com.azure.core.util.tracing.Tracer.*; import static com.azure.messaging.eventhubs.implementation.ClientConstants.AZ_NAMESPACE_VALUE; -public abstract class Batch { +public abstract class EventDataBatchBase { private final ClientLogger logger = new ClientLogger(this.getClass()); private final Object lock = new Object(); private final int maxMessageSize; @@ -43,8 +43,8 @@ public abstract class Batch { private final String entityPath; private final String hostname; - Batch(int maxMessageSize, String partitionId, String partitionKey, ErrorContextProvider contextProvider, - TracerProvider tracerProvider, String entityPath, String hostname) { + EventDataBatchBase(int maxMessageSize, String partitionId, String partitionKey, ErrorContextProvider contextProvider, + TracerProvider tracerProvider, String entityPath, String hostname) { this.maxMessageSize = maxMessageSize; this.partitionKey = partitionKey; this.partitionId = partitionId; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index 73015e6c8965d..8589ae2acfc31 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -5,13 +5,11 @@ import com.azure.core.amqp.implementation.TracerProvider; import com.azure.core.util.logging.ClientLogger; import com.azure.core.experimental.serializer.ObjectSerializer; -import reactor.core.publisher.Mono; import java.io.ByteArrayOutputStream; -import java.io.OutputStream; import java.util.Objects; -public final class ObjectBatch extends Batch { +public final class ObjectBatch extends EventDataBatchBase { private final ClientLogger logger = new ClientLogger(ObjectBatch.class); private final Object lock = new Object(); private final Class batchType; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/BatchTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchBaseTest.java similarity index 98% rename from sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/BatchTest.java rename to sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchBaseTest.java index 1833d24ece7df..8a8a529ff7ab7 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/BatchTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventDataBatchBaseTest.java @@ -20,7 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; -public class BatchTest { +public class EventDataBatchBaseTest { private static final String PARTITION_KEY = "PartitionIDCopyFromProducerOption"; @Mock From c5d39fd91518226d6a1c0b98233d9c3c515b8bdb Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 14:09:44 -0700 Subject: [PATCH 14/29] add EventDataBatchBase javadoc --- .../com/azure/messaging/eventhubs/EventDataBatchBase.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java index 3955589f1cf9c..85345f6e11f5c 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java @@ -29,6 +29,11 @@ import static com.azure.core.util.tracing.Tracer.*; import static com.azure.messaging.eventhubs.implementation.ClientConstants.AZ_NAMESPACE_VALUE; +/** + * Base class containing common implementation for batch sending. + * + * Implemented by {@link ObjectBatch} and {@link EventDataBatch}. + */ public abstract class EventDataBatchBase { private final ClientLogger logger = new ClientLogger(this.getClass()); private final Object lock = new Object(); From 7a0fc351d37e69958bd3f8dd032e24ea195a8ef2 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 14:12:45 -0700 Subject: [PATCH 15/29] mono TryAdd --- .../messaging/eventhubs/ObjectBatch.java | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index 8589ae2acfc31..d5a423aa2a6d9 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -5,28 +5,23 @@ import com.azure.core.amqp.implementation.TracerProvider; import com.azure.core.util.logging.ClientLogger; import com.azure.core.experimental.serializer.ObjectSerializer; +import reactor.core.publisher.Mono; import java.io.ByteArrayOutputStream; import java.util.Objects; +/** + * A class for aggregating Java objects into a single, size-limited, batch. Objects are serialized into EventData + * objects and are added to the batch. It is treated as a single message when sent to the Azure Event Hubs service. + * + * @param type of objects in the batch. Multi-type batches are not permitted. + */ public final class ObjectBatch extends EventDataBatchBase { private final ClientLogger logger = new ClientLogger(ObjectBatch.class); private final Object lock = new Object(); private final Class batchType; private final ObjectSerializer objectSerializer; - /** - * - * @param maxMessageSize - * @param partitionId - * @param partitionKey - * @param batchType - * @param contextProvider - * @param tracerProvider - * @param objectSerializer - * @param entityPath - * @param hostname - */ ObjectBatch(int maxMessageSize, String partitionId, String partitionKey, Class batchType, ErrorContextProvider contextProvider, TracerProvider tracerProvider, ObjectSerializer objectSerializer, String entityPath, String hostname) { @@ -45,7 +40,7 @@ public final class ObjectBatch extends EventDataBatchBase { * @throws AmqpException if serialized object as {@link EventData} is larger than the maximum size * of the {@link EventDataBatch}. */ - public Boolean tryAdd(final T object) { + public Mono tryAdd(final T object) { if (object == null) { throw logger.logExceptionAsWarning(new IllegalArgumentException("object cannot be null")); } @@ -55,6 +50,6 @@ public Boolean tryAdd(final T object) { EventData eventData = new EventData(s.toByteArray()); EventData event = tracerProvider.isEnabled() ? traceMessageSpan(eventData) : eventData; return tryAdd(event); - }).block(); + }); } } From c9c1f295e395d3bf48e77efdff214a5b948c2251 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 15:18:30 -0700 Subject: [PATCH 16/29] fix modifiers --- .../com/azure/messaging/eventhubs/EventDataBatchBase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java index 85345f6e11f5c..4210e6abfab3a 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java @@ -34,7 +34,7 @@ * * Implemented by {@link ObjectBatch} and {@link EventDataBatch}. */ -public abstract class EventDataBatchBase { +abstract class EventDataBatchBase { private final ClientLogger logger = new ClientLogger(this.getClass()); private final Object lock = new Object(); private final int maxMessageSize; @@ -44,7 +44,7 @@ public abstract class EventDataBatchBase { private final byte[] eventBytes; private final String partitionId; private int sizeInBytes; - protected final TracerProvider tracerProvider; + private final TracerProvider tracerProvider; private final String entityPath; private final String hostname; From 6ea6bb61871ed659a1b13e4067e9183fd8681b7c Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 15:18:57 -0700 Subject: [PATCH 17/29] remove send mode --- .../EventHubProducerAsyncClient.java | 29 ++++--------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java index 47776a6511ba1..fe1193cbe8c6c 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java @@ -216,6 +216,11 @@ public Mono createBatch(CreateBatchOptions options) { return monoError(logger, new NullPointerException("'options' cannot be null.")); } + Mono optionsError = validateBatchOptions(options); + if (optionsError != null) { + return optionsError; + } + final String partitionKey = options.getPartitionKey(); final String partitionId = options.getPartitionId(); final int batchMaxSize = options.getMaximumSizeInBytes(); @@ -284,11 +289,6 @@ public Mono> createBatch(Class objectType, CreateBatchOpti return monoError(logger, new NullPointerException("'options' cannot be null.")); } - Mono> sendModeError = verifySendMode(SendMode.OBJECT); - if (sendModeError != null) { - return sendModeError; - } - Mono> optionsError = validateBatchOptions(options); if (optionsError != null) { return optionsError; @@ -584,25 +584,6 @@ private Mono getSendLink(String partitionId) { .flatMap(connection -> connection.createSendLink(linkName, entityPath, retryOptions)); } - private Mono verifySendMode(SendMode mode) { - switch (mode) { - case EVENT_DATA: - if (serializer != null) { - return monoError(logger, new IllegalStateException()); - } - break; - case OBJECT: - if (serializer == null) { - return monoError(logger, new IllegalStateException()); - } - break; - default: - break; - } - - return null; - } - private Mono validateBatchOptions(CreateBatchOptions options) { if (!CoreUtils.isNullOrEmpty(options.getPartitionKey()) && !CoreUtils.isNullOrEmpty(options.getPartitionId())) { From 4fdfa93da80d135d7667052a19f8f5dfa24a2c6c Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 15:19:21 -0700 Subject: [PATCH 18/29] fix object batch javadoc --- .../com/azure/messaging/eventhubs/ObjectBatch.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index d5a423aa2a6d9..88b7eecd5b613 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -18,7 +18,6 @@ */ public final class ObjectBatch extends EventDataBatchBase { private final ClientLogger logger = new ClientLogger(ObjectBatch.class); - private final Object lock = new Object(); private final Class batchType; private final ObjectSerializer objectSerializer; @@ -31,11 +30,11 @@ public final class ObjectBatch extends EventDataBatchBase { } /** - * Tries to add an object to the batch. + * Tries to asynchronously serialize an object into an EventData payload and add the EventData to the batch. * * @param object The object to add to the batch. - * @return {@code true} if the object could be added to the batch; {@code false} if the serialized object - * was too large to fit in the batch. + * @return Mono {@code true} if the object could be added to the batch; {@code false} if the serialized + * object was too large to fit in the batch. * @throws IllegalArgumentException if object is {@code null}. * @throws AmqpException if serialized object as {@link EventData} is larger than the maximum size * of the {@link EventDataBatch}. @@ -46,10 +45,6 @@ public Mono tryAdd(final T object) { } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - return objectSerializer.serialize(outputStream, object).map(s -> { - EventData eventData = new EventData(s.toByteArray()); - EventData event = tracerProvider.isEnabled() ? traceMessageSpan(eventData) : eventData; - return tryAdd(event); - }); + return objectSerializer.serialize(outputStream, object).map(s -> tryAdd(new EventData(s.toByteArray()))); } } From b976d2de3e787609f4579529395ed3498a1246bc Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 15:19:49 -0700 Subject: [PATCH 19/29] partition event deserialize to async --- .../messaging/eventhubs/models/PartitionEvent.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java index a4c272b798af4..10c012c1f8adb 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java @@ -6,6 +6,7 @@ import com.azure.core.annotation.Immutable; import com.azure.core.experimental.serializer.ObjectSerializer; import com.azure.messaging.eventhubs.EventData; +import reactor.core.publisher.Mono; import java.io.ByteArrayInputStream; import java.util.Objects; @@ -67,18 +68,18 @@ public LastEnqueuedEventProperties getLastEnqueuedEventProperties() { return lastEnqueuedEventProperties; } - public T getDeserializedObject(Class objectType) { + public Mono getDeserializedObject(Class objectType) { Objects.requireNonNull(objectSerializer, "No serializer set for deserializing event data payload."); + Objects.requireNonNull(objectType, "objectType cannot be null."); if (deserialized != null) { if (objectType.isInstance(deserialized)) { - return objectType.cast(deserialized); + return Mono.just(objectType.cast(deserialized)); }; } - T typedDeserializedObject = - objectSerializer.deserialize(new ByteArrayInputStream(eventData.getBody()), objectType).block(); - deserialized = typedDeserializedObject; - return typedDeserializedObject; + Mono objectMono = objectSerializer.deserialize(new ByteArrayInputStream(eventData.getBody()), objectType); + objectMono.subscribe(o -> deserialized = o); + return objectMono; } } From 114f68d5e512069c61c754c56810c88837aee4f6 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 15:20:02 -0700 Subject: [PATCH 20/29] uncomment azure core --- .../azure-messaging-eventhubs/src/main/java/module-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java index 7a942988e3c46..a448c57eb2abd 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java @@ -2,7 +2,7 @@ // Licensed under the MIT License. module com.azure.messaging.eventhubs { -// requires transitive com.azure.core; + requires transitive com.azure.core; requires com.azure.core.experimental; requires transitive com.azure.core.amqp; From 45c819ae7eb838eead933cb8d9f1e230c57f6a39 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 15:38:45 -0700 Subject: [PATCH 21/29] javadoc syntax --- .../main/java/com/azure/messaging/eventhubs/ObjectBatch.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index 88b7eecd5b613..11665fefe5c8b 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -33,7 +33,7 @@ public final class ObjectBatch extends EventDataBatchBase { * Tries to asynchronously serialize an object into an EventData payload and add the EventData to the batch. * * @param object The object to add to the batch. - * @return Mono {@code true} if the object could be added to the batch; {@code false} if the serialized + * @return {@code true} if the object could be added to the batch; {@code false} if the serialized * object was too large to fit in the batch. * @throws IllegalArgumentException if object is {@code null}. * @throws AmqpException if serialized object as {@link EventData} is larger than the maximum size From 533df1eb1f98bbbfb95ba14788a84973b6bb50a9 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 16:02:58 -0700 Subject: [PATCH 22/29] remove temp interface --- .../avro/SchemaRegistryAvroAsyncDeserializer.java | 3 +-- .../schemaregistry/avro/SchemaRegistryAvroAsyncSerializer.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncDeserializer.java b/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncDeserializer.java index 20227a9c1b629..e43ab1de10f51 100644 --- a/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncDeserializer.java +++ b/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncDeserializer.java @@ -3,7 +3,6 @@ package com.azure.data.schemaregistry.avro; -import com.azure.data.schemaregistry.SchemaRegistryDataDeserializer; import com.azure.data.schemaregistry.SerializationException; import reactor.core.publisher.Mono; import reactor.core.scheduler.Scheduler; @@ -14,7 +13,7 @@ /** * Asynchronous registry-based deserializer implementation. */ -public class SchemaRegistryAvroAsyncDeserializer implements SchemaRegistryDataDeserializer { +public class SchemaRegistryAvroAsyncDeserializer { private static final int DEFAULT_THREAD_POOL_SIZE = 8; private final SchemaRegistryAvroDeserializer deserializer; diff --git a/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncSerializer.java b/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncSerializer.java index e004ea98bb083..9d11d6bd76317 100644 --- a/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncSerializer.java +++ b/sdk/schemaregistry/azure-data-schemaregistry-avro/src/main/java/com/azure/data/schemaregistry/avro/SchemaRegistryAvroAsyncSerializer.java @@ -3,7 +3,6 @@ package com.azure.data.schemaregistry.avro; -import com.azure.data.schemaregistry.SchemaRegistryDataSerializer; import com.azure.data.schemaregistry.SerializationException; import reactor.core.publisher.Mono; import reactor.core.scheduler.Scheduler; @@ -14,7 +13,7 @@ /** * Asynchronous registry-based serializer implementation. */ -public class SchemaRegistryAvroAsyncSerializer implements SchemaRegistryDataSerializer { +public class SchemaRegistryAvroAsyncSerializer { private static final int DEFAULT_THREAD_POOL_SIZE = 8; private final SchemaRegistryAvroSerializer serializer; From d295b83b0bb6ecff5c6372115c6931b56318cf9c Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Mon, 6 Jul 2020 19:03:44 -0700 Subject: [PATCH 23/29] only core-experimental, not core --- sdk/eventhubs/azure-messaging-eventhubs/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/pom.xml b/sdk/eventhubs/azure-messaging-eventhubs/pom.xml index e853e6e7c62de..488bec433021b 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/pom.xml +++ b/sdk/eventhubs/azure-messaging-eventhubs/pom.xml @@ -39,11 +39,6 @@ azure-core-experimental 1.0.0-beta.1 - - com.azure - azure-core - 1.6.0 - com.azure azure-core-amqp From 28c5f63ea6f12674ad18b8635368df8fc6d8d669 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Tue, 7 Jul 2020 00:23:20 -0700 Subject: [PATCH 24/29] checkstyle --- .../messaging/eventhubs/EventDataBatchBase.java | 14 +++++++++++--- .../messaging/eventhubs/EventHubAsyncClient.java | 4 ++-- .../eventhubs/EventHubConsumerAsyncClient.java | 7 ++++--- .../eventhubs/EventHubPartitionAsyncConsumer.java | 8 +++++--- .../eventhubs/EventHubProducerAsyncClient.java | 6 ++++-- .../com/azure/messaging/eventhubs/ObjectBatch.java | 5 ++++- .../messaging/eventhubs/models/PartitionEvent.java | 9 ++++++++- .../azure/messaging/eventhubs/ObjectBatchTest.java | 4 +++- 8 files changed, 41 insertions(+), 16 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java index 4210e6abfab3a..6964ec79c1719 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventDataBatchBase.java @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.azure.messaging.eventhubs; import com.azure.core.amqp.AmqpMessageConstant; @@ -26,7 +29,11 @@ import java.util.Objects; import java.util.Optional; -import static com.azure.core.util.tracing.Tracer.*; +import static com.azure.core.util.tracing.Tracer.AZ_TRACING_NAMESPACE_KEY; +import static com.azure.core.util.tracing.Tracer.DIAGNOSTIC_ID_KEY; +import static com.azure.core.util.tracing.Tracer.ENTITY_PATH_KEY; +import static com.azure.core.util.tracing.Tracer.HOST_NAME_KEY; +import static com.azure.core.util.tracing.Tracer.SPAN_CONTEXT_KEY; import static com.azure.messaging.eventhubs.implementation.ClientConstants.AZ_NAMESPACE_VALUE; /** @@ -48,8 +55,9 @@ abstract class EventDataBatchBase { private final String entityPath; private final String hostname; - EventDataBatchBase(int maxMessageSize, String partitionId, String partitionKey, ErrorContextProvider contextProvider, - TracerProvider tracerProvider, String entityPath, String hostname) { + EventDataBatchBase(int maxMessageSize, String partitionId, String partitionKey, + ErrorContextProvider contextProvider, TracerProvider tracerProvider, String entityPath, + String hostname) { this.maxMessageSize = maxMessageSize; this.partitionKey = partitionKey; this.partitionId = partitionId; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java index 1df8f1ee5cac4..bdf0593b703b6 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java @@ -36,8 +36,8 @@ class EventHubAsyncClient implements Closeable { private final ObjectSerializer objectSerializer; EventHubAsyncClient(EventHubConnectionProcessor connectionProcessor, TracerProvider tracerProvider, - MessageSerializer messageSerializer, ObjectSerializer objectSerializer, Scheduler scheduler, boolean isSharedConnection, - Runnable onClientClose) { + MessageSerializer messageSerializer, ObjectSerializer objectSerializer, Scheduler scheduler, + boolean isSharedConnection, Runnable onClientClose) { this.tracerProvider = Objects.requireNonNull(tracerProvider, "'tracerProvider' cannot be null."); this.messageSerializer = Objects.requireNonNull(messageSerializer, "'messageSerializer' cannot be null."); this.connectionProcessor = Objects.requireNonNull(connectionProcessor, diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java index 31ab2f7aed91a..b0ef95e6b9163 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java @@ -85,9 +85,10 @@ public class EventHubConsumerAsyncClient implements Closeable { new ConcurrentHashMap<>(); EventHubConsumerAsyncClient(String fullyQualifiedNamespace, String eventHubName, - EventHubConnectionProcessor connectionProcessor, MessageSerializer messageSerializer, - ObjectSerializer objectSerializer, String consumerGroup, int prefetchCount, - Scheduler scheduler, boolean isSharedConnection, Runnable onClientClosed) { + EventHubConnectionProcessor connectionProcessor, + MessageSerializer messageSerializer, ObjectSerializer objectSerializer, + String consumerGroup, int prefetchCount, Scheduler scheduler, + boolean isSharedConnection, Runnable onClientClosed) { this.fullyQualifiedNamespace = fullyQualifiedNamespace; this.eventHubName = eventHubName; this.connectionProcessor = connectionProcessor; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java index e63775e87fd42..ff1ef8ce449d7 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java @@ -45,9 +45,11 @@ class EventHubPartitionAsyncConsumer implements AutoCloseable { private volatile Long currentOffset; EventHubPartitionAsyncConsumer(AmqpReceiveLinkProcessor amqpReceiveLinkProcessor, - MessageSerializer messageSerializer, String fullyQualifiedNamespace, String eventHubName, String consumerGroup, - String partitionId, ObjectSerializer objectSerializer, AtomicReference> currentEventPosition, - boolean trackLastEnqueuedEventProperties, Scheduler scheduler) { + MessageSerializer messageSerializer, String fullyQualifiedNamespace, + String eventHubName, String consumerGroup, String partitionId, + ObjectSerializer objectSerializer, + AtomicReference> currentEventPosition, + boolean trackLastEnqueuedEventProperties, Scheduler scheduler) { this.initialPosition = Objects.requireNonNull(currentEventPosition.get().get(), "'currentEventPosition.get().get()' cannot be null."); this.amqpReceiveLinkProcessor = amqpReceiveLinkProcessor; diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java index fe1193cbe8c6c..4c1f0fa27606b 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java @@ -124,8 +124,10 @@ private enum SendMode { * load balance the messages amongst available partitions. */ EventHubProducerAsyncClient(String fullyQualifiedNamespace, String eventHubName, - EventHubConnectionProcessor connectionProcessor, AmqpRetryOptions retryOptions, TracerProvider tracerProvider, - MessageSerializer messageSerializer, ObjectSerializer serializer, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClose) { + EventHubConnectionProcessor connectionProcessor, AmqpRetryOptions retryOptions, + TracerProvider tracerProvider, MessageSerializer messageSerializer, + ObjectSerializer serializer, Scheduler scheduler, boolean isSharedConnection, + Runnable onClientClose) { this.fullyQualifiedNamespace = Objects.requireNonNull(fullyQualifiedNamespace, "'fullyQualifiedNamespace' cannot be null."); this.eventHubName = Objects.requireNonNull(eventHubName, "'eventHubName' cannot be null."); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index 11665fefe5c8b..14379960b3f3f 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -1,3 +1,6 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.azure.messaging.eventhubs; import com.azure.core.amqp.exception.AmqpException; @@ -23,7 +26,7 @@ public final class ObjectBatch extends EventDataBatchBase { ObjectBatch(int maxMessageSize, String partitionId, String partitionKey, Class batchType, ErrorContextProvider contextProvider, TracerProvider tracerProvider, - ObjectSerializer objectSerializer, String entityPath, String hostname) { + ObjectSerializer objectSerializer, String entityPath, String hostname) { super(maxMessageSize, partitionId, partitionKey, contextProvider, tracerProvider, entityPath, hostname); this.batchType = Objects.requireNonNull(batchType, "'batchType' cannot be null."); this.objectSerializer = Objects.requireNonNull(objectSerializer, "'objectSerializer' cannot be null."); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java index 10c012c1f8adb..a18b8f41fdcaf 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java @@ -68,6 +68,13 @@ public LastEnqueuedEventProperties getLastEnqueuedEventProperties() { return lastEnqueuedEventProperties; } + /** + * Deserializes event payload into object. + * + * @param objectType Class object of type T + * @param object type for deserialization + * @return deserialized object as type T + */ public Mono getDeserializedObject(Class objectType) { Objects.requireNonNull(objectSerializer, "No serializer set for deserializing event data payload."); Objects.requireNonNull(objectType, "objectType cannot be null."); @@ -75,7 +82,7 @@ public Mono getDeserializedObject(Class objectType) { if (deserialized != null) { if (objectType.isInstance(deserialized)) { return Mono.just(objectType.cast(deserialized)); - }; + } } Mono objectMono = objectSerializer.deserialize(new ByteArrayInputStream(eventData.getBody()), objectType); diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/ObjectBatchTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/ObjectBatchTest.java index 26b7012402502..3cff1916bd214 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/ObjectBatchTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/ObjectBatchTest.java @@ -1,8 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + package com.azure.messaging.eventhubs; import com.azure.core.amqp.implementation.ErrorContextProvider; import com.azure.core.experimental.serializer.ObjectSerializer; -import net.bytebuddy.pool.TypePool; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; From 2e66eb11ab6b56896e089e6128800fd4b7328f8b Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Tue, 7 Jul 2020 15:07:12 -0700 Subject: [PATCH 25/29] update partition event deserialize --- .../EventHubPartitionAsyncConsumer.java | 8 +-- .../eventhubs/models/PartitionEvent.java | 42 +++++++++----- .../EventHubPartitionAsyncConsumerTest.java | 55 +++++++++++++++++++ 3 files changed, 86 insertions(+), 19 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java index ff1ef8ce449d7..950d4c532674c 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumer.java @@ -40,14 +40,14 @@ class EventHubPartitionAsyncConsumer implements AutoCloseable { private final Scheduler scheduler; private final EmitterProcessor emitterProcessor; private final EventPosition initialPosition; - private final ObjectSerializer objectSerializer; + private final ObjectSerializer serializer; private volatile Long currentOffset; EventHubPartitionAsyncConsumer(AmqpReceiveLinkProcessor amqpReceiveLinkProcessor, MessageSerializer messageSerializer, String fullyQualifiedNamespace, String eventHubName, String consumerGroup, String partitionId, - ObjectSerializer objectSerializer, + ObjectSerializer serializer, AtomicReference> currentEventPosition, boolean trackLastEnqueuedEventProperties, Scheduler scheduler) { this.initialPosition = Objects.requireNonNull(currentEventPosition.get().get(), @@ -58,7 +58,7 @@ class EventHubPartitionAsyncConsumer implements AutoCloseable { this.eventHubName = eventHubName; this.consumerGroup = consumerGroup; this.partitionId = partitionId; - this.objectSerializer = objectSerializer; + this.serializer = serializer; this.trackLastEnqueuedEventProperties = trackLastEnqueuedEventProperties; this.scheduler = Objects.requireNonNull(scheduler, "'scheduler' cannot be null."); @@ -143,6 +143,6 @@ private PartitionEvent onMessageReceived(Message message) { final PartitionContext partitionContext = new PartitionContext(fullyQualifiedNamespace, eventHubName, consumerGroup, partitionId); - return new PartitionEvent(partitionContext, event, lastEnqueuedEventProperties.get(), this.objectSerializer); + return new PartitionEvent(partitionContext, event, lastEnqueuedEventProperties.get(), this.serializer); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java index a18b8f41fdcaf..cc7f9b2dcf61c 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/models/PartitionEvent.java @@ -5,12 +5,15 @@ import com.azure.core.annotation.Immutable; import com.azure.core.experimental.serializer.ObjectSerializer; +import com.azure.core.util.logging.ClientLogger; import com.azure.messaging.eventhubs.EventData; import reactor.core.publisher.Mono; import java.io.ByteArrayInputStream; import java.util.Objects; +import static com.azure.core.util.FluxUtil.monoError; + /** * A container for {@link EventData} along with the partition information for this event data. */ @@ -20,9 +23,21 @@ public class PartitionEvent { private final PartitionContext partitionContext; private final EventData eventData; private final LastEnqueuedEventProperties lastEnqueuedEventProperties; - private final ObjectSerializer objectSerializer; + private final ObjectSerializer serializer; + private final ClientLogger logger = new ClientLogger(PartitionEvent.class); - private Object deserialized; + /** + * Creates an instance of PartitionEvent. + * + * @param partitionContext The partition information associated with the event data. + * @param eventData The event data received from the Event Hub. + * @param lastEnqueuedEventProperties The properties of the last enqueued event in the partition. + * @throws NullPointerException if {@code partitionContext} or {@code eventData} is {@code null}. + */ + public PartitionEvent(final PartitionContext partitionContext, final EventData eventData, + LastEnqueuedEventProperties lastEnqueuedEventProperties) { + this(partitionContext, eventData, lastEnqueuedEventProperties, null); + } /** * Creates an instance of PartitionEvent. @@ -30,15 +45,15 @@ public class PartitionEvent { * @param partitionContext The partition information associated with the event data. * @param eventData The event data received from the Event Hub. * @param lastEnqueuedEventProperties The properties of the last enqueued event in the partition. - * @param objectSerializer ObjectSerializer implementation for deserializing event data payload. May be null. + * @param serializer ObjectSerializer implementation for deserializing event data payload. May be null. * @throws NullPointerException if {@code partitionContext} or {@code eventData} is {@code null}. */ public PartitionEvent(final PartitionContext partitionContext, final EventData eventData, - LastEnqueuedEventProperties lastEnqueuedEventProperties, ObjectSerializer objectSerializer) { + LastEnqueuedEventProperties lastEnqueuedEventProperties, ObjectSerializer serializer) { this.partitionContext = Objects.requireNonNull(partitionContext, "'partitionContext' cannot be null"); this.eventData = Objects.requireNonNull(eventData, "'eventData' cannot be null"); this.lastEnqueuedEventProperties = lastEnqueuedEventProperties; - this.objectSerializer = objectSerializer; + this.serializer = serializer; } /** @@ -76,17 +91,14 @@ public LastEnqueuedEventProperties getLastEnqueuedEventProperties() { * @return deserialized object as type T */ public Mono getDeserializedObject(Class objectType) { - Objects.requireNonNull(objectSerializer, "No serializer set for deserializing event data payload."); - Objects.requireNonNull(objectType, "objectType cannot be null."); - - if (deserialized != null) { - if (objectType.isInstance(deserialized)) { - return Mono.just(objectType.cast(deserialized)); - } + if (this.serializer == null) { + return monoError(logger, + new NullPointerException("No serializer set for deserializing EventData payload.")); + } + if (objectType == null) { + return monoError(logger, new IllegalArgumentException("objectType cannot be null.")); } - Mono objectMono = objectSerializer.deserialize(new ByteArrayInputStream(eventData.getBody()), objectType); - objectMono.subscribe(o -> deserialized = o); - return objectMono; + return serializer.deserialize(new ByteArrayInputStream(eventData.getBody()), objectType); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java index 0d95457f03d35..64cd339cbd64e 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/test/java/com/azure/messaging/eventhubs/EventHubPartitionAsyncConsumerTest.java @@ -8,6 +8,7 @@ import com.azure.core.amqp.AmqpRetryPolicy; import com.azure.core.amqp.implementation.AmqpReceiveLink; import com.azure.core.amqp.implementation.MessageSerializer; +import com.azure.core.experimental.serializer.ObjectSerializer; import com.azure.core.util.Context; import com.azure.core.util.logging.ClientLogger; import com.azure.messaging.eventhubs.implementation.AmqpReceiveLinkProcessor; @@ -30,9 +31,12 @@ import reactor.core.publisher.DirectProcessor; import reactor.core.publisher.Flux; import reactor.core.publisher.FluxSink; +import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; import reactor.test.StepVerifier; +import java.io.InputStream; +import java.io.OutputStream; import java.time.Duration; import java.time.Instant; import java.util.Date; @@ -224,6 +228,57 @@ void receiveMultipleTimes() { Assertions.assertFalse(actual.isInclusive()); } + @Test + void receiveAndDeserialize() { + // just a test value + Object o = 0; + ObjectSerializer testSerializer = new ObjectSerializer() { + @Override + public Mono deserialize(InputStream stream, Class clazz) { + if (clazz.isInstance(o)) { + return Mono.just(clazz.cast(o)); + } + return null; + } + + @Override + public Mono serialize(S stream, Object value) { + return null; + } + }; + + // Arrange + linkProcessor = createSink(link1, link2).subscribeWith(new AmqpReceiveLinkProcessor(PREFETCH, retryPolicy, parentConnection)); + consumer = new EventHubPartitionAsyncConsumer(linkProcessor, messageSerializer, HOSTNAME, EVENT_HUB_NAME, + CONSUMER_GROUP, PARTITION_ID, testSerializer, currentPosition, false, Schedulers.parallel()); + + final EventData event = new EventData("Foo"); + final LastEnqueuedEventProperties last = new LastEnqueuedEventProperties(10L, 15L, + Instant.ofEpochMilli(1243454), Instant.ofEpochMilli(1240004)); + + when(messageSerializer.deserialize(same(message1), eq(EventData.class))).thenReturn(event); + when(messageSerializer.deserialize(same(message1), eq(LastEnqueuedEventProperties.class))).thenReturn(last); + + // Act & Assert + StepVerifier.create(consumer.receive()) + .then(() -> { + messageProcessorSink.next(message1); + }) + .assertNext(partitionEvent -> { + verifyPartitionContext(partitionEvent.getPartitionContext()); + verifyLastEnqueuedInformation(false, last, + partitionEvent.getLastEnqueuedEventProperties()); + Assertions.assertSame(event, partitionEvent.getData()); + Assertions.assertSame(Integer.class.cast(o), partitionEvent.getDeserializedObject(Integer.class).block()); + }) + .thenCancel() + .verify(); + + // The emitter processor is not closed until the partition consumer is. + Assertions.assertFalse(linkProcessor.isTerminated()); + Assertions.assertSame(originalPosition, currentPosition.get().get()); + } + /** * Verifies that the consumer closes and completes any listeners on a shutdown signal. From 8947c09fbb7f3cdc2efa18ca9d27da998e95b0b5 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Wed, 8 Jul 2020 09:47:45 -0700 Subject: [PATCH 26/29] monoError for object batch --- .../main/java/com/azure/messaging/eventhubs/ObjectBatch.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index 14379960b3f3f..3f9f5c6a0c461 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -13,6 +13,8 @@ import java.io.ByteArrayOutputStream; import java.util.Objects; +import static com.azure.core.util.FluxUtil.monoError; + /** * A class for aggregating Java objects into a single, size-limited, batch. Objects are serialized into EventData * objects and are added to the batch. It is treated as a single message when sent to the Azure Event Hubs service. @@ -44,7 +46,7 @@ public final class ObjectBatch extends EventDataBatchBase { */ public Mono tryAdd(final T object) { if (object == null) { - throw logger.logExceptionAsWarning(new IllegalArgumentException("object cannot be null")); + return monoError(logger, new IllegalArgumentException("object cannot be null")); } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); From 7496de8745084b789a87b9289a3a41b4b7002df5 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Wed, 8 Jul 2020 13:56:06 -0700 Subject: [PATCH 27/29] rename objectSerializer to serializer --- .../messaging/eventhubs/EventHubAsyncClient.java | 12 ++++++------ .../eventhubs/EventHubConsumerAsyncClient.java | 8 ++++---- .../com/azure/messaging/eventhubs/ObjectBatch.java | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java index bdf0593b703b6..27191d8d1f985 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubAsyncClient.java @@ -33,11 +33,11 @@ class EventHubAsyncClient implements Closeable { private final boolean isSharedConnection; private final Runnable onClientClose; private final TracerProvider tracerProvider; - private final ObjectSerializer objectSerializer; + private final ObjectSerializer serializer; EventHubAsyncClient(EventHubConnectionProcessor connectionProcessor, TracerProvider tracerProvider, - MessageSerializer messageSerializer, ObjectSerializer objectSerializer, Scheduler scheduler, - boolean isSharedConnection, Runnable onClientClose) { + MessageSerializer messageSerializer, ObjectSerializer serializer, Scheduler scheduler, + boolean isSharedConnection, Runnable onClientClose) { this.tracerProvider = Objects.requireNonNull(tracerProvider, "'tracerProvider' cannot be null."); this.messageSerializer = Objects.requireNonNull(messageSerializer, "'messageSerializer' cannot be null."); this.connectionProcessor = Objects.requireNonNull(connectionProcessor, @@ -46,7 +46,7 @@ class EventHubAsyncClient implements Closeable { this.onClientClose = Objects.requireNonNull(onClientClose, "'onClientClose' cannot be null."); this.isSharedConnection = isSharedConnection; - this.objectSerializer = objectSerializer; + this.serializer = serializer; } /** @@ -109,7 +109,7 @@ Mono getPartitionProperties(String partitionId) { EventHubProducerAsyncClient createProducer() { return new EventHubProducerAsyncClient(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), connectionProcessor, connectionProcessor.getRetryOptions(), tracerProvider, messageSerializer, - objectSerializer, scheduler, isSharedConnection, onClientClose); + serializer, scheduler, isSharedConnection, onClientClose); } /** @@ -133,7 +133,7 @@ EventHubConsumerAsyncClient createConsumer(String consumerGroup, int prefetchCou } return new EventHubConsumerAsyncClient(connectionProcessor.getFullyQualifiedNamespace(), getEventHubName(), - connectionProcessor, messageSerializer, objectSerializer, consumerGroup, prefetchCount, scheduler, + connectionProcessor, messageSerializer, serializer, consumerGroup, prefetchCount, scheduler, isSharedConnection, onClientClose); } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java index b0ef95e6b9163..ae986f147a2c0 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubConsumerAsyncClient.java @@ -71,7 +71,7 @@ public class EventHubConsumerAsyncClient implements Closeable { private final String eventHubName; private final EventHubConnectionProcessor connectionProcessor; private final MessageSerializer messageSerializer; - private final ObjectSerializer objectSerializer; + private final ObjectSerializer serializer; private final String consumerGroup; private final int prefetchCount; private final Scheduler scheduler; @@ -86,14 +86,14 @@ public class EventHubConsumerAsyncClient implements Closeable { EventHubConsumerAsyncClient(String fullyQualifiedNamespace, String eventHubName, EventHubConnectionProcessor connectionProcessor, - MessageSerializer messageSerializer, ObjectSerializer objectSerializer, + MessageSerializer messageSerializer, ObjectSerializer serializer, String consumerGroup, int prefetchCount, Scheduler scheduler, boolean isSharedConnection, Runnable onClientClosed) { this.fullyQualifiedNamespace = fullyQualifiedNamespace; this.eventHubName = eventHubName; this.connectionProcessor = connectionProcessor; this.messageSerializer = messageSerializer; - this.objectSerializer = objectSerializer; + this.serializer = serializer; this.consumerGroup = consumerGroup; this.prefetchCount = prefetchCount; this.scheduler = scheduler; @@ -369,7 +369,7 @@ private EventHubPartitionAsyncConsumer createPartitionConsumer(String linkName, new AmqpReceiveLinkProcessor(prefetchCount, retryPolicy, connectionProcessor)); return new EventHubPartitionAsyncConsumer(linkMessageProcessor, messageSerializer, getFullyQualifiedNamespace(), - getEventHubName(), consumerGroup, partitionId, objectSerializer, + getEventHubName(), consumerGroup, partitionId, serializer, initialPosition, receiveOptions.getTrackLastEnqueuedEventProperties(), scheduler); } } diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java index 3f9f5c6a0c461..587e98d31f68d 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/ObjectBatch.java @@ -24,14 +24,14 @@ public final class ObjectBatch extends EventDataBatchBase { private final ClientLogger logger = new ClientLogger(ObjectBatch.class); private final Class batchType; - private final ObjectSerializer objectSerializer; + private final ObjectSerializer serializer; ObjectBatch(int maxMessageSize, String partitionId, String partitionKey, Class batchType, ErrorContextProvider contextProvider, TracerProvider tracerProvider, - ObjectSerializer objectSerializer, String entityPath, String hostname) { + ObjectSerializer serializer, String entityPath, String hostname) { super(maxMessageSize, partitionId, partitionKey, contextProvider, tracerProvider, entityPath, hostname); this.batchType = Objects.requireNonNull(batchType, "'batchType' cannot be null."); - this.objectSerializer = Objects.requireNonNull(objectSerializer, "'objectSerializer' cannot be null."); + this.serializer = Objects.requireNonNull(serializer, "'serializer' cannot be null."); } /** @@ -50,6 +50,6 @@ public Mono tryAdd(final T object) { } ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - return objectSerializer.serialize(outputStream, object).map(s -> tryAdd(new EventData(s.toByteArray()))); + return serializer.serialize(outputStream, object).map(s -> tryAdd(new EventData(s.toByteArray()))); } } From 03693c9fe6470ef28aebc6c179cbb088d326a8d2 Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Wed, 8 Jul 2020 13:59:56 -0700 Subject: [PATCH 28/29] add serializer null check in object batch creation --- .../messaging/eventhubs/EventHubProducerAsyncClient.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java index 4c1f0fa27606b..1d8e12b6d90bb 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java @@ -285,7 +285,11 @@ public Mono> createBatch(Class objectType) { */ public Mono> createBatch(Class objectType, CreateBatchOptions options) { if (objectType == null) { - return monoError(logger, new NullPointerException("'objectType' cannot be null.")); + return monoError(logger, new IllegalArgumentException("'objectType' cannot be null.")); + } + if (serializer == null) { + return monoError(logger, + new NullPointerException("No serializer set for performing object serialization for ObjectBatch.")); } if (options == null) { return monoError(logger, new NullPointerException("'options' cannot be null.")); From 447522a5a9f105ed55bebb8ed1324a1942ef043d Mon Sep 17 00:00:00 2001 From: Arthur Erlendsson Date: Wed, 8 Jul 2020 16:31:12 -0700 Subject: [PATCH 29/29] cleanup --- .../messaging/eventhubs/EventHubProducerAsyncClient.java | 5 ----- .../azure-messaging-eventhubs/src/main/java/module-info.java | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java index 1d8e12b6d90bb..f7906c6a573a5 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/com/azure/messaging/eventhubs/EventHubProducerAsyncClient.java @@ -113,11 +113,6 @@ public class EventHubProducerAsyncClient implements Closeable { private final Runnable onClientClose; private final ObjectSerializer serializer; - private enum SendMode { - EVENT_DATA, - OBJECT - } - /** * Creates a new instance of this {@link EventHubProducerAsyncClient} that can send messages to a single partition * when {@link CreateBatchOptions#getPartitionId()} is not null or an empty string. Otherwise, allows the service to diff --git a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java index a448c57eb2abd..e743ad96cb64a 100644 --- a/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java +++ b/sdk/eventhubs/azure-messaging-eventhubs/src/main/java/module-info.java @@ -3,7 +3,7 @@ module com.azure.messaging.eventhubs { requires transitive com.azure.core; - requires com.azure.core.experimental; + requires transitive com.azure.core.experimental; requires transitive com.azure.core.amqp; requires com.microsoft.azure.qpid.protonj.extensions;