0

I'm trying the java getting started sample on https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-java-java-getstarted on an iot hub with 4 partitions.

I adapted the part about receiving events by creating 1 client instance and calling client.createReceiver for each partition like below:

public class App {

  private static String connStr = "...";

  public static void main(String[] args) throws IOException, EventHubException, ExecutionException, InterruptedException {

    EventHubClient client = createClient();
    String[] partitionIds = client.getRuntimeInformation()
            .thenApply(eventHubRuntimeInformation -> eventHubRuntimeInformation.getPartitionIds())
            .get();

    client.createReceiver(DEFAULT_CONSUMER_GROUP_NAME, "0", Instant.now())
            .thenAccept(receiverHandler("0"));
    client.createReceiver(DEFAULT_CONSUMER_GROUP_NAME, "1", Instant.now())
            .thenAccept(receiverHandler("0"));
    client.createReceiver(DEFAULT_CONSUMER_GROUP_NAME, "2", Instant.now())
            .thenAccept(receiverHandler("2"));
    client.createReceiver(DEFAULT_CONSUMER_GROUP_NAME, "3", Instant.now())
            .thenAccept(receiverHandler("3"));


    System.out.println("Press ENTER to exit.");
    System.in.read();
    try {
        client.closeSync();
        System.exit(0);
    } catch (Exception e) {
        System.exit(1);
    }

  }

  private static Consumer<PartitionReceiver> receiverHandler(String partitionId) {
    return receiver -> {
        System.out.println("** Created receiver on partition " + partitionId);
        try {
            while (true) {
                receiver.receive(10)
                        .thenAccept(receivedEvents -> {
                                    int batchSize = 0;
                                    if (receivedEvents != null) {
                                        System.out.println("Got some evenst");
                                        for (EventData receivedEvent : receivedEvents) {
                                            System.out.println(String.format("Offset: %s, SeqNo: %s, EnqueueTime: %s",
                                                    receivedEvent.getSystemProperties().getOffset(),
                                                    receivedEvent.getSystemProperties().getSequenceNumber(),
                                                    receivedEvent.getSystemProperties().getEnqueuedTime()));
                                            System.out.println(String.format("| Device ID: %s",
                                                    receivedEvent.getSystemProperties().get("iothub-connection-device-id")));
                                            System.out.println(String.format("| Message Payload: %s",
                                                    new String(receivedEvent.getBytes(), Charset.defaultCharset())));
                                            batchSize++;
                                        }
                                    }
                                    System.out.println(String.format("Partition: %s, ReceivedBatch Size: %s", partitionId, batchSize));
                                }
                        ).get();

            }
        } catch (Exception e) {
            System.out.println("Failed to receive messages: " + e.getMessage());
        }
    };
  }

  private static EventHubClient createClient() {
    EventHubClient client = null;
    try {
        client = EventHubClient.createFromConnectionStringSync(connStr);
    } catch (Exception e) {
        System.out.println("Failed to create client: " + e.getMessage());
        System.exit(1);
    }
    return client;
  }
}

The events that are sent from the simulated device happen to arrive on partition 3. The problem is that no events are received in the following situations:

  1. the device is not sending events when starting the event receiver
  2. the device is sending events when starting the event receiver, but is restarted afterwards. In that case the above code stops receiving events after the device restart

The above problems don't occur when we only connect to partition 3.
The above problems don't occur when we only connect to partition 3 and 1 other partition.
The above problems does occur when we connect to partition 3 and 2 or 3 other partitions.

Any clues?

Jan Bols
  • 457
  • 4
  • 11

1 Answers1

0

The above problems does occur when we connect to partition 3 and 2 or 3 other partitions.

I use your code failed with this error "lambda expressions are not supported in -source 1.5 java".

Then I edit the sample code in the tutorial and enable one client to connect to four partition receivers(Here four device events are put in three partitions, not four because events of device1 and device2 are all put in the partition2.):

public class App 
{
    private static String connStr = "Endpoint=sb://iothub-ns-ritatestio-265731-93e2a49f65.servicebus.windows.net/;EntityPath=ritatestiothub;SharedAccessKeyName=iothubowner;SharedAccessKey=z+QM62TftPlTfwS3CnN9348X2cmMkCaEFaC1IqYpiW8=";
    private static EventHubClient client = null;

    public static void main( String[] args ) throws IOException
    {       
        try {
          client = EventHubClient.createFromConnectionStringSync(connStr);
        } catch (Exception e) {
          System.out.println("Failed to create client: " + e.getMessage());
          System.exit(1);
        }

        // Create receivers for partitions 0 and 1.
        receiveMessages("0");
        receiveMessages("1");
        receiveMessages("2");
        receiveMessages("3");
        System.out.println("Press ENTER to exit.");

        System.in.read();
        try {
          client.closeSync();
          System.exit(0);
        } catch (Exception e) {
          System.exit(1);
        }
    }

    // Create a receiver on a partition.
private static void receiveMessages(final String partitionId) {
  try {
    // Create a receiver using the
    // default Event Hubs consumer group
    // that listens for messages from now on.
    client.createReceiver(EventHubClient.DEFAULT_CONSUMER_GROUP_NAME, partitionId, Instant.now())
      .thenAccept(new Consumer<PartitionReceiver>() {
        public void accept(PartitionReceiver receiver) {
          System.out.println("** Created receiver on partition " + partitionId);
          try {
            while (true) {
              Iterable<EventData> receivedEvents = receiver.receive(100).get();

              int batchSize = 0;
              if (receivedEvents != null) {
                for (EventData receivedEvent : receivedEvents) {
                  batchSize++;
                  System.out.println(String.format("Partition: %s, ReceivedBatch Size: %s, Device ID: %s, SeqNo: %s", partitionId, batchSize,receivedEvent.getSystemProperties().get("iothub-connection-device-id"),receivedEvent.getSystemProperties().getSequenceNumber()));
                }
              }

            }
          } catch (Exception e) {
            System.out.println("Failed to receive messages: " + e.getMessage());
          }
        }
      });
    } catch (Exception e) {
      System.out.println("Failed to create receiver: " + e.getMessage());
  }

}
}

I can get three partition receivers receiving events after the device restart. You can check the following snapshot:

enter image description here

Update: Change 4 devices to 1 device to send. Still, the receiver can continue to receive messages after the device restarts.

enter image description here

enter image description here

Rita Han
  • 9,574
  • 1
  • 11
  • 24
  • In my example, I only have 1 device so all events end up in the same partition. It looks like in your example you have 4 devices ending up in 3 of the 4 partitions. – Jan Bols Dec 04 '17 at 08:07
  • @JanBols I test only 1 device sending but still not reproduced your issue. Please check my update. You can use my code to test to see if the issue still exists. – Rita Han Dec 05 '17 at 01:55