Writing xml to Azure blob storage from spring boot app using Stax writer

146 Views Asked by At

I wanted read a xml file from azure blob storage and write to another xml file to azure blob storage. I am using spring cloud to integrate with azure blob storage. I tried writing with JAXB as follows which works well

private void launchJaxb() {
        AtomicInteger counter = new AtomicInteger(0);
        List<Verify> verifications = new ArrayList<>();
        Resource readResource = resourceLoader.getResource(String.format(BLOB_RESOURCE_PATTERN, containerName, "9898.xml"));
        Resource writeResource = resourceLoader.getResource(String.format(BLOB_RESOURCE_PATTERN, containerName, "9898-out.xml"));

        try {
            XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
            XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(readResource.getInputStream());
            JAXBContext readJc = JAXBContext.newInstance(Verify.class);
            Unmarshaller unmarshaller = readJc.createUnmarshaller();

            BufferedOutputStream bos = new BufferedOutputStream(((WritableResource) writeResource).getOutputStream());
            JAXBContext writeJc = JAXBContext.newInstance(Verify.class);
            Marshaller marshaller = writeJc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

            var rootElements = createRootElements();

            while (xmlEventReader.hasNext()) {
                if (xmlEventReader.peek().isStartElement() && xmlEventReader.peek().asStartElement().getName().getLocalPart().equals("account")) {
                    Verification verification = (Verification) unmarshaller.unmarshal(xmlEventReader);
                    counter.incrementAndGet();
                    verifications.add(verification);
                    if (verifications.size() == 100) {
                        var accountValidationResponses = process.verify(verifications);
                        for (Report report : accountValidationResponses) {
                            rootElements.getReport().add(report);
                        }
                        verifications = new ArrayList<>();
                    }

                }
                xmlEventReader.nextEvent();
            }
            rootElements.setNumberOfEvents(BigInteger.valueOf(counter.get()));
            marshaller.marshal(rootElements, bos);
            bos.close();
            log.info("Total processed verifications {}", counter.get());
        } catch (IOException | XMLStreamException | JAXBException e) {
            throw new RuntimeException(e);
        }
    }

Using above code i was able to write xml file blob storage. But i wanted to use Stax as i file i writing might end up being very huge. I tried the following.

private void launchXmlStreamWriter() {
        AtomicInteger counter = new AtomicInteger(0);
        List< Verify > verifications = new ArrayList<>();
        Resource readResource = resourceLoader.getResource(String.format(BLOB_RESOURCE_PATTERN, containerName, "9898.xml"));
        Resource writeResource = resourceLoader.getResource(String.format(BLOB_RESOURCE_PATTERN, containerName, "9898-out.xml"));

        try {
            XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
            XMLEventReader xmlEventReader = xmlInputFactory.createXMLEventReader(readResource.getInputStream());
            JAXBContext readJc = JAXBContext.newInstance(Verify.class);
            Unmarshaller unmarshaller = readJc.createUnmarshaller();

            OutputStream outputStream = ((WritableResource) writeResource).getOutputStream();
            XMLStreamWriter xmlOut = XMLOutputFactory.newFactory().createXMLStreamWriter(outputStream);
            xmlOut.writeStartDocument();
            xmlOut.writeStartElement("rootElement");

            JAXBContext context = JAXBContext.newInstance(Verify.class);
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);

            while (xmlEventReader.hasNext()) {
                if (xmlEventReader.peek().isStartElement() && xmlEventReader.peek().asStartElement().getName().getLocalPart().equals("verify")) {
                    Verification verification = (Verification) unmarshaller.unmarshal(xmlEventReader);
                    counter.incrementAndGet();
                    verifications.add(verification);
                    if (verifications.size() == 100) {
                        var accountValidationResponses = process.verify(verifications);
                        for (Report report : accountValidationResponses) {
                            JAXBElement<Report> element = new JAXBElement<>(QName.valueOf(""), Report.class, report);
                            marshaller.marshal(element, xmlOut);
                        }
                        verifications = new ArrayList<>();
                    }

                }
                xmlEventReader.nextEvent();
            }
            xmlOut.close();
            log.info("Total processed verifications {}", counter.get());
        } catch (IOException | XMLStreamException | JAXBException e) {
            throw new RuntimeException(e);
        }
    }

Above code runs through all the elements in xml file but doesnt create any output file.If i change the writeResource to FileSystemResource then a file is created. What am i missing to generate file on azure storage account using Stax?

0

There are 0 best solutions below