0

I have a Java method which creates the customer information in JSON format using the streams approach and returns as and when it is created in an asynchronous approach using the Multi from SmallRye Mutiny.

I would like to add the wrapper to this JSON which is being created using the Jackson JsonGenerator. I don't understand how to add the same. I believe I need to make use of the Multi.createBy().concatenating() to achieve this.

The following is the method that I have:

public static Multi<Customer> generateCustomer(final Input input) {
    try {
        return Multi.createFrom().publisher(new CustomerPublisher(input));
    } catch (Exception e) {
        throw new NewException("Exception occurred during the generation of Customer : " + e);
    }
}

The above method currently returns something like this asynchronously:

[
  {
    "name":"Batman",
    "age":45,
    "city":"gotham"
  },
  {
    "name":"superman",
    "age":50,
    "city":"moon"
  }
]

I would like to add a wrapper to this JSON and create something like this:

{
  "isA": "customerDocument",
  "createdOn": "2022-10-10T12:29:43",
  "customerBody": {
    "customerList": [
      {
        "name": "Batman",
        "age": 45,
        "city": "gotham"
      },
      {
        "name": "superman",
        "age": 50,
        "city": "moon"
      }
    ]
  }
}

So I have added a method which does this and I would like to call the same, but I am unable to append the same to my return Multi.createFrom().publisher

public class CustomerGenerator {

    private ByteArrayOutputStream jsonOutput;
    private JsonGenerator jsonGenerator;

    private CustomerGenerator() {
        try {
            jsonOutput = new ByteArrayOutputStream();
            jsonGenerator = new JsonFactory().createGenerator(jsonOutput).useDefaultPrettyPrinter();
        } catch (IOException ex) {
            throw new TestDataGeneratorException("Exception occurred during the generation of customer document : " + ex);
        }
    }

    public static Multi < Customer > generateCustomer(final Input input) {
        CustomerGenerator customerGenerator = new CustomerGenerator();
        customerGenerator.wrapperStart();
        try {
            return Multi.createFrom().publisher(new CustomerPublisher(input));
        } catch (Exception e) {
            throw new NewException("Exception occurred during the generation of Customer : " + e);
        } finally {
            System.out.println("ALL DONE");
            customerGenerator.wrapperEnd();
        }
    }

    public void wrapperStart() {
        try {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField("type", "customerDocument");
            jsonGenerator.writeStringField("creationDate", Instant.now().toString());
            jsonGenerator.writeFieldName("customerBody");
            jsonGenerator.writeStartObject();
            jsonGenerator.writeFieldName("customerList");
        } catch (IOException ex) {
            throw new TestDataGeneratorException("Exception occurred during customer document wrapper creation : " + ex);
        }
    }

    public void wrapperEnd() {
        try {
            jsonGenerator.writeEndObject(); // End body
            jsonGenerator.writeEndObject(); // End whole json file
        } catch (IOException ex) {
            throw new TestDataGeneratorException("Exception occurred during customer document wrapper creation : " + ex);
        } finally {
            try {
                jsonGenerator.close();
                System.out.println("JSON DOCUMENT STRING : " + jsonOutput.toString());
            } catch (Exception e) {
                // do nothing
            }
        }
    }

}
BATMAN_2008
  • 2,788
  • 3
  • 31
  • 98
  • I had created a `jsongenerator` that creates the wrapper for your first json (not using mutiny) , this could help you ? – dariosicily Oct 22 '22 at 17:30
  • @dariosicily Thanks a lot for your response but I did not understand your response completely. Do you mean you have created JSON using the `JsonGenerator` which you would like to provide? I am already creating the wrapper using the `JsonGenerator` and provided the same using the question. All I need to do is append that JSON to the mutiny which is returning the response asynchronously. I am unable to do it. – BATMAN_2008 Oct 22 '22 at 20:30

1 Answers1

0

Your approach wouldn't make as you are wrapping random input that goes out of the CustomGenerator control.

Since you are able to generate the final output only when all emitted Customer object are emitted, and supposing you would like to retain a object oriented approach (i.e. not shifting to emitting JSON tokens), you should collect the emitted customers then wrap the collected items into your final JSON output:

Uni<byte[]> result = Multi.createFrom().publisher(new CustomerPublisher(input))
    .collect()
    .asList()
    .map(customers -> {
        ByteArrayOutputStream jsonOutput = new ByteArrayOutputStream();
        JsonGenerator jsonGenerator = new JsonFactory().createGenerator(jsonOutput).useDefaultPrettyPrinter();
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("type", "customerDocument");
        jsonGenerator.writeStringField("creationDate", Instant.now().toString());
        jsonGenerator.writeFieldName("customerBody");
        jsonGenerator.writeStartObject();
        jsonGenerator.writeArrayFieldStart("customerList");
        customers.forEach(customer -> jsonGenerator.writeObject(customer));
        jsonGenerator.writeEndArray();
        jsonGenerator.writeEndObject();
        jsonGenerator.writeEndObject();
        jsonGnenerator.close();
        return jsonOutput.toByteArray();
    });
tmarwen
  • 15,750
  • 5
  • 43
  • 62