    /**
     * Test method for {@link datawave.core.iterators.RangeSplitter#RangeSplitter(org.apache.accumulo.core.data.Range, int)}.
     */
    @Test
    public void testDeepCopySynchronization() {
        final Set<SortedKeyValueIterator<Key,Value>> sources = new HashSet<>();
        final SourcePool<Key,Value> pool = new SourcePool(factory, 100);

        final List<Throwable> failed = new ArrayList<Throwable>();
        final List<Thread> threads = new ArrayList<Thread>();

        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(() -> {
                try {
                    SortedKeyValueIterator<Key,Value> source = pool.checkOut();
                    Assert.assertNotNull(source);
                    Assert.assertFalse(sources.contains(source));
                    sources.add(source);
                    Assert.assertNotEquals(factory.source, source);
                } catch (Throwable e) {
                    synchronized (failed) {
                        e.printStackTrace();
                        failed.add(e);
                    }
                }
            });
            thread.setUncaughtExceptionHandler((t, e) -> {
                synchronized (failed) {
                    e.printStackTrace();
                    failed.add(e);
                }
            });
            thread.start();
            threads.add(thread);
        }

        for (Thread thread : threads) {
            while (thread.isAlive()) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ie) {
                    // Do nothing
                }
            }
        }
        threads.clear();

        Assert.assertTrue(failed.isEmpty());
        Assert.assertEquals(100, copies);

        for (int i = 0; i < 10; i++) {
            SortedKeyValueIterator<Key,Value> source = pool.checkOut();
            Assert.assertNull(source);
        }
        Assert.assertEquals(100, copies);

        for (SortedKeyValueIterator<Key,Value> source : sources) {
            final SortedKeyValueIterator<Key,Value> threadSource = source;
            Thread thread = new Thread(() -> {
                try {
                    pool.checkIn(threadSource);
                } catch (Throwable e) {
                    synchronized (failed) {
                        e.printStackTrace();
                        failed.add(e);
                    }
                }
            });
            thread.setUncaughtExceptionHandler((t, e) -> {
                synchronized (failed) {
                    e.printStackTrace();
                    failed.add(e);
                }
            });
            thread.start();
            threads.add(thread);
        }

        for (Thread thread : threads) {
            while (thread.isAlive()) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ie) {
                    // Do nothing
                }
            }
        }
        threads.clear();

        Assert.assertTrue(failed.isEmpty());
        Assert.assertEquals(100, copies);
    }

    /**
     * Test method for {@link datawave.core.iterators.RangeSplitter#RangeSplitter(org.apache.accumulo.core.data.Range, int)}.
     */
    @Test
    public void testDeepCopySynchronization() {
        final Set<SortedKeyValueIterator<Key,Value>> sources = new HashSet<>();
        final SourcePool<Key,Value> pool = new SourcePool(factory, 100);

        final List<Throwable> failed = new ArrayList<Throwable>();
        final List<Thread> threads = new ArrayList<Thread>();

        for (int i = 0; i < 100; i++) {
            Thread thread = new Thread(new Runnable() {
                public void run() {
                    try {
                        SortedKeyValueIterator<Key,Value> source = pool.checkOut();
                        Assert.assertNotNull(source);
                        Assert.assertFalse(sources.contains(source));
                        sources.add(source);
                        Assert.assertNotEquals(factory.source, source);
                    } catch (Throwable e) {
                        synchronized (failed) {
                            e.printStackTrace();
                            failed.add(e);
                        }
                    }
                }
            });
            thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(Thread t, Throwable e) {
                    synchronized (failed) {
                        e.printStackTrace();
                        failed.add(e);
                    }
                }
            });
            thread.start();
            threads.add(thread);
        }

        for (Thread thread : threads) {
            while (thread.isAlive()) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ie) {
                    // Do nothing
                }
            }
        }
        threads.clear();

        Assert.assertTrue(failed.isEmpty());
        Assert.assertEquals(100, copies);

        for (int i = 0; i < 10; i++) {
            SortedKeyValueIterator<Key,Value> source = pool.checkOut();
            Assert.assertNull(source);
        }
        Assert.assertEquals(100, copies);

        for (SortedKeyValueIterator<Key,Value> source : sources) {
            final SortedKeyValueIterator<Key,Value> threadSource = source;
            Thread thread = new Thread(new Runnable() {
                public void run() {
                    try {
                        pool.checkIn(threadSource);
                    } catch (Throwable e) {
                        synchronized (failed) {
                            e.printStackTrace();
                            failed.add(e);
                        }
                    }
                }
            });
            thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(Thread t, Throwable e) {
                    synchronized (failed) {
                        e.printStackTrace();
                        failed.add(e);
                    }
                }
            });
            thread.start();
            threads.add(thread);
        }

        for (Thread thread : threads) {
            while (thread.isAlive()) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ie) {
                    // Do nothing
                }
            }
        }
        threads.clear();

        Assert.assertTrue(failed.isEmpty());
        Assert.assertEquals(100, copies);
    }

Replace Anonymous With Lambda datawave.core.iterators.SourcePoolTest.testDeepCopySynchronization.thread.new Thread.new Runnable with () -> {trySortedKeyValueIterator<Key,Value> source=pool.checkOut(); in method public testDeepCopySynchronization() : void from class datawave.core.iterators.SourcePoolTest


    /**
     * Test method for {@link datawave.core.iterators.RangeSplitter#RangeSplitter(org.apache.accumulo.core.data.Range, int)}.
     */
    @Test
    public void testSourcePoolWait() throws InterruptedException {
        final Set<SortedKeyValueIterator<Key,Value>> sources = new HashSet<>();
        final SourcePool<Key,Value> pool = new SourcePool(factory, 10);
        for (int i = 0; i < 10; i++) {
            SortedKeyValueIterator<Key,Value> source = pool.checkOut();
            sources.add(source);
        }

        for (int i = 0; i < 10; i++) {
            SortedKeyValueIterator<Key,Value> source = pool.checkOut(i + 10);
            Assert.assertNull(source);
        }

        final List<Throwable> failed = new ArrayList<Throwable>();

        final MutableBoolean waitingForCheckOut = new MutableBoolean(true);
        final SortedKeyValueIterator<Key,Value> threadSource = sources.iterator().next();
        sources.remove(threadSource);
        Thread thread = new Thread(() -> {
            try {
                SortedKeyValueIterator<Key,Value> source = pool.checkOut(-1);
                waitingForCheckOut.setValue(false);
                Assert.assertNotNull(source);
                Assert.assertFalse(sources.contains(source));
                sources.add(source);
                Assert.assertNotEquals(factory.source, source);
            } catch (Throwable e) {
                synchronized (failed) {
                    e.printStackTrace();
                    failed.add(e);
                }
            }
        });
        thread.setUncaughtExceptionHandler((t, e) -> {
            synchronized (failed) {
                e.printStackTrace();
                failed.add(e);
            }
        });

        thread.start();

        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            Assert.assertTrue(waitingForCheckOut.booleanValue());
            Assert.assertTrue(thread.isAlive());
            Assert.assertTrue(failed.isEmpty());
        }

        pool.checkIn(threadSource);

        int count = 0;
        while (thread.isAlive()) {
            try {
                count++;
                Thread.sleep(10);
                if (count > 1000) {
                    Assert.fail("Expected thread to complete");
                    break;
                }
            } catch (InterruptedException ie) {
                // Do nothing
            }
        }

        Assert.assertFalse(waitingForCheckOut.booleanValue());
        Assert.assertTrue(failed.isEmpty());
    }

    /**
     * Test method for {@link datawave.core.iterators.RangeSplitter#RangeSplitter(org.apache.accumulo.core.data.Range, int)}.
     */
    @Test
    public void testSourcePoolWait() throws InterruptedException {
        final Set<SortedKeyValueIterator<Key,Value>> sources = new HashSet<>();
        final SourcePool<Key,Value> pool = new SourcePool(factory, 10);
        for (int i = 0; i < 10; i++) {
            SortedKeyValueIterator<Key,Value> source = pool.checkOut();
            sources.add(source);
        }

        for (int i = 0; i < 10; i++) {
            SortedKeyValueIterator<Key,Value> source = pool.checkOut(i + 10);
            Assert.assertNull(source);
        }

        final List<Throwable> failed = new ArrayList<Throwable>();

        final MutableBoolean waitingForCheckOut = new MutableBoolean(true);
        final SortedKeyValueIterator<Key,Value> threadSource = sources.iterator().next();
        sources.remove(threadSource);
        Thread thread = new Thread(new Runnable() {
            public void run() {
                try {
                    SortedKeyValueIterator<Key,Value> source = pool.checkOut(-1);
                    waitingForCheckOut.setValue(false);
                    Assert.assertNotNull(source);
                    Assert.assertFalse(sources.contains(source));
                    sources.add(source);
                    Assert.assertNotEquals(factory.source, source);
                } catch (Throwable e) {
                    synchronized (failed) {
                        e.printStackTrace();
                        failed.add(e);
                    }
                }
            }
        });
        thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                synchronized (failed) {
                    e.printStackTrace();
                    failed.add(e);
                }
            }
        });

        thread.start();

        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            Assert.assertTrue(waitingForCheckOut.booleanValue());
            Assert.assertTrue(thread.isAlive());
            Assert.assertTrue(failed.isEmpty());
        }

        pool.checkIn(threadSource);

        int count = 0;
        while (thread.isAlive()) {
            try {
                count++;
                Thread.sleep(10);
                if (count > 1000) {
                    Assert.fail("Expected thread to complete");
                    break;
                }
            } catch (InterruptedException ie) {
                // Do nothing
            }
        }

        Assert.assertFalse(waitingForCheckOut.booleanValue());
        Assert.assertTrue(failed.isEmpty());
    }

Replace Anonymous With Lambda datawave.core.iterators.SourcePoolTest.testSourcePoolWait.thread.new Thread.new Runnable with () -> {trySortedKeyValueIterator<Key,Value> source=pool.checkOut(-1); in method public testSourcePoolWait() : void from class datawave.core.iterators.SourcePoolTest


    @Test
    public void testClonesInThreads() throws Exception {
        final Set<Object> exceptions = Collections.synchronizedSet(new HashSet<>());

        Thread[] threads = new Thread[256];
        String originalQuery = "FOO =~ 'a.*' && FOO == null";
        ASTJexlScript script = JexlASTHelper.parseJexlQuery(originalQuery);
        final Map<String,ExpressionFilter> base = EventDataQueryExpressionVisitor.getExpressionFilters(script, attrFactory);

        final Key p1 = createKey("FOO", "abc");
        final Key n1 = createKey("FOO", "def");
        final Object gate = new Object();
        final AtomicInteger started = new AtomicInteger();
        final AtomicInteger running = new AtomicInteger();
        final AtomicInteger completed = new AtomicInteger();
        Runnable runnable = () -> {
            try {
                final Map<String,? extends Predicate<Key>> filter = ExpressionFilter.clone(base);
                started.getAndIncrement();
                synchronized (gate) {
                    gate.wait();
                }
                running.getAndIncrement();
                for (int i = 0; i < 1024; i++) {
                    assertTrue(filter.get("FOO").apply(n1));
                    assertTrue(filter.get("FOO").apply(p1));
                    assertFalse(filter.get("FOO").apply(n1));
                    assertTrue(filter.get("FOO").apply(p1));

                    ExpressionFilter.reset(filter);
                }
            } catch (InterruptedException e) {} catch (Throwable t) {
                exceptions.add(t);
            }
            completed.getAndIncrement();
        };
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(runnable);
            threads[i].start();
        }
        while (started.get() < threads.length) {
            Thread.sleep(100);
        }
        synchronized (gate) {
            gate.notifyAll();
        }
        while (running.get() < threads.length) {
            synchronized (gate) {
                gate.notifyAll();
            }
        }
        while (completed.get() < threads.length) {
            Thread.sleep(100);
        }

        assertTrue(exceptions.isEmpty());
    }

    @Test
    public void testClonesInThreads() throws Exception {
        final Set<Object> exceptions = Collections.synchronizedSet(new HashSet<>());

        Thread[] threads = new Thread[256];
        String originalQuery = "FOO =~ 'a.*' && FOO == null";
        ASTJexlScript script = JexlASTHelper.parseJexlQuery(originalQuery);
        final Map<String,ExpressionFilter> base = EventDataQueryExpressionVisitor.getExpressionFilters(script, attrFactory);

        final Key p1 = createKey("FOO", "abc");
        final Key n1 = createKey("FOO", "def");
        final Object gate = new Object();
        final AtomicInteger started = new AtomicInteger();
        final AtomicInteger running = new AtomicInteger();
        final AtomicInteger completed = new AtomicInteger();
        Runnable runnable = new Runnable() {
            public void run() {
                try {
                    final Map<String,? extends Predicate<Key>> filter = EventDataQueryExpressionVisitor.ExpressionFilter.clone(base);
                    started.getAndIncrement();
                    synchronized (gate) {
                        gate.wait();
                    }
                    running.getAndIncrement();
                    for (int i = 0; i < 1024; i++) {
                        assertTrue(filter.get("FOO").apply(n1));
                        assertTrue(filter.get("FOO").apply(p1));
                        assertFalse(filter.get("FOO").apply(n1));
                        assertTrue(filter.get("FOO").apply(p1));

                        ExpressionFilter.reset(filter);
                    }
                } catch (InterruptedException e) {} catch (Throwable t) {
                    exceptions.add(t);
                }
                completed.getAndIncrement();
            }
        };
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(runnable);
            threads[i].start();
        }
        while (started.get() < threads.length) {
            Thread.sleep(100);
        }
        synchronized (gate) {
            gate.notifyAll();
        }
        while (running.get() < threads.length) {
            synchronized (gate) {
                gate.notifyAll();
            }
        }
        while (completed.get() < threads.length) {
            Thread.sleep(100);
        }

        assertTrue(exceptions.isEmpty());
    }

Replace Anonymous With Lambda datawave.query.jexl.visitors.EventDataQueryExpressionVisitorTest.testClonesInThreads.runnable.new Runnable with () -> {tryfinal Map<String,? extends Predicate<Key>> filter=ExpressionFilter.clone(base); in method public testClonesInThreads() : void from class datawave.query.jexl.visitors.EventDataQueryExpressionVisitorTest


    @Override
    public Long getCountsByFieldInDayWithTypes(String fieldName, String date, final Set<String> datatypes) {
        Preconditions.checkNotNull(fieldName);
        Preconditions.checkNotNull(date);
        Preconditions.checkNotNull(datatypes);

        Map<String,Long> countsByType = this.cardinalityByDataTypeForFieldAndDate.get(Maps.immutableEntry(fieldName, date));

        if (null == countsByType) {
            return 0L;
        }

        Iterable<Map.Entry<String,Long>> filteredByType = Iterables.filter(countsByType.entrySet(), input -> datatypes.contains(input.getKey()));

        long sum = 0;
        for (Map.Entry<String,Long> entry : filteredByType) {
            sum += entry.getValue();
        }

        return sum;
    }

    @Override
    public Long getCountsByFieldInDayWithTypes(String fieldName, String date, final Set<String> datatypes) {
        Preconditions.checkNotNull(fieldName);
        Preconditions.checkNotNull(date);
        Preconditions.checkNotNull(datatypes);

        Map<String,Long> countsByType = this.cardinalityByDataTypeForFieldAndDate.get(Maps.immutableEntry(fieldName, date));

        if (null == countsByType) {
            return 0L;
        }

        Iterable<Map.Entry<String,Long>> filteredByType = Iterables.filter(countsByType.entrySet(), new Predicate<Map.Entry<String,Long>>() {
            @Override
            public boolean apply(Map.Entry<String,Long> input) {
                return datatypes.contains(input.getKey());
            }
        });

        long sum = 0;
        for (Map.Entry<String,Long> entry : filteredByType) {
            sum += entry.getValue();
        }

        return sum;
    }

Replace Anonymous With Lambda datawave.query.util.MockMetadataHelper.getCountsByFieldInDayWithTypes.filteredByType.filter.new Predicate<Map.Entry<String,Long>> with input -> datatypes.contains(input.getKey()) in method public getCountsByFieldInDayWithTypes(fieldName String, date String, datatypes Set<String>) : Long from class datawave.query.util.MockMetadataHelper


    public CachedRunningQuery retrieve(String id, String owner) throws IOException {

        CachedRunningQuery crq;

        synchronized (CachedResultsBean.class) {
            try {
                log.debug("retrieving cachedRunningQuery " + id + " from cache");
                crq = this.cachedRunningQueryCache.get(owner + "-" + id);
                if (crq != null) {
                    log.debug("retrieved cachedRunningQuery " + id + " from cache with status " + crq.getStatus().toString());
                }
            } catch (Exception e) {
                log.error("Caught attempting to retrieve cached results from infinispan cache: " + e.getMessage(), e);
                throw new IOException(e.getClass().getName() + " caught attempting to retrieve cached results from infinispan cache", e);
            }

            log.debug("Details not in cache, checking the database");
            if (crq == null) {

                try {
                    log.debug("retrieving cachedRunningQuery " + id + " from database");
                    crq = CachedRunningQuery.retrieveFromDatabase(id, ctx.getCallerPrincipal(), metricFactory);
                    if (crq != null) {
                        log.debug("retrieved cachedRunningQuery " + id + " from database with status " + crq.getStatus().toString());
                        this.cachedRunningQueryCache.put(owner + "-" + id, crq);
                    }
                } catch (Exception e) {
                    throw new IOException(e.getClass().getName() + " caught attempting to retrieve cached results state from database", e);
                }
            }
        }

        if (null == crq) {
            try {
                log.debug("Details not in database, checking for exported table in HDFS");
                String hdfsUri = cachedResultsConfiguration.getParameters().get("HDFS_URI");
                String hdfsDir = cachedResultsConfiguration.getParameters().get("HDFS_DIR");
                if (log.isDebugEnabled())
                    log.debug("HDFS uri: " + hdfsUri + ", dir: " + hdfsDir);
                if (!StringUtils.isEmpty(hdfsUri) && !StringUtils.isEmpty(hdfsDir) && (null != importFileUrl)) {
                    // Then we didn't find it in the database. Try looking in HDFS for an export of the data
                    // from another instance.
                    org.apache.hadoop.conf.Configuration conf = new org.apache.hadoop.conf.Configuration();
                    conf.set("fs.defaultFS", hdfsUri);
                    final FileSystem fs = FileSystem.get(conf);
                    Path crPath = new Path(hdfsDir);
                    Path userPath = new Path(crPath, owner);
                    if (log.isDebugEnabled())
                        log.debug("Looking for exported cached for " + id + " results in: " + userPath.toString());
                    if (fs.exists(userPath)) {
                        // Find any directory that contains the id as a .alias, .view, or .queryId file
                        ArrayList<FileStatus> list = new ArrayList<>();
                        recursiveList(fs, userPath, id, list);
                        if (null != list && list.size() > 0) {
                            for (FileStatus f : list) {
                                // Get the parent of the matching file, this will be the directory that contains
                                // the table dump
                                Path tableDirectory = f.getPath().getParent();
                                ProcessBuilder builder = new ProcessBuilder(this.importFileUrl.getPath(), tableDirectory.toString());
                                builder.redirectErrorStream(false);
                                Process process = builder.start();
                                InputStream stdout = process.getInputStream();
                                final BufferedReader outReader = new BufferedReader(new InputStreamReader(stdout));
                                InputStream stderr = process.getErrorStream();
                                final BufferedReader errReader = new BufferedReader(new InputStreamReader(stderr));
                                try {
                                    Thread outReadThread = new Thread(() -> {
                                        try {
                                            String line = outReader.readLine();
                                            while (line != null) {
                                                log.info(line);
                                                line = outReader.readLine();
                                            }
                                        } catch (IOException e) {
                                            log.error("Error in readThread", e);
                                        }
                                    });
                                    Thread errReadThread = new Thread(() -> {
                                        try {
                                            String line = errReader.readLine();
                                            while (line != null) {
                                                log.error(line);
                                                line = errReader.readLine();
                                            }
                                        } catch (IOException e) {
                                            log.error("Error in readThread", e);
                                        }
                                    });
                                    outReadThread.setName(id + "-StdOutReadThread");
                                    outReadThread.start();
                                    errReadThread.setName(id + "-StdErrReadThread");
                                    errReadThread.start();
                                    log.info("Importing cached results from: " + tableDirectory.toString());
                                    int exitVal = process.waitFor();
                                    if (0 != exitVal) {
                                        throw new IOException("Error importing cached results data from: " + tableDirectory.toString() + ". Exit value: "
                                                        + exitVal);
                                    }
                                    outReadThread.join();
                                    errReadThread.join();
                                } catch (InterruptedException e) {
                                    log.error("Thread interrupted waiting for import to finish, killing import process");
                                    process.destroy();
                                } finally {
                                    outReader.close();
                                    errReader.close();
                                }
                                crq = CachedRunningQuery.retrieveFromDatabase(id, ctx.getCallerPrincipal(), metricFactory);
                                if (crq != null) {
                                    break;
                                }
                            }
                        } else {
                            // No matching table dumps for this user
                        }
                    } else {
                        // Does not exist
                    }
                } else {
                    log.warn("HDFS Parameters not set up, will not try to import data");
                }
                if (crq != null) {
                    synchronized (CachedResultsBean.class) {
                        this.cachedRunningQueryCache.put(owner + "-" + id, crq);
                    }
                }
            } catch (Exception e) {
                throw new IOException(e.getClass().getName() + " caught attempting to retrieve cached results state from hdfs", e);
            }
        }
        return crq;
    }

    public CachedRunningQuery retrieve(String id, String owner) throws IOException {

        CachedRunningQuery crq;

        synchronized (CachedResultsBean.class) {
            try {
                log.debug("retrieving cachedRunningQuery " + id + " from cache");
                crq = this.cachedRunningQueryCache.get(owner + "-" + id);
                if (crq != null) {
                    log.debug("retrieved cachedRunningQuery " + id + " from cache with status " + crq.getStatus().toString());
                }
            } catch (Exception e) {
                log.error("Caught attempting to retrieve cached results from infinispan cache: " + e.getMessage(), e);
                throw new IOException(e.getClass().getName() + " caught attempting to retrieve cached results from infinispan cache", e);
            }

            log.debug("Details not in cache, checking the database");
            if (crq == null) {

                try {
                    log.debug("retrieving cachedRunningQuery " + id + " from database");
                    crq = CachedRunningQuery.retrieveFromDatabase(id, ctx.getCallerPrincipal(), metricFactory);
                    if (crq != null) {
                        log.debug("retrieved cachedRunningQuery " + id + " from database with status " + crq.getStatus().toString());
                        this.cachedRunningQueryCache.put(owner + "-" + id, crq);
                    }
                } catch (Exception e) {
                    throw new IOException(e.getClass().getName() + " caught attempting to retrieve cached results state from database", e);
                }
            }
        }

        if (null == crq) {
            try {
                log.debug("Details not in database, checking for exported table in HDFS");
                String hdfsUri = cachedResultsConfiguration.getParameters().get("HDFS_URI");
                String hdfsDir = cachedResultsConfiguration.getParameters().get("HDFS_DIR");
                if (log.isDebugEnabled())
                    log.debug("HDFS uri: " + hdfsUri + ", dir: " + hdfsDir);
                if (!StringUtils.isEmpty(hdfsUri) && !StringUtils.isEmpty(hdfsDir) && (null != importFileUrl)) {
                    // Then we didn't find it in the database. Try looking in HDFS for an export of the data
                    // from another instance.
                    org.apache.hadoop.conf.Configuration conf = new org.apache.hadoop.conf.Configuration();
                    conf.set("fs.defaultFS", hdfsUri);
                    final FileSystem fs = FileSystem.get(conf);
                    Path crPath = new Path(hdfsDir);
                    Path userPath = new Path(crPath, owner);
                    if (log.isDebugEnabled())
                        log.debug("Looking for exported cached for " + id + " results in: " + userPath.toString());
                    if (fs.exists(userPath)) {
                        // Find any directory that contains the id as a .alias, .view, or .queryId file
                        ArrayList<FileStatus> list = new ArrayList<>();
                        recursiveList(fs, userPath, id, list);
                        if (null != list && list.size() > 0) {
                            for (FileStatus f : list) {
                                // Get the parent of the matching file, this will be the directory that contains
                                // the table dump
                                Path tableDirectory = f.getPath().getParent();
                                ProcessBuilder builder = new ProcessBuilder(this.importFileUrl.getPath(), tableDirectory.toString());
                                builder.redirectErrorStream(false);
                                Process process = builder.start();
                                InputStream stdout = process.getInputStream();
                                final BufferedReader outReader = new BufferedReader(new InputStreamReader(stdout));
                                InputStream stderr = process.getErrorStream();
                                final BufferedReader errReader = new BufferedReader(new InputStreamReader(stderr));
                                try {
                                    Thread outReadThread = new Thread() {
                                        @Override
                                        public void run() {
                                            try {
                                                String line = outReader.readLine();
                                                while (line != null) {
                                                    log.info(line);
                                                    line = outReader.readLine();
                                                }
                                            } catch (IOException e) {
                                                log.error("Error in readThread", e);
                                            }
                                        }
                                    };
                                    Thread errReadThread = new Thread() {
                                        @Override
                                        public void run() {
                                            try {
                                                String line = errReader.readLine();
                                                while (line != null) {
                                                    log.error(line);
                                                    line = errReader.readLine();
                                                }
                                            } catch (IOException e) {
                                                log.error("Error in readThread", e);
                                            }
                                        }
                                    };
                                    outReadThread.setName(id + "-StdOutReadThread");
                                    outReadThread.start();
                                    errReadThread.setName(id + "-StdErrReadThread");
                                    errReadThread.start();
                                    log.info("Importing cached results from: " + tableDirectory.toString());
                                    int exitVal = process.waitFor();
                                    if (0 != exitVal) {
                                        throw new IOException("Error importing cached results data from: " + tableDirectory.toString() + ". Exit value: "
                                                        + exitVal);
                                    }
                                    outReadThread.join();
                                    errReadThread.join();
                                } catch (InterruptedException e) {
                                    log.error("Thread interrupted waiting for import to finish, killing import process");
                                    process.destroy();
                                } finally {
                                    outReader.close();
                                    errReader.close();
                                }
                                crq = CachedRunningQuery.retrieveFromDatabase(id, ctx.getCallerPrincipal(), metricFactory);
                                if (crq != null) {
                                    break;
                                }
                            }
                        } else {
                            // No matching table dumps for this user
                        }
                    } else {
                        // Does not exist
                    }
                } else {
                    log.warn("HDFS Parameters not set up, will not try to import data");
                }
                if (crq != null) {
                    synchronized (CachedResultsBean.class) {
                        this.cachedRunningQueryCache.put(owner + "-" + id, crq);
                    }
                }
            } catch (Exception e) {
                throw new IOException(e.getClass().getName() + " caught attempting to retrieve cached results state from hdfs", e);
            }
        }
        return crq;
    }

Replace Anonymous With Lambda datawave.webservice.results.cached.CachedResultsBean.retrieve.outReadThread.new Thread with () -> {tryString line=outReader.readLine(); in method public retrieve(id String, owner String) : CachedRunningQuery from class datawave.webservice.results.cached.CachedResultsBean


    /**
     * Watches the eviction path for new eviction messages. If a message is received, then {@code callback} is invoked, and then zookeeper is updated to
     * indicate this server has responded to the eviction request. Once all running servers have responded, then a cleanup thread running on each server will
     * attempt to remove the eviction request marker so as not to overpopulate zookeeper. All servers may try, but only one will actually delete all of the
     * nodes.
     */
    public void watchForEvictions(final EvictionCallback callback) {
        ArgumentChecker.notNull(callback);

        evictionPathCache.getListenable().addListener((client, event) -> {
            if (event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)) {
                // Call our eviction handler to do local eviction
                        String path = event.getData().getPath();
                        String dn = ZKPaths.getNodeFromPath(path);
                        callback.evict(dn);

                        // Now register ourselves under the eviction node that that once
                        // a child for each running web server appears, the eviction node
                        // can be cleaned up.
                        String responsePath = ZKPaths.makePath(path, localName);
                        try {
                            if (curatorClient.checkExists().creatingParentContainersIfNeeded().forPath(responsePath) == null) {
                                curatorClient.create().creatingParentContainersIfNeeded().forPath(responsePath);
                            }
                        } catch (KeeperException.NodeExistsException e) {
                            // ignored on purpose -- someone beat us to creating the node
                        }
                    }
                });
    }

    /**
     * Watches the eviction path for new eviction messages. If a message is received, then {@code callback} is invoked, and then zookeeper is updated to
     * indicate this server has responded to the eviction request. Once all running servers have responded, then a cleanup thread running on each server will
     * attempt to remove the eviction request marker so as not to overpopulate zookeeper. All servers may try, but only one will actually delete all of the
     * nodes.
     */
    public void watchForEvictions(final EvictionCallback callback) {
        ArgumentChecker.notNull(callback);

        evictionPathCache.getListenable().addListener(new PathChildrenCacheListener() {

            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                if (event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)) {
                    // Call our eviction handler to do local eviction
                    String path = event.getData().getPath();
                    String dn = ZKPaths.getNodeFromPath(path);
                    callback.evict(dn);

                    // Now register ourselves under the eviction node that that once
                    // a child for each running web server appears, the eviction node
                    // can be cleaned up.
                    String responsePath = ZKPaths.makePath(path, localName);
                    try {
                        if (curatorClient.checkExists().creatingParentContainersIfNeeded().forPath(responsePath) == null) {
                            curatorClient.create().creatingParentContainersIfNeeded().forPath(responsePath);
                        }
                    } catch (KeeperException.NodeExistsException e) {
                        // ignored on purpose -- someone beat us to creating the node
                    }
                }
            }
        });
    }

Replace Anonymous With Lambda datawave.webservice.common.cache.SharedCacheCoordinator.watchForEvictions.addListener.new PathChildrenCacheListener with (client, event) -> {if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){String path=event.getData().getPath(); in method public watchForEvictions(callback EvictionCallback) : void from class datawave.webservice.common.cache.SharedCacheCoordinator


    @Test
    public void testEphemeralNodeReconnect() throws Exception {
        String ephemeralNodePath = Whitebox.getInternalState(cacheCoordinator, "serverIdentifierPath");
        boolean exists = curatorClient.checkExists().forPath(ephemeralNodePath) != null;
        assertTrue("Ephemeral server node " + ephemeralNodePath + " doesn't exist before a zookeeper restart", exists);

        final ConnectionState[] state = new ConnectionState[] {ConnectionState.CONNECTED};
        curatorClient.getConnectionStateListenable().addListener((client, newState) -> state[0] = newState);

        testingZooKeeperServer.restart();

        for (int i = 0; i < 50; ++i) {
            if (ConnectionState.RECONNECTED.equals(state[0]))
                break;
            Thread.sleep(200L);
        }
        assertEquals("Client never reconnected.", ConnectionState.RECONNECTED, state[0]);

        for (int i = 0; i < 50; ++i) {
            exists = curatorClient.checkExists().forPath(ephemeralNodePath) != null;
            if (exists)
                break;
            Thread.sleep(200L);
        }
        assertTrue("Ephemeral node " + ephemeralNodePath + " was not recreated.", exists);
    }

    @Test
    public void testEphemeralNodeReconnect() throws Exception {
        String ephemeralNodePath = Whitebox.getInternalState(cacheCoordinator, "serverIdentifierPath");
        boolean exists = curatorClient.checkExists().forPath(ephemeralNodePath) != null;
        assertTrue("Ephemeral server node " + ephemeralNodePath + " doesn't exist before a zookeeper restart", exists);

        final ConnectionState[] state = new ConnectionState[] {ConnectionState.CONNECTED};
        curatorClient.getConnectionStateListenable().addListener(new ConnectionStateListener() {
            @Override
            public void stateChanged(CuratorFramework client, ConnectionState newState) {
                state[0] = newState;
            }
        });

        testingZooKeeperServer.restart();

        for (int i = 0; i < 50; ++i) {
            if (ConnectionState.RECONNECTED.equals(state[0]))
                break;
            Thread.sleep(200L);
        }
        assertEquals("Client never reconnected.", ConnectionState.RECONNECTED, state[0]);

        for (int i = 0; i < 50; ++i) {
            exists = curatorClient.checkExists().forPath(ephemeralNodePath) != null;
            if (exists)
                break;
            Thread.sleep(200L);
        }
        assertTrue("Ephemeral node " + ephemeralNodePath + " was not recreated.", exists);
    }

Replace Anonymous With Lambda datawave.webservice.common.cache.SharedCacheCoordinatorTest.testEphemeralNodeReconnect.addListener.new ConnectionStateListener with (client, newState) -> state[0]=newState in method public testEphemeralNodeReconnect() : void from class datawave.webservice.common.cache.SharedCacheCoordinatorTest


    @Test
    @Category(IntegrationTest.class)
    public void testSharedCounterUpdateAfterConnectionLost() throws Exception {
        final String COUNTER = "testCounter";
        final ConnectionState[] state = new ConnectionState[] {ConnectionState.CONNECTED};
        final int[] count = new int[] {1};

        CuratorFramework curatorFramework = Whitebox.getInternalState(cacheCoordinator, CuratorFramework.class);
        curatorFramework.getConnectionStateListenable().addListener((client, newState) -> state[0] = newState);
        cacheCoordinator.registerCounter(COUNTER, new SharedCountListener() {
            @Override
            public void countHasChanged(SharedCountReader sharedCount, int newCount) throws Exception {
                count[0] = newCount;
                cacheCoordinator.checkCounter(COUNTER, newCount);
            }

            @Override
            public void stateChanged(CuratorFramework client, ConnectionState newState) {}
        });

        SharedCount counter = new SharedCount(curatorClient, "/counters/" + COUNTER, 1);
        counter.start();

        try {

            int newCount = 10;
            VersionedValue<Integer> oldCount = counter.getVersionedValue();
            counter.trySetCount(oldCount, newCount);

            for (int i = 0; i < 50; ++i) {
                if (count[0] == newCount)
                    break;
                Thread.sleep(200L);
            }
            assertEquals("Counter never updated.", newCount, count[0]);
            assertTrue("Counter never updated.", cacheCoordinator.checkCounter(COUNTER, newCount));

            testingZooKeeperServer.kill();

            for (int i = 0; i < 15; ++i) {
                if (ConnectionState.LOST.equals(state[0]))
                    break;
                Thread.sleep(3000L);
            }
            assertEquals("Client never lost connection.", ConnectionState.LOST, state[0]);

            testingZooKeeperServer.restart();

            for (int i = 0; i < 15; ++i) {
                if (ConnectionState.RECONNECTED.equals(state[0]))
                    break;
                Thread.sleep(3000L);
            }
            assertEquals("Client never reconnected.", ConnectionState.RECONNECTED, state[0]);

            newCount = 42;
            oldCount = counter.getVersionedValue();
            counter.trySetCount(oldCount, newCount);

            for (int i = 0; i < 10; ++i) {
                if (count[0] == newCount)
                    break;
                Thread.sleep(200L);
            }
            assertEquals("Counter never updated after restart.", newCount, count[0]);
            assertTrue("Counter never updated.", cacheCoordinator.checkCounter(COUNTER, newCount));
        } finally {
            counter.close();
        }
    }

    @Test
    @Category(IntegrationTest.class)
    public void testSharedCounterUpdateAfterConnectionLost() throws Exception {
        final String COUNTER = "testCounter";
        final ConnectionState[] state = new ConnectionState[] {ConnectionState.CONNECTED};
        final int[] count = new int[] {1};

        CuratorFramework curatorFramework = Whitebox.getInternalState(cacheCoordinator, CuratorFramework.class);
        curatorFramework.getConnectionStateListenable().addListener(new ConnectionStateListener() {
            @Override
            public void stateChanged(CuratorFramework client, ConnectionState newState) {
                state[0] = newState;
            }
        });
        cacheCoordinator.registerCounter(COUNTER, new SharedCountListener() {
            @Override
            public void countHasChanged(SharedCountReader sharedCount, int newCount) throws Exception {
                count[0] = newCount;
                cacheCoordinator.checkCounter(COUNTER, newCount);
            }

            @Override
            public void stateChanged(CuratorFramework client, ConnectionState newState) {}
        });

        SharedCount counter = new SharedCount(curatorClient, "/counters/" + COUNTER, 1);
        counter.start();

        try {

            int newCount = 10;
            VersionedValue<Integer> oldCount = counter.getVersionedValue();
            counter.trySetCount(oldCount, newCount);

            for (int i = 0; i < 50; ++i) {
                if (count[0] == newCount)
                    break;
                Thread.sleep(200L);
            }
            assertEquals("Counter never updated.", newCount, count[0]);
            assertTrue("Counter never updated.", cacheCoordinator.checkCounter(COUNTER, newCount));

            testingZooKeeperServer.kill();

            for (int i = 0; i < 15; ++i) {
                if (ConnectionState.LOST.equals(state[0]))
                    break;
                Thread.sleep(3000L);
            }
            assertEquals("Client never lost connection.", ConnectionState.LOST, state[0]);

            testingZooKeeperServer.restart();

            for (int i = 0; i < 15; ++i) {
                if (ConnectionState.RECONNECTED.equals(state[0]))
                    break;
                Thread.sleep(3000L);
            }
            assertEquals("Client never reconnected.", ConnectionState.RECONNECTED, state[0]);

            newCount = 42;
            oldCount = counter.getVersionedValue();
            counter.trySetCount(oldCount, newCount);

            for (int i = 0; i < 10; ++i) {
                if (count[0] == newCount)
                    break;
                Thread.sleep(200L);
            }
            assertEquals("Counter never updated after restart.", newCount, count[0]);
            assertTrue("Counter never updated.", cacheCoordinator.checkCounter(COUNTER, newCount));
        } finally {
            counter.close();
        }
    }

Replace Anonymous With Lambda datawave.webservice.common.cache.SharedCacheCoordinatorTest.testSharedCounterUpdateAfterConnectionLost.addListener.new ConnectionStateListener with (client, newState) -> state[0]=newState in method public testSharedCounterUpdateAfterConnectionLost() : void from class datawave.webservice.common.cache.SharedCacheCoordinatorTest


    /**
     * Watches the eviction path for new eviction messages. If a message is received, then {@code callback} is invoked, and then zookeeper is updated to
     * indicate this server has responded to the eviction request. Once all running servers have responded, then a cleanup thread running on each server will
     * attempt to remove the eviction request marker so as not to overpopulate zookeeper. All servers may try, but only one will actually delete all of the
     * nodes.
     */
    public void watchForEvictions(final EvictionCallback callback) {
        ArgumentChecker.notNull(callback);

        evictionPathCache.getListenable().addListener((client, event) -> {
            if (event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)) {
                // Call our eviction handler to do local eviction
                        String path = event.getData().getPath();
                        String dn = ZKPaths.getNodeFromPath(path);
                        callback.evict(dn);

                        // Now register ourselves under the eviction node that that once
                        // a child for each running web server appears, the eviction node
                        // can be cleaned up.
                        String responsePath = ZKPaths.makePath(path, localName);
                        curatorClient.newNamespaceAwareEnsurePath(responsePath).ensure(curatorClient.getZookeeperClient());
                    }
                });
    }

    /**
     * Watches the eviction path for new eviction messages. If a message is received, then {@code callback} is invoked, and then zookeeper is updated to
     * indicate this server has responded to the eviction request. Once all running servers have responded, then a cleanup thread running on each server will
     * attempt to remove the eviction request marker so as not to overpopulate zookeeper. All servers may try, but only one will actually delete all of the
     * nodes.
     */
    public void watchForEvictions(final EvictionCallback callback) {
        ArgumentChecker.notNull(callback);

        evictionPathCache.getListenable().addListener(new PathChildrenCacheListener() {

            @Override
            public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
                if (event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)) {
                    // Call our eviction handler to do local eviction
                    String path = event.getData().getPath();
                    String dn = ZKPaths.getNodeFromPath(path);
                    callback.evict(dn);

                    // Now register ourselves under the eviction node that that once
                    // a child for each running web server appears, the eviction node
                    // can be cleaned up.
                    String responsePath = ZKPaths.makePath(path, localName);
                    curatorClient.newNamespaceAwareEnsurePath(responsePath).ensure(curatorClient.getZookeeperClient());
                }
            }
        });
    }

Replace Anonymous With Lambda datawave.webservice.common.curator.TestSharedCacheCoordinator.watchForEvictions.addListener.new PathChildrenCacheListener with (client, event) -> {if(event.getType().equals(PathChildrenCacheEvent.Type.CHILD_ADDED)){String path=event.getData().getPath(); in method public watchForEvictions(callback EvictionCallback) : void from class datawave.webservice.common.curator.TestSharedCacheCoordinator


    /**
     * Returns the a tar file where each tar entry is a result file.
     *
     * @param jobId
     * @return tar file
     * @RequestHeader X-ProxiedEntitiesChain use when proxying request for user by specifying a chain of DNs of the identities to proxy
     * @RequestHeader X-ProxiedIssuersChain required when using X-ProxiedEntitiesChain, specify one issuer DN per subject DN listed in X-ProxiedEntitiesChain
     * @ResponseHeader X-OperationTimeInMS time spent on the server performing the operation, does not account for network or result serialization
     * @HTTP 200 success
     * @HTTP 404 if jobId is invalid or cannot be found
     * @HTTP 500
     */
    @GET
    @Produces("*/*")
    @javax.ws.rs.Path("/{jobId}/getAllFiles")
    @GZIP
    public StreamingOutput getResultFiles(@Required("jobId") @PathParam("jobId") final String jobId, @Context HttpServletResponse httpResponse) {
        MapReduceInfoResponseList response = list(jobId);
        MapReduceInfoResponse result = response.getResults().get(0);
        String hdfs = result.getHdfs();
        String resultsDir = result.getResultsDirectory();
        final FileSystem fs = getFS(hdfs, response);

        final Path jobDirectory = new Path(resultsDir);
        final int jobDirectoryPathLength = jobDirectory.toUri().getPath().length();
        try {
            if (!fs.exists(jobDirectory) || !fs.getFileStatus(jobDirectory).isDirectory()) {
                NotFoundQueryException qe = new NotFoundQueryException(DatawaveErrorCode.JOB_DIRECTORY_NOT_FOUND, MessageFormat.format("{0} at path {1}",
                                jobId, jobDirectory));
                response.addException(qe);
                throw new NotFoundException(qe, response);
            }
        } catch (IOException e1) {
            NotFoundQueryException qe = new NotFoundQueryException(DatawaveErrorCode.RESULT_DIRECTORY_ACCESS_ERROR, e1, MessageFormat.format("{0}", resultsDir));
            log.error(qe);
            response.addException(qe);
            throw new NotFoundException(qe, response);
        }

        // Get the children
        List<FileStatus> resultFiles = new ArrayList<>();
        try {
            // recurse through the directory to find all files
            Queue<FileStatus> fileQueue = new LinkedList<>();
            fileQueue.add(fs.getFileStatus(jobDirectory));
            while (!fileQueue.isEmpty()) {
                FileStatus currentFileStatus = fileQueue.remove();
                if (currentFileStatus.isFile()) {
                    resultFiles.add(currentFileStatus);
                } else {
                    FileStatus[] dirList = fs.listStatus(currentFileStatus.getPath());
                    for (FileStatus fileStatus : dirList) {
                        fileQueue.add(fileStatus);
                    }
                }
            }
        } catch (IOException e) {
            QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_LISTING_ERROR, e, MessageFormat.format("directory: {0}", resultsDir));
            log.error(qe);
            response.addException(qe);
            throw new DatawaveWebApplicationException(qe, response);
        }

        String filename = jobId + "-files.tar";
        httpResponse.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");

        // Make final references for use in anonymous class
        final List<FileStatus> paths = resultFiles;
        return output -> {
            TarArchiveOutputStream tos = new TarArchiveOutputStream(output);
            tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
            try {
                for (FileStatus fileStatus : paths) {
                    if (fileStatus.isDirectory())
                        continue;
                    // The archive entry will be started when the first (and possibly only) chunk is
                    // written out. It is done this way because we need to know the size of the file
                    // for the archive entry, and don't want to scan twice to get that info (once
                    // here and again in streamFile).
                    String fileName = fileStatus.getPath().toUri().getPath().substring(jobDirectoryPathLength + 1);
                    TarArchiveEntry entry = new TarArchiveEntry(jobId + "/" + fileName, false);
                    entry.setSize(fileStatus.getLen());
                    tos.putArchiveEntry(entry);
                    FSDataInputStream fis = fs.open(fileStatus.getPath());
                    byte[] buf = new byte[BUFFER_SIZE];
                    int read;
                    try {
                        read = fis.read(buf);
                        while (read != -1) {
                            tos.write(buf, 0, read);
                            read = fis.read(buf);
                        }
                    } catch (Exception e) {
                        log.error("Error writing result file to output", e);
                        throw new WebApplicationException(e);
                    } finally {
                        try {
                            if (null != fis)
                                fis.close();
                        } catch (IOException e) {
                            log.error("Error closing FSDataInputStream for file: " + fileStatus.getPath().getName(), e);
                        }
                    }
                    tos.closeArchiveEntry();
                }
                tos.finish();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            } finally {
                try {
                    if (null != tos)
                        tos.close();
                } catch (IOException ioe) {
                    log.error("Error closing TarArchiveOutputStream", ioe);
                }
                try {
                    if (null != fs)
                        fs.close();
                } catch (IOException ioe) {
                    log.error("Error closing HDFS client", ioe);
                }
            }
        };

    }

    /**
     * Returns the a tar file where each tar entry is a result file.
     *
     * @param jobId
     * @return tar file
     * @RequestHeader X-ProxiedEntitiesChain use when proxying request for user by specifying a chain of DNs of the identities to proxy
     * @RequestHeader X-ProxiedIssuersChain required when using X-ProxiedEntitiesChain, specify one issuer DN per subject DN listed in X-ProxiedEntitiesChain
     * @ResponseHeader X-OperationTimeInMS time spent on the server performing the operation, does not account for network or result serialization
     * @HTTP 200 success
     * @HTTP 404 if jobId is invalid or cannot be found
     * @HTTP 500
     */
    @GET
    @Produces("*/*")
    @javax.ws.rs.Path("/{jobId}/getAllFiles")
    @GZIP
    public StreamingOutput getResultFiles(@Required("jobId") @PathParam("jobId") final String jobId, @Context HttpServletResponse httpResponse) {
        MapReduceInfoResponseList response = list(jobId);
        MapReduceInfoResponse result = response.getResults().get(0);
        String hdfs = result.getHdfs();
        String resultsDir = result.getResultsDirectory();
        final FileSystem fs = getFS(hdfs, response);

        final Path jobDirectory = new Path(resultsDir);
        final int jobDirectoryPathLength = jobDirectory.toUri().getPath().length();
        try {
            if (!fs.exists(jobDirectory) || !fs.getFileStatus(jobDirectory).isDirectory()) {
                NotFoundQueryException qe = new NotFoundQueryException(DatawaveErrorCode.JOB_DIRECTORY_NOT_FOUND, MessageFormat.format("{0} at path {1}",
                                jobId, jobDirectory));
                response.addException(qe);
                throw new NotFoundException(qe, response);
            }
        } catch (IOException e1) {
            NotFoundQueryException qe = new NotFoundQueryException(DatawaveErrorCode.RESULT_DIRECTORY_ACCESS_ERROR, e1, MessageFormat.format("{0}", resultsDir));
            log.error(qe);
            response.addException(qe);
            throw new NotFoundException(qe, response);
        }

        // Get the children
        List<FileStatus> resultFiles = new ArrayList<>();
        try {
            // recurse through the directory to find all files
            Queue<FileStatus> fileQueue = new LinkedList<>();
            fileQueue.add(fs.getFileStatus(jobDirectory));
            while (!fileQueue.isEmpty()) {
                FileStatus currentFileStatus = fileQueue.remove();
                if (currentFileStatus.isFile()) {
                    resultFiles.add(currentFileStatus);
                } else {
                    FileStatus[] dirList = fs.listStatus(currentFileStatus.getPath());
                    for (FileStatus fileStatus : dirList) {
                        fileQueue.add(fileStatus);
                    }
                }
            }
        } catch (IOException e) {
            QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_LISTING_ERROR, e, MessageFormat.format("directory: {0}", resultsDir));
            log.error(qe);
            response.addException(qe);
            throw new DatawaveWebApplicationException(qe, response);
        }

        String filename = jobId + "-files.tar";
        httpResponse.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");

        // Make final references for use in anonymous class
        final List<FileStatus> paths = resultFiles;
        return new StreamingOutput() {
            @Override
            public void write(OutputStream output) throws IOException, WebApplicationException {
                TarArchiveOutputStream tos = new TarArchiveOutputStream(output);
                tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
                try {
                    for (FileStatus fileStatus : paths) {
                        if (fileStatus.isDirectory())
                            continue;
                        // The archive entry will be started when the first (and possibly only) chunk is
                        // written out. It is done this way because we need to know the size of the file
                        // for the archive entry, and don't want to scan twice to get that info (once
                        // here and again in streamFile).
                        String fileName = fileStatus.getPath().toUri().getPath().substring(jobDirectoryPathLength + 1);
                        TarArchiveEntry entry = new TarArchiveEntry(jobId + "/" + fileName, false);
                        entry.setSize(fileStatus.getLen());
                        tos.putArchiveEntry(entry);
                        FSDataInputStream fis = fs.open(fileStatus.getPath());
                        byte[] buf = new byte[BUFFER_SIZE];
                        int read;
                        try {
                            read = fis.read(buf);
                            while (read != -1) {
                                tos.write(buf, 0, read);
                                read = fis.read(buf);
                            }
                        } catch (Exception e) {
                            log.error("Error writing result file to output", e);
                            throw new WebApplicationException(e);
                        } finally {
                            try {
                                if (null != fis)
                                    fis.close();
                            } catch (IOException e) {
                                log.error("Error closing FSDataInputStream for file: " + fileStatus.getPath().getName(), e);
                            }
                        }
                        tos.closeArchiveEntry();
                    }
                    tos.finish();
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                } finally {
                    try {
                        if (null != tos)
                            tos.close();
                    } catch (IOException ioe) {
                        log.error("Error closing TarArchiveOutputStream", ioe);
                    }
                    try {
                        if (null != fs)
                            fs.close();
                    } catch (IOException ioe) {
                        log.error("Error closing HDFS client", ioe);
                    }
                }
            }
        };

    }

Replace Anonymous With Lambda datawave.webservice.mr.MapReduceBean.getResultFiles.new StreamingOutput with output -> {TarArchiveOutputStream tos=new TarArchiveOutputStream(output); in method public getResultFiles(jobId String, httpResponse HttpServletResponse) : StreamingOutput from class datawave.webservice.mr.MapReduceBean


    /**
     * Common code to setup distributed cache and classpath for the job
     *
     * @param job
     * @param jobDir
     * @throws Exception
     */
    protected void prepareClasspath(String jobId, Job job, Path jobDir) throws Exception {
        FileSystem fs = getFileSystem(job.getConfiguration());
        if (!fs.exists(baseDir))
            if (!fs.mkdirs(baseDir)) {
                QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_CREATE_ERROR, MessageFormat.format("Directory: {0}", baseDir.toString()));
                throw qe;
            }

        // Create the directory for this job
        if (!fs.exists(jobDir))
            if (!fs.mkdirs(jobDir)) {
                QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_CREATE_ERROR, MessageFormat.format("Directory: {0}", jobDir.toString()));
                throw qe;
            }

        // Create classpath directory for this job
        Path classpath = new Path(jobDir, "classpath");
        if (!fs.exists(classpath))
            if (!fs.mkdirs(classpath)) {
                QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_CREATE_ERROR, MessageFormat.format("Directory: {0}",
                                classpath.toString()));
                throw qe;
            }

        // Add all of the jars to the classpath dir and to the DistributedCache
        for (String jarFile : this.classpathJarFiles) {
            int idx = jarFile.indexOf('!');
            Pattern pattern = null;
            if (idx > 0) {
                pattern = Pattern.compile(jarFile.substring(idx + 1));
                jarFile = jarFile.substring(0, idx);
            }

            File file = new File(jarFile);
            if (pattern == null) {
                Path cachedJarPath = new Path(classpath, file.getName());
                addSingleFile(jarFile, cachedJarPath, jobId, job, fs);
            } else {
                // Jars within the deployed EAR in Wildfly use the VFS protocol, and need to be handled specially.
                if (jarFile.startsWith("vfs:")) {
                    Set<String> files = new HashSet<>();
                    try (InputStream urlInputStream = new URL(jarFile).openStream()) {
                        JarInputStream jarInputStream = (JarInputStream) urlInputStream;
                        for (JarEntry jarEntry = jarInputStream.getNextJarEntry(); jarEntry != null; jarEntry = jarInputStream.getNextJarEntry()) {
                            if (pattern.matcher(jarEntry.getName()).matches()) {
                                String name = jarEntry.getName();
                                if (name.endsWith("/"))
                                    name = name.substring(0, name.length() - 1);
                                files.add(jarFile + "/" + name);
                            }
                        }
                    }
                    for (String nestedFile : files) {
                        Path cachedJarPath = new Path(classpath, new File(nestedFile).getName());
                        addSingleFile(nestedFile, cachedJarPath, jobId, job, fs);
                    }
                } else if (jarFile.startsWith("archive:")) {
                    jarFile = jarFile.substring("archive:".length());
                    addArchivedDirectory(jarFile, pattern, classpath, jobId, job, fs);
                } else {
                    addArchiveFile(file, pattern, classpath, jobId, job, fs);
                }
            }
        }

        String homeDir = System.getProperty("jboss.home.dir");
        // Add all of the jars in the server lib directory
        File libDir = new File(homeDir, "bin/client");
        if (!(libDir.isDirectory() && libDir.canRead())) {
            QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_READ_ERROR, MessageFormat.format("directory: {0}", libDir));
            throw qe;
        }
        FilenameFilter jarFilter = (dir, name) -> name.toLowerCase().endsWith(".jar");
        File[] jarFiles = libDir.listFiles(jarFilter);
        if (jarFiles != null) {
            for (File jar : jarFiles) {
                addSingleFile(jar, new Path(classpath, jar.getName()), jobId, job, fs);
            }
        }

        // Add all of the jars in the server mapreduce helper lib directory
        libDir = new File(homeDir, "tools/mapreduce/lib");
        if (!(libDir.isDirectory() && libDir.canRead())) {
            QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_READ_ERROR, MessageFormat.format("directory: {0}", libDir));
            throw qe;
        }
        jarFiles = libDir.listFiles(jarFilter);
        if (jarFiles != null) {
            for (File jar : jarFiles) {
                addSingleFile(jar, new Path(classpath, jar.getName()), jobId, job, fs);
            }
        }
    }

    /**
     * Common code to setup distributed cache and classpath for the job
     *
     * @param job
     * @param jobDir
     * @throws Exception
     */
    protected void prepareClasspath(String jobId, Job job, Path jobDir) throws Exception {
        FileSystem fs = getFileSystem(job.getConfiguration());
        if (!fs.exists(baseDir))
            if (!fs.mkdirs(baseDir)) {
                QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_CREATE_ERROR, MessageFormat.format("Directory: {0}", baseDir.toString()));
                throw qe;
            }

        // Create the directory for this job
        if (!fs.exists(jobDir))
            if (!fs.mkdirs(jobDir)) {
                QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_CREATE_ERROR, MessageFormat.format("Directory: {0}", jobDir.toString()));
                throw qe;
            }

        // Create classpath directory for this job
        Path classpath = new Path(jobDir, "classpath");
        if (!fs.exists(classpath))
            if (!fs.mkdirs(classpath)) {
                QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_CREATE_ERROR, MessageFormat.format("Directory: {0}",
                                classpath.toString()));
                throw qe;
            }

        // Add all of the jars to the classpath dir and to the DistributedCache
        for (String jarFile : this.classpathJarFiles) {
            int idx = jarFile.indexOf('!');
            Pattern pattern = null;
            if (idx > 0) {
                pattern = Pattern.compile(jarFile.substring(idx + 1));
                jarFile = jarFile.substring(0, idx);
            }

            File file = new File(jarFile);
            if (pattern == null) {
                Path cachedJarPath = new Path(classpath, file.getName());
                addSingleFile(jarFile, cachedJarPath, jobId, job, fs);
            } else {
                // Jars within the deployed EAR in Wildfly use the VFS protocol, and need to be handled specially.
                if (jarFile.startsWith("vfs:")) {
                    Set<String> files = new HashSet<>();
                    try (InputStream urlInputStream = new URL(jarFile).openStream()) {
                        JarInputStream jarInputStream = (JarInputStream) urlInputStream;
                        for (JarEntry jarEntry = jarInputStream.getNextJarEntry(); jarEntry != null; jarEntry = jarInputStream.getNextJarEntry()) {
                            if (pattern.matcher(jarEntry.getName()).matches()) {
                                String name = jarEntry.getName();
                                if (name.endsWith("/"))
                                    name = name.substring(0, name.length() - 1);
                                files.add(jarFile + "/" + name);
                            }
                        }
                    }
                    for (String nestedFile : files) {
                        Path cachedJarPath = new Path(classpath, new File(nestedFile).getName());
                        addSingleFile(nestedFile, cachedJarPath, jobId, job, fs);
                    }
                } else if (jarFile.startsWith("archive:")) {
                    jarFile = jarFile.substring("archive:".length());
                    addArchivedDirectory(jarFile, pattern, classpath, jobId, job, fs);
                } else {
                    addArchiveFile(file, pattern, classpath, jobId, job, fs);
                }
            }
        }

        String homeDir = System.getProperty("jboss.home.dir");
        // Add all of the jars in the server lib directory
        File libDir = new File(homeDir, "bin/client");
        if (!(libDir.isDirectory() && libDir.canRead())) {
            QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_READ_ERROR, MessageFormat.format("directory: {0}", libDir));
            throw qe;
        }
        FilenameFilter jarFilter = new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.toLowerCase().endsWith(".jar");
            }
        };
        File[] jarFiles = libDir.listFiles(jarFilter);
        if (jarFiles != null) {
            for (File jar : jarFiles) {
                addSingleFile(jar, new Path(classpath, jar.getName()), jobId, job, fs);
            }
        }

        // Add all of the jars in the server mapreduce helper lib directory
        libDir = new File(homeDir, "tools/mapreduce/lib");
        if (!(libDir.isDirectory() && libDir.canRead())) {
            QueryException qe = new QueryException(DatawaveErrorCode.DFS_DIRECTORY_READ_ERROR, MessageFormat.format("directory: {0}", libDir));
            throw qe;
        }
        jarFiles = libDir.listFiles(jarFilter);
        if (jarFiles != null) {
            for (File jar : jarFiles) {
                addSingleFile(jar, new Path(classpath, jar.getName()), jobId, job, fs);
            }
        }
    }

Replace Anonymous With Lambda datawave.webservice.mr.configuration.MapReduceJobConfiguration.prepareClasspath.jarFilter.new FilenameFilter with (dir, name) -> name.toLowerCase().endsWith(".jar") in method protected prepareClasspath(jobId String, job Job, jobDir Path) : void from class datawave.webservice.mr.configuration.MapReduceJobConfiguration


    public Map<String,Pair<QueryLogic<?>,Connector>> entriesOlderThan(final Long now, final Long expiration) {
        Iterable<Entry<Pair<String,Long>,Triple>> iter = Iterables.filter(cache.entrySet(), input -> {
            Long timeInserted = input.getKey().getSecond();

            // If this entry was inserted more than the TTL 'time' ago, do not return it
                        if ((now - expiration) > timeInserted) {
                            return true;
                        }

                        return false;
                    });

        Map<String,Pair<QueryLogic<?>,Connector>> result = Maps.newHashMapWithExpectedSize(32);
        for (Entry<Pair<String,Long>,Triple> entry : iter) {
            result.put(entry.getKey().getFirst(), tripToPair.apply(entry.getValue()));
        }

        return result;
    }

    public Map<String,Pair<QueryLogic<?>,Connector>> entriesOlderThan(final Long now, final Long expiration) {
        Iterable<Entry<Pair<String,Long>,Triple>> iter = Iterables.filter(cache.entrySet(), new Predicate<Entry<Pair<String,Long>,Triple>>() {
            @Override
            public boolean apply(Entry<Pair<String,Long>,Triple> input) {
                Long timeInserted = input.getKey().getSecond();

                // If this entry was inserted more than the TTL 'time' ago, do not return it
                if ((now - expiration) > timeInserted) {
                    return true;
                }

                return false;
            }
        });

        Map<String,Pair<QueryLogic<?>,Connector>> result = Maps.newHashMapWithExpectedSize(32);
        for (Entry<Pair<String,Long>,Triple> entry : iter) {
            result.put(entry.getKey().getFirst(), tripToPair.apply(entry.getValue()));
        }

        return result;
    }

Replace Anonymous With Lambda datawave.webservice.query.cache.CreatedQueryLogicCacheBean.entriesOlderThan.iter.filter.new Predicate<Entry<Pair<String,Long>,Triple>> with input -> {Long timeInserted=input.getKey().getSecond(); in method public entriesOlderThan(now Long, expiration Long) : Map<String,Pair<QueryLogic<?>,Connector>> from class datawave.webservice.query.cache.CreatedQueryLogicCacheBean


    @Override
    public GenericQueryConfiguration initialize(Connector connection, Query settings, Set<Authorizations> runtimeQueryAuthorizations) throws Exception {

        for (BaseQueryLogic<?> logic : queryLogics) {
            final BaseQueryLogic<?> queryLogic = logic;
            int count = CollectionUtils.countMatches(queryLogics, object -> {
                if (object instanceof BaseQueryLogic<?>) {
                    BaseQueryLogic<?> other = (BaseQueryLogic<?>) object;
                    if (queryLogic.getClass().equals(other.getClass()) && queryLogic.getTableName().equals(other.getTableName())) {
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    return false;
                }
            });

            if (count > 1) {
                throw new RuntimeException("More than one instance of query logic class configured with the same table: " + logic.getClass().getName());
            }
        }

        Iterator<BaseQueryLogic<?>> itr = queryLogics.iterator();
        StringBuilder logicQueryStringBuilder = new StringBuilder("CompositeQueryLogic: ");
        while (itr.hasNext()) {
            BaseQueryLogic<?> logic = itr.next();
            GenericQueryConfiguration config = null;
            try {
                config = logic.initialize(connection, settings, runtimeQueryAuthorizations);
                logicQueryStringBuilder.append("(table=" + config.getTableName());
                logicQueryStringBuilder.append(",query=" + config.getQueryString());
                logicQueryStringBuilder.append(") ");
                QueryLogicHolder holder = new QueryLogicHolder(logic.getClass().getSimpleName());
                holder.setConfig(config);
                holder.setSettings(settings);
                holder.setMaxResults(logic.getMaxResults());
                logicState.put(logic, holder);
            } catch (Exception e) {
                log.info(e.getMessage() + " removing query logic " + logic.getClass().getName() + " from CompositeQuery");
                itr.remove();
                if (itr.hasNext() == false && logicState.size() == 0) {
                    // all logics have failed to initialize, rethrow the last exception caught
                    throw new IllegalStateException("All logics have failed to initialize", e);
                }
            }
        }
        startLatch = new CountDownLatch(logicState.values().size());
        completionLatch = new CountDownLatch(logicState.values().size());
        this.results = new CompositeQueryLogicResults(Math.min(settings.getPagesize() * 2, 1000), completionLatch);
        if (log.isDebugEnabled()) {
            log.debug("CompositeQuery initialized with the following queryLogics: ");
            for (Entry<BaseQueryLogic<?>,QueryLogicHolder> entry : this.logicState.entrySet()) {
                log.debug("\tLogicName: " + entry.getKey().getClass().getSimpleName() + ", tableName: " + entry.getKey().getTableName());
            }
        }

        final String compositeQueryString = logicQueryStringBuilder.toString();
        return new GenericQueryConfiguration() {
            @Override
            public String getQueryString() {
                return compositeQueryString;
            }
        };
    }

    @Override
    public GenericQueryConfiguration initialize(Connector connection, Query settings, Set<Authorizations> runtimeQueryAuthorizations) throws Exception {

        for (BaseQueryLogic<?> logic : queryLogics) {
            final BaseQueryLogic<?> queryLogic = logic;
            int count = CollectionUtils.countMatches(queryLogics, new Predicate() {
                @Override
                public boolean evaluate(Object object) {
                    if (object instanceof BaseQueryLogic<?>) {
                        BaseQueryLogic<?> other = (BaseQueryLogic<?>) object;
                        if (queryLogic.getClass().equals(other.getClass()) && queryLogic.getTableName().equals(other.getTableName())) {
                            return true;
                        } else {
                            return false;
                        }
                    } else {
                        return false;
                    }
                }
            });

            if (count > 1) {
                throw new RuntimeException("More than one instance of query logic class configured with the same table: " + logic.getClass().getName());
            }
        }

        Iterator<BaseQueryLogic<?>> itr = queryLogics.iterator();
        StringBuilder logicQueryStringBuilder = new StringBuilder("CompositeQueryLogic: ");
        while (itr.hasNext()) {
            BaseQueryLogic<?> logic = itr.next();
            GenericQueryConfiguration config = null;
            try {
                config = logic.initialize(connection, settings, runtimeQueryAuthorizations);
                logicQueryStringBuilder.append("(table=" + config.getTableName());
                logicQueryStringBuilder.append(",query=" + config.getQueryString());
                logicQueryStringBuilder.append(") ");
                QueryLogicHolder holder = new QueryLogicHolder(logic.getClass().getSimpleName());
                holder.setConfig(config);
                holder.setSettings(settings);
                holder.setMaxResults(logic.getMaxResults());
                logicState.put(logic, holder);
            } catch (Exception e) {
                log.info(e.getMessage() + " removing query logic " + logic.getClass().getName() + " from CompositeQuery");
                itr.remove();
                if (itr.hasNext() == false && logicState.size() == 0) {
                    // all logics have failed to initialize, rethrow the last exception caught
                    throw new IllegalStateException("All logics have failed to initialize", e);
                }
            }
        }
        startLatch = new CountDownLatch(logicState.values().size());
        completionLatch = new CountDownLatch(logicState.values().size());
        this.results = new CompositeQueryLogicResults(Math.min(settings.getPagesize() * 2, 1000), completionLatch);
        if (log.isDebugEnabled()) {
            log.debug("CompositeQuery initialized with the following queryLogics: ");
            for (Entry<BaseQueryLogic<?>,QueryLogicHolder> entry : this.logicState.entrySet()) {
                log.debug("\tLogicName: " + entry.getKey().getClass().getSimpleName() + ", tableName: " + entry.getKey().getTableName());
            }
        }

        final String compositeQueryString = logicQueryStringBuilder.toString();
        return new GenericQueryConfiguration() {
            @Override
            public String getQueryString() {
                return compositeQueryString;
            }
        };
    }

Replace Anonymous With Lambda datawave.webservice.query.logic.composite.CompositeQueryLogic.initialize.count.countMatches.new Predicate with object -> {if(object instanceof BaseQueryLogic<?>){BaseQueryLogic<?> other=(BaseQueryLogic<?>)object; in method public initialize(connection Connector, settings Query, runtimeQueryAuthorizations Set<Authorizations>) : GenericQueryConfiguration from class datawave.webservice.query.logic.composite.CompositeQueryLogic


    private void handleLegacyEvents(BaseQueryMetric queryMetric) {
        long lastUpdated;
        List<PageMetric> pages = queryMetric.getPageTimes();
        if (pages != null && !pages.isEmpty()) {
            // only old events should lack page numbers
            if (pages.get(0).getPageNumber() == -1) {

                Comparator<PageMetric> c = (m1, m2) -> {
                    CompareToBuilder builder = new CompareToBuilder();
                    builder.append(m1.getPageRequested(), m2.getPageRequested());
                    builder.append(m1.getPageReturned(), m2.getPageReturned());
                    return builder.toComparison();
                };

                // Sort by pageRequested and pageReturned
                Collections.sort(pages, c);

                // lastUpdated used to be set in the ShardTableQueryMetricHandler
                // Now it is done in the QueryMetricsBean.
                // If this message was stuck on the queue, then lastUpdated will not have been set yet.
                lastUpdated = pages.get(pages.size() - 1).getPageReturned();

                // if an older message is pulled off of the queue that does not have page numbers assigned,
                // then sort by pageRequested time and assign page numbers
                long x = 0;
                Long lastPage = lastPageMap.get(queryMetric.getQueryId());
                Iterator<PageMetric> itr = pages.iterator();
                while (itr.hasNext()) {
                    x++;
                    PageMetric p = itr.next();
                    // if we have a record of the last page recorded, then remove that page and all
                    // pages before it to limit the time necessary in updating
                    if (lastPage != null && x <= lastPage) {
                        itr.remove();
                    } else {
                        p.setPageNumber(x);
                    }
                }
                lastPageMap.put(queryMetric.getQueryId(), x);
                queryMetric.setLastUpdated(new Date(lastUpdated));
            }
        }
    }

    private void handleLegacyEvents(BaseQueryMetric queryMetric) {
        long lastUpdated;
        List<PageMetric> pages = queryMetric.getPageTimes();
        if (pages != null && !pages.isEmpty()) {
            // only old events should lack page numbers
            if (pages.get(0).getPageNumber() == -1) {

                Comparator<PageMetric> c = new Comparator<PageMetric>() {
                    @Override
                    public int compare(PageMetric m1, PageMetric m2) {
                        CompareToBuilder builder = new CompareToBuilder();
                        builder.append(m1.getPageRequested(), m2.getPageRequested());
                        builder.append(m1.getPageReturned(), m2.getPageReturned());
                        return builder.toComparison();
                    }
                };

                // Sort by pageRequested and pageReturned
                Collections.sort(pages, c);

                // lastUpdated used to be set in the ShardTableQueryMetricHandler
                // Now it is done in the QueryMetricsBean.
                // If this message was stuck on the queue, then lastUpdated will not have been set yet.
                lastUpdated = pages.get(pages.size() - 1).getPageReturned();

                // if an older message is pulled off of the queue that does not have page numbers assigned,
                // then sort by pageRequested time and assign page numbers
                long x = 0;
                Long lastPage = lastPageMap.get(queryMetric.getQueryId());
                Iterator<PageMetric> itr = pages.iterator();
                while (itr.hasNext()) {
                    x++;
                    PageMetric p = itr.next();
                    // if we have a record of the last page recorded, then remove that page and all
                    // pages before it to limit the time necessary in updating
                    if (lastPage != null && x <= lastPage) {
                        itr.remove();
                    } else {
                        p.setPageNumber(x);
                    }
                }
                lastPageMap.put(queryMetric.getQueryId(), x);
                queryMetric.setLastUpdated(new Date(lastUpdated));
            }
        }
    }

Replace Anonymous With Lambda datawave.webservice.query.metric.QueryMetricsWriter.handleLegacyEvents.c.new Comparator<PageMetric> with (m1, m2) -> {CompareToBuilder builder=new CompareToBuilder(); in method private handleLegacyEvents(queryMetric BaseQueryMetric) : void from class datawave.webservice.query.metric.QueryMetricsWriter


    @PostConstruct
    public void init() {

        Multimap<String,PatternWrapper> infos = HashMultimap.create();
        traceInfos = queryTraceCache.putIfAbsent("traceInfos", infos);
        if (traceInfos == null)
            traceInfos = infos;
        traceCacheListener = (key, traceInfo) -> {
            if ("traceInfos".equals(key)) {
                traceInfos = traceInfo;
            }
        };
        queryTraceCache.addListener(traceCacheListener);

        this.lookupUUIDUtil = new LookupUUIDUtil(this.lookupUUIDConfiguration, this, this.ctx, this.responseObjectFactory);
    }

    @PostConstruct
    public void init() {

        Multimap<String,PatternWrapper> infos = HashMultimap.create();
        traceInfos = queryTraceCache.putIfAbsent("traceInfos", infos);
        if (traceInfos == null)
            traceInfos = infos;
        traceCacheListener = new CacheListener() {
            @Override
            public void cacheEntryModified(String key, Multimap<String,PatternWrapper> traceInfo) {
                if ("traceInfos".equals(key)) {
                    traceInfos = traceInfo;
                }
            }
        };
        queryTraceCache.addListener(traceCacheListener);

        this.lookupUUIDUtil = new LookupUUIDUtil(this.lookupUUIDConfiguration, this, this.ctx, this.responseObjectFactory);
    }

Replace Anonymous With Lambda datawave.webservice.query.runner.QueryExecutorBean.init.new CacheListener with (key, traceInfo) -> {if("traceInfos".equals(key)){traceInfos=traceInfo; in method public init() : void from class datawave.webservice.query.runner.QueryExecutorBean