{{announcement.body}}
{{announcement.title}}

Validating EDI Data in Java

DZone 's Guide to

Validating EDI Data in Java

This article reveals how the EDI validator notifies an application about validation events, and dives into EDI standards and implementations.

· Java Zone ·
Free Resource

One of the most common requirements when dealing with EDI data is the need to validate messages. Last time, we looked at reading EDI data in Java which included a basic example of validating an X12 acknowledgment message. In that article, a sample schema (a set of validation rules) was given along with some basic Java code using the StAEDI library to set up the validator. This time, let's dig a little deeper into how the validator notifies an application about validation events and also discuss the differences between EDI standards and implementations — and how to validate both.

EDI Event Streams with Errors

While reading through an EDI message using the EDIStreamReader in StAEDI, the various structures found in the data are reported to an application as events. When a schema has been provided and the EDI data does not match the schema in some way, the invalid segments and elements are also reported as events as they are found in the data.

Let's look at a contrived schema to understand how the validation rules are declared. In this example, the transaction structure declares that any EDI message conforming to the schema must begin with a segment SAA, contain up to five occurrences of a loop starting with segment S11, and finally, have a segment SZZ. Note that the schema does not mention the message header and trailer segments ( ST / SE  for X12 or  UNH / UNT  for EDIFACT). Those segments are handled separately by the parser and should not be in the message schema. 

For the purposes of demonstrating the structure of the transaction's schema, all segments are composed of the same two element types. The elements themselves have length requirements that any conforming transaction must meet.

XML
 




x


 
1
<schema xmlns="http://xlate.io/EDISchema/v3">
2
  <transaction>
3
    <sequence>
4
      <segment type="SAA" minOccurs="1" />
5
      <loop code="L0000" maxOccurs="5">
6
        <sequence>
7
          <segment type="S11" />
8
          <segment type="S12" maxOccurs="5" />
9
        </sequence>
10
      </loop>
11
      <segment type="SZZ" minOccurs="1" />
12
    </sequence>
13
  </transaction>
14
 
          
15
  <elementType name="E001" base="string" minLength="2" />
16
  <elementType name="E002" base="decimal" maxLength="9" />
17
 
          
18
  <segmentType name="S11">
19
    <sequence>
20
      <element type="E001" minOccurs="1" />
21
      <element type="E002" />
22
    </sequence>
23
  </segmentType>
24
 
          
25
  <segmentType name="S12">
26
    <sequence>
27
      <element type="E001" minOccurs="1" />
28
    </sequence>
29
  </segmentType>
30
 
          
31
  <segmentType name="SAA">
32
    <sequence>
33
      <element type="E001" minOccurs="1" />
34
    </sequence>
35
  </segmentType>
36
 
          
37
  <segmentType name="SZZ">
38
    <sequence>
39
      <element type="E001" minOccurs="1" />
40
    </sequence>
41
  </segmentType>
42
</schema>


A sample message using this schema might look like the following. This example shows multiple occurrences of the schema's L0000 loop (starting with segment  S11 ). The first occurrence contains two S12 segments whereas the second contains none — S12 segments are optional (minOccurs is 0 by default).

Plain Text
 




xxxxxxxxxx
1


 
1
SAA*11~
2
S11*X1*2.5~
3
S12*01~
4
S12*2~
5
S11*X2*5.25~
6
SZZ*99~


There is something wrong here, however. Did you notice that the second occurrence of S12 contains an element that is too short? The value  2 does not meet the schema's required minimum length of 2 characters. Now let's take a look at how a Java program would receive the events from this simple message. The following code snippet skips over the envelope segments and jumps straight to the segments from the example message.

Java
 




x


1
EDIInputFactory factory = EDIInputFactory.newFactory();
2
InputStream stream = new FileInputStream("my_edi_file.txt");
3
EDIStreamReader reader = factory.createEDIStreamReader(stream);
4
EDIStreamEvent event = reader.next(); // START_INTERCHANGE
5
 
          
6
// (...) Skipping forward to the start of the transation
7
 
          
8
if (event == EDIStreamEvent.START_TRANSACTION) {
9
  // When the START_TRANSACTION event is received the schema may be configured.
10
  SchemaFactory schemaFactory = SchemaFactory.newFactory();
11
  // my_edi_schema.xml contains the example schema shown earlier in this article
12
  InputStream fileStream = new FileInputStream("my_edi_schema.xml");
13
  Schema txSchema = schemaFactory.createSchema(fileStream);
14
  reader.setTransactionSchema(txSchema);
15
}
16
 
          
17
// (...) Skip past the transaction header segment
18
 
          
19
// Segment: SAA*11~
20
event = reader.next(); // START_SEGMENT
21
reader.getText(); // "SAA"
22
event = reader.next(); // ELEMENT_DATA
23
reader.getText(); // "11"
24
event = reader.next(); // END_SEGMENT
25
 
          
26
// Segment: S11*X1*2.5~
27
event = reader.next(); // START_LOOP
28
reader.getReferenceCode(); // "L0000"
29
 
          
30
event = reader.next(); // START_SEGMENT
31
reader.getText(); // "S11"
32
event = reader.next(); // ELEMENT_DATA
33
reader.getText(); // "X1"
34
event = reader.next(); // ELEMENT_DATA
35
reader.getText(); // "2.5"
36
event = reader.next(); // END_SEGMENT
37
 
          
38
// Segment: S12*01~
39
event = reader.next(); // START_SEGMENT
40
reader.getText(); // "S12"
41
event = reader.next(); // ELEMENT_DATA
42
reader.getText(); // "01"
43
event = reader.next(); // END_SEGMENT
44
 
          
45
// Segment: S12*2~
46
event = reader.next(); // START_SEGMENT
47
reader.getText(); // "S12"
48
event = reader.next(); // ELEMENT_DATA_ERROR
49
reader.getErrorType(); // DATA_ELEMENT_TOO_SHORT *****
50
event = reader.next(); // ELEMENT_DATA
51
reader.getText(); // "2"
52
event = reader.next(); // END_SEGMENT
53
 
          
54
event = reader.next(); // END_LOOP
55
 
          
56
// Segment: S11*X2*5.25~
57
event = reader.next(); // START_LOOP
58
reader.getReferenceCode(); // "L0000"
59
 
          
60
event = reader.next(); // START_SEGMENT
61
reader.getText(); // "S11"
62
event = reader.next(); // ELEMENT_DATA
63
reader.getText(); // "X2"
64
event = reader.next(); // ELEMENT_DATA
65
reader.getText(); // "5.25"
66
event = reader.next(); // END_SEGMENT
67
 
          
68
event = reader.next(); // END_LOOP
69
 
          
70
// (...) Remainder of events omitted


As can be seen in this example, the EDI stream is received by an application as a series of events. The events that are only available when a schema has been configured are those dealing with loop boundaries and errors. In this case, we can see that the S11 segments initiate a START_LOOP event and also that the data error that was noted earlier (where the segment S12*2~ contained an element shorter than the requirement) resulted in the ELEMENT_DATA_ERROR event coupled with the DATA_ELEMENT_TOO_SHORT error type.

Standards Versus Implementations

The schema XML above is an example of a standard schema. Standard schemas are the rules published by standards bodies such as ANSI (X12) or the UN (EDIFACT). In the example, the transaction element is used in the XML to identify the standard message structure. Additionally all of the "type" elements are used to identify the standard segment, composite element, and simple element structure and requirements.

Most EDI exchanges go beyond the standards, however. Business partners often define how the standard must be structured for their particular industry or use case. This is when an implementation schema becomes useful. Implementations allow for the further refinement of the rules and also allows for loops and segments to carry different data. Implementations of loops and segments may include some or all of the components defined by the standard, but must always adhere to the standard.

We can now extend the schema from the earlier example. Below, only the transaction and implementation elements are shown along with their sub-elements. All of the types used in the standard example above are implied (elementType and segmentType XML elements).

XML
 




x




1
<transaction>
2
  <sequence>
3
    <segment type="SAA" minOccurs="1"/>
4
    <loop code="L0000" maxOccurs="5">
5
      <sequence>
6
        <segment type="S11"/>
7
        <segment type="S12" maxOccurs="5"/>
8
      </sequence>
9
    </loop>
10
    <segment type="SZZ" minOccurs="1"/>
11
  </sequence>
12
</transaction>
13
 
          
14
<implementation>
15
  <sequence>
16
    <!-- Standard requires at least 1 SAA, implementation permits at most 1. -->
17
    <segment type="SAA" maxOccurs="1">
18
      <sequence>
19
        <element position="1">
20
          <enumeration>
21
            <!-- Implementation requires SAA01 to be 'ZZ'. -->
22
            <value>ZZ</value>
23
          </enumeration>
24
        </element>
25
      </sequence>
26
    </segment>
27
    
28
    <!-- Occurrence of standard loop L0000 identified as "0000A".
29
         The discriminator element (1.0, element 1, component N/A) 
30
         provides the values that differentiate 0000A from other
31
         loops of the same type.
32
     -->
33
    <loop type="L0000" code="0000A" discriminator="1.0">
34
      <sequence>
35
        <segment type="S11">
36
          <sequence>
37
            <element position="1">
38
              <enumeration>
39
                <!-- Implementation requires SAA01 to be 'X1'. -->
40
                <value>X1</value>
41
              </enumeration>
42
            </element>
43
            <!-- The second element is omitted, therefore not 
44
                 used by this implementation of the loop. -->
45
          </sequence>
46
        </segment>
47
        <segment type="S12" maxOccurs="2" />
48
      </sequence>
49
    </loop>
50
    
51
    <!-- Additional occurrence of standard loop L0000 identified 
52
         as "0000B". The position of the discriminator element 
53
         (1.0, element 1, component N/A) must be the same as other
54
         implementations of L0000.
55
     -->
56
    <loop type="L0000" code="0000B" discriminator="1.0">
57
      <sequence>
58
        <segment type="S11">
59
          <sequence>
60
            <element position="1">
61
              <enumeration>
62
                <value>QQ</value>
63
              </enumeration>
64
            </element>
65
            <!-- Second element used as-is from the standard SAA segment. -->
66
            <element position="2" />
67
          </sequence>
68
        </segment>
69
        <!-- Segment S12 is not used by loop 0000B -->
70
      </sequence>
71
    </loop>
72
    
73
    <!-- Segment SZZ is used as-is from the standard. -->
74
    <segment type="SZZ" />
75
  </sequence>
76
</implementation>


In this implementation example, we can see a several things.

  1. The implementation restricts the number of occurrences of the SAA segment to one.
  2. There are two "types" of the L0000 loop, 0000A and 0000B. Each type is identifier by the value of the first element of the first segment, S11. When element S1101 is X1, the rules for loop 0000A apply and when S1101 is QQ, the rules for loop 0000B apply. The value of the discriminator attribute on the loop indicates which element of the loop's first segment contains the enumerated values used to identify that instance of the standard loop.
  3. Note the differences between the two occurrences of the loop. In the "A" type, element S1102 is forbidden (not used) and the occurrences of segment S12 are limited to two (three fewer than allowed in the standard). In the "B" type, S1102 is allowed, but the S12 segment is omitted and therefore not allowed.

Conclusion

Validation of EDI data can be a complicated task — especially when developers need to check both the standard rules as well as the rules specific to a particular industry or trading partner. Using the validation features in the StAEDI Java library, this task becomes a little bit simpler.

Are you writing custom code to process EDI data in Java? Have you tried StAEDI and encountered an issue? Give your feedback in the comments, or open an issue on the StAEDI GitHub repository.

Topics:
edi ,edi developer ,edi software ,edi standards ,edia validation ,java ,tutorial ,validation

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}