@PostConstruct
 private void init() {
   objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
   client = HttpClients.createDefault();
   this.url = telegramUrl + telegramToken + "/sendMessage";
   TimerTask timerTask =
       new TimerTask() {
         @Override
         public void run() {
           SendMessage sendMessage = null;
           try {
             if (!outQueue.isEmpty()) {
               sendMessage = outQueue.take();
               deliverMessage(sendMessage);
             }
           } catch (InterruptedException e) {
             logger.error("error in reading outQueue", e);
           } catch (Exception e) {
             logger.error("error sending message " + sendMessage, e);
           }
         }
       };
   Timer timer = new Timer();
   timer.schedule(timerTask, TimeUnit.MINUTES.toMillis(1), TimeUnit.MILLISECONDS.toMillis(200));
 }
  /*
   * Test that Metrics are automatically unregistered after the job is closed
   */
  @Test
  public void automaticMetricCleanup1() throws Exception {
    // Declare topology with custom metric oplet
    Topology t = newTopology();
    AtomicInteger n = new AtomicInteger(0);
    TStream<Integer> ints = t.poll(() -> n.incrementAndGet(), 10, TimeUnit.MILLISECONDS);
    ints.pipe(new TestOplet<Integer>());

    // Submit job
    Future<? extends Job> fj = getSubmitter().submit(t);
    Job job = fj.get();
    Thread.sleep(TimeUnit.MILLISECONDS.toMillis(50));

    // At least one tuple was processed
    int tupleCount = n.get();
    assertTrue("Expected more tuples than " + tupleCount, tupleCount > 0);

    // Each test oplet registers two metrics
    Map<String, Metric> all = metricRegistry.getMetrics();
    assertEquals(2, all.size());

    // After close all metrics have been unregistered
    job.stateChange(Job.Action.CLOSE);
    assertEquals(0, all.size());
  }
 protected void waitForRegionEntryEvents() {
   ThreadUtils.waitFor(TimeUnit.SECONDS.toMillis(20))
       .checkEvery(TimeUnit.MILLISECONDS.toMillis(500))
       .on(
           new CompletableTask() {
             @Override
             public boolean isComplete() {
               return (regionCacheListenerEventValues.size() >= 2);
             }
           });
 }
 IndexingStats.Stats stats(boolean isThrottled, long currentThrottleMillis) {
   return new IndexingStats.Stats(
       indexMetric.count(),
       TimeUnit.NANOSECONDS.toMillis(indexMetric.sum()),
       indexCurrent.count(),
       indexFailed.count(),
       deleteMetric.count(),
       TimeUnit.NANOSECONDS.toMillis(deleteMetric.sum()),
       deleteCurrent.count(),
       noopUpdates.count(),
       isThrottled,
       TimeUnit.MILLISECONDS.toMillis(currentThrottleMillis));
 }
Exemple #5
0
 public static String msecs(long msecs, boolean truncate) {
   final long hr = TimeUnit.MILLISECONDS.toHours(msecs);
   msecs -= TimeUnit.HOURS.toMillis(hr);
   final long min = TimeUnit.MILLISECONDS.toMinutes(msecs);
   msecs -= TimeUnit.MINUTES.toMillis(min);
   final long sec = TimeUnit.MILLISECONDS.toSeconds(msecs);
   msecs -= TimeUnit.SECONDS.toMillis(sec);
   final long ms = TimeUnit.MILLISECONDS.toMillis(msecs);
   if (!truncate) return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
   if (hr != 0) return String.format("%2d:%02d:%02d.%03d", hr, min, sec, ms);
   if (min != 0) return String.format("%2d min %2d.%03d sec", min, sec, ms);
   return String.format("%2d.%03d sec", sec, ms);
 }
 private static String formatInterval(final long l) {
   final long hr = TimeUnit.MILLISECONDS.toHours(l);
   final long min = TimeUnit.MILLISECONDS.toMinutes(l - TimeUnit.HOURS.toMillis(hr));
   final long sec =
       TimeUnit.MILLISECONDS.toSeconds(
           l - TimeUnit.HOURS.toMillis(hr) - TimeUnit.MINUTES.toMillis(min));
   final long ms =
       TimeUnit.MILLISECONDS.toMillis(
           l
               - TimeUnit.HOURS.toMillis(hr)
               - TimeUnit.MINUTES.toMillis(min)
               - TimeUnit.SECONDS.toMillis(sec));
   return String.format("%02dh:%02dm:%02d.%03ds", hr, min, sec, ms);
 }
  public OperationResult execute(Long customerId, CustomerAddress newAddress) throws Exception {

    OperationResult result = null;
    logger.trace("CustomerAddressService.execute");

    Long start = System.currentTimeMillis();

    try {
      RestTemplate restTemplate = new RestTemplate();
      restTemplate
          .getMessageConverters()
          .add(0, new StringHttpMessageConverter(Charset.forName("UTF-8")));

      HttpHeaders headers = new HttpHeaders();
      headers.setContentType(MediaType.APPLICATION_JSON);

      StringBuilder sBuilder =
          new StringBuilder(inventoryServiceURL)
              .append(InventoryServiceActions.ADDRESS)
              .append("/")
              .append(customerId.toString());

      UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(sBuilder.toString());

      String requestJson = new ObjectMapper().writeValueAsString(newAddress);
      HttpEntity<String> entity = new HttpEntity<String>(requestJson, headers);

      result =
          restTemplate
              .exchange(
                  builder.build().encode().toString(),
                  HttpMethod.PUT,
                  entity,
                  OperationResult.class)
              .getBody();
      if (result == null) {
        throw new Exception("Unable to get responce from inventory service");
      }
    } catch (Exception ex) {
      logger.warn(ex.getMessage());
      throw ex;
    } finally {
      logger.info(
          "Execution time: " + TimeUnit.MILLISECONDS.toMillis(System.currentTimeMillis() - start));
    }

    return result;
  }
  @Test(timeout = 60000)
  public void testSendAfterMissingHeartbeat() throws Exception {

    String connectFrame =
        "STOMP\n"
            + "login:system\n"
            + "passcode:manager\n"
            + "accept-version:1.1\n"
            + "heart-beat:1000,0\n"
            + "host:localhost\n"
            + "\n"
            + Stomp.NULL;

    stompConnection.sendFrame(connectFrame);
    String f = stompConnection.receiveFrame();
    assertTrue(f.startsWith("CONNECTED"));
    assertTrue(f.indexOf("version:1.1") >= 0);
    assertTrue(f.indexOf("heart-beat:") >= 0);
    assertTrue(f.indexOf("session:") >= 0);
    LOG.debug("Broker sent: " + f);

    Wait.waitFor(
        new Wait.Condition() {

          @Override
          public boolean isSatisified() throws Exception {
            return getProxyToBroker().getCurrentConnectionsCount() == 0;
          }
        },
        TimeUnit.SECONDS.toMillis(5),
        TimeUnit.MILLISECONDS.toMillis(25));

    try {
      String message =
          "SEND\n"
              + "destination:/queue/"
              + getQueueName()
              + "\n"
              + "receipt:1\n\n"
              + "Hello World"
              + Stomp.NULL;
      stompConnection.sendFrame(message);
      stompConnection.receiveFrame();
      fail("SEND frame has been accepted after missing heart beat");
    } catch (Exception ex) {
      LOG.info(ex.getMessage());
    }
  }
  private static void busyWaitForPort(
      InetAddress address, int port, boolean expectedConnectionState) {
    long maxAcceptableWaitTime = TimeUnit.SECONDS.toMillis(10);
    long waitQuantum = TimeUnit.MILLISECONDS.toMillis(500);
    long waitTimeSoFar = 0;
    boolean connectionState = !expectedConnectionState;

    while (connectionState != expectedConnectionState && waitTimeSoFar < maxAcceptableWaitTime) {
      connectionState = CCMBridge.pingPort(address, port);
      try {
        Thread.sleep(waitQuantum);
        waitTimeSoFar += waitQuantum;
      } catch (InterruptedException e) {
        throw new RuntimeException("Interrupted while pinging " + address + ":" + port, e);
      }
    }
  }
  /**
   * 返回自身类的单个实例。
   *
   * @return
   */
  public static synchronized Singleton_3 getInstance() {
    if (uniqueInstance == null) {
      /*
       * 注意:如果我们不需要这个实例,它就永远不会产生。
       * 这就是“延迟实例化”(Lazy Instantiate)。
       */
      uniqueInstance = new Singleton_3(); // 在多线程下,可能会被实例化多次!
      instanceCount.incrementAndGet(); // 实例计数

      // 暂停50ms,模拟这里需要一定的处理时间!
      try {
        Thread.sleep(TimeUnit.MILLISECONDS.toMillis(50L));
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    return uniqueInstance;
  }
  public enum TemporaryTrigger {
    PLAYER_UNSAFE_ENCHANTMENT_CHECK(TimeUnit.SECONDS.toMillis(10)),
    PLAYER_CLEAR_INVENTORY_CHECK(TimeUnit.SECONDS.toMillis(10)),
    PLAYER_SUICIDE_CHECK(TimeUnit.SECONDS.toMillis(15)),
    PROTECTION_CHECK(TimeUnit.MILLISECONDS.toMillis(500)),
    PROTECTION_BUILD_MODE_WARNING(TimeUnit.MINUTES.toMillis(2)),
    PROTECTION_BEING_LOADED(TimeUnit.SECONDS.toMillis(3)),
    PROTECTION_RESPONSE(TimeUnit.SECONDS.toMillis(5)),
    PROTECTION_MINIMUM_HEIGHT(TimeUnit.MINUTES.toMillis(4)),
    DELETE_CONSTRUCTION_CHECK(TimeUnit.SECONDS.toMillis(15)),
    BAN_PLAYER(TimeUnit.SECONDS.toMillis(15)),

    WORLD_EDIT_PLAYER_PROTECTION_WARNING(TimeUnit.SECONDS.toMillis(30));

    private final long conditionTime;

    TemporaryTrigger(long conditionTime) {
      this.conditionTime = conditionTime;
    }

    private long getConditionTime() {
      return conditionTime;
    }
  }
  @Transactional(propagation = Propagation.REQUIRED)
  public Long createSubscription(Subscription model)
      throws SubscriptionAlreadyExistException, SubscriptionResourceFetchException,
          SubscriptionResourceExistException, ResourceInconsistentStateException {
    logger.trace(
        "SubscriptionService_Create.createSubscription: Subscription = " + model.toString());

    Long subscriptionId = -1L;
    Long start = System.currentTimeMillis();

    try {
      SubscriptionProviderEntity spe =
          this.subscriptionProviderDao.getByName(model.getSubscriptionProviderName());
      SubscriptionStateEntity sse =
          this.subscriptionStateDao.getByName(SubscriptionState.PREUSE.toString());

      // 1. create subscription
      SubscriptionEntity se = subscriptionDao.getBySubscriptionID(model.getSubscriptionId());
      if (se != null && se.getSubscriptionProvider().getId() == spe.getId())
        throw new SubscriptionAlreadyExistException(
            "Subscription ID="
                + model.getSubscriptionId()
                + " already exist for operator "
                + spe.getName());
      se = new SubscriptionEntity(model.getSubscriptionId(), spe, sse);
      subscriptionId = subscriptionDao.create(se);

      // 2. assign resource on subscription
      List<SubscriptionSimResourceFlatEntity> simResources =
          subscriptionSimResourceFlatDao.getByICCID(model.getICCID());
      if (simResources.size() == 0)
        // TODO: SIM_CARD_NOT_FOUND
        throw new SubscriptionResourceFetchException(
            "ICCID Resource doesn't exist. ICCID = " + model.getICCID());
      if (simResources.size() > 1)
        throw new SubscriptionResourceFetchException(
            "ICCID Resource fetching exception. More than one resource exist. ICCID = "
                + model.getICCID());
      if (simResources.get(0).getIccidState() != SimResourceState.PREACTIVE.getId())
        throw new ResourceInconsistentStateException(
            "Resource ICCID "
                + model.getICCID()
                + " is in state "
                + simResources.get(0).getIccidState());

      // TODO: compare IMSI & MSISDN: error code - INVALID_REQUEST_ARGUMENTS
      // MSISDN Provided (%s) Does not match SIM Cards MSISDN (%s)
      // IMSI Provided (%s) Does not match IMSI Number for SIM Card (%s)
      ResourceConfigurationEntity ssre = resourceConfigurationDao.read(simResources.get(0).getId());
      if (ssre.getSubscription() != null)
        throw new ResourceInconsistentStateException(
            "Resource ID "
                + ssre.getId()
                + " already assigned on subscription "
                + ssre.getSubscription().getId());

      ssre.setSubscription(se);

      resourceConfigurationDao.update(ssre);
    } catch (ConstraintViolationException ex) {
      throw new SubscriptionResourceExistException("Subscription or Resource already exists.");
    } catch (Exception ex) {
      throw ex;
    } finally {
      logger.info(
          "Execution time: " + TimeUnit.MILLISECONDS.toMillis(System.currentTimeMillis() - start));
    }

    return subscriptionId;
  }
/** Configures deadlock detection. */
public class DeadlockDetectionConfiguration {
  public static final AttributeDefinition<Boolean> ENABLED =
      AttributeDefinition.builder("enabled", false).immutable().build();
  public static final AttributeDefinition<Long> SPIN_DURATION =
      AttributeDefinition.builder("spinDuration", TimeUnit.MILLISECONDS.toMillis(100))
          .immutable()
          .build();

  static AttributeSet attributeDefinitionSet() {
    return new AttributeSet(DeadlockDetectionConfiguration.class, ENABLED, SPIN_DURATION);
  }

  private final Attribute<Boolean> enabled;
  private final Attribute<Long> spinDuration;
  private final AttributeSet attributes;

  DeadlockDetectionConfiguration(AttributeSet attributes) {
    this.attributes = attributes.checkProtection();
    enabled = attributes.attribute(ENABLED);
    spinDuration = attributes.attribute(SPIN_DURATION);
  }

  /**
   * Time period that determines how often is lock acquisition attempted within maximum time allowed
   * to acquire a particular lock
   */
  public long spinDuration() {
    return attributes.attribute(SPIN_DURATION).get();
  }

  /** Whether deadlock detection is enabled or disabled */
  public boolean enabled() {
    return enabled.get();
  }

  public AttributeSet attributes() {
    return attributes;
  }

  @Override
  public String toString() {
    return "DeadlockDetectionConfiguration [attributes=" + attributes + "]";
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    DeadlockDetectionConfiguration other = (DeadlockDetectionConfiguration) obj;
    if (attributes == null) {
      if (other.attributes != null) return false;
    } else if (!attributes.equals(other.attributes)) return false;
    return true;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
    return result;
  }
}
Exemple #14
0
  @Test(timeout = 60000)
  public void testMultipleDurableSubsWithOfflineMessages() throws Exception {
    stompConnection.setVersion(Stomp.V1_1);

    final BrokerViewMBean view = getProxyToBroker();

    String connectFrame =
        "STOMP\n"
            + "login:system\n"
            + "passcode:manager\n"
            + "accept-version:1.1\n"
            + "host:localhost\n"
            + "client-id:test\n"
            + "\n"
            + Stomp.NULL;
    stompConnection.sendFrame(connectFrame);

    String frame = stompConnection.receiveFrame();
    LOG.debug("Broker sent: " + frame);

    assertTrue(frame.startsWith("CONNECTED"));
    assertEquals(view.getDurableTopicSubscribers().length, 0);

    // subscribe to first destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "1"
            + "\n"
            + "ack:auto\n"
            + "receipt:1\n"
            + "id:durablesub-1\n"
            + "activemq.subscriptionName:test1\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    StompFrame receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("1", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 1);

    // subscribe to second destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "2"
            + "\n"
            + "ack:auto\n"
            + "receipt:2\n"
            + "id:durablesub-2\n"
            + "activemq.subscriptionName:test2\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("2", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 2);

    frame = "DISCONNECT\nclient-id:test\n\n" + Stomp.NULL;
    stompConnection.sendFrame(frame);
    assertTrue(
        Wait.waitFor(
            new Wait.Condition() {

              @Override
              public boolean isSatisified() throws Exception {
                return view.getCurrentConnectionsCount() == 1;
              }
            },
            TimeUnit.SECONDS.toMillis(5),
            TimeUnit.MILLISECONDS.toMillis(25)));

    // reconnect and send some messages to the offline subscribers and then try to get
    // them after subscribing again.
    stompConnect();
    stompConnection.sendFrame(connectFrame);
    frame = stompConnection.receiveFrame();
    LOG.debug("Broker sent: " + frame);
    assertTrue(frame.contains("CONNECTED"));
    assertEquals(view.getDurableTopicSubscribers().length, 0);
    assertEquals(view.getInactiveDurableTopicSubscribers().length, 2);

    frame =
        "SEND\n"
            + "destination:/topic/"
            + getQueueName()
            + "1\n"
            + "receipt:10\n"
            + "\n"
            + "Hello World 1"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);
    receipt = stompConnection.receive();
    assertEquals("10", receipt.getHeaders().get(Stomp.Headers.Response.RECEIPT_ID));

    frame =
        "SEND\n"
            + "destination:/topic/"
            + getQueueName()
            + "2\n"
            + "receipt:11\n"
            + "\n"
            + "Hello World 2"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);
    receipt = stompConnection.receive();
    assertEquals("11", receipt.getHeaders().get(Stomp.Headers.Response.RECEIPT_ID));

    // subscribe to first destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "1"
            + "\n"
            + "ack:auto\n"
            + "receipt:3\n"
            + "id:durablesub-1\n"
            + "activemq.subscriptionName:test1\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("3", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 1);

    StompFrame message = stompConnection.receive();
    assertEquals(Stomp.Responses.MESSAGE, message.getAction());
    assertEquals("durablesub-1", message.getHeaders().get(Stomp.Headers.Message.SUBSCRIPTION));

    assertEquals(view.getDurableTopicSubscribers().length, 1);
    assertEquals(view.getInactiveDurableTopicSubscribers().length, 1);

    // subscribe to second destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "2"
            + "\n"
            + "ack:auto\n"
            + "receipt:4\n"
            + "id:durablesub-2\n"
            + "activemq.subscriptionName:test2\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("4", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 2);

    message = stompConnection.receive();
    assertEquals(Stomp.Responses.MESSAGE, message.getAction());
    assertEquals("durablesub-2", message.getHeaders().get(Stomp.Headers.Message.SUBSCRIPTION));

    assertEquals(view.getDurableTopicSubscribers().length, 2);
    assertEquals(view.getInactiveDurableTopicSubscribers().length, 0);
  }
Exemple #15
0
  @Test(timeout = 60000)
  public void testDurableSubAndUnSubOnTwoTopics() throws Exception {
    stompConnection.setVersion(Stomp.V1_1);

    String domain = "org.apache.activemq";
    ObjectName brokerName = new ObjectName(domain + ":type=Broker,brokerName=localhost");

    BrokerViewMBean view =
        (BrokerViewMBean)
            brokerService
                .getManagementContext()
                .newProxyInstance(brokerName, BrokerViewMBean.class, true);

    String connectFrame =
        "STOMP\n"
            + "login:system\n"
            + "passcode:manager\n"
            + "accept-version:1.1\n"
            + "host:localhost\n"
            + "client-id:test\n"
            + "\n"
            + Stomp.NULL;
    stompConnection.sendFrame(connectFrame);

    String frame = stompConnection.receiveFrame();
    LOG.debug("Broker sent: " + frame);

    assertTrue(frame.startsWith("CONNECTED"));
    assertEquals(view.getDurableTopicSubscribers().length, 0);

    // subscribe to first destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "1"
            + "\n"
            + "ack:auto\n"
            + "receipt:1\n"
            + "id:durablesub-1\n"
            + "activemq.subscriptionName:test1\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    StompFrame receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("1", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 1);

    // subscribe to second destination durably
    frame =
        "SUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "2"
            + "\n"
            + "ack:auto\n"
            + "receipt:2\n"
            + "id:durablesub-2\n"
            + "activemq.subscriptionName:test2\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);

    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + receipt);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("2", receipt.getHeaders().get("receipt-id"));
    assertEquals(view.getDurableTopicSubscribers().length, 2);

    frame = "DISCONNECT\nclient-id:test\n\n" + Stomp.NULL;
    stompConnection.sendFrame(frame);
    Wait.waitFor(
        new Wait.Condition() {

          @Override
          public boolean isSatisified() throws Exception {
            return getProxyToBroker().getCurrentConnectionsCount() == 0;
          }
        },
        TimeUnit.SECONDS.toMillis(5),
        TimeUnit.MILLISECONDS.toMillis(25));

    // reconnect and send some messages to the offline subscribers and then try to get
    // them after subscribing again.
    stompConnect();
    stompConnection.sendFrame(connectFrame);
    frame = stompConnection.receiveFrame();
    LOG.debug("Broker sent: " + frame);
    assertTrue(frame.startsWith("CONNECTED"));
    assertEquals(view.getDurableTopicSubscribers().length, 0);
    assertEquals(view.getInactiveDurableTopicSubscribers().length, 2);

    // unsubscribe from topic 1
    frame =
        "UNSUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "1\n"
            + "id:durablesub-1\n"
            + "receipt:3\n"
            + "activemq.subscriptionName:test1\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);
    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + frame);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("3", receipt.getHeaders().get("receipt-id"));

    assertEquals(view.getInactiveDurableTopicSubscribers().length, 1);

    // unsubscribe from topic 2
    frame =
        "UNSUBSCRIBE\n"
            + "destination:/topic/"
            + getQueueName()
            + "2\n"
            + "id:durablesub-2\n"
            + "receipt:4\n"
            + "activemq.subscriptionName:test2\n\n"
            + Stomp.NULL;
    stompConnection.sendFrame(frame);
    receipt = stompConnection.receive();
    LOG.debug("Broker sent: " + frame);
    assertTrue(receipt.getAction().startsWith("RECEIPT"));
    assertEquals("4", receipt.getHeaders().get("receipt-id"));

    assertEquals(view.getInactiveDurableTopicSubscribers().length, 0);
  }