Menu

Custom Jasperreport to pdf doesn't work anymore in OXPro7

Bart Devos
2023-02-07
2023-02-16
  • Bart Devos

    Bart Devos - 2023-02-07

    Hi,
    A custom Jasperreport to generate a pdf doesn't work anymore in OXPro 7. It logs (full log in attachment):

    net.sf.jasperreports.engine.JRRuntimeException: Empty input source supplied to the exporter in batch mode.
    

    When I google on the matter the "solutions" always point to missing fonts. I installed the so called missing fonts but without success. The weirdest thing is if I set an unexisting path to the jrxml file I still get the same error. So, it is not complaining not finding the file.
    I attach herewith the different custom code (mostly based on OX code). But as I stated, it worked before.
    In addition: I have no clue where to put the custom reports. I'm quite lost in the Maven structure...
    Kind regards,
    Bart.

     
  • Juan Leonardo Gutierrez Toledano

    Hello,
    Right now I don't have a lot of time to go through your code, but with the migration to v7 and maven, I locate my jrxmls in src\main\resources\reports and when I reference them I do so as "reports/myFilename.jrxml". In the deployment file, they are in target\eell\WEB-INF\classes\reports
    I think that the famous problem of the fonts shows otrer lines in the log.
    Regards

     
    • Bart Devos

      Bart Devos - 2023-02-08

      Thank you Juan, I'll try that.
      Indeed the log doesn't mention any fontproblem, but when I google the outputline there is mostly a reference to a missing font or image. Although in my case the font isn't missing and there are no images.

       
  • Bart Devos

    Bart Devos - 2023-02-11

    Debugging my code learned me that the problem is not the report generation but the non-functioning of getTab().getSelectedKeys(). In other parts of my code that works, but for some reason it doesn't work in the action GeneratePackListsAction.java. I have a suspicion that the reason somehow is tied to the fact that the TabBaseAction is extended in an action "2 levels above". In the actions that work with getTab().getSelectedKeys(), TabBaseAction is extended directly in the functioning action. I'm not sure if that is the reason (it shouldn't, it compiles) but that's the main difference with the working routines.
    I'll explain:
    The calling method (the one defined in controllers.xml) is:

    GeneratePackListsAction extends JasperConcatReport4TabBaseAction
    

    then:

    JasperConcatReport4TabBaseAction extends JasperMultipleReport4TabBaseAction
    

    and then:

    JasperMultipleReport4TabBaseAction extends TabBaseAction
    

    The length of the result is always getTab().getSelectedKeys() = 0, hence the jrmx file array is not filled.

    I included the source files.
    Note that this code worked before in OXPro 6.x.
    Thanks in advance for any input!

    Bart.

     

    Last edit: Bart Devos 2023-02-11
  • Bart Devos

    Bart Devos - 2023-02-11

    I can confirm now for sure that, if I extend GeneratePackListsAction.java with TabBaseAction directly (commenting out any Jasperreport references), the result of getSelectedKeys() stays empty. Routines with the same call on the same model (Bestellingen) work correctly.
    This drives me crazy...

     
  • Bart Devos

    Bart Devos - 2023-02-13

    Ok, I found a workaround to fix this, but I feel suspicious why this worked in previous OXPro 6.x versions and not in OXPro7.0.5.
    The previous situation:
    I have a mechanism that I use thru-out my code to be able to evaluate if the user selected records or not and give a dialog accordingly. I achieve that by:

        <controller name="ApplyToSelectedBestellingenSub"> <!-- This is part of the menu the user can select -->
            ...
            <action name="CreatePacklistDialog" class="org.openxava.zokola.actions.ShowConfirmationDialog" mode="list"> <!-- The user is supposed to select at least one 'Bestellijn', if not there is a warning, if so confirmation is asked-->
                <set value="createpacklist" property="qcontext"/> <!-- Parameter to make ShowConfirmationDialog generic, so it can be used in other contexts. 'qcontext' stands for 'questioncontext' -->
            </action>
            ...
        </controller>
    

    ShowConfirmationDialog.java

    package org.openxava.zokola.actions;
    
    import java.util.*;
    
    import org.directwebremoting.util.*;
    import org.openxava.actions.*;
    import org.openxava.annotations.*;
    import org.openxava.model.*;
    import org.openxava.util.SessionData;
    import org.openxava.zokola.model.*;
    import org.openxava.zokola.utilities.*;
    
    public class ShowConfirmationDialog extends TabBaseAction{
        private Logger log = Logger.getLogger(ShowConfirmationDialog.class);
    
        @Hidden
        private String question; //The question to ask - see controller.xml
    
        @Hidden
        private String qcontext; //The question context (used to evaluate the confirmation)
                                // - see controller.xml
        @Override
        public void execute() throws Exception {
            switch (qcontext){
                    ...
                    case "createpacklist":      createPacklist();
                                                                                                            break;
                     ...
                    default:                    break;
            }
            showDialog();
            getView().setModelName("ConfirmationDialog");
            getView().setViewName("simple");
            getView().setValue("qcontext", this.qcontext);
            getView().setHidden("qcontext", true); //Impossible to set a value of a prop that is not in the view
                                                    //therefor you have to hide it.
            getView().setValue("question", question);
            if(qcontext.equals("NotAllFromSameKlant") || qcontext.equals("NoLeveringsbonsSelected") 
                                || qcontext.equals("SomeLeveringsbonsNotPrintedYet")
                                || qcontext.equals("NoFa4RemindersSelected")
                                || qcontext.equals("NoBestellingenSelectedPacklist")){
                addActions("ConfDialog.affirmatief");           
            } else {
                addActions("ConfDialog.negatief", "ConfDialog.affirmatief");
            }
        }
    
    ...
    private void createPacklist() {
            log.debug("============>>>>>>>>>>>>> CREATEPACKLIST");
            if(getTab().getSelectedKeys().length == 0){
                qcontext = "NoBestellingenSelectedPacklist";
            } else {
                qcontext = "SomeBestellingenSelectedPacklist";
            }
            question = ConfirmQuestionStringUtil.getInstance().getQuestion4Context(qcontext);
        }
    
    ...
    
        public String getQuestion() {
            return question;
        }
    
        public void setQuestion(String question) {
            this.question = question;
        }
    
        public String getQcontext() {
            return qcontext;
        }
    
        public void setQcontext(String qcontext) {
            this.qcontext = qcontext;
        }
    }
    

    The answer given in the dialog is evaluated due to following mechanism:

        <controller name="ConfDialog">
                    <action name="affirmatief" class="org.openxava.zokola.actions.TrueAction"/> <!-- In this case only 1 possible outcome is this-->
    
                    <action name="negatief" class="org.openxava.zokola.actions.FalseAction"/>
                       ...
                    <action name="GeneratePackListsAction" class="org.openxava.zokola.actions.GeneratePackListsAction">
            </action>
        </controller>
    

    TrueAction.java executes the requested action by evaluating the 'qcontext' value stored as a hidden property in the dialog.

    public class TrueAction extends TabBaseAction implements IChainActionWithArgv{
        Logger log = Logger.getLogger(this.getClass());
        private String argNextAction = null;
        private String nextAction = null;
    
        @Override
        public void execute() throws Exception {
            String qcontext = (String)getView().getValue("qcontext"); //qcontext is the context this dialog is about
                                                                    //it allows to filter the actionbehaviour
            switch (qcontext) {
            case "NoBestellijnenSelected":  log.info("ACTION FOR NoBestellijnenSelected"); <!-- Some other possible qactions, not relevant for this case-->
                                            cloneBestellijnen();
                                            closeDialog();
                                            break;
            case "SomeBestellijnenSelected":    log.info("ACTION FOR SomeBestellijnenSelected");  <!-- Some other possible qactions, not relevant for this case-->
                                                cloneBestellijnen();
                                                closeDialog();
                                                break;
    
            ...
            case "NoBestellingenSelectedPacklist":      log.info("ACTION FOR NoBestellingenSelectedPacklist"); <!-- Exit when no Bestellijnen are selected-->
                                                                                                                                                    closeDialog();
                                                                                                                                                    break;
    
            case "SomeBestellingenSelectedPacklist":    log.info("ACTION FOR SomeBestellingenSelectedPacklist");
                                                                                                                                                    generatePacklists(); <!-- This is the method we are looking for if at least 1 bestellijn is selected -->
                                                                                                                                                    closeDialog();
                                                                                                                                                    break;
    
            ...
    
            default:                            closeDialog();
                                                break;
            }
        }
    
    private void generatePacklists() {
            log.debug("generatePacklists");
            nextAction = "GeneratePackListsAction";
        }
        ...
            @Override
        public String getNextAction() throws Exception {
            //Hier de volgende actie sturen
            return nextAction;
        }
    
        @Override
        public String getNextActionArgv() throws Exception {
            // Hier de argumenten voor de volgende actie sturen
            return argNextAction;
        }
    

    In the controller the action is redirected:

    <controller name="ConfDialog">
                ...
                <action name="GeneratePackListsAction" class="org.openxava.zokola.actions.GeneratePackListsAction"/>
                ...
        </controller>
    

    And finally GeneratePackListsAction.java (just the relevant code):

    public class GeneratePackListsAction extends JasperConcatReport4TabBaseAction {
        private Logger log = Logger.getLogger(getClass());
        private String jrxmlFileName = "reports/PacklistReport.jrxml";
        private ArrayList<JRDataSource> dataSources = new ArrayList<JRDataSource>();
        private ArrayList<String> jrXMLs = new ArrayList<String>();
    
        public void execute() throws Exception{
            Map[] resultKeys = getTab().getSelectedKeys(); <<<<<<!!!! THIS RESULTS ALWAYS IN ZERO LENGTH SINCE VERSION 7.X
                for(Map key : resultKeys) {
                    Map parameters = new HashMap();
                    Bestellingen bestelling = null;
                    try {
    ...
    

    The workaround I made is setting the selected keys in a sessionobject:
    In "ConfirmationDialog > createPacklist()" I added:

    SessionData.put("BestellingenSelectedKeyMap", getTab().getSelectedKeys());
    

    And in "GeneratePackListsAction > execute()" I added:

            Map[] resultKeys = (Map[])SessionData.get("BestellingenSelectedKeyMap");
            SessionData.remove("BestellingenSelectedKeyMap");
    

    This workaround works but getting the selected keys of a given module is so elementary that I'm afraid that on a lot of places in my code I'll have unexpected results. I'm afraid I'm missing something basic.
    Thanks in advance for any input!

    Kind regards,

    Bart.

     
  • Javier Paniza

    Javier Paniza - 2023-02-14

    Hi Bart:

    The workaround I made is setting the selected keys in a sessionobject

    Yes, that's the way. getSelectedKeys() is always refreshed from the marked checkbox in the list, in this moment a dialog is shown with no list, so the selected keys are reseted. Maybe we could improve it in some way. However, it should work in the same way in 6 and 7, perhaps some bug fixed for dialogs or lists has changed the behavior. This one, maybe?:

    • Fix: Original list condition lost when a dialog from list mode shows another list

    Help others in this forum as I help you.

     
    • Bart Devos

      Bart Devos - 2023-02-16

      Ok, thank you Javier. You could be right that in the passed a bug served my purpose... ;-)

       

Log in to post a comment.

MongoDB Logo MongoDB