0

I'm working in a desktop application for generating reports with Java Swing and Jasper Reports. Some days ago I ran into a problem because of a Groovy function that my code was not able to find. I found this answer and the problem was solved (note I left a comment) but when I packaged my application and tried to run it from the console I got the same issue. This is the stacktrace:

net.sf.jasperreports.engine.JRRuntimeException: Function MONTH not found.
    at net.sf.jasperreports.compilers.GroovyEvaluator.functionCall(GroovyEvaluator.java:106)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210)
    at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:52)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:154)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:174)
    at subReporteSummary_1502405767221_591326.methodMissing(calculator_subReporteSummary_1502405767221_591326:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
    at groovy.lang.MetaClassImpl.invokeMissingMethod(MetaClassImpl.java:939)
    at groovy.lang.MetaClassImpl.invokePropertyOrMissing(MetaClassImpl.java:1262)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1215)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:69)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:52)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:154)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
    at subReporteSummary_1502405767221_591326.evaluateEstimated(calculator_subReporteSummary_1502405767221_591326:336)
    at net.sf.jasperreports.engine.fill.JREvaluator.evaluateEstimated(JREvaluator.java:342)
    ... 14 more

But when I inspect the jar I'm able to find the MONTH function, which is in the net.sf.jasperreports.functions.standard.DateTimeFunctions class

@Function("MONTH")
@FunctionParameters({
    @FunctionParameter("dateObject")})
public static Integer MONTH(Object dateObject){
    return getCalendarFieldFromDate(dateObject,Calendar.MONTH)+1;
}

from the jasperreports-functions package which is in my classpath and is added to the package, as you may note by my maven configuration

<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <repositories>
        <!-- Jasper Reports repository to get japerreports-functions -->
        <repository>
            <id>jr-ce-releases</id>
            <url>http://jaspersoft.artifactoryonline.com/jaspersoft/jr-ce-releases</url>
        </repository>
    </repositories>

    <dependencies>
        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports</artifactId>
            <version>6.4.0</version>
            <!-- Exclusions to avoid some JasperReports certificates problems -->
            <exclusions>
                <exclusion>
                    <groupId>org.bouncycastle</groupId>
                    <artifactId>bcmail-jdk14</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>bouncycastle</groupId>
                    <artifactId>bcmail-jdk14</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.bouncycastle</groupId>
                    <artifactId>bctsp-jdk14</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>bouncycastle</groupId>
                    <artifactId>bcprov-jdk14</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- Groovy functions for Jasper Reports-->
        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports-functions</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.4.12</version>
        </dependency>

        <!-- Driver needed to connect to the DB -->
        <dependency>
            <groupId>com.ibm.informix</groupId>
            <artifactId>jdbc</artifactId>
            <version>4.10.8.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- This is to include all my dependencies in my package (it works fine) -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.0.2</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>ar.edu.unt.gui.MainFrame</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>

        <resources>
            <resource>
                <!-- I don't want to package the reports' source file -->
                <directory>src/main/resources</directory>
                <excludes>
                    <exclude>*.jrxml</exclude>
                </excludes>
            </resource>
        </resources>
    </build>
</project>

The MONTH function is called from a subreport. I found this post in the Jaspersoft Community but my report doesn't have such <returnValue> tag. This is the fragment from the main report where the subreport is declared:

<summary>
    <band height="239" splitType="Stretch">
        <subreport>
            <reportElement x="0" y="0" width="469" height="200" uuid="2da4b923-ee34-4a6d-9a04-8d050a2feb0f"/>
            <subreportParameter name="NRO_PAGINAS_PADRE">
                <subreportParameterExpression><![CDATA[$V{PAGE_NUMBER}]]></subreportParameterExpression>
            </subreportParameter>
            <connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
            <subreportExpression><![CDATA["subReporteSummary.jasper"]]></subreportExpression>
        </subreport>
        <textField evaluationTime="Auto">
            <reportElement x="175" y="219" width="126" height="20" uuid="28a4ff7e-d6dd-47f5-a655-5e0ea7bec50b"/>
            <textElement textAlignment="Center" verticalAlignment="Middle"/>
            <textFieldExpression><![CDATA["- Página " + $V{NRO_PAGINA_ACTUAL} + " de " + $V{PAGE_NUMBER} + " -"]]></textFieldExpression>
        </textField>
    </band>
</summary>

And this is the subReporteSummary.jrxml (summarySubreport in spanish) fragment where the MONTH function is called:

<variable name="NOMBRE_MES" class="java.lang.String" resetType="None">
    <variableExpression><![CDATA[MONTH($F{fechacancelacion}) == 1? "Enero" :
    MONTH($F{fechacancelacion}) == 2? "Febrero" :
    MONTH($F{fechacancelacion}) == 3? "Marzo" :
    MONTH($F{fechacancelacion}) == 4? "Abril" :
    MONTH($F{fechacancelacion}) == 5? "Mayo" :
    MONTH($F{fechacancelacion}) == 6? "Junio" :
    MONTH($F{fechacancelacion}) == 7? "Julio" :
    MONTH($F{fechacancelacion}) == 8? "Agosto" :
    MONTH($F{fechacancelacion}) == 9? "Septiembre" :
    MONTH($F{fechacancelacion}) == 10? "Octubre" :
    MONTH($F{fechacancelacion}) == 11? "Noviembre" : "Diciembre"]]></variableExpression>
    <initialValueExpression><![CDATA[MONTH($F{fechacancelacion}) == 1? "Enero" :
    MONTH($F{fechacancelacion}) == 2? "Febrero" :
    MONTH($F{fechacancelacion}) == 3? "Marzo" :
    MONTH($F{fechacancelacion}) == 4? "Abril" :
    MONTH($F{fechacancelacion}) == 5? "Mayo" :
    MONTH($F{fechacancelacion}) == 6? "Junio" :
    MONTH($F{fechacancelacion}) == 7? "Julio" :
    MONTH($F{fechacancelacion}) == 8? "Agosto" :
    MONTH($F{fechacancelacion}) == 9? "Septiembre" :
    MONTH($F{fechacancelacion}) == 10? "Octubre" :
    MONTH($F{fechacancelacion}) == 11? "Noviembre" : "Diciembre"]]></initialValueExpression>
</variable>

briefly: fechacancelacion is a java.util.Date variable and the expression is for get the month's names in upper case (is a requirement), which I can't get with a DATEFORMAT function because it gives me the names only in lowercase.

But getting back to the issue and to summarize, I have the MONTH function available in my JAR, the report compiles and shows correctly when I run my application from the IDE (Netbeans) but I'm getting an error running from the console with java -jar myapp-1.0.jar from the target folder.

If you need any other evidence, comment it out. Any help will be appreciated. Thanks in advance for your answers

Alvaro Pedraza
  • 1,176
  • 6
  • 20
  • 44
  • Most jasper function are in form 'Month' not 'MONTH', check doc – Jacek Cz Aug 19 '17 at 07:14
  • @JacekCz, I updated the post, is `MONTH` (in uppercase) and not `Month` as you can see. I've already checked it but forgot to post the snippet. Check it out please. Thanks for your time – Alvaro Pedraza Aug 19 '17 at 19:53
  • You have jasperreports 6.4.0 but jasperreports-functions 5.2.0. Try using jasperreports-functions 6.4.0. – dada67 Aug 21 '17 at 05:59
  • jasperreports-functions 5.2.0 is the latest version available in the repositories. If you know about another repository with that version please let me know. Best regards – Alvaro Pedraza Aug 21 '17 at 11:35
  • @dada67, today I checked again the repository https://jaspersoft.artifactoryonline.com/jaspersoft/jr-ce-releases and there is the `jasperreports-functions-6.4.0.jar` since november 2016. Maybe I missed the last time I checked. However I updated my project and ran `mvn package` but the result is the same. Maybe I'll be forced to move from groovy to java in my report... pitty – Alvaro Pedraza Aug 25 '17 at 22:54
  • 1
    If you're using the maven shade plugin to package your jar, you'll have to merge jasperreports_extension.properties from all the jars as described here https://stackoverflow.com/questions/35023908/jasperreports-extension-properties-overwritten-by-maven-assembly-plugin – dada67 Aug 26 '17 at 05:48
  • @dada67 I've been in a rush with another jobs but finally I was able to try the solution in the link you posted. Please post your comment as an answer and I'll mark it as the correct (I've already voted up your comment). Thank you so much for your time – Alvaro Pedraza Aug 28 '17 at 22:48

1 Answers1

1

If you're using the maven shade plugin to package your jar, you'll have to merge jasperreports_extension.properties from all the jars as described here in order for JasperReports extensions (such as functions) to be registered properly.

dada67
  • 4,723
  • 17
  • 19