public static Read<JmsRecord> read() {
    return new AutoValue_JmsIO_Read.Builder<JmsRecord>()
        .setMaxNumRecords(Long.MAX_VALUE)
        .setCoder(SerializableCoder.of(JmsRecord.class))
        .setCloseTimeout(DEFAULT_CLOSE_TIMEOUT)
        .setRequiresDeduping(false)
        .setMessageMapper(
            new MessageMapper<JmsRecord>() {
              @Override
              public JmsRecord mapMessage(Message message) throws Exception {
                TextMessage textMessage = (TextMessage) message;
                Map<String, Object> properties = new HashMap<>();
                @SuppressWarnings("rawtypes")
                Enumeration propertyNames = textMessage.getPropertyNames();
                while (propertyNames.hasMoreElements()) {
                  String propertyName = (String) propertyNames.nextElement();
                  properties.put(propertyName, textMessage.getObjectProperty(propertyName));
                }

                return new JmsRecord(
                    textMessage.getJMSMessageID(),
                    textMessage.getJMSTimestamp(),
                    textMessage.getJMSCorrelationID(),
                    textMessage.getJMSReplyTo(),
                    textMessage.getJMSDestination(),
                    textMessage.getJMSDeliveryMode(),
                    textMessage.getJMSRedelivered(),
                    textMessage.getJMSType(),
                    textMessage.getJMSExpiration(),
                    textMessage.getJMSPriority(),
                    properties,
                    textMessage.getText());
              }
            })
        .build();
  }
@Test
  public void testDiscardCheckpointMark() throws Exception {
    Connection connection =
        connectionFactoryWithSyncAcksAndWithoutPrefetch.createConnection(USERNAME, PASSWORD);
    connection.start();
    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    MessageProducer producer = session.createProducer(session.createQueue(QUEUE));
    for (int i = 0; i < 10; i++) {
      producer.send(session.createTextMessage("test " + i));
    }
    producer.close();
    session.close();
    connection.close();

    JmsIO.Read spec =
        JmsIO.read()
            .withConnectionFactory(connectionFactoryWithSyncAcksAndWithoutPrefetch)
            .withUsername(USERNAME)
            .withPassword(PASSWORD)
            .withQueue(QUEUE);
    JmsIO.UnboundedJmsSource source = new JmsIO.UnboundedJmsSource(spec);
    JmsIO.UnboundedJmsReader reader = source.createReader(PipelineOptionsFactory.create(), null);

    // start the reader and move to the first record
    assertTrue(reader.start());

    // consume 3 more messages (NB: start already consumed the first message)
    for (int i = 0; i < 3; i++) {
      assertTrue(reader.advance());
    }

    // the messages are still pending in the queue (no ACK yet)
    assertEquals(10, count(QUEUE));

    // we finalize the checkpoint
    reader.getCheckpointMark().finalizeCheckpoint();

    // the checkpoint finalize ack the messages, and so they are not pending in the queue anymore
    assertEquals(6, count(QUEUE));

    // we read the 6 pending messages
    for (int i = 0; i < 6; i++) {
      assertTrue(reader.advance());
    }

    // still 6 pending messages as we didn't finalize the checkpoint
    assertEquals(6, count(QUEUE));

    // But here we discard the pending checkpoint
    reader.checkpointMarkPreparer.discard();
    // we finalize the checkpoint: no messages should be acked
    reader.getCheckpointMark().finalizeCheckpoint();

    assertEquals(6, count(QUEUE));
  }