Travel Bookings Example
Use Case
The UVW
Travel Agency has a web site where customers can book any combination
of air travel, hotel accommodation and car rental. The web interface
allows the customer to browse flights, hotels and rental agencies,
and to make their selection and pay online with a credit card, which
is then approved by a Web Service invocation to a third-party agency.
After credit card approval has been granted, the web application
submits the booking details to a workflow management system, which
attempts to make the requested bookings. If a booking attempt fails,
any successful bookings must be cancelled.
Interfaces
Workflow Invocation Interface
travel(INOUT
Bookings customerBookings)
Java Interfaces
package com.uvw.travel;
public interface Address extends java.io.Serializable {
String getAddress1();
String getAddress2();
String getState();
String getPostCode();
String getCountry();
}
public interface Bookings extends java.io.Serializable {
interface Booking extends Serializable {
int ERROR = -4;
int CARD_DECLINED = -3;
int UNAVAILABLE = -2;
int CANCELLED = -1;
int PENDING = 0;
int SUCCESS = 1;
int getStatus();
void setStatus(int status);
String getCreditCardAuthorizationCode();
void setCreditCardAuthorizationCode(String code);
Person[] getPeople();
Customer getCustomer();
CreditCard getCreditCard();
}
interface FlightBooking extends Booking {
Flight[] getFlights();
}
interface HotelBooking extends Booking {
String getHotelName();
Address getHotelAddress();
Date getCheckinDate();
Date getCheckoutDate();
}
interface RentalCarBooking extends Booking {
String SMALL = "SMALL";
String MEDIUM = "MEDIUM";
String LARGE = "LARGE";
String getRentalAgency();
String getCarClass();
Date getPickupDate();
Date getDropoffDate();
}
Customer getCustomer();
CreditCard getCreditCard();
FlightBooking createFlightBooking(Person[] people, Flight[] flights);
HotelBooking createHotelBooking(Person[] people, String hotelName,
Address hotelAddress, Date checkinDate, Date checkoutDate);
RentalCarBooking createRentalCarBooking(Person[] people,
String rentalAgency, String carClass, Date pickupDate,
Date dropoffDate);
FlightBooking getFlightBooking();
HotelBooking getHotelBooking();
RentalCarBooking getRentalCarBooking();
}
public interface CreditCard extends java.io.Serializable {
String AMEX = "AMEX";
String MC = "MASTERCARD";
String VISA = "VISA";
Name getCardHolder();
String getCardType();
String getCardNumber();
Date getExpiryDate();
int getSecurityDigits();
}
public interface Customer extends Person {
String getAccountNumber();
}
public interface Flight extends java.io.Serializable {
String getFlightNumber();
String getFromAirportCode();
String getToAirportCode();
Date getDepartureTime();
Date getArrivalTime();
}
public interface Name extends java.io.Serializable {
String getFirstName();
Character getMiddleInitial();
String getLastName();
String getFullName();
}
public interface Person extends java.io.Serializable {
Name getName();
Address getAddress();
}
The
workflow process makes and if necessary cancels the various bookings
by invoking operations from the following service interface:
package com.uvw.travel;
public interface BookingService {
void placeBooking(Bookings.Booking booking) throws BookingException;
void cancelBooking(Bookings.Booking booking) throws BookingException;
}
Hints
-
Use
<xpdl:TypeDeclaration>
with
<xpdl:ExternalReference>
to refer to
the Java interfaces. Assume that the workflow engine will interpret
a URI scheme of java:
as the
prefix to a fully qualified Java class or interface name. For
example, the Bookings
<xpdl:TypeDeclaration>
would be
defined using an <xpdl:ExternalReference>
with a
location attribute of java:com.uvw.travel.Bookings
.
-
Declare
an
<xpdl:Application>
for each
of the operations in the BookingService
interface, making both parameters of type IN
.
-
Make
the bookings in parallel, but remember that any combination of
bookings can be made. Provide paths that conditionally bypass each
of the booking types, to ensure that the parallel threads can join
up again.
-
Use
JavaScript (
application/javascript
) to access the booking
fields.
Questions
- Why
is it necessary to use
IN
parameters? XPDL requires pass-by-value semantics for such
parameters, but this is impractical when an expression yields a
non-primitive type – why? OBE uses pass-by-reference for complex
parameter values.
- What
would happen if you tried to use
INOUT
to force XPDL copy-restore style semantics?
Solution
Process
Model Description
- The workflow is triggered by the
TravelBookingReceived
event (defined in
$OBE_HOME/examples/config/BasicApplicationEvent.xml
). Notice the
<xpdl:ExtendedAttribute name="obe.Event">
element attached to the <WorkflowProcess>
below:
see how it initializes the mandatory
1 custBookings
process attribute from the event by specifying it as an OUT
parameter of the event.
- Route Activity
a1
serves to initiate the appropriate
bookings via transitions (t1, t3, t4
) bearing guard
conditions that only fire if the Bookings
object contains a
Booking
of the appropriate type.
- The 'Book Flight' activity is activated by transition
t1
if a FlightBooking
has been requested. The
activity invokes the placeBooking()
procedure,
passing the custBookings.flightBooking
object.
- The 'Book Hotel' activity is activated by transition
t3
if a HotelBooking
has been requested. The activity
invokes the placeBookin
g()
procedure,
passing the custBookings.hotelBooking
object.
- The 'Book Rental Car' activity is activated by transition
t4
if a RentalCarBooking
has been requested. The
activity invokes the placeBookin
g()
procedure, passing the custBookings.rentalCarBooking
object.
- Transitions (
t27, t28, t29
) respectively bear the
inverse
guard conditions and provide alternative workflow paths in the 'booking
type not requested' cases.
- Route activity
a5
has an AND-join that is satisfied only
once all inbound transitions (t33, t34, t35
) have fired.
This is the reason why it was necessary to provide the aforementioned
alternative paths - to ensure that activity a5
starts
regardless of which booking types have been requested.
- Transition
t15
linking activity a5
to activity
a6
only fires if all requested booking types were made
successfully.
- If any booking failed, the
OTHERWISE
transition
t16
fires instead, activating the appropriate compensating transactions in
activities 'Cancel Flight', 'Cancel Hotel' and 'Cancel Rental Car', each
of which calls the cancelBooking()
procedure. Note that
each of these compensating activities also has a bypass transition (
t18, t19, t20
) with the inverse conditions, to ensure that
transitions (t24, t25, t26)
always fire regardless of which
bookings had to be cancelled.
- Route activity
a6
has an XOR join that is fired by either
transition t15
(success path) or t17
(failure
path). It auto-completes immediately thereby resulting in the completion
of the workflow process.
XPDL Process Model
<?xml version="1.0" encoding="UTF-8"?>
<Package Id="travel-booking" Name="UVW Travel Agency" xmlns="http://www.wfmc.org/2002/XPDL1.0"
xmlns:xpdl="http://www.wfmc.org/2002/XPDL1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.wfmc.org/2002/XPDL1.0 http://wfmc.org/standards/docs/TC-1025_schema_10_xpdl.xsd">
<PackageHeader>
<XPDLVersion>1.0</XPDLVersion>
<Vendor>Open Business Engine</Vendor>
<Created>2004-08-08 22:32:06</Created>
</PackageHeader>
<RedefinableHeader PublicationStatus="UNDER_TEST"/>
<ConformanceClass GraphConformance="NON_BLOCKED"/>
<Script Type="application/javascript" Version="1.0"/>
<TypeDeclarations>
<TypeDeclaration Id="Customer">
<ExternalReference location="java:com.uvw.travel.Customer"/>
</TypeDeclaration>
<TypeDeclaration Id="Address">
<ExternalReference location="java:com.uvw.travel.Address"/>
<Description>A generic address object.</Description>
</TypeDeclaration>
<TypeDeclaration Id="CreditCard" Name="Credit Card">
<ExternalReference location="java:com.uvw.travel.CreditCard"/>
</TypeDeclaration>
<TypeDeclaration Id="Flight">
<ExternalReference location="java:com.uvw.travel.Flight"/>
</TypeDeclaration>
<TypeDeclaration Id="Bookings" Name="Customer Bookings">
<ExternalReference location="java:com.uvw.travel.Bookings"/>
<Description>Bookings to make for a customer.</Description>
</TypeDeclaration>
<TypeDeclaration Id="Booking">
<ExternalReference location="java:com.uvw.travel.Bookings$Booking"/>
</TypeDeclaration>
<TypeDeclaration Id="FlightBooking" Name="Flight Booking">
<ExternalReference location="java:com.uvw.travel.Bookings$FlightBooking"/>
</TypeDeclaration>
<TypeDeclaration Id="HotelBooking" Name="Hotel Booking">
<ExternalReference location="java:com.uvw.travel.Bookings$HotelBooking"/>
</TypeDeclaration>
<TypeDeclaration Id="RentalCarBooking" Name="Rental Car Booking">
<ExternalReference location="java:com.uvw.travel.Bookings$RentalCarBooking"/>
</TypeDeclaration>
</TypeDeclarations>
<WorkflowProcesses>
<WorkflowProcess AccessLevel="PUBLIC" Id="travel-booking" Name="Travel Booking">
<ProcessHeader DurationUnit="D">
<Created>2004-08-08 22:33:02</Created>
<Description>Coordinates multiple travel-related bookings.</Description>
</ProcessHeader>
<RedefinableHeader PublicationStatus="UNDER_TEST">
<Author>Adrian Price</Author>
</RedefinableHeader>
<FormalParameters>
<FormalParameter Id="custBookings" Mode="IN">
<DataType>
<DeclaredType Id="Bookings"/>
</DataType>
<Description>These are the bookings the customer wishes to make.</Description>
</FormalParameter>
</FormalParameters>
<Applications>
<Application Id="createBooking" Name="Create a booking">
<Description>Creates a booking.</Description>
<FormalParameters>
<FormalParameter Id="creditCard" Mode="IN">
<DataType>
<DeclaredType Id="CreditCard"/>
</DataType>
<Description>The credit card to charge for the booking.</Description>
</FormalParameter>
<FormalParameter Id="booking" Mode="IN">
<DataType>
<DeclaredType Id="Booking"/>
</DataType>
<Description>The booking to make.</Description>
</FormalParameter>
</FormalParameters>
</Application>
<Application Id="cancelBooking" Name="Cancel a Booking">
<Description>Cancels a previous booking.</Description>
<FormalParameters>
<FormalParameter Id="creditCard" Mode="IN">
<DataType>
<DeclaredType Id="CreditCard"/>
</DataType>
<Description>The credit card to refund.</Description>
</FormalParameter>
<FormalParameter Id="booking" Mode="IN">
<DataType>
<DeclaredType Id="Booking"/>
</DataType>
<Description>The booking to cancel.</Description>
</FormalParameter>
</FormalParameters>
</Application>
</Applications>
<Activities>
<Activity Id="a1">
<Route/>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Split Type="AND">
<TransitionRefs>
<TransitionRef Id="t3"/>
<TransitionRef Id="t29"/>
<TransitionRef Id="t28"/>
<TransitionRef Id="t27"/>
<TransitionRef Id="t4"/>
<TransitionRef Id="t1"/>
</TransitionRefs>
</Split>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="140"/>
<ExtendedAttribute Name="YOffset" Value="130"/>
</ExtendedAttributes>
</Activity>
<Activity Id="book-flight" Name="Book Flight">
<Implementation>
<Tool Id="createBooking" Type="PROCEDURE">
<ActualParameters>
<ActualParameter>custBookings.creditCard</ActualParameter>
<ActualParameter>custBookings.bookings.flightBooking</ActualParameter>
</ActualParameters>
</Tool>
</Implementation>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="280"/>
<ExtendedAttribute Name="YOffset" Value="10"/>
</ExtendedAttributes>
</Activity>
<Activity Id="book-hotel" Name="Book Hotel">
<Implementation>
<Tool Id="createBooking" Type="PROCEDURE">
<ActualParameters>
<ActualParameter>custBookings.creditCard</ActualParameter>
<ActualParameter>custBookings.bookings.hotelBooking</ActualParameter>
</ActualParameters>
</Tool>
</Implementation>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="280"/>
<ExtendedAttribute Name="YOffset" Value="130"/>
</ExtendedAttributes>
</Activity>
<Activity Id="book-rental-car" Name="Book Rental Car">
<Implementation>
<Tool Id="createBooking" Type="PROCEDURE">
<ActualParameters>
<ActualParameter>custBookings.creditCard</ActualParameter>
<ActualParameter>custBookings.bookings.rentalCarBooking</ActualParameter>
</ActualParameters>
</Tool>
</Implementation>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="280"/>
<ExtendedAttribute Name="YOffset" Value="250"/>
</ExtendedAttributes>
</Activity>
<Activity Id="a5">
<Route/>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Join Type="AND"/>
<Split Type="XOR">
<TransitionRefs>
<TransitionRef Id="t16"/>
<TransitionRef Id="t15"/>
</TransitionRefs>
</Split>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="430"/>
<ExtendedAttribute Name="YOffset" Value="190"/>
</ExtendedAttributes>
</Activity>
<Activity Id="a6">
<Route/>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Join Type="XOR"/>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="900"/>
<ExtendedAttribute Name="YOffset" Value="190"/>
</ExtendedAttributes>
</Activity>
<Activity Id="cancel-flight" Name="Cancel Flight">
<Implementation>
<Tool Id="cancelBooking" Type="PROCEDURE">
<ActualParameters>
<ActualParameter>custBookings.creditCard</ActualParameter>
<ActualParameter>custBookings.bookings.flightBooking</ActualParameter>
</ActualParameters>
</Tool>
</Implementation>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="640"/>
<ExtendedAttribute Name="YOffset" Value="230"/>
</ExtendedAttributes>
</Activity>
<Activity Id="cancel-hotel" Name="Cancel Hotel">
<Implementation>
<Tool Id="cancelBooking" Type="PROCEDURE">
<ActualParameters>
<ActualParameter>custBookings.creditCard</ActualParameter>
<ActualParameter>custBookings.bookings.hotelBooking</ActualParameter>
</ActualParameters>
</Tool>
</Implementation>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="640"/>
<ExtendedAttribute Name="YOffset" Value="350"/>
</ExtendedAttributes>
</Activity>
<Activity Id="cancel-rental-car" Name="Cancel Rental Car">
<Implementation>
<Tool Id="cancelBooking" Type="PROCEDURE">
<ActualParameters>
<ActualParameter>custBookings.creditCard</ActualParameter>
<ActualParameter>custBookings.bookings.rentalCarBooking</ActualParameter>
</ActualParameters>
</Tool>
</Implementation>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="640"/>
<ExtendedAttribute Name="YOffset" Value="470"/>
</ExtendedAttributes>
</Activity>
<Activity Id="a10">
<Route/>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Split Type="AND">
<TransitionRefs>
<TransitionRef Id="t19"/>
<TransitionRef Id="t11"/>
<TransitionRef Id="t20"/>
<TransitionRef Id="t18"/>
<TransitionRef Id="t10"/>
<TransitionRef Id="t9"/>
</TransitionRefs>
</Split>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="490"/>
<ExtendedAttribute Name="YOffset" Value="350"/>
</ExtendedAttributes>
</Activity>
<Activity Id="a11">
<Route/>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Join Type="AND"/>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="790"/>
<ExtendedAttribute Name="YOffset" Value="410"/>
</ExtendedAttributes>
</Activity>
<Activity Id="a12">
<Route/>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Join Type="XOR"/>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="640"/>
<ExtendedAttribute Name="YOffset" Value="290"/>
</ExtendedAttributes>
</Activity>
<Activity Id="a13">
<Route/>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Join Type="XOR"/>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="640"/>
<ExtendedAttribute Name="YOffset" Value="410"/>
</ExtendedAttributes>
</Activity>
<Activity Id="a14">
<Route/>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Join Type="XOR"/>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="640"/>
<ExtendedAttribute Name="YOffset" Value="530"/>
</ExtendedAttributes>
</Activity>
<Activity Id="a15">
<Route/>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Join Type="XOR"/>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="280"/>
<ExtendedAttribute Name="YOffset" Value="70"/>
</ExtendedAttributes>
</Activity>
<Activity Id="a16">
<Route/>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Join Type="XOR"/>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="280"/>
<ExtendedAttribute Name="YOffset" Value="190"/>
</ExtendedAttributes>
</Activity>
<Activity Id="a17">
<Route/>
<StartMode>
<Automatic/>
</StartMode>
<FinishMode>
<Automatic/>
</FinishMode>
<TransitionRestrictions>
<TransitionRestriction>
<Join Type="XOR"/>
</TransitionRestriction>
</TransitionRestrictions>
<ExtendedAttributes>
<ExtendedAttribute Name="ParticipantID" Value="FreeTextExpressionParticipant"/>
<ExtendedAttribute Name="XOffset" Value="280"/>
<ExtendedAttribute Name="YOffset" Value="310"/>
</ExtendedAttributes>
</Activity>
</Activities>
<Transitions>
<Transition From="a1" Id="t1" To="book-flight">
<Condition Type="CONDITION">custBookings.flightBooking != null</Condition>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a1" Id="t3" To="book-hotel">
<Condition Type="CONDITION">custBookings.hotelBooking != null</Condition>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a1" Id="t4" To="book-rental-car">
<Condition Type="CONDITION">custBookings.rentalCarBooking != null</Condition>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a10" Id="t9" To="cancel-flight">
<Condition Type="CONDITION">custBookings.flightBooking != null && custBookings.flightBooking.status = 1</Condition>
<Description>If we succeeded in booking a flight, cancel it.</Description>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a10" Id="t10" To="cancel-hotel">
<Condition Type="CONDITION">custBookings.hotelBooking != null && custBookings.hotelBooking.status = 1</Condition>
<Description>If we succeeded in booking an hotel, cancel it.</Description>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a10" Id="t11" To="cancel-rental-car">
<Condition Type="CONDITION">custBookings.rentalCarBooking != null && custBookings.rentalCarBooking.status = 1</Condition>
<Description>If we succeeded in booking a rental car, cancel it.</Description>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a5" Id="t15" To="a6">
<Condition Type="CONDITION">custBookings.flightBooking == null || custBookings.flightBooking.status = 1 && custBookings.hotelBooking == null || custBookings.hotelBooking.status = 1 && custBookings.rentalCarBooking == null || custBookings.rentalCarBooking.status = 1</Condition>
<Description>If all required bookings succeeded, proceed.</Description>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a5" Id="t16" To="a10">
<Condition Type="OTHERWISE"/>
<Description>Otherwise, cancel any bookings that succeeded.</Description>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a11" Id="t17" To="a6">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a10" Id="t18" Name="Transition" To="a12">
<Condition Type="CONDITION">custBookings.flightBooking == null || custBookings.flightBooking.status != 1</Condition>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a10" Id="t19" To="a13">
<Condition Type="CONDITION">custBookings.hotelBooking == null || custBookings.hotelBooking.status != 1</Condition>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a10" Id="t20" To="a14">
<Condition Type="CONDITION">custBookings.rentalCarBooking == null || custBookings.rentalCarBooking.status != 1</Condition>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="cancel-flight" Id="t21" To="a12">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="cancel-hotel" Id="t22" To="a13">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="cancel-rental-car" Id="t23" To="a14">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a12" Id="t24" To="a11">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a13" Id="t25" To="a11">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a14" Id="t26" To="a11">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a1" Id="t27" To="a15">
<Condition Type="CONDITION">custBookings.flightBooking == null</Condition>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a1" Id="t28" To="a16">
<Condition Type="CONDITION">custBookings.hotelBooking == null</Condition>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a1" Id="t29" To="a17">
<Condition Type="CONDITION">custBookings.rentalCarBooking == null</Condition>
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="book-flight" Id="t30" To="a15">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="book-hotel" Id="t31" To="a16">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="book-rental-car" Id="t32" To="a17">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a15" Id="t33" To="a5">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a16" Id="t34" To="a5">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
<Transition From="a17" Id="t35" To="a5">
<ExtendedAttributes>
<ExtendedAttribute Name="RoutingType" Value="NOROUTING"/>
</ExtendedAttributes>
</Transition>
</Transitions>
<ExtendedAttributes>
<ExtendedAttribute Name="obe.Event">
<obe:Event Id="TravelBookingReceived">
<xpdl:ActualParameters>
<xpdl:ActualParameter>custBookings</xpdl:ActualParameter>
</xpdl:ActualParameters>
</obe:Event>
</ExtendedAttribute>
<ExtendedAttribute Name="StartOfWorkflow" Value="FreeTextExpressionParticipant;a1;60;130;NOROUTING"/>
<ExtendedAttribute Name="EndOfWorkflow" Value="FreeTextExpressionParticipant;a6;1020;190;NOROUTING"/>
<ExtendedAttribute Name="ParticipantVisualOrder" Value="FreeTextExpressionParticipant;"/>
</ExtendedAttributes>
</WorkflowProcess>
</WorkflowProcesses>
<ExtendedAttributes>
<ExtendedAttribute Name="MadeBy" Value="JaWE"/>
<ExtendedAttribute Name="Version" Value="1.2"/>
</ExtendedAttributes>
</Package>
Solution Files
See the solution files under $OBE_HOME/examples
:
config/processes/travel-booking.xpdl
config/
BasicToolAgentFactory.xml
etc/TravelBooking/bookings.ser
src/com/uvw/travel/Address.java
src/com/uvw/travel/BookingException.java
src/com/uvw/travel/Bookings.java
src/com/uvw/travel/
BookingService
.java
src/com/uvw/travel/CreditCard.java
src/com/uvw/travel/Flight.java
src/com/uvw/travel/Name.java
src/com/uvw/travel/Person.java
src/com/uvw/travel/impl/
AddressImpl
.java
src/com/uvw/travel/impl/
BookingServiceImpl
.java
src/com/uvw/travel/impl/
BookingsImpl
.java
src/com/uvw/travel/impl/
CreditCardImpl
.java
src/com/uvw/travel/impl/
CustomerImpl
.java
src/com/uvw/travel/impl/Flight
Impl
.java
src/com/uvw/travel/impl/
NameImpl
.java
src/com/uvw/travel/impl/Person
Impl
.java
Deployment and Execution
This particular workflow process cannot be manually started; instead, it must be
triggered by the TravelBookingReceived
application event. Such
an event contains a Java object which implements the
com.uvw.travel.Bookings
interface.
- Deploy the travel-booking
.xpdl
package.
- Open a console window and navigate to the
$OBE_HOME/examples/etc/TravelBooking
directory.
- Start a workflow instance by executing the command:
jmsclient -f bookings.ser -t object send
queue/org/obe/jms/ApplicationEventQueue
- You can enable logging to
observe in-flight process activity, or use a worklist client or the
cladmin
tool to probe process instances.
- The test data in
bookings.ser
were produced by the
com.uvw.travel.test.TravelBookingTest
program. You may wish
to edit the source to change the data in order to experiment with
different paths through the workflow.
1 Mandatory, because the
custBookings
attribute appears as a <FormalParameter>
of the
<WorkflowProcess>
, meaning that it must be assigned a value
before a newly created process instance can be started.