Scriptlet afterDetailEval runs twice

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>

ict-programmer's picture
Joined: May 19 2014 - 5:26pm
Last seen: 2 years 12 months ago

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.

ict-programmer's picture
Joined: May 19 2014 - 5:26pm
Last seen: 2 years 12 months ago

I am using JasperStudio 5.6.1 and same problem and i ain't got sort fields.

neskk.24 - 8 years 5 months ago
Feedback