Usage

X12Translator interface is the entry point for reading and writing X12 documents. Instantiating DefaultX12Translator will give you a reference to X12Translator:

io.portx.x12.translator.api.X12Translator x12Translator = new io.portx.x12.translator.impl.DefaultX12Translator();

DefaultX12Translator is a thread-safe implementation of X12Translator which means that different threads of execution can concurrently invoke methods on an instance of DefaultX12Translator without compromising its state. We strongly recommend that DefaultX12Translator is instantiated only once and used throughout your application in order to leverage its caching features.

Reading an interchange

The translator offers two ways to read an X12 envelope:

Small document

Can be read as simple string

Large document

Can be read from a stream in chunks, which facilitates keeping the Java process’s memory consumption manageable. X12Translator#read(…​) is called to obtain an X12EnvelopeIterator object and iterate over an envelope’s transaction sets:

io.portx.x12.translator.api.X12Translator x12Translator = new io.portx.x12.translator.impl.DefaultX12Translator();
io.portx.x12.translator.reader.X12EnvelopeIterator x12EnvelopeIterator = x12Translator.read(interchange);
while (x12EnvelopeIterator.hasNext()) {
  io.portx.x12.translator.api.X12Envelope x12Envelope = x12EnvelopeIterator.next();
  Map<String, Object> map = x12Envelope.getAsMap();
  ...
}

The Java snippet above is a standard template for reading an interchange. x12EnvelopeIterator.next() processes the next batch of unprocessed transaction sets and returns an X12Envelope which is an in-memory model of the processed batch. The batch size is unbounded by default though it can be controlled by the maxTransactionSets parameter set when calling DefaultX12Translator's constructor. A good strategy to keep the memory footprint to a minimum is to process one transaction set a time, as follows:

io.portx.x12.translator.api.X12Translator x12Translator = new io.portx.x12.translator.impl.DefaultX12Translator(1);
Neither X12EnvelopeIterator nor X12Envelope are thread-safe. Access from different threads should be synchronized.

A digestible form of the transaction sets can be obtained from X12Envelope as a java.util.Map or as JSON with X12Envelope#getAsMap() and X12Envelope#getAsJson(), respectively.

getAsMap() is useful for scenarios in which you want to interact with the in-memory model programmatically.

getAsJson() is useful when you want to transmit the transaction sets to a downstream remote process.

Functional Group Reports

X12Envelope reports provide an overview of the processed transaction sets as well any errors encountered during processing. For instance, you can determine the idnenty of the sender as follows:

System.out.println(x12Envelope.getFunctionalGroupReports().get(0).getApplicationSenderCode());

Similarly, you may be interested as to whether a functional group was processed without errors:

System.out.println(x12Envelope.getFunctionalGroupReports().get(0).getStatus().toString());

Consult the insert API link documentation for more information about reports.

Generating Acknowledgments

A common requirement after processing an inbound interchange is to acknowledge receipt to the sender. An acknowledgement like the FA 997 can be constructed from a JSON document or a java.util.Map object; however, X12EnvelopeIterator has a convenience method named generateAck() that does this programmatically. When called, the method returns all supported acknowledgments for the transaction sets processed at the time of the method call. Alternatively, X12Envelope#generateAck() returns acknowledgments for the encapsulated transaction sets.

Writing an interchange

X12Translator#write(…​) transforms a JSON document into its X12 counterpart and writes it to a java.io.OutputStream or a java.nio.channels.WritableByteChannel object.

At a minimum, the X12Translator#write(…​) method accepts two arguments:

  1. A reference to a JSON document that adheres to a valid interchange structure. The document can be a string reference, but you should choose an appropriate java.io.Reader stream implementation for large streaming documents.

  2. The destination to which the document will be written. As aforementioned, this can be either an instance of type OutputStream or a WritableByteChannel.

The following snippet shows a JSON representation of a generated acknowledgment transformed to X12 with the write(…​) method:

io.portx.x12.translator.api.X12Translator x12Translator = new io.portx.x12.translator.impl.DefaultX12Translator();
io.portx.x12.translator.reader.X12EnvelopeIterator x12EnvelopeIterator = x12Translator.read(interchange);
while (x12EnvelopeIterator.hasNext()) {
  io.portx.x12.translator.api.X12Envelope x12Envelope = x12EnvelopeIterator.next();
  io.portx.x12.translator.api.X12Envelope ackX12Envelope = x12Envelope.generateAck();

  java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
  x12Translator.write(ackX12Envelope.getAsJson(), outputStream);

  System.out.println(new String(outputStream.toByteArray()));
}

Similar to X12Translator#read(…​), the write method processes a JSON document in increments with the maxTransactionSets knob used to control the increment size.