Juan Ignacio Durante
Juan Ignacio Durante

Reputation: 107

Exception: Generating incomplete JSON

I have the following method which generates a json file with the given arguments, and if the file exists it reads it to get the data and then append the new info to it. Basically, I get this error either with our without having the json file already created.

public void cargarVentasDiaMesaJson(Mesas m, double total) {
    FileInputStream fI = null;
    JsonReader jRe = null;
    FileOutputStream f = null;
    JsonWriter jR = null;
    try {
        f = new FileOutputStream("C:\\archivos\\VentasDiaMesa.json");
        jR = Json.createWriter(f);
        JsonObjectBuilder obj = Json.createObjectBuilder();
        JsonArrayBuilder arrayB = Json.createArrayBuilder();
        File file = new File("C:\\archivos\\VentasDiaMesa.json");
        if(file.exists()) {
            fI = new FileInputStream("C:\\archivos\\VentasDiaMesa.json");
            jRe = Json.createReader(fI);
            JsonObject jsonR = jRe.readObject();
            JsonArray array = jsonR.getJsonArray("ventasDiaMesa");
            for(int i=0; i<array.size(); i++) {
                JsonObject vDiaMesa = array.getJsonObject(i);
                String fecha = vDiaMesa.getString("fecha");
                int numero = vDiaMesa.getInt("numero");
                double tot = Double.parseDouble(vDiaMesa.getString("total"));
                JsonObjectBuilder diaMesa = Json.createObjectBuilder();
                diaMesa.add("fecha", fecha);
                diaMesa.add("numero", numero);
                diaMesa.add("total", tot);
                JsonObject objLinea = diaMesa.build();
                arrayB.add(objLinea);
            }
        }
        JsonObjectBuilder diaMesa = Json.createObjectBuilder();
        Calendar fecha = Calendar.getInstance();
        String mes = (fecha.get(Calendar.MONTH)+1)<10?"0"+(fecha.get(Calendar.MONTH)+1):""+(fecha.get(Calendar.MONTH)+1);
        String dia = fecha.get(Calendar.DATE)<10?"0"+fecha.get(Calendar.DATE):""+fecha.get(Calendar.DATE);
        String date = "" + fecha.get(Calendar.YEAR) + mes + dia;
        diaMesa.add("fecha", date);
        String numero = (m.getNumero()<10)?"0"+m.getNumero():""+m.getNumero();
        diaMesa.add("numero", numero);
        String tot = Double.toString(total);
        while(tot.length() != 10) {
            tot = "0" + tot;
        }
        diaMesa.add("total", tot);
        JsonObject objLinea = diaMesa.build();
        arrayB.add(objLinea);
        JsonArray arr = arrayB.build();
        obj.add("ventasDiaMesa", arr);
        JsonObject obbbj = obj.build();
        jR.writeObject(obbbj);
    } catch (IOException e) {
        // TODO: handle exception
        e.printStackTrace();
    } finally {
        jR.close();
    }
}

And I get the following error message

Exception in thread "AWT-EventQueue-0" javax.json.stream.JsonGenerationException: Generating incomplete JSON
at org.glassfish.json.JsonGeneratorImpl.close(JsonGeneratorImpl.java:509)
at org.glassfish.json.JsonWriterImpl.close(JsonWriterImpl.java:150)
at Modelo.DAO.VentasDiaMesaJSON.cargarVentasDiaMesaJson(VentasDiaMesaJSON.java:77)
at Controlador.ControladorPedidos.totalMesa(ControladorPedidos.java:94)
at Controlador.ControladorPedidos.cerrarDia(ControladorPedidos.java:119)
at Vista.PedidosGUI$1.actionPerformed(PedidosGUI.java:50)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.AbstractButton.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(Unknown Source)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

I am creating 3 object builders which I then proceed to build, and finally write the main object before closing the file. I am not able to see the error here. Any ideas where it could be?

Thanks

Upvotes: 0

Views: 1073

Answers (1)

bsaverino
bsaverino

Reputation: 1285

I believe that you are reading and writing the same file at the same time. Also the inputstream is not closed when you happen to write to the file again. This could put the writer in a odd state. Could you please try with the following adjustments.

public void cargarVentasDiaMesaJson(Mesas m, double total) {
    String fileName = "C:\\archivos\\VentasDiaMesa.json";

    try {
        JsonObjectBuilder obj = Json.createObjectBuilder();
        JsonArrayBuilder arrayB = Json.createArrayBuilder();
        File file = new File(fileName);
        if (file.exists()) {
            // Try-with-resources: will auto-close JsonReader and inputStream
            //  >> close() of this stream was missing in original code
            try (JsonReader jRe = Json.createReader(new FileInputStream(file))) {
                JsonObject jsonR = jRe.readObject();
                JsonArray array = jsonR.getJsonArray("ventasDiaMesa");
                for (int i = 0; i < array.size(); i++) {
                    JsonObject vDiaMesa = array.getJsonObject(i);
                    String fecha = vDiaMesa.getString("fecha");
                    int numero = vDiaMesa.getInt("numero");
                    double tot = Double.parseDouble(vDiaMesa.getString("total"));
                    JsonObjectBuilder diaMesa = Json.createObjectBuilder();
                    diaMesa.add("fecha", fecha);
                    diaMesa.add("numero", numero);
                    diaMesa.add("total", tot);
                    JsonObject objLinea = diaMesa.build();
                    arrayB.add(objLinea);
                }
            }
        }
        JsonObjectBuilder diaMesa = Json.createObjectBuilder();
        Calendar fecha = Calendar.getInstance();
        String mes = (fecha.get(Calendar.MONTH) + 1) < 10 ? "0" + (fecha.get(Calendar.MONTH) + 1) : "" + (fecha.get(Calendar.MONTH) + 1);
        String dia = fecha.get(Calendar.DATE) < 10 ? "0" + fecha.get(Calendar.DATE) : "" + fecha.get(Calendar.DATE);
        String date = "" + fecha.get(Calendar.YEAR) + mes + dia;
        diaMesa.add("fecha", date);
        String numero = (m.getNumero() < 10) ? "0" + m.getNumero() : "" + m.getNumero();
        diaMesa.add("numero", numero);
        String tot = Double.toString(total);
        while (tot.length() != 10) {
            tot = "0" + tot;
        }
        diaMesa.add("total", tot);
        JsonObject objLinea = diaMesa.build();
        arrayB.add(objLinea);
        JsonArray arr = arrayB.build();
        obj.add("ventasDiaMesa", arr);
        JsonObject obbbj = obj.build();

        // (Re)Write object
        //   >> Opening of this stream was made too early in original code.
        JsonWriter jR;
        try {
            jR = Json.createWriter(new FileOutputStream(fileName));
            jR.writeObject(obbbj);
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            jR.close();
        }
    } catch (Exception e) {
        // TODO: handle exception
        e.printStackTrace();
    }
}

It would be really appreciated that you clean your code up before posting it. It is barely readable. I suggest at least to:

  • use correct variables naming by giving a human-readable name to your variables and in CamelCase. Try really avoid single and double-letter names.
  • create more methods
  • help your code breath
  • create less useless (one-shot) variables or references

For example:

public void cargarVentasDiaMesaJson(Mesas m, double total) {
    String fileName = "C:\\archivos\\VentasDiaMesa.json";

    try {
        JsonArrayBuilder updReadArrayB = Json.createArrayBuilder();

        File file = new File(fileName);
        if (file.exists()) {
            // Try-with-resources: will auto-close JsonReader and inputStream
            //  >> close() of this stream was missing in original code
            try (JsonReader jReader = Json.createReader(new FileInputStream(file))) {
                readPrepareObject(jReader, updReadArrayB);
            } catch (IOException ex) {
                // Cannot read file
                ex.printStackTrace();
            }

            JsonObject outJsonObj = rebuildObject(m, total, updReadArrayB, Json.createObjectBuilder());

            // (Re)Write object
            //   >> Opening of this stream was made too early in original code.
            JsonWriter jWriter;
            try {
                jWriter = Json.createWriter(new FileOutputStream(fileName));
                jWriter.writeObject(outJsonObj);
            } catch (IOException ex) {
                ex.printStackTrace();
            } finally {
                jWriter.close();
            }
        }
    } catch (Exception e) {
        // TODO: handle exception
        e.printStackTrace();
    }
}

private void readPrepareObject(final JsonReader jRe, JsonArrayBuilder arrayB) throws NumberFormatException {
    JsonObject jsonR = jRe.readObject();
    JsonArray array = jsonR.getJsonArray("ventasDiaMesa");

    for (int i = 0; i < array.size(); i++) {
        JsonObject vDiaMesa = array.getJsonObject(i);
        String fecha = vDiaMesa.getString("fecha");
        int numero = vDiaMesa.getInt("numero");
        double tot = Double.parseDouble(vDiaMesa.getString("total"));
        JsonObjectBuilder diaMesa = Json.createObjectBuilder();
        diaMesa.add("fecha", fecha);
        diaMesa.add("numero", numero);
        diaMesa.add("total", tot);

        arrayB.add(diaMesa.build());
    }
}

private JsonObject rebuildObject(Mesas m, double total, JsonArrayBuilder arrayB, JsonObjectBuilder obj) {
    JsonObjectBuilder diaMesa = Json.createObjectBuilder();

    Calendar fecha = Calendar.getInstance();
    String mes = (fecha.get(Calendar.MONTH) + 1) < 10 ? "0" + (fecha.get(Calendar.MONTH) + 1) : "" + (fecha.get(Calendar.MONTH) + 1);
    String dia = fecha.get(Calendar.DATE) < 10 ? "0" + fecha.get(Calendar.DATE) : "" + fecha.get(Calendar.DATE);
    String date = "" + fecha.get(Calendar.YEAR) + mes + dia;
    diaMesa.add("fecha", date);
    String numero = (m.getNumero() < 10) ? "0" + m.getNumero() : "" + m.getNumero();
    diaMesa.add("numero", numero);
    String tot = Double.toString(total);
    while (tot.length() != 10) {
        tot = "0" + tot;
    }
    diaMesa.add("total", tot);
    JsonObject objLinea = diaMesa.build();
    arrayB.add(objLinea);
    JsonArray arr = arrayB.build();
    obj.add("ventasDiaMesa", arr);

    return obj.build();
}

Please note I didn't check (and barely modified) your Json manipulation instructions.

And last but not least: do not execute long, blocking or IO-related code in the AWT event thread. You should use an ExecutorService to execute most of your logic outside of the AWT event queue.

Upvotes: 2

Related Questions