package org.dcm4chee.archive.conf.olock;
import org.dcm4che3.conf.core.api.ConfigurableClassExtension;
import org.dcm4che3.conf.core.api.Configuration;
import org.dcm4che3.conf.core.api.OptimisticLockException;
import org.dcm4che3.conf.core.normalization.DefaultsAndNullFilterDecorator;
import org.dcm4che3.conf.core.olock.HashBasedOptimisticLockingConfiguration;
import org.dcm4che3.conf.core.storage.InMemoryConfiguration;
import org.dcm4che3.conf.core.storage.SingleJsonFileConfigurationStorage;
import org.dcm4che3.conf.core.util.ConfigNodeUtil;
import org.dcm4che3.conf.core.util.Extensions;
import org.dcm4che3.conf.dicom.CommonDicomConfiguration;
import org.dcm4che3.conf.dicom.CommonDicomConfigurationWithHL7;
import org.dcm4che3.conf.dicom.DicomPath;
import org.dcm4che3.data.Tag;
import org.dcm4che3.net.*;
import org.dcm4che3.net.audit.AuditLogger;
import org.dcm4che3.net.audit.AuditRecordRepository;
import org.dcm4che3.net.hl7.HL7DeviceExtension;
import org.dcm4che3.net.imageio.ImageReaderExtension;
import org.dcm4che3.net.imageio.ImageWriterExtension;
import org.dcm4che3.net.web.WebServiceAEExtension;
import org.dcm4chee.archive.conf.*;
import org.dcm4chee.archive.conf.defaults.DefaultArchiveConfigurationFactory.FactoryParams;
import org.dcm4chee.archive.conf.defaults.DefaultDicomConfigInitializer;
import org.dcm4chee.archive.conf.defaults.ExtendedStudyDictionary;
import org.dcm4chee.archive.conf.defaults.test.DeepEquals;
import org.dcm4chee.storage.conf.Availability;
import org.dcm4chee.storage.conf.StorageDeviceExtension;
import org.dcm4chee.storage.conf.StorageSystem;
import org.dcm4chee.storage.conf.SyncPolicy;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;
/**
* @author Roman K
*/
public class DicomConfigOptimisticLockingTest {
private CommonDicomConfigurationWithHL7 dicomConfig;
private Configuration bareStorage;
@Before
public void before() {
// prepare storage
ArrayList<ConfigurableClassExtension> extensions = ArchiveDeviceTest.getDefaultExtensions();
ArrayList<ConfigurableClassExtension> defaultExtensions = extensions;
defaultExtensions.add(new OlockedDeviceExtension());
ArrayList<Class> allExtensionClasses = new ArrayList<Class>();
for (ConfigurableClassExtension extension : defaultExtensions)
allExtensionClasses.add(extension.getClass());
// Configuration storage = new SingleJsonFileConfigurationStorage("target/config.json");
Configuration storage = new InMemoryConfiguration();
bareStorage = storage;
storage = new HashBasedOptimisticLockingConfiguration(storage, allExtensionClasses, storage);
storage = new DefaultsAndNullFilterDecorator(storage, allExtensionClasses, CommonDicomConfiguration.createDefaultDicomVitalizer());
dicomConfig = new CommonDicomConfigurationWithHL7(
storage,
Extensions.getAMapOfExtensionsByBaseExtension(defaultExtensions)
);
// wipe out clean
dicomConfig.purgeConfiguration();
// init default config
DefaultDicomConfigInitializer init = new DefaultDicomConfigInitializer();
FactoryParams params = new FactoryParams();
params.generateUUIDsBasedOnName = true;
params.useGroupBasedTCConfig = true;
init.persistDefaultConfig(dicomConfig, dicomConfig, params);
}
@Test
public void optimisticLockingDemoTest() {
//// three users load the config at the same time
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
Device device2 = dicomConfig.findDevice("dcm4chee-arc");
Device device3 = dicomConfig.findDevice("dcm4chee-arc");
//// one user modifies the port of a connection
device1.getConnections().get(0).setPort(12121);
dicomConfig.merge(device1);
//// second user tries to modify the same connection but fails
device2.getConnections().get(0).setBindAddress("anotherhost");
try {
dicomConfig.merge(device2);
Assert.fail("Should not succeed");
} catch (OptimisticLockException ignored) {
}
//// third user adds a storage system. This change does not conflict with connection settings, so it succeeds
// create new storage system
StorageSystem fs2 = new StorageSystem();
fs2.setStorageSystemID("fs2");
fs2.setProviderName("org.dcm4chee.storage.filesystem");
fs2.setStorageSystemPath("someNewPath");
fs2.setAvailability(Availability.OFFLINE);
fs2.setSyncPolicy(SyncPolicy.ON_ASSOCIATION_CLOSE);
// add it
device3.getDeviceExtension(StorageDeviceExtension.class).getStorageSystemGroup("DEFAULT").addStorageSystem(fs2);
// merge
dicomConfig.merge(device3);
//// the resulting device includes both changes from first and third user
Device loaded = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertEquals(12121, loaded.getConnections().get(0).getPort());
Assert.assertNotNull(loaded.getDeviceExtension(StorageDeviceExtension.class).getStorageSystemGroup("DEFAULT").getStorageSystem("fs2"));
}
@Test
public void differentSSGChanges() {
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
Device device2 = dicomConfig.findDevice("dcm4chee-arc");
// create new storage system in DEFAULT
StorageSystem fs2 = new StorageSystem();
fs2.setStorageSystemID("fs2");
fs2.setProviderName("org.dcm4chee.storage.filesystem");
fs2.setStorageSystemPath("someNewPath");
fs2.setAvailability(Availability.OFFLINE);
fs2.setSyncPolicy(SyncPolicy.ON_ASSOCIATION_CLOSE);
device1.getDeviceExtension(StorageDeviceExtension.class).getStorageSystemGroup("DEFAULT").addStorageSystem(fs2);
dicomConfig.merge(device1);
// create new storage system in METADATA
StorageSystem fsB = new StorageSystem();
fsB.setStorageSystemID("fsB");
fsB.setProviderName("org.dcm4chee.storage.filesystem");
fsB.setStorageSystemPath("someOtherNewPath");
fsB.setAvailability(Availability.ONLINE);
fsB.setSyncPolicy(SyncPolicy.ON_ASSOCIATION_CLOSE);
device2.getDeviceExtension(StorageDeviceExtension.class).getStorageSystemGroup("METADATA").addStorageSystem(fsB);
// should succeed
dicomConfig.merge(device2);
// both should be there
Device device3 = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertEquals("someNewPath",
device3
.getDeviceExtension(StorageDeviceExtension.class)
.getStorageSystem("DEFAULT", "fs2")
.getStorageSystemPath());
Assert.assertEquals("someOtherNewPath",
device3
.getDeviceExtension(StorageDeviceExtension.class)
.getStorageSystem("METADATA", "fsB")
.getStorageSystemPath());
}
@Test
public void optimisticLockingTestDefAe() {
Device device = dicomConfig.findDevice("dcm4chee-arc");
Map deviceNode = (Map) dicomConfig
.getConfigurationStorage()
.getConfigurationNode(DicomPath.DeviceByName.set("deviceName", "dcm4chee-arc").path(), Device.class);
Object node = ConfigNodeUtil.getNode(deviceNode, "dcmDefaultAE/_.hash");
Assert.assertNull(node);
}
@Test
public void changeStringArrayElement() {
// set iocm config with 'dcmext'
IOCMConfig iocmConfig = new IOCMConfig();
Device device = dicomConfig.findDevice("dcm4chee-arc");
device.getDeviceExtension(ArchiveDeviceExtension.class).setIocmConfig(iocmConfig);
iocmConfig.setIocmDestinations(new String[]{"dcmext"});
dicomConfig.merge(device);
// load and change to 'DCMEXT
Device deviceCopy = dicomConfig.findDevice("dcm4chee-arc");
deviceCopy
.getDeviceExtension(ArchiveDeviceExtension.class)
.getIocmConfig()
.setIocmDestinations(new String[]{"DCMEXT"});
dicomConfig.merge(deviceCopy);
// load and assert
Device anotherDev = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertEquals("DCMEXT",
anotherDev
.getDeviceExtension(ArchiveDeviceExtension.class)
.getIocmConfig()
.getIocmDestinations()[0]);
}
@Test
public void persistNodeHavingIntegerKeyedMap() {
Device device = dicomConfig.findDevice("dcm4chee-arc");
ArchiveDeviceExtension archExt = device.getDeviceExtension(ArchiveDeviceExtension.class);
Map<Integer, String> STUDY_PRIVATE_ATTRS = new TreeMap<Integer, String>();
STUDY_PRIVATE_ATTRS.put(ExtendedStudyDictionary.StudyLastUpdateDateTime, "EXTENDED STUDY");
AttributeFilter filter = new AttributeFilter(new int[]{Tag.StudyID}, STUDY_PRIVATE_ATTRS);
// This will set the dcmPrivateTag in AttributeFilter which is a map
// that has an Integer key type
archExt.setAttributeFilter(Entity.Study, filter);
dicomConfig.merge(device);
}
@Test
public void testPersistDeviceNoHash() {
// Make changes, then persist original node without hashes - should fully overwrite the existing node
Object exportedDeviceNode = bareStorage.getConfigurationNode(DicomPath.DeviceByName.set("deviceName", "dcm4chee-arc").path(), null);
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
device1.setDescription("a new description");
device1.getApplicationEntity("DCM4CHEE").setDescription("another new desc");
device1.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).setIANMaxRetries(100);
dicomConfig.merge(device1);
// check if changes persisted
Device device2 = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertEquals(device1.getDescription(), device2.getDescription());
Assert.assertEquals(device1.getApplicationEntity("DCM4CHEE").getDescription(), device2.getApplicationEntity("DCM4CHEE").getDescription());
Assert.assertEquals(
device1.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).getIANMaxRetries(),
device2.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).getIANMaxRetries()
);
// persist original node with no hashes
dicomConfig.getConfigurationStorage().persistNode(
DicomPath.DeviceByName.set("deviceName", "dcm4chee-arc").path(),
(Map<String, Object>) exportedDeviceNode,
Device.class
);
// all changes should be reverted
Device device3 = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertNotEquals(device1.getDescription(), device3.getDescription());
Assert.assertNotEquals(device1.getApplicationEntity("DCM4CHEE").getDescription(), device3.getApplicationEntity("DCM4CHEE").getDescription());
Assert.assertNotEquals(
device1.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).getIANMaxRetries(),
device3.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).getIANMaxRetries()
);
}
@Test
public void testFullImportExport() {
// Make changes, then persist original ROOT node without hashes - should fully overwrite the existing config
Object exportedConfig = dicomConfig.getConfigurationStorage().getConfigurationNode("/", null);
// Object exportedConfig = dicomConfig.getConfigurationStorage().getConfigurationRoot();
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
device1.setDescription("a new description");
device1.getApplicationEntity("DCM4CHEE").setDescription("another new desc");
device1.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).setIANMaxRetries(100);
dicomConfig.merge(device1);
// check if changes persisted
Device device2 = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertEquals(device1.getDescription(), device2.getDescription());
Assert.assertEquals(device1.getApplicationEntity("DCM4CHEE").getDescription(), device2.getApplicationEntity("DCM4CHEE").getDescription());
Assert.assertEquals(
device1.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).getIANMaxRetries(),
device2.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).getIANMaxRetries()
);
// persist original root node with no hashes
dicomConfig.getConfigurationStorage().persistNode("/", (Map<String, Object>) exportedConfig, null);
// all changes should be reverted
Device device3 = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertNotEquals(device1.getDescription(), device3.getDescription());
Assert.assertNotEquals(device1.getApplicationEntity("DCM4CHEE").getDescription(), device3.getApplicationEntity("DCM4CHEE").getDescription());
Assert.assertNotEquals(
device1.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).getIANMaxRetries(),
device3.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).getIANMaxRetries()
);
}
@Test
public void testMultiDepthMerge() {
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
Device device2 = dicomConfig.findDevice("dcm4chee-arc");
Device device3 = dicomConfig.findDevice("dcm4chee-arc");
Device device4 = dicomConfig.findDevice("dcm4chee-arc");
// modify device and ae ext
device1.setLimitOpenAssociations(10);
device1.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).setModifyingSystem("asdgf");
dicomConfig.merge(device1);
// modify ae param
device2.getApplicationEntity("DCM4CHEE").getConnections().remove(0);
device2.getApplicationEntity("DCM4CHEE").setAeInstalled(false);
dicomConfig.merge(device2);
// none of conflicting should succeed
device3.setDescription("bla");
try {
dicomConfig.merge(device3);
Assert.fail("Should have failed");
} catch (OptimisticLockException e) {
//noop
}
device4.getApplicationEntity("DCM4CHEE").setDescription("blabla");
try {
dicomConfig.merge(device4);
Assert.fail("Should have failed");
} catch (OptimisticLockException e) {
//noop
}
// all 4 changes should make it
Device loaded = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertEquals(10, loaded.getLimitOpenAssociations());
Assert.assertEquals("asdgf", loaded.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).getModifyingSystem());
Assert.assertEquals(1, device2.getApplicationEntity("DCM4CHEE").getConnections().size());
Assert.assertEquals(false, device2.getApplicationEntity("DCM4CHEE").getAeInstalled());
// make sure nothing else changed but what we changed and the hashes
device2.setLimitOpenAssociations(10);
device2.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).setModifyingSystem("asdgf");
device2.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).setOlockHash(
loaded.getApplicationEntity("DCM4CHEE").getAEExtension(ArchiveAEExtension.class).getOlockHash()
);
device2.getApplicationEntity("DCM4CHEE").setOlockHash(
loaded.getApplicationEntity("DCM4CHEE").getOlockHash()
);
device2.setOlockHash(loaded.getOlockHash());
boolean condition = DeepEquals.deepEquals(loaded, device2);
if (!condition) DeepEquals.printOutInequality();
Assert.assertTrue(condition);
}
@Test
public void renameAEtest() {
// rename AE
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
device1.getApplicationEntity("DCM4CHEE").setAETitle("DCM4CHEE-NEW");
dicomConfig.merge(device1);
Device loaded = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertEquals(4, loaded.getApplicationAETitles().size());
Assert.assertNotEquals(null, loaded.getApplicationEntity("DCM4CHEE-NEW"));
Assert.assertEquals(null, loaded.getApplicationEntity("DCM4CHEE"));
}
@Test
public void renameAEconcurrentModTest() {
// rename AE with concurrent change in that AE
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
Device device2 = dicomConfig.findDevice("dcm4chee-arc");
device1.getApplicationEntity("DCM4CHEE").setAETitle("DCM4CHEE-NEW");
dicomConfig.merge(device1);
device2.getApplicationEntity("DCM4CHEE").setDescription("A new descr");
dicomConfig.merge(device2);
Device loaded = dicomConfig.findDevice("dcm4chee-arc");
loaded.getApplicationEntity("DCM4CHEE-NEW").setOlockHash(null);
device1.getApplicationEntity("DCM4CHEE-NEW").setOlockHash(null);
loaded.setOlockHash(null);
device1.setOlockHash(null);
boolean b = DeepEquals.deepEquals(loaded, device1);
if (!b) DeepEquals.printOutInequality();
Assert.assertTrue("Changes in device2 should be ignored, nothing should change", b);
// now first make change, then rename AE
before();
device1 = dicomConfig.findDevice("dcm4chee-arc");
device2 = dicomConfig.findDevice("dcm4chee-arc");
device2.getApplicationEntity("DCM4CHEE").setDescription("A new descr");
dicomConfig.merge(device2);
device1.getApplicationEntity("DCM4CHEE").setAETitle("DCM4CHEE-NEW");
dicomConfig.merge(device1);
loaded = dicomConfig.findDevice("dcm4chee-arc");
loaded.getApplicationEntity("DCM4CHEE-NEW").setOlockHash(null);
device1.getApplicationEntity("DCM4CHEE-NEW").setOlockHash(null);
loaded.setOlockHash(null);
device1.setOlockHash(null);
b = DeepEquals.deepEquals(loaded, device1);
if (!b) DeepEquals.printOutInequality();
Assert.assertTrue("Changes in device2 should be ignored, nothing should change", b);
}
@Test
public void doubleRenameAETest() {
// rename AE with concurrent change in that AE
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
Device device2 = dicomConfig.findDevice("dcm4chee-arc");
device1.getApplicationEntity("DCM4CHEE_TRASH").setAETitle("DCM4CHEE_TRASH-NEW");
dicomConfig.merge(device1);
device2.getApplicationEntity("DCM4CHEE_TRASH").setAETitle("DCM4CHEE_TRASH-NEW-BUT-DIFF");
try {
dicomConfig.merge(device2);
Assert.fail();
} catch (OptimisticLockException ignored) {
}
Device loaded = dicomConfig.findDevice("dcm4chee-arc");
loaded.getApplicationEntity("DCM4CHEE_TRASH-NEW").setOlockHash(null);
device1.getApplicationEntity("DCM4CHEE_TRASH-NEW").setOlockHash(null);
loaded.setOlockHash(null);
device1.setOlockHash(null);
boolean b = DeepEquals.deepEquals(loaded, device1);
if (!b) DeepEquals.printOutInequality();
Assert.assertTrue("State in the storage should be eq to device1", b);
}
@Test
public void renameAEAndConcurrentlyModifyOtherAE() {
// rename AE with concurrent change in that AE
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
Device device2 = dicomConfig.findDevice("dcm4chee-arc");
device1.getApplicationEntity("DCM4CHEE").setAETitle("DCM4CHEE-NEW");
dicomConfig.merge(device1);
device2.getApplicationEntity("DCM4CHEE_TRASH").setDescription("A new descr");
dicomConfig.merge(device2);
Device loaded = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertNotEquals("both changes should make it", null, loaded.getApplicationEntity("DCM4CHEE-NEW"));
Assert.assertEquals("both changes should make it", "A new descr", loaded.getApplicationEntity("DCM4CHEE_TRASH").getDescription());
loaded.getApplicationEntity("DCM4CHEE-NEW").setOlockHash(null);
device1.getApplicationEntity("DCM4CHEE-NEW").setOlockHash(null);
loaded.getApplicationEntity("DCM4CHEE_TRASH").setOlockHash(null);
device1.getApplicationEntity("DCM4CHEE_TRASH").setOlockHash(null);
loaded.getApplicationEntity("DCM4CHEE_TRASH").setDescription(null);
loaded.setOlockHash(null);
device1.setOlockHash(null);
boolean b = DeepEquals.deepEquals(loaded, device1);
if (!b) DeepEquals.printOutInequality();
Assert.assertTrue("nothing else should change", b);
// now first make change, then rename AE
}
public void extensionsTest() {
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
Device device2 = dicomConfig.findDevice("dcm4chee-arc");
}
@Test
public void oneModifiesConnectionAnotherRemovesApreviousConnection() {
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
Device device2 = dicomConfig.findDevice("dcm4chee-arc");
device1.getConnections().remove(0);
for (ApplicationEntity entity : device1.getApplicationEntities()) {
entity.getConnections().remove(0);
}
device1.getDeviceExtension(AuditLogger.class).getConnections().clear();
dicomConfig.merge(device1);
device2.getConnections().get(1).setSocketCloseDelay(12345);
device2.getConnections().get(0).setSocketCloseDelay(23456);
dicomConfig.merge(device2);
Device loaded = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertEquals(12345, loaded.getConnections().get(0).getSocketCloseDelay());
// the rest should be identical
loaded.setOlockHash(null);
device1.setOlockHash(null);
loaded.getConnections().get(0).setSocketCloseDelay(50);
for (ApplicationEntity entity : loaded.getApplicationEntities()) {
entity.setOlockHash(null);
for (Connection connection : entity.getConnections()) connection.setOlockHash(null);
}
for (ApplicationEntity entity : device1.getApplicationEntities()) {
entity.setOlockHash(null);
for (Connection connection : entity.getConnections()) connection.setOlockHash(null);
}
boolean b = DeepEquals.deepEquals(loaded, device1);
if (!b) DeepEquals.printOutInequality();
Assert.assertTrue(b);
}
@Test
public void twoModifiedConnectionsOneAddedOneFails() {
Device device1 = dicomConfig.findDevice("dcm4chee-arc");
Device device2 = dicomConfig.findDevice("dcm4chee-arc");
Device device3 = dicomConfig.findDevice("dcm4chee-arc");
Device device4 = dicomConfig.findDevice("dcm4chee-arc");
Connection conn = new Connection();
conn.setCommonName("newConn");
conn.setPort(12346);
device1.addConnection(conn);
dicomConfig.merge(device1);
device2.getConnections().get(0).setSocketCloseDelay(23456);
dicomConfig.merge(device2);
device3.getConnections().get(1).setSocketCloseDelay(12345);
dicomConfig.merge(device3);
device4.getConnections().remove(0);
try {
dicomConfig.merge(device4);
Assert.fail();
} catch (OptimisticLockException ignored) {
}
Device loaded = dicomConfig.findDevice("dcm4chee-arc");
Assert.assertEquals(23456, loaded.getConnections().get(0).getSocketCloseDelay());
Assert.assertEquals(12345, loaded.getConnections().get(1).getSocketCloseDelay());
Assert.assertEquals(6, loaded.getConnections().size());
// the rest should be identical
loaded.setOlockHash(null);
device1.setOlockHash(null);
loaded.getConnections().get(0).setSocketCloseDelay(50);
loaded.getConnections().get(1).setSocketCloseDelay(50);
for (Connection connection : device1.getConnections()) connection.setOlockHash(null);
for (Connection connection : loaded.getConnections()) connection.setOlockHash(null);
for (ApplicationEntity entity : loaded.getApplicationEntities()) {
entity.setOlockHash(null);
}
for (ApplicationEntity entity : device1.getApplicationEntities()) {
entity.setOlockHash(null);
}
boolean b = DeepEquals.deepEquals(loaded, device1);
if (!b) DeepEquals.printOutInequality();
Assert.assertTrue(b);
}
@Test
public void testRandomScenarios() throws Exception {
Device device = dicomConfig.findDevice("dcm4chee-arc");
Device deviceCopy = dicomConfig.findDevice("dcm4chee-arc");
Device device3 = dicomConfig.findDevice("dcm4chee-arc");
// change ae ref
device.setDefaultAE(device.getApplicationEntity("DCM4CHEE_ADMIN"));
dicomConfig.merge(device);
// conflicting change
deviceCopy.setLimitOpenAssociations(25);
try {
dicomConfig.merge(deviceCopy);
Assert.fail("Should have failed");
} catch (OptimisticLockException e) {
//it correct
}
// no changes
dicomConfig.merge(device3);
}
}