/** * The contents of this file are subject to the Mozilla Public License * Version 1.1 (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.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations under * the License. * * The Original Code is OpenELIS code. * * Copyright (C) ITECH, University of Washington, Seattle WA. All Rights Reserved. * */ package us.mn.state.health.lims.dataexchange.aggregatereporting; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletResponse; import org.hibernate.HibernateException; import org.hibernate.Transaction; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import us.mn.state.health.lims.common.log.LogEvent; import us.mn.state.health.lims.common.util.ConfigurationProperties; import us.mn.state.health.lims.common.util.ConfigurationProperties.Property; import us.mn.state.health.lims.common.util.DateUtil; import us.mn.state.health.lims.common.util.StringUtil; import us.mn.state.health.lims.dataexchange.aggregatereporting.dao.ReportExternalExportDAO; import us.mn.state.health.lims.dataexchange.aggregatereporting.daoimpl.ReportExternalExportDAOImpl; import us.mn.state.health.lims.dataexchange.aggregatereporting.daoimpl.ReportQueueTypeDAOImpl; import us.mn.state.health.lims.dataexchange.aggregatereporting.valueholder.ReportExternalExport; import us.mn.state.health.lims.dataexchange.aggregatereporting.valueholder.ReportQueueType; import us.mn.state.health.lims.dataexchange.common.ITransmissionResponseHandler; import us.mn.state.health.lims.dataexchange.common.ReportTransmission; import us.mn.state.health.lims.hibernate.HibernateUtil; import us.mn.state.health.lims.scheduler.dao.CronSchedulerDAO; import us.mn.state.health.lims.scheduler.daoimpl.CronSchedulerDAOImpl; import us.mn.state.health.lims.scheduler.valueholder.CronScheduler; import us.mn.state.health.lims.siteinformation.dao.SiteInformationDAO; import us.mn.state.health.lims.siteinformation.daoimpl.SiteInformationDAOImpl; import us.mn.state.health.lims.siteinformation.valueholder.SiteInformation; public class AggregateReportJob implements Job { private static String LAB_INDICATOR_REPORT_ID; private static ReportExternalExportDAO reportExternalExportDAO = new ReportExternalExportDAOImpl(); private static CronSchedulerDAO cronSchedulerDAO = new CronSchedulerDAOImpl(); private static SiteInformationDAO siteInfoDAO = new SiteInformationDAOImpl(); static { ReportQueueType reportType = new ReportQueueTypeDAOImpl().getReportQueueTypeByName("labIndicator"); if (reportType != null) { LAB_INDICATOR_REPORT_ID = reportType.getId(); } } @Override public void execute(JobExecutionContext arg0) throws JobExecutionException { System.out.println("Reporting triggered: " + DateUtil.getCurrentDateAsText("dd-MM-yyyy hh:mm")); LogEvent.logInfo("AggregateReportJob", "execute()", "Reporting triggered: " + DateUtil.getCurrentDateAsText("dd-MM-yyyy hh:mm")); updateRunTimestamp(); List<ReportExternalExport> sendableReports = reportExternalExportDAO.getUnsentReportExports(LAB_INDICATOR_REPORT_ID); if (!sendableReports.isEmpty()) { SendingAggregateReportWrapper wrapper = new SendingAggregateReportWrapper(); wrapper.setSiteId(ConfigurationProperties.getInstance().getPropertyValue(Property.SiteCode)); SiteInformation authInfo = siteInfoDAO.getSiteInformationByName("testUsageAggregationUserName"); wrapper.setUser(authInfo == null ? " " : authInfo.getValue()); authInfo = siteInfoDAO.getSiteInformationByName("testUsageAggregationPassword"); wrapper.setPassword(authInfo == null ? " " : authInfo.getValue()); List<AggregateReportXmit> reportXmit = new ArrayList<AggregateReportXmit>(); for (ReportExternalExport report : sendableReports) { reportXmit.add(new AggregateReportXmit(report)); } wrapper.setReports(reportXmit); String castorPropertyName = "AggregateReportingMapping"; String url = ConfigurationProperties.getInstance().getPropertyValue(Property.testUsageReportingURL) + "/IndicatorAggregation";// boolean sendAsychronously = false; ResponseHandler responseHandler = new ResponseHandler(); responseHandler.setReports(sendableReports); responseHandler.setReAttemptTry(wrapper, castorPropertyName, url); //String xml = createXML(wrapper); new ReportTransmission().sendReport(wrapper, castorPropertyName, url, sendAsychronously, responseHandler); //new ReportTransmission().sendRawReport(xml, url, sendAsychronously, responseHandler); } } /* * This is an alternative if castor is not behaving well. It was adding newline chars to the data which was messing it up when it's displayed */ /* private String createXML(SendingAggregateReportWrapper wrapper) { StringBuffer buffer = new StringBuffer(); buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); buffer.append("<aggregate-reports>\n"); buffer.append("<version>1</version>\n"); buffer.append("<drowssap>"); buffer.append(wrapper.getPassword()); buffer.append("</drowssap>\n"); buffer.append(" <user>"); buffer.append(wrapper.getUser()); buffer.append("</user>\n"); buffer.append("<site-id>"); buffer.append(wrapper.getSiteId()); buffer.append("</site-id>\n"); for (AggregateReportXmit report : wrapper.getReports()) { buffer.append(" <reports xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"report\">\n"); buffer.append("<event-date>"); buffer.append(report.getEventDate()); buffer.append("</event-date>\n"); buffer.append("<data>"); buffer.append(report.getData().replace("\"", """).replace("'", "'")); buffer.append("</data>\n"); buffer.append("</reports>\n"); } buffer.append("</aggregate-reports>"); return buffer.toString(); } */ private void updateRunTimestamp() { CronScheduler reportScheduler = cronSchedulerDAO.getCronScheduleByJobName("sendSiteIndicators"); reportScheduler.setLastRun(DateUtil.getNowAsTimestamp()); reportScheduler.setSysUserId("1"); Transaction tx = HibernateUtil.getSession().beginTransaction(); try { cronSchedulerDAO.update(reportScheduler); tx.commit(); } catch (HibernateException e) { tx.rollback(); } } class ResponseHandler implements ITransmissionResponseHandler { private static final long MAX_DELAY = 256; // Anything past this will be // a cumulative time of over // 8 hours private static final long MILLI_SEC_PER_MIN = 1000L * 60L; private List<ReportExternalExport> sendableReports; private ReportExternalExportDAO reportExternalExportDAO = new ReportExternalExportDAOImpl(); private long delayInMin = 5L; private SendingAggregateReportWrapper wrapper; private String castorPropertyName; private String url; private ResponseHandler instance = this; public void setReports(List<ReportExternalExport> sendableReports) { this.sendableReports = sendableReports; } public void setReAttemptTry(SendingAggregateReportWrapper wrapper, String castorPropertyName, String url) { this.wrapper = wrapper; this.castorPropertyName = castorPropertyName; this.url = url; } @Override public void handleResponse(int httpReturnStatus, List<String> errors, String msg) { switch (httpReturnStatus) { case HttpServletResponse.SC_OK: handleSuccess(); break; case HttpServletResponse.SC_UNAUTHORIZED: handleUnauthorized(); retry(); break; case HttpServletResponse.SC_NOT_FOUND: handleNotFound(errors); retry(); break; case HttpServletResponse.SC_BAD_REQUEST: handleBadRequest(errors); break; default: handleUnknownFailure(errors); retry(); } } private void handleSuccess() { Transaction tx = HibernateUtil.getSession().beginTransaction(); try { for (ReportExternalExport report : sendableReports) { report = reportExternalExportDAO.loadReport(report); report.setSend(false); report.setSentDate(DateUtil.getNowAsTimestamp()); report.setSysUserId("1"); reportExternalExportDAO.updateReportExternalExport(report); } SiteInformation sendInfo = siteInfoDAO.getSiteInformationByName("testUsageSendStatus"); if (sendInfo != null) { sendInfo.setValue(StringUtil.getMessageForKey("http.success")); sendInfo.setSysUserId("1"); siteInfoDAO.updateData(sendInfo); } tx.commit(); } catch (HibernateException e) { tx.rollback(); } } private void handleUnknownFailure(List<String> errors) { for (String error : errors) { if (error.startsWith("Unable to connect")) { writeSendStatus(StringUtil.getMessageForKey("http.site.unreachable")); return; } } writeSendStatus(StringUtil.getMessageForKey("http.unknown.failure")); } private void handleUnauthorized() { writeSendStatus(StringUtil.getMessageForKey("http.unauthorized")); } private void handleNotFound(List<String> errors) { String error = errors.isEmpty() ? "" : errors.get(0); writeSendStatus(StringUtil.getContextualMessageForKey("http.notfound") + ": " + error); } private void handleBadRequest(List<String> errors) { String error = errors.isEmpty() ? "" : errors.get(0); writeSendStatus(StringUtil.getContextualMessageForKey("http.badrequest") + ": " + error); } private void retry() { delayInMin = delayInMin * 2L; if (delayInMin < MAX_DELAY) { new Thread() { public void run() { System.out.println("Aggregate Report: Will attempt to resend report in " + delayInMin + " minutes."); LogEvent.logInfo("AggregateReportJob", "retry()", "Will attempt to resend report in " + delayInMin + " minutes."); try { sleep(delayInMin * MILLI_SEC_PER_MIN); } catch (InterruptedException e) { e.printStackTrace(); } new ReportTransmission().sendReport(wrapper, castorPropertyName, url, false, instance); } }.start(); } else { System.out.println("Aggregate report: Giving up trying to connect"); LogEvent.logInfo("AggregateReportJob", "retry()", "Giving up trying to connect"); } } private void writeSendStatus(String status) { Transaction tx = HibernateUtil.getSession().beginTransaction(); try { SiteInformation sendInfo = siteInfoDAO.getSiteInformationByName("testUsageSendStatus"); if (sendInfo != null) { sendInfo.setValue(status); sendInfo.setSysUserId("1"); siteInfoDAO.updateData(sendInfo); } tx.commit(); } catch (HibernateException e) { tx.rollback(); } } } }