@Override
        public Iterator<Map.Entry<String, String>> iterator() {
            return new Iterator<>()
            {

                Iterator<Map.Entry<String, String>> iter = properties.entrySet().iterator();
                Map.Entry<String, String> current = null;

                @Override
                public boolean hasNext()
                {
                    return iter.hasNext();
                }

                @Override
                public Map.Entry<String, String> next()
                {
                    current = iter.next();
                    return current;
                }

                @Override
                public void remove()
                {
                    if (current == null) {
                        throw new IllegalStateException();
                    }
                    String key = current.getKey();
                    try {
                        UserManager.getUserPropertyProvider().deleteProperty(username, key);
                        iter.remove();
                        // Fire event.
                        Map<String, Object> params = new HashMap<>();
                        params.put("type", "propertyDeleted");
                        params.put("propertyKey", key);
                        UserEventDispatcher.dispatchEvent(User.this,
                            UserEventDispatcher.EventType.user_modified, params);
                    } catch (UserNotFoundException e) {
                        Log.error("Unable to delete property for user " + username, e);
                    }
                }
            };
        }
Set implementation that updates the database when properties are deleted.
xmppserver/src/main/java/org/jivesoftware/openfire/user/User.java