@Override
    public void bulkPublishedItems( List<PublishedItem> addList, List<PublishedItem> delList )
    {
        // TODO Consider re-instating 'xmpp.pubsub.item.retry' property, to allow for retries of failed database
        // writes for items. Note that this behavior was first introduced when the work load was cached. As that's
        // no longer the case, there likely is no reason to assume that a retry (which would be immediate) would
        // succeed. There's a case to be made to reinstate this behavior in CachingPubsubPersistneceProvider,
        // instead of here.

        // is there anything to do?
        if ( addList == null ) {
            addList = new ArrayList<>();
        }

        if ( delList == null ) {
            delList = new ArrayList<>();
        }

        if ( addList.isEmpty() && delList.isEmpty() )
        {
            return;
        }

        log.debug( "Processing collection of changes to published items. Additions: {}, deletes: {}", addList.size(), delList.size() );

        // Ensure there are no duplicates by deleting before adding.
        delList.addAll( addList );

        boolean rollback = false;
        Connection con;
        try
        {
            con = DbConnectionManager.getTransactionConnection();
        }
        catch ( SQLException e )
        {
            log.error( "Failed to obtain a database connection, to process a batch of changes to published items from DB.", e );
            return;
        }

        try
        {
            log.debug( "Try to add the pending items as a database batch." );
            removePublishedItems( con, delList, true ); // delete first (to remove possible duplicates), then add new items
            savePublishedItems( con, addList, true );
        }
        catch ( SQLException e1 )
        {
            log.warn( "Failed to process a collection of changes to published items from DB. Retrying individually.", e1);
            log.debug( "Retry each item individually, rather than rolling back.");
            try
            {
                removePublishedItems( con, delList, false ); // delete first (to remove possible duplicates), then add new items
                savePublishedItems( con, addList, false );
            }
            catch ( SQLException e2 )
            {
                // Individual retries also failed. Roll back.
                log.error( "Failed to process a collection of changes both as a database batch as wel as individual changes. Rolling back transaction and giving up. Data is lost.", e2 );
                rollback = true;
            }
        }
        finally
        {
            DbConnectionManager.closeTransactionConnection(con, rollback);
        }
    }
Writes large changesets to the database, using batches and transactions when
available.

The 'delete' list takes precedence over the 'add' list: when an item exists
on both lists, it is removed (and not re-added) to the database.

To prevent duplicates to exist in the database, this method will attempt to
remove all items to-be-added from the database, before re-adding them.

Note that multiple attempts to write items to the DB are made:
1) insert all pending items in a single batch
2) if the batch insert fails, retry by inserting each item separately

@param addList A list of items to be added to the database.
@param delList A list of items to be removed from the database.
xmppserver/src/main/java/org/jivesoftware/openfire/pubsub/DefaultPubSubPersistenceProvider.java