I am using JasperStudio 5.5.1 and JasperServer 5.5.0. I wrote a small Scriptlet which extends JRDefaultScriptlet. Everything works perfectly, except that it works perfectly twice. The only method I'm overriding is afterDetailEval(). I know that this was an issue raised several years ago (http://community.jaspersoft.com/questions/528909/every-function-my-scriptlet-called-twice), and I have done everything I can to find any duplicate jars, including using Tattletale, but cannot find anything. I have been able to learn that my class is only being initialized once (I put a System.out in the constructor, and it only prints once), but the afterDetailEval() method is being run twice. I'm thinking that there must be a simple solution, but I can't find it. This problem happens both when I run the report from JasperStudio and when I run it from JasperServer.
I have a report that gets a list of accounts and the e-mails associated with each account. The idea is that after each detail is evaluated, the program sends the info to the Jasper Server Scheduler so that account statements are automatically e-mailed for each account. If anyone has an idea of an easier/better way to do this, that would be helpful, too. Everything works great except that two e-mails get scheduled for each account instead of one. (For testing purposes, right now it only sends to the 1023 account.)
Scriptlet:
package mypackage; Â import java.io.OutputStreamWriter; import java.net.Authenticator; import java.net.HttpURLConnection; import java.net.PasswordAuthentication; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Random; import net.sf.jasperreports.engine.JRDefaultScriptlet; import net.sf.jasperreports.engine.JRScriptletException; Â public class MonthEnd extends JRDefaultScriptlet { Date sched; Calendar cal; SimpleDateFormat mySQLDateFormat; SimpleDateFormat scheduletime; int randVal; Â public MonthEnd() { sched = new Date(); cal = Calendar.getInstance(); mySQLDateFormat = new SimpleDateFormat("yyyy-MM-dd"); scheduletime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Random rand = new Random(); randVal = rand.nextInt(); Â System.out.println("Initialized MonthEnd - "+randVal); cal.setTime(sched); // the e-mails will start about 30 seconds after the report is run (because incrementTime will also be run) cal.add(Calendar.SECOND, 20); } Â private String incrementTime() { // should send an e-mail out about every 10 seconds cal.add(Calendar.SECOND, 10); return scheduletime.format(cal.getTime()); } Â @Override public void afterDetailEval() throws JRScriptletException { String acct = (String)this.getFieldValue("acctgroup"); String startdate = mySQLDateFormat.format(this.getParameterValue("PeriodStartDate")); String enddate = mySQLDateFormat.format(this.getParameterValue("PeriodEndDate")); Boolean sendemail = (Boolean) this.getParameterValue("SendEmails"); if (sendemail) { if (acct.trim().matches("1023")) { String schedTime = incrementTime(); System.out.println("Ran the 1023 account code: "+randVal+" - "+Math.random()); int scheduleEmail = setSchedule(acct.trim(),"/ReportToEmail",startdate,enddate,schedTime,(String)this.getFieldValue("accountemail")); if (scheduleEmail == 200) { this.setVariableValue("chkAcct", "E-mail Scheduled for "+schedTime); } else { this.setVariableValue("chkAcct", "Response Error: "+scheduleEmail); } } else { this.setVariableValue("chkAcct", "Not Sent"); } } } Â public int setSchedule(String acct, String reportToSend, String StartDate, String EndDate, String sendReportTime, String emailAddress) { // put the list of e-mail addresses in an array List<String> emaillist = Arrays.asList(emailAddress.split("\\s*,\\s*")); Â String data = "{\"baseOutputFilename\":\""; data += "Account_Statement-"+acct.trim(); data += "\",\"outputFormats\":{\"outputFormat\":[\"PDF\"]},\"source\":{\"reportUnitURI\":\""; data += reportToSend; data += "\",\"parameters\":{\"parameterValues\":{\"AR_accountcode\":[\""; data += acct.trim(); data += "%\"],\"PeriodStartDate\":[\""; data += StartDate; data += "\"],\"PeriodEndDate\":[\""; data += EndDate; data += "\"]}}},\"trigger\":{\"simpleTrigger\":{\"timezone\":\"Pacific/Port_Moresby\",\"occurrenceCount\":1,\"startType\":2,\"recurrenceInterval\":null,\"recurrenceIntervalUnit\":null,\"endDate\":null,\"startDate\":\""; data += sendReportTime; data += "\"}},\"outputTimeZone\":\"America/New_York\",\"repositoryDestination\":{\"overwriteFiles\":false,\"sequentialFilenames\":false,\"folderURI\":\"/\",\"saveToRepository\":false,\"timestampPattern\":null,\"outputFTPInfo\":{\"type\":\"ftp\",\"port\":21,\"folderPath\":null,\"password\":null,\"propertiesMap\":{},\"serverName\":null,\"userName\":null}},\"mailNotification\":{\"toAddresses\":{\"address\":["; int counter = 0; for(String elist : emaillist) { if (counter != 0) { data += ","; } data += "\""+elist+"\""; counter++; } data += "]},\"subject\":\"Monthly Statement\",\"messageText\":\"If you are receiving this, go ahead and dance a little jig.\",\"resultSendType\":\"SEND_ATTACHMENT\",\"skipEmptyReports\":true},"; data += "\"alert\":{\"toAddresses\":{\"address\":[\"myemail@test.org\"]},\"subject\":\"Failed account statement\",\"messageText\":\"\",\"messageTextWhenJobFails\":\""; data += "Something went wrong with the report for account: "+acct.trim(); data += "\",\"jobState\":\"FAIL_ONLY\",\"includingReportJobInfo\":true,\"includingStackTrace\":true},\"label\":\"AutomaticMonthlyEmails\",\"description\":\"\"}"; Â try { Authenticator.setDefault(new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("user", "password".toCharArray()); } }); Â URL url = new URL("http://mydomain.org:8080/jasperserver/rest_v2/jobs"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); Â connection.setRequestMethod("PUT"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/job+json"); connection.setRequestProperty("Accept", "application/job+json"); try (OutputStreamWriter osw = new OutputStreamWriter(connection.getOutputStream())) { osw.write(data); osw.flush(); } Â int respcode = connection.getResponseCode(); return respcode; } catch (Exception e) { System.err.println(e.getMessage()); return 0; } } }
Report JRXML:
<?xml version="1.0" encoding="UTF-8"?> <!-- Created with Jaspersoft Studio version last--> <jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="PersonnelOverview" pageWidth="842" pageHeight="595" orientation="Landscape" columnWidth="802" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" isIgnorePagination="true" uuid="56afbef4-9dfd-41f5-a016-bc8399f51f39"> <property name="com.jaspersoft.studio.data.defaultdataadapter" value="Informix Pronto"/> <property name="ireport.jasperserver.url" value="http://mydomain.org:8080/jasperserver/"/> <property name="ireport.jasperserver.report.resource" value="/Business/BusinessOffice/MonthEnd/AccountEmails_files/main_jrxml"/> <property name="ireport.jasperserver.reportUnit" value="/Business/BusinessOffice/MonthEnd/AccountEmails"/> <scriptlet name="MonthEnd" class="mypackage.MonthEnd"> <scriptletDescription><![CDATA[]]></scriptletDescription> </scriptlet> <parameter name="PeriodStartDate" class="java.sql.Date"/> <parameter name="PeriodEndDate" class="java.sql.Date"/> <parameter name="SendEmails" class="java.lang.Boolean"> <defaultValueExpression><![CDATA[false]]></defaultValueExpression> </parameter> <queryString language="SQL"> <![CDATA[EXECUTE FUNCTION getMonthEndPersonnelEmails();]]> </queryString> <field name="acctgroup" class="java.lang.String"/> <field name="acctname" class="java.lang.String"/> <field name="location1" class="java.lang.String"/> <field name="location2" class="java.lang.String"/> <field name="location3" class="java.lang.String"/> <field name="location4" class="java.lang.String"/> <field name="location5" class="java.lang.String"/> <field name="accountemail" class="java.lang.String"/> <sortField name="location1"/> <sortField name="location2"/> <sortField name="location3"/> <sortField name="location4"/> <sortField name="location5"/> <sortField name="acctgroup"/> <variable name="acctgroup1" class="java.lang.Integer" resetType="Group" resetGroup="location4" calculation="Count"> <variableExpression><![CDATA[$F{acctgroup}]]></variableExpression> </variable> <variable name="acctgroup2" class="java.lang.Integer" resetType="Group" resetGroup="location3" calculation="Count"> <variableExpression><![CDATA[$F{acctgroup}]]></variableExpression> </variable> <variable name="acctgroup3" class="java.lang.Integer" resetType="Group" resetGroup="location2" calculation="Count"> <variableExpression><![CDATA[$F{acctgroup}]]></variableExpression> </variable> <variable name="acctgroup4" class="java.lang.Integer" calculation="Count"> <variableExpression><![CDATA[$F{acctgroup}]]></variableExpression> </variable> <variable name="chkAcct" class="java.lang.String" calculation="System"/> <group name="location2"> <groupExpression><![CDATA[$F{location2}]]></groupExpression> <groupHeader> <band height="28"> <rectangle radius="8"> <reportElement x="0" y="0" width="800" height="22" forecolor="#7088FF" backcolor="#7088FF" uuid="8b1bb0b4-6e18-42af-b582-b4492a42f37a"> <property name="local_mesure_unitheight" value="pixel"/> <property name="com.jaspersoft.studio.unit.height" value="px"/> </reportElement> </rectangle> <textField> <reportElement x="10" y="0" width="780" height="22" uuid="2ee5de52-4bdc-49bb-a3e1-5a0e8afbdadb"/> <textElement verticalAlignment="Middle"> <font size="14" isBold="true"/> </textElement> <textFieldExpression><![CDATA[$F{location2}]]></textFieldExpression> </textField> </band> </groupHeader> </group> <group name="location3"> <groupExpression><![CDATA[$F{location3}]]></groupExpression> <groupHeader> <band height="28"> <printWhenExpression><![CDATA[$F{location3} != null]]></printWhenExpression> <rectangle radius="8"> <reportElement x="20" y="0" width="780" height="22" forecolor="#B3C3FF" backcolor="#B3C3FF" uuid="6e2b12f6-0b70-472e-97ee-9565b354d611"/> </rectangle> <textField> <reportElement x="30" y="0" width="760" height="22" uuid="d6ef5a3f-0eca-4b6e-8702-de0fbe6c37d8"/> <textElement verticalAlignment="Middle"> <font size="12" isBold="true"/> </textElement> <textFieldExpression><![CDATA[$F{location3}]]></textFieldExpression> </textField> </band> </groupHeader> </group> <group name="location4"> <groupExpression><![CDATA[$F{location4}.trim()+($F{location5}!=null ? " - "+$F{location5} : "")]]></groupExpression> <groupHeader> <band height="24"> <printWhenExpression><![CDATA[$F{location4} != null]]></printWhenExpression> <rectangle radius="8"> <reportElement x="40" y="0" width="760" height="20" forecolor="#E6E7FF" backcolor="#E6E7FF" uuid="b6b1bb57-ec2c-4ae2-b2e1-e516c886b8ad"/> </rectangle> <textField> <reportElement x="50" y="0" width="740" height="20" uuid="2f85f401-9b9e-4e95-8e01-94a1d4eb33f5"/> <textElement verticalAlignment="Middle"> <font size="12"/> </textElement> <textFieldExpression><![CDATA[$F{location4}.trim()+($F{location5}!=null ? " - "+$F{location5} : "")]]></textFieldExpression> </textField> </band> </groupHeader> </group> <background> <band splitType="Stretch"/> </background> <title> <band height="38" splitType="Stretch"> <staticText> <reportElement x="0" y="0" width="800" height="30" forecolor="#7088FF" uuid="f83f847a-66a1-4682-863a-b549d7ce64a3"/> <textElement textAlignment="Center"> <font size="20" isBold="true"/> </textElement> <text><![CDATA[Month-End Emails]]></text> </staticText> </band> </title> <detail> <band height="17" splitType="Stretch"> <textField> <reportElement x="100" y="0" width="40" height="14" uuid="2176ceb0-09b4-4792-b933-0504fd6c51d0"> <property name="local_mesure_unitheight" value="pixel"/> <property name="com.jaspersoft.studio.unit.height" value="px"/> </reportElement> <textFieldExpression><![CDATA[$F{acctgroup}]]></textFieldExpression> </textField> <textField> <reportElement x="150" y="0" width="270" height="14" uuid="3fc04188-d9db-439a-8c46-1a47e90822cf"> <property name="com.jaspersoft.studio.unit.height" value="px"/> </reportElement> <textFieldExpression><![CDATA[$F{acctname}.trim()]]></textFieldExpression> </textField> <textField isStretchWithOverflow="true"> <reportElement x="430" y="0" width="230" height="14" uuid="3a807127-386b-4488-9525-ce460133e8f7"> <property name="com.jaspersoft.studio.unit.height" value="px"/> </reportElement> <textFieldExpression><![CDATA[$F{accountemail}]]></textFieldExpression> </textField> <textField isStretchWithOverflow="true" isBlankWhenNull="true"> <reportElement x="660" y="0" width="140" height="14" uuid="266b4dff-bbb6-45aa-b600-8ba21fbf0178"/> <textFieldExpression><![CDATA[$V{chkAcct}]]></textFieldExpression> </textField> </band> </detail> </jasperReport>
1 Answer:
The problem can be resolved by removing all of the
<sortField name="xxxx"/>
lines from the jrxml file. I am assuming this is because the server reads all the data once, and then goes through it again to get the proper sorting, thus causing the afterDetailEval function to fire twice. I believe this to be a bug.
I am using JasperStudio 5.6.1 and same problem and i ain't got sort fields.