protected String dumpMediaMimeInfo(final MediaModel media) {
    final PK mediaPK = media.getPk();
    final Media jaloItem = JaloSession.getCurrentSession().getItem(mediaPK);

    final boolean isNew = modelService.isNew(media);
    final boolean isDirty = modelService.isModified(media);
    final boolean txRunning = Transaction.current().isRunning();
    final boolean txCacheIsolationEnabled = Config.itemCacheIsolationActivated();
    final boolean itemCacheBound = jaloItem.isCacheBound();

    return "Media(pk:"
        + media.getPk()
        + "/"
        + jaloItem.getPK()
        + ", new="
        + isNew
        + ", modified="
        + isDirty
        + ", txRunning="
        + txRunning
        + ", txCacheIsolation="
        + txCacheIsolationEnabled
        + ", cacheBound="
        + itemCacheBound;
  }
  private void testBusyWaitingUpdateReload(final int durationSeconds) {
    final MediaModel media = setupMedia("cat", "media", MIME_BEFORE);
    final Media jaloMedia = modelService.getSource(media);
    final PK mediaPK = media.getPk();
    assertEquals(mediaPK, jaloMedia.getPK());

    final RunnerCreator<BusyWaitingUpdateReloadRunner> creator =
        new RunnerCreator<ItemModelTransactionPerformanceTest.BusyWaitingUpdateReloadRunner>() {
          @Override
          public BusyWaitingUpdateReloadRunner newRunner(final int threadNumber) {
            return new BusyWaitingUpdateReloadRunner(modelService, media, 0 == threadNumber);
          }
        };

    final TestThreadsHolder<BusyWaitingUpdateReloadRunner> threads =
        new TestThreadsHolder<ItemModelTransactionPerformanceTest.BusyWaitingUpdateReloadRunner>(
            2, creator);

    threads.startAll();

    for (int sec = 0; sec < durationSeconds && !threads.hasErrors(); sec++) {
      try {
        Thread.sleep((long) (1000 * timeFactor));
      } catch (final InterruptedException e) {
        break;
      }
    }
    threads.stopAndDestroy(5);

    assertEquals(Collections.EMPTY_MAP, threads.getErrors());
  }
  private MediaModel setupMedia(
      final String catalogId, final String mediaCode, final String initialMime) {
    final CatalogVersionModel catVersion = setUpCatalog(catalogId);

    final MediaModel media = createAndSaveMedia(catVersion, mediaCode, initialMime);
    final PK mediaPk = media.getPk();
    final Media jaloMedia = modelService.getSource(media);

    assertNotNull(mediaPk);
    assertNotNull(jaloMedia);
    assertEquals(mediaPk, jaloMedia.getPK());

    assertEquals(mediaCode, media.getCode());
    assertEquals(initialMime, media.getMime());

    assertEquals(mediaCode, jaloMedia.getCode());
    assertEquals(initialMime, jaloMedia.getMime());

    return media;
  }
  private void testModificationTimeUpdateTx(final boolean commit) throws InterruptedException {
    final MediaModel media = setupMedia("cat", "media", MIME_BEFORE);
    try {
      final Media jaloMedia = modelService.getSource(media);
      final PK mediaPK = media.getPk();
      assertEquals(mediaPK, jaloMedia.getPK());

      final Date modModelBefore = media.getModifiedtime();
      final Date modJaloBefore = jaloMedia.getModificationTime();
      assertNotNull(modModelBefore);
      assertNotNull(modJaloBefore);
      assertEquals(modJaloBefore, modModelBefore);
      Thread.sleep((long) (1500 * timeFactor)); // Some DB (MySql) do not have milliseconds!

      Date[] innerTxMod = null;
      final Transaction tx = Transaction.current();
      try {
        innerTxMod =
            (Date[])
                tx.execute(
                    new TransactionBody() {
                      @Override
                      public Object execute() throws Exception {
                        media.setMime(MIME_AFTER);
                        modelService.save(media);
                        final Date modModelAfter = media.getModifiedtime();
                        final Date modJaloAfter = jaloMedia.getModificationTime();

                        assertNotNull(modModelAfter);
                        assertNotNull(modJaloAfter);
                        assertEquals(modModelAfter, modJaloAfter);
                        assertTrue(modJaloBefore.before(modJaloAfter));

                        final Date[] otherThreadMod = getModTimeFromOtherThread(mediaPK);

                        assertNotNull(otherThreadMod);
                        assertNotNull(otherThreadMod[0]);
                        assertNotNull(otherThreadMod[1]);
                        assertEquals(modJaloBefore, otherThreadMod[0]);
                        assertEquals(modModelBefore, otherThreadMod[1]);

                        if (commit) {
                          return new Date[] {modJaloAfter, modModelAfter};
                        } else {
                          throw new RuntimeException("rollback");
                        }
                      }
                    });
      } catch (final Exception e) {
        assertFalse("unexpected tx error " + e, commit);
      }

      modelService.refresh(media); // actually not necessary but more likely to find error

      final Date modModelAfterTx = media.getModifiedtime();
      final Date modJaloAfterTx = jaloMedia.getModificationTime();

      assertNotNull(modModelAfterTx);
      assertNotNull(modJaloAfterTx);
      assertEquals(modModelAfterTx, modJaloAfterTx);
      if (commit) {
        assertEquals(adjustToDB(innerTxMod[0]).getTime(), modJaloAfterTx.getTime());
        assertEquals(adjustToDB(innerTxMod[1]).getTime(), modModelAfterTx.getTime());
        assertTrue(modJaloBefore.before(modJaloAfterTx));
      } else {
        assertEquals(modJaloBefore.getTime(), modJaloAfterTx.getTime());
        assertEquals(modModelBefore.getTime(), modModelAfterTx.getTime());
      }
    } finally {
      destroyMedia(media);
    }
  }