MultipleClientReportDownloader { public Collection<File> downloadReports( AdWordsSession.Builder sessionBuilder, ReportDefinition reportDefinition, Set<Long> clientCustomerIds) throws ReportProcessingException { ExecutorService executorService = Executors.newFixedThreadPool(numThreads); Stopwatch stopwatch = Stopwatch.createStarted(); logger.info("Downloading {" + reportDefinition.getReportType() + "} reports..."); List<Long> taskIds = Lists.newArrayList(); List<CallableReportDownloader> taskJobs = Lists.newArrayList(); Map<Long, String> failures = Maps.newHashMap(); ImmutableAdWordsSession session = null; for (Long clientCustomerId : clientCustomerIds) { try { session = AdWordsSessionUtil.buildImmutableSessionForCid(sessionBuilder, clientCustomerId); } catch (ValidationException e) { logger.error("Failed to create valid adwords session for CID " + clientCustomerId + ", skipping it."); failures.put(clientCustomerId, e.getMessage()); continue; } taskIds.add(clientCustomerId); taskJobs.add(genCallableReportDownloader(session, reportDefinition)); } List<Future<File>> taskResults; try { taskResults = executorService.invokeAll(taskJobs); } catch (InterruptedException e) { throw new ReportProcessingException( "MultipleClientReportDownloader encounters InterruptedException.", e); } List<File> results = Lists.newArrayList(); for (int i = 0; i < taskResults.size(); i++) { try { results.add(taskResults.get(i).get()); } catch (ExecutionException e) { failures.put(taskIds.get(i), e.getMessage()); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new ReportProcessingException( "MultiClientReportDownloader encounters InterruptedException.", e); } } executorService.shutdown(); stopwatch.stop(); logger.info("Downloaded reports for " + clientCustomerIds.size() + " accounts in " + stopwatch.elapsed(TimeUnit.SECONDS) + " seconds."); logger.info("Result: " + results.size() + " successes, " + failures.size() + " failures."); if (!failures.isEmpty()) { StringBuilder sb = new StringBuilder("*** Account IDs of download failures ***"); sb.append(SEPARATOR); sb.append(Joiner.on(SEPARATOR).withKeyValueSeparator(": ").join(failures)); logger.error(sb.toString()); } return results; } MultipleClientReportDownloader(int numThreads); Collection<File> downloadReports(
      AdWordsSession.Builder sessionBuilder,
      ReportDefinition reportDefinition,
      Set<Long> clientCustomerIds);  }
@Test public void testDownloadReports() throws ReportProcessingException { AdWordsSession.Builder sessionBuilder = new AdWordsSession.Builder().withEndpoint("http: .withDeveloperToken("DeveloperToken") .withClientCustomerId("123") .withUserAgent("UserAgent") .withOAuth2Credential(new GoogleCredential.Builder().build()); Set<Long> cids = ImmutableSet.of(1L, 2L, 3L, 4L, 5L); Collection<File> results = multipleClientReportDownloader.downloadReports(sessionBuilder, reportDefinition, cids); assertEquals(cids.size(), results.size()); }