Programming Sabre with Java, C#, and XML

Starting in 2001 and continuing for most of this decade, I have had the unusual experience of programming very similar applications in both Java, J2EE (Enterprise JavaBeans), and .Net (C#). These applications were middle-tiers for the travel industry, mediating between Web-based front-ends and the Sabre Global Distribution System, at more than 40 years, the world’s oldest production system. I have learned many lessons and hope to help others developing such systems. (If, after reading, you contacted me for consulting, I wouldn’t be offended, either!)

The first thing to know about programming Sabre is that its a fundamentally stateful system, and you will be forced to deal with that, either by compromising the scalability of your system or by encapsulating multiple Sabre calls within a single middle-tier service. You cannot, for instance, create a non-trivial Passenger Name Record (PNR) with a single call. Sabre’s XML Toolkit does do some behind-the-scenes call sequences, but these are almost certainly insufficient to cover real-world business rules. While the XML Toolkit is definitely superior to “screen-scraping,” DIY raw commands, and Structured Data Source (Sabre SDS), you almost certainly will be frequently using the “pass through” command (val) to interact directly with Sabre. Plan on it!

The next thing to know is that your timeframe is not Sabre’s. Documentation and effective developer support are problems. You will often be dealing with out-of-date documentation and you may easily find yourself being told you’re the first to raise some seemingly obvious issue. In my opinion, this actually argues for the use of the “lower-level” Sabre toolkits, as opposed to the more expensive ones. There are mistakes in Sabre’s implementations of their own toolkits and these are often harder to workaround than mistakes in your own implementation. For instance, the last time I used Sabre’s EJB-based solution, there was a bug that threw an error every time it passivated and it was not difficult to track it down to their attempt to persist a non-serializable field. Pretty obvious problem, but it took us days to talk to the programmer, who basically said “Yeah, it’s a problem. We aren’t going to patch it, but we’ll fix it eventually.”

Finally, my experience has been that the challenge in developing Sabre-based solutions is understanding the business rules and processes of the travel agents. There are a great many ways to do the same thing in Sabre, and each travel agency or supplier typically has a complete back-office solution based on one particular way that has evolved over the years. Working with these solutions and moving forward to transform them into a scalable Web-based solution can be challenging, as there are usually relatively few agents / representatives who truly know the complete solution, their time is valuable, and, as a programmer, you can’t quite do the same thing as a person at a screen. This means that it is very important to:

Nail down the formats you’ll be using and make sure your TAs are configured properly for the formats and for the login technique of your toolkit

Nail down PNR formatting, especially if the PNR is processed by a back-office system

Nail down issues relating to taxes and fees. Be aware that calculating surcharges, especially on non-published fares, can easily require several Sabre queries

Use jUnit, nUnit, or other unit-testing framework to continuously test the system as you develop it (I cannot stress this enough)

Design a robust parsing solution. Use good object-oriented design to create objects from the responses; do not use ad hoc text processing techniques

Do not expect logically-related Sabre responses to share data structures. For instance, the response from the standard availability format and the response from the journey record format differ rather dramatically. Don’t try to shoehorn the two response data structures into a single object: search for the shared data (for instance, seats available, service class, date, flight number, etc.) and move them into an interface (say, IAvailability) and use the two specific data structures as implementations of that interface (JourneyRecordResponse and StandardAvailabilityResponse)

Sabre data structures, even when in XML, are flat and suffer from procedural cohesion. That means that you’ll get a series of say, seven booking class codes and then a series of numbers representing how many seats are available in the corresponding booking class index. It can become quite complex to “stitch together” a single consistent object when dealing with, say, bargain hunter and journey record requests. Do not expect to use a “magic bullet” serialization mechanism to transform data into objects and back

Establish a consistent and configurable exception-handling mechanism. Exceptions and error messages in Sabre are very inconsistent: you must consider failure modes early

Avoid using the Nortel VPN boxes in production. In my experience, leased-line TAs are much more reliable at that 99.9+% uptime challenge. (The Nortel boxes are fine for development, although they can be a pain to configure and make a lot of noise.)

If you’re going to scale, you must do your own TA pool management. Sabre’s claims about managing TAs in the toolkits are overstated: they manage sign-in, but they do not manage pooling signed-in TAs between stateless queries (like availability) and stateful multi-queries (like PNR manipulation). Even if your public API is stateless (as it should be), behind the scenes, you are going to deal with stateful TAs. It’s not hard to implement a TA pool, but take the time to do it right, with support for monitoring the pool and tracing traffic on individual TAs

Use Sabre’s terminology as often as possible and be pragmatic about OO purity. For instance, it is literally an OO cliche for their to a Flight object would correspond with┬áthat big shiny plane at the gate. The Flight object would have data representing the carrier, flight number, and date, and this Flight object would have some amount of ServiceClass objects, which in turn would have BookingClasses, and these would have Availability. Except that this is not how Sabre views a flight! To Sabre, a “flight” is just the carrier and flight number, and does not include the date. It’s counter-productive to create your own “correct” object model, unless your business rules are so complex that they essentially cannot be dealt with using Sabre’s data model

Don’t deal with groups of more than 7. It sounds like a joke, but Sabre stores availability in 3 bits! That’s how old the system it!

Avoid “bargain hunting” beyond Sabre’s capabilities. Going beyond Sabre’s capabilities introduces all sorts of combinatorial challenges. These may be interesting problems and, if your customer understands the time and cost associated, can be satisfying to solve and optimize. But if you’re going to tackle such a thing, it better be a big jump from what Sabre can offer with a Bargain Hunter format, because it’s going to take a lot of effort

Are you considering Sabre development? Contact me first (lobrien@kninvisibleowing.net)– I guarantee that I can save you time, money, and considerable grief!

div>