/**
 *    Copyright 2016 Sven Loesekann

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
package ch.xxx.trader.usecase.services;

import java.io.ByteArrayOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import ch.xxx.trader.domain.model.dto.QuotePdf;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;

@Service
public class ReportGenerator {
	private static final Logger LOGGER = LoggerFactory.getLogger(ReportGenerator.class);
	//volatile to protect concurrent read/write accesses
	private static volatile JasperReport jasperReport = null;
	//limit cpu load to max 2 concurrently generated reports
	private final Scheduler mongoScheduler = Schedulers.newBoundedElastic(2, 100, "reports", 10);

	public Mono<byte[]> generateReport(Flux<QuotePdf> quotes) {
		return quotes.publishOn(mongoScheduler).collectList().map(quotePdfs -> {
			byte[] result = new byte[0];
			Date start = new Date();
			try {
				if (jasperReport == null) {
					jasperReport = JasperCompileManager.compileReport(
							this.getClass().getClassLoader().getResourceAsStream("currencyReport.jrxml"));
				}
				Map<String, Object> params = new HashMap<>();
				params.put("quotes", new JRBeanCollectionDataSource(quotePdfs));
				JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params,
						new JRBeanCollectionDataSource(quotePdfs));

				JRPdfExporter pdfExporter = new JRPdfExporter();
				pdfExporter.setExporterInput(new SimpleExporterInput(jasperPrint));
				ByteArrayOutputStream pdfReportStream = new ByteArrayOutputStream();
				pdfExporter.setExporterOutput(new SimpleOutputStreamExporterOutput(pdfReportStream));
				pdfExporter.exportReport();

				result = pdfReportStream.toByteArray();
			} catch (JRException e) {
				LOGGER.error("Report generation failed.", e);
			}
			LOGGER.info("Report generated in: " + (new Date().getTime() - start.getTime()) + "ms");
			return result;
		});
	}
}

@@ -2323,24 +2323,116 @@
 t.jrxml%22));%0A
+%09%09%09%09%09LOGGER.info(%22Report compiled in: %22 + (new Date().getTime() - start.getTime()) + %22ms%22);%0A
 %09%09%09%09%7D%0A%09%09%09%09Ma

add logging