@Override
    public synchronized ConfigurationChanges persist(Device device, EnumSet<Option> options)
            throws ConfigurationException {
        ensureConfigurationExists();
        String deviceName = device.getDeviceName();
        String deviceDN = deviceRef(deviceName);
        boolean rollback = false;
        ArrayList<String> destroyDNs = new ArrayList<>();

        try {
            if (options != null && options.contains(Option.REGISTER))
                register(device, destroyDNs);

            ConfigurationChanges diffs = configurationChangesOf(options);
            ConfigurationChanges.ModifiedObject ldapObj =
                    ConfigurationChanges.addModifiedObject(diffs, deviceDN, ConfigurationChanges.ChangeType.C);
            createSubcontext(deviceDN,
                    storeTo(ConfigurationChanges.nullifyIfNotVerbose(diffs, ldapObj),
                            device, new BasicAttributes(true)));
            rollback = true;
            storeChilds(ConfigurationChanges.nullifyIfNotVerbose(diffs, diffs), deviceDN, device);
            if (options == null || !options.contains(Option.PRESERVE_CERTIFICATE))
                updateCertificates(device);
            rollback = false;
            destroyDNs.clear();
            return diffs;
        } catch (NameAlreadyBoundException e) {
            throw new ConfigurationAlreadyExistsException(deviceName);
        } catch (NamingException e) {
            throw new ConfigurationException(e);
        } catch (CertificateException e) {
            throw new ConfigurationException(e);
        } finally {
            if (rollback) {
                try {
                    destroySubcontextWithChilds(deviceDN);
                } catch (NamingException e) {
                    LOG.warn("Rollback failed:", e);
                }
            }
            unregister(destroyDNs);
        }
    }
@Test
    public void testPersist() throws Exception {
        try {
            config.removeDevice("Test-Device-1", null);
        }  catch (ConfigurationNotFoundException e) {}
        Device device = createDevice("Test-Device-1", "TEST-AET1");
        config.persist(device, null);
        ApplicationEntity ae = config.findApplicationEntity("TEST-AET1");
        assertFalse(ae.isAssociationInitiator());
        assertTrue(ae.isAssociationAcceptor());
        assertTrue(ae.getConnections().get(0).isServer());
        TransferCapability echoSCP = ae.getTransferCapabilityFor(
                UID.Verification, TransferCapability.Role.SCP);
        assertNotNull(echoSCP);
        assertArrayEquals(new String[] { UID.ImplicitVRLittleEndian }, echoSCP.getTransferSyntaxes());
        TransferCapability ctSCP = ae.getTransferCapabilityFor(
                UID.CTImageStorage, TransferCapability.Role.SCP);
        assertNotNull(ctSCP);
        assertArrayEquals(new String[] { UID.ImplicitVRLittleEndian, UID.ExplicitVRLittleEndian },
                sort(ctSCP.getTransferSyntaxes()));
        assertNull(ctSCP.getStorageOptions());
        TransferCapability findSCP = ae.getTransferCapabilityFor(
                UID.StudyRootQueryRetrieveInformationModelFind, TransferCapability.Role.SCP);
        assertNotNull(findSCP);
        assertArrayEquals(new String[] { UID.ImplicitVRLittleEndian }, findSCP.getTransferSyntaxes());
        assertEquals(EnumSet.of(QueryOption.RELATIONAL), findSCP.getQueryOptions());
        assertEquals(1, config.listDeviceInfos(deviceInfo("Test-Device-1")).length);
        try {
            config.persist(createDevice("Test-Device-1", "TEST-AET1"), null);
            fail("ConfigurationAlreadyExistsException expected");
        } catch (ConfigurationAlreadyExistsException e) {}
        config.removeDevice("Test-Device-1", null);
    }