You are on page 1of 243

Introducing the SPL

Framework

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Logical Architecture

HTML Presentation Business Data Access

HTT
P
Oracle
Servlets/XSLT Services Persistent
JavaScript/ DB2/UDB
Entities
XSLT Caches Data Service
Objects Hibernate MSSQL
Session State (Java/COBOL)
JDBC

Web Browser Web Application Server Database

Web browser (Internet Explorer 6.0) information


presented in HTML and JavaScript (no Java
applets)
Browser communicates with Web App Server via
HTTP
2
Logical Architecture

HTML Presentation Business Data Access

HTT
P
Oracle
Servlets/XSLT Services Persistent
JavaScript/ DB2/UDB
Entities
XSLT Caches Data Service
Objects Hibernate MSSQL
Session State (Java/COBOL)
JDBC

Web Browser Web Application Server Database

Web App Server divided into several logical tiers:


Presentation services
Business logic
Data access

3
Logical Architecture

HTML Presentation Business Data Access

HTT
P
Oracle
Servlets/XSLT Services Persistent
JavaScript/ DB2/UDB
Entities
XSLT Caches Data Service
Objects Hibernate MSSQL
Session State (Java/COBOL)
JDBC

Web Browser Web Application Server Database

Presentation layer
Java Servlets handle inbound HTTP requests from browser
Invoke data service objects when required
Various static data e.g. control tables, language-specific messages
and labels are cached
Uses XSL/T technology to create HTML
4
Logical Architecture

HTML Presentation Business Data Access

HTT
P
Oracle
Servlets/XSLT Services Persistent
JavaScript/ DB2/UDB
Entities
XSLT Caches Data Service
Objects Hibernate MSSQL
Session State (Java/COBOL)
JDBC

Web Browser Web Application Server Database

Business layer
Data service objects are invoked from presentation
These services ultimately perform business functions
Service objects themselves are Java, but business logic could be
implemented in Java or COBOL
Invoke data access objects to communicate with database
5
Logical Architecture

HTML Presentation Business Data Access

HTT
P
Oracle
Servlets/XSLT Services Persistent
JavaScript/ DB2/UDB
Entities
XSLT Caches Data Service
Objects Hibernate MSSQL
Session State (Java/COBOL)
JDBC

Web Browser Web Application Server Database

Data access layer


Uses Hibernate Object Relational Model (ORM) framework for
database access and persistence
Java Database Connectivity API (JDBC) is used for SQL statements
from COBOL
All database calls are routed through frameworks data access layer
application programs do not issue direct calls to database
6
Logical Architecture
Batch Control
Data Access
splbatch.sh
splbatch.sh/ /cmd
cmd Standalone Executor
(command
(commandline)
line) Persistent Oracle
Batch Process Entities
DB2/UDB
Scheduler
Scheduler Hibernate
Business MSSQL
Etc.
Etc. Data Service Objects JDBC
(Java/COBOL)

Submission Batch Server Database

Batch Processing
Standalone Executor (batch control program) invokes Java/COBOL
batch process
Business layer components perform business functions where
appropriate (same as web)
Uses data access layer to communicate with database (same as web)

7
SPL Services

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Services - Service Dispatcher
Service dispatcher acts as conduit to business objects
from presentation layer
A service invocation represents a database transaction
Invokes Java or COBOL service

Service
Service COBOL
COBOLSvc
Svc
Web
WebServer
Server Dispatcher
Dispatcher Wrapper
Wrapper

COBOL
COBOLApp
App
Java Service
JDBC
JDBC
Business Objects Data Access

Hibernate
Hibernate JDBC
JDBC DB
DB

9
Service Dispatching
Service dispatcher is invoked from Web servlet
Invokes appropriate service for Web request:
Page
List
Search

Service
ServiceDispatcher
Dispatcher Dispatched
DispatchedService
Service

Page
PageService
Service List
ListService
Service Search
SearchService
Service

10
COBOL Services

SPLs COBOL support is for backward


compatibility
Allows us to run COBOL under control of Java
framework
COBOL topic here serves as overview only
All application extensions algorithms (a.k.a.
plug-ins) and user-exits (Java Change Handlers)
are to be coded in Java
To provide background, following is a high-level
discussion of SPLs implementation of COBOL
services
11
COBOL Services
Majority of CC&B application currently still coded in COBOL
COBOL same as pre-V2 except
SQL calls routed through Java framework ultimately JDBC
Extensions (plug-ins, user exits) can, and SHOULD, be done in Java

Service
Service COBOL
COBOLSvc
Svc
Web
WebServer
Server Dispatcher
Dispatcher Wrapper
Wrapper

COBOL
COBOLApp
App
Java Service
JDBC
JDBC
Business Objects Data Access

Hibernate
Hibernate JDBC
JDBC DB
DB

12
COBOL Services
Service dispatcher determines if Java implementation for service
exists if not, assumes COBOL service
Service dispatcher (Java) invokes COBOL service wrapper in
separate child Java Virtual Machine (JVM)
Wrapper calls COBOL service program (as per CC&B 1.5)

Service
Service COBOL
COBOLSvc
Svc
Web
WebServer
Server Dispatcher
Dispatcher Wrapper
Wrapper

JVM
COBOL
COBOLApp
App
Java Service
JDBC
JDBC
Business Objects Data Access

Hibernate
Hibernate JDBC
JDBC DB
DB

13
COBOL Services
COBOL application programs do callbacks to framework for
data access & Java objects (e.g. Java-coded algorithms)
This technique enables COBOL to use frameworks database
connections for data access (in same transaction)

Service
Service COBOL
COBOLSvc
Svc
Web
WebServer
Server Dispatcher
Dispatcher Wrapper
Wrapper

JVM
COBOL
COBOLApp
App
Java Service
JDBC
JDBC
Business Objects Data Access

Hibernate
Hibernate JDBC
JDBC DB
DB

14
Inside COBOL Services
COBOL works as before (pre-V2)
Page Maintenance orchestrates calls to List Maintenance programs
List & Page programs call Row Maintenance programs for DB
access

Service
Service COBOL
COBOLSvc
Svc
Dispatcher
Dispatcher Wrapper
Wrapper

Page
Page Row
Row
Maintenance
Maintenance Maintenance
Maintenance

List
List List
List List
List List
List
Maintenance
Maintenance Maintenance
Maintenance Maintenance
Maintenance Maintenance
Maintenance

Row
Row Row
Row Row
Row Row
Row
Maintenance
Maintenance Maintenance
Maintenance Maintenance
Maintenance Maintenance
Maintenance
15
Inside COBOL Services
For example, Person object maintenance in COBOL
Well use this example on following slides
Note the row maintenance program names

Service
Service COBOL
COBOLSvc
Svc
Dispatcher
Dispatcher Wrapper
Wrapper

Person
Person Person
Person
Page
Page Row
Row

Name
Name ID
ID Phone
Phone Characteristic
Characteristic
List
List List
List List
List List
List

Name
Name ID
ID Phone
Phone Characteristic
Characteristic
Row
Row Row
Row Row
Row Row
Row
16
Inside COBOL Services
See how this maps to entity relationship for Person at the data level
One row maintenance program per table
Entity relationship for main CCB object (e.g. Person, Account,
Premise, etc.) known as Maintenance Object

Service COBOL Svc


Dispatcher Wrapper

Person
CI_PER
CI_PER
Page

Name ID Phone Characteristic


List List List List

CI_PER_NAME
CI_PER_NAME CI_PER_ID
CI_PER_ID CI_PER_PHONE
CI_PER_PHONE CI_PER_CHAR
CI_PER_CHAR

17
Inside COBOL Services User Exits
COBOL user exit points exist in Row and Page Maintenance programs and will
continue to work on V2
HOWEVER, in Java world we use Change Handlers well learn more about this later

Page
Page Person
Person Person
Person Row
Row
User
UserExit
Exit Page
Page Row
Row User
UserExit
Exit

Name
Name ID
ID Phone
Phone Characteristic
Characteristic
List
List List
List List
List List
List

Name
Name ID
ID Phone
Phone Characteristic
Characteristic
Row
Row Row
Row Row
Row Row
Row

Row
Row Row
Row Row
Row Row
Row
User
UserExit
Exit User
UserExit
Exit User
UserExit
Exit User
UserExit
Exit

18
COBOL Services Recap
COBOL will continue to be maintained and
supported, but only for base product components
Programmers should in future use Java to code
extensions
Lets take a quick look at Java services

19
Java Services
Some services now coded entirely in Java
Mostly Admin services (e.g. AlgorithmType
service)

20
Java Services
Service dispatcher determines if Java implementation for
a service exists (if not, assumes COBOL service)
Service dispatcher invokes Java service e.g. Java Page
or Search service

Service
Service COBOL
COBOLSvc
Svc
Web
WebServer
Server Dispatcher
Dispatcher Wrapper
Wrapper

COBOL
COBOLApp
App
Java Service
JDBC
JDBC
Business Objects Data Access

Hibernate
Hibernate JDBC
JDBC DB
DB

21
Java Services
Java service invokes maintenance / list / search objects to satisfy
Web servlets request
In general, Java objects communicate with DB using HQL
(Hibernate) in data access layer
Can also contain JDBC (SQL) calls

Service
Service COBOL
COBOLSvc
Svc
Web
WebServer
Server Dispatcher
Dispatcher Wrapper
Wrapper

COBOL
COBOLApp
App
Java Service
JDBC
JDBC
Business Objects Data Access

Hibernate
Hibernate JDBC
JDBC DB
DB

22
Java Services
Java services consist of many components,
some framework, some generated and some
application based hand-coded ones
For remainder of the course we will take a more
in-depth look at the main hand-coded
components and introduce other framework and
generated ones as needed

23
Business Entities

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Inside Business Entities
Business Entities handle database persistence
In general, a Business Entity class exists for each table in
system
Example here illustrates Person and Person Name tables
and related classes
AbstractBusinessEntity

+createDTO()

Person_Gen PersonName_Gen
-id -id
-address1 CI_PER_NAME -entityName
CI_PER
+getId() +getId()
+getAddress() PK,FK1 PER_ID +getEntityName()
PK PER_ID PK SEQ
Person_Impl ADDRESS1 ENTITY_NAME PersonName_Impl

PersonName
Person Interface
Interface
25
Inside Business Entities
A class for an entity has superclass and number of
subclasses (in reality, there is more than shown here)
Most of these are framework or generated
Only small number require human coding (e.g. below)
AbstractBusinessEntity

+createDTO()

Person_Gen PersonName_Gen
-id -id
-address1 CI_PER_NAME -entityName
CI_PER
+getId() +getId()
+getAddress() PK,FK1 PER_ID +getEntityName()
PK PER_ID PK SEQ
Person_Impl ADDRESS1 ENTITY_NAME PersonName_Impl

PersonName
Person Interface
Interface
26
Business Entity and Related Classes
Business Entity related classes are divided into 3 categories:
1. Framework
2. Generated
3. Hand-coded

AbstractDataTransferObject StringId AbstractBusinessEntity interface AbstractEntityList


SimpleEntityList
+createDTO()

Person_Id Person_Gen
Person_DTO
-id PersonNames_Impl
-address1 interface
PersonNames
+getId()
+getAddress() +add()
+remove()
interface
Person
+getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()
27
Business Entity and Related Classes
Goal of framework was to keep hand-coded logic to a
minimum
When creating a new Business Entity, only the Impl
class is hand coded; others are framework or generated
by the Artifact Generator more about this later
AbstractDataTransferObject StringId AbstractBusinessEntity interface AbstractEntityList
SimpleEntityList
+createDTO()

Person_Id Person_Gen
Person_DTO
-id PersonNames_Impl
-address1 interface
PersonNames
+getId()
+getAddress() +add()
+remove()
interface
Person
+getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()
28
Business Entity and Related Classes
For now, lets look at how classes below are used
Business Entities
Data Transfer Objects (DTOs)
String Ids
Entity Lists

AbstractDataTransferObject StringId AbstractBusinessEntity interface AbstractEntityList


SimpleEntityList
+createDTO()

Person_Id Person_Gen
Person_DTO
-id PersonNames_Impl
-address1 interface
PersonNames
+getId()
+getAddress() +add()
+remove()
interface
Person
+getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()
29
Business Entities
Business Entities handle database persistence i.e.
responsible for retrieval and storage of data
All are generated by Artifact Generator
Java programs typically do not call database directly;
use Business Entities where possible
For example, to fetch a Person from the database
Person_Id perId = new Person_Id("1185477091");
Person perEntity = perId.getEntity(); AbstractBusinessEntity

Person_Gen
-id
-address1
+getId()
+getAddress()

interface
Person
+getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()

30
Business Entities
To fetch multiple persons from the database
Query query = SessionHolder.getSession().createQuery("from Person");
Person perEntity = null;
QueryIterator qIter = query.iterate();
while (qIter.hasNext()) {
perEntity = (Person)qIter.next();
...
}

AbstractBusinessEntity

This is an early introduction to SPLs


Java Persistence Framework (JPF) &
Hibernate. JPF & Hibernate are Person_Gen
-id
-address1
discussed in detail later, but we will +getId()
+getAddress()
see more references to them over the interface
Person
following slides +getId()
+getAddress1()
Person_Impl

+getInfo() +getInfo()
+getDTO()()
+setDTO()()

31
Business Entities
Framework creates instances of Business Entities when
fetching data for example
Person perEntity = perId.getEntity();
or
Person perEntity = (Person)qIter.next();

will create new instance of Person


Therefore: Instance (object) of a Business Entity class
represents a row in a database table
Person
Person: :Person_Impl
Person_Impl
idid==1550000001
PER_ID ADDRESS1
1550000001
address1
address1==Easy
EasyStreet
Street 1550000001 Easy Street
Person
Person: :Person_Impl
Person_Impl 7804500002 Penny Lane
idid==7804500002
7804500002
address1
address1==Penny
PennyLane
Lane
32
Business Entities
Creating new instance of Business Entity creates a new
database row (when transaction commits)
Likewise, when changing or deleting an instance,
database row is updated or deleted (when transaction
commits)
Database commit happens at frameworks discretion
application code has no direct control over it

Person
Person: :Person_Impl
Person_Impl
idid==1550000001
PER_ID ADDRESS1
1550000001
address1
address1==Easy
EasyStreet
Street 1550000001 Easy Street
Person
Person: :Person_Impl
Person_Impl 7804500002 Penny Lane
idid==7804500002
7804500002
address1
address1==Penny
PennyLane
Lane
33
Business Entities
Business Entity has getters (get methods) for retrieval of its properties
Example
Person perEntity = (Person)query.firstRow();
String emailAddress = perEntity.getEmailAddress();
Will retrieve a persons email address
Most getters are specific to object (e.g. emailAddress on Person), but there are common
ones
getId() retrieves identifier (Account Id,
Person Id, Premise Id, etc.) depending on object
getDTO() retrieves an instance of Data Transfer
Object (DTO) for Business Entity

AbstractBusinessEntity

Person_Gen
-id
-address1
+getId()
+getAddress()

interface
Person
+getId() Person_Impl
More about Ids and DTOs in a +getAddress1()
+getInfo()
minute +getDTO()()
+getInfo()

+setDTO()()

34
Business Entities
Business Entity does not have setters for its
properties
Properties can only be updated via DTO
Business Entity has setDTO() method to register
a modified DTO and thus update database
AbstractBusinessEntity

Person_Gen
More about Ids and DTOs in a minute -id
-address1
+getId()
+getAddress()

interface
Person
+getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()

35
Data Transfer Objects
Data Transfers Objects (DTOs) are transient (temporary /
non-persistent) holders of Business Entity properties
Acquired via Business Entity getDTO() method e.g.
Person perEntity = (Person)query.firstRow();
Person_DTO perDTO = perEntity.getDTO();

Use DTO getters and setters (get/set methods) to


retrieve or update properties, for example:
String emailAddress = perDTO.getEmailAddress();
...
perDTO.setEmailAddress(emailAddress);

AbstractDataTransferObject

Person_DTO

36
Data Transfer Objects
Updating DTO property (via setter method) does not
update entity (database object) automatically
Business Entity has setDTO method to update modified
DTO, for example
Person perEntity = (Person)query.firstRow();
Person_DTO perDTO = perEntity.getDTO();
perDTO.setEmailAddress(testemail@splwg.com);
perEntity.setDTO(perDTO);

This effectively updates the database, but the actual database


update & commit happen at the discretion of the framework
AbstractDataTransferObject

Person_DTO

37
String Ids
Simple string keys (e.g. Person Id) defined as objects in framework
(??? New Ids created by system not a typical custom function
remove this !)
ID retrieved from DTO or Business Entity, e.g.
Person_Id perId = perDTO.getId();
or
Person_Id perId = perEntity.getId();

Use getIdValue() method to get value of Id


String perIdString = perId.getIdValue();

StringId

Person_Id

38
String Ids
Use Id object to retrieve Business Entity, for
example
Person_Id perId = new Person_Id("6785704944");
Person perEntity = perId.getEntity();
Person_DTO perDTO = perEntity.getDTO();
...

StringId

Person_Id

39
Entity Lists
Entity lists reference collections of entities, such as person names, phone
numbers, characteristics, etc.
Retrieved from Business Entity, e.g.
Person_Id perId = new Person_Id("1185477091");
Person perEntity = perId.getEntity();
PersonNames perNames = perEntity.getNames();

Elements in entity list can be:


Sequentially retrieved
Removed
Added

interface AbstractEntityList
SimpleEntityList

PersonNames_Impl
interface
PersonNames
+add()
+remove()

40
Entity Lists
For example, to retrieve all person names for a person:
Person_Id perId = new Person_Id("1185477091");
Person perEntity = perId.getEntity();
PersonNames perNames = perEntity.getNames();
Iterator iterator = perNames.iterator();
while (iterator.hasNext()) {
PersonName perName = (PersonName)iterator.next();
String entityName = perName.getEntityName();
...
}

interface AbstractEntityList
SimpleEntityList

PersonNames_Impl
interface
PersonNames
+add()
+remove()

41
Artifact Generator

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Artifact Generator
Artifact Generator is SPL tool to generate supporting classes for an SPL object
For example, in this implementation of Person object, Person_Gen class and Person
interface are generated by Artifact Generator
Generation based on Class Annotations in hand coded class Person_Impl in this example
Artifact Generator is executed from
Eclipse development environment
upcoming exercises will illustrate this
Well discuss annotations next

AbstractBusinessEntity

Person_Gen
-id
-address1
+getId()
+getAddress()

interface
Person
+getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()

43
Class Annotations
Meta-data used to describe Java objects to
Artifact Generator
Meta-data lives in Java code (instead of database,
as before)
Annotations stored in Java-doc comment before
class definition (enclosed in /** and */)
We use structured annotations:
Demarked by @ followed by annotation name (e.g.
@BusinessEntity)
Contain comma-separated property-value pairs (i.e.
property=value)
Value can be string, Boolean, array or another annotation
44
Class Annotations
Heres an example
1 /**
2 @SampleAnnotation (
simpleString = value,
complexString = "A string with spaces",
3 boolean = true,
arrayOfStrings = {abc, def, "g h i" },
fkAnnotation = @NestedAnnotation ( property = value ),
4 arrayOfAnnotations = { @ChildAnnotation (name=first),
@ChildAnnotation (name=second)}
)
1 */
public class ExampleClass {
....
}

1. Java-doc comments
2. Annotation name
3. Property-value pairs strings and Booleans
4. Array of annotations
45
Class Annotations
Different annotations exist for different
components, for example:
@BusinessEntity defines how to create artifacts for
persistent objects (Artifact Generator creates Hibernate
mapping files and objects based on this
@ChangeHandler declares change handlers class and
binds it to persistent entity to monitor
@AlgorithmComponent binds algorithm class to entity and
declares soft parameters

Refer to documentation for all annotations and


their parameters
46
Introduction to Eclipse

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Eclipse IDE
Definition:
The Eclipse Platform is designed for building integrated development
environments (IDEs), and arbitrary tools.
(www.eclipse.org)
In fact, can also be used to develop applications
SPL Framework developed using Eclipse Java
Development Tooling (JDT)
JDT is full-featured Java IDE for Eclipse Platform
Java projects Compare
Editing Compile
Code formatting Run
Refactoring Debug
Search
48
Eclipse IDE Menu Bar

Just a few things to point out


Debug button runs a Java class in debug mode
also used to debug Tomcat for online debugging
Run button runs a Java class normally used to
run Artifact Generator, JUnit tests and batch
Click on tiny arrow
next to button for
drop-down to select
task to run

49
Eclipse IDE Menu Bar

Just a few things to point out


Source menu has some useful features
Automatically override methods when extending/implementing
other classes
Generate try/catch blocks
Generate setters and getters
Block-comment / uncomment

Navigate menu has command to show hierarchy for a


class i.e. where implemented/extended also very
useful
50
Eclipse IDE Menu Bar

Just a few things to point out


Project will be compiled when class modified and saved

However, when generating files, project must be


manually rebuilt use F5 key to refresh and
rebuild

Remember these few points for Eclipse


exercises coming up, but also feel free to
explore all features!

51
Eclipse CM1 Project

For this training, Eclipse loaded with project CM1


This project for training purposes, but may be used for
real customizations too
Contains necessary packages and folders to get started
java - place all hand coded source in this package
test - place all JUnit test classes here
gen - all generated source files are placed here
52
Eclipse CM1 Project

Java package contains sub-package


com.splwg.cm.domain
Under this, packages divided into various sub-
packages for sub-systems, batch, etc.
Contains CustomMessages class for global CM
message definitions
53
Eclipse CM1 Project

When ready for deployment, create CM jar file


from this project using File -> Export

54
Eclipse for SPL Development
SPL does NOT bundle Eclipse with SDK
Clients have to download and install Eclipse
A few things to remember
If an annotation has been changed, run artifact generator
When artifact generator has run, MUST refresh project
(F5)
When deleting a class, MUST do a clean project build to
delete old binary classes from output
Will experience first-hand during exercises

55
Customizations

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Customizations Overview
Customizations refers to system (not program)
modification for specific customer behavior
SPL base code framework or application is never
modified for customization purposes
System can be customized using following methods:
1. Change Handlers (analogous to user exits)
2. Algorithms (a.k.a plug-ins)
3. Batch programs
4. New Maintenance Objects (new transactions)
(XAI may be included in this list, but falls outside of scope)

This training covers all 4 of these topics

57
Change Handlers
Part I

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Change Handlers I
V2 framework implements custom extensions
(user exits) as Change Handlers
Extend baseline behavior
One or more Change Handlers may exist for a
Business Entity framework will call all
Business Entity is specified in annotations
tells framework which entity to attach Change
Handler to at runtime
Change Handler extends
AbstractChangeHandler framework class
Class name must end in _CHandler
59
Change Handlers I Example 1
/**
* @ChangeHandler (entityName = characteristicType)
*/
public class CmCharacteristicType_Chandler
extends AbstractChangeHandler {
...
}

This example:
Annotation specifies Change Handler for Characteristic
Type Business Entity
Extends AbstractChangeHandler
Class name ends in _CHandler

60
Change Handlers I
Change Handlers add event-driven logic to
entities (similar to COBOL row and page user
exits)
Can perform 2 things:
1. Validate data changes
2. Cause cascading changes
Well take a look at validation first
Topic of cascading changes requires knowledge
of Hibernate persistence and HQL will leave
that for later

61
Change Handlers I Validation Rules
Framework uses Validation Rules to determine how to
validate a Business Entity at runtime
Validation Rules for Business Entity are declared in
Change Handlers
Declarative style means programmer specifies WHAT to
validate, not HOW or WHEN
Number of standard rules exist that require minimal
programming
Custom rules require programming step-by-step logic
of HOW to validate
Validation rules are side-effect free
Cannot change persistent state of system
Insures all validations are performed on complete set of changes
62
Change Handlers I Validation Rules
Following standard rules exist
AllowAndRequireRule both allows and requires property to be
populated
AllowRule allows value to be populated
CustomRule creates rule out of Custom Validation class (to
implement logic not handled by any of above)
NotAllowRule one or more properties not allowed
PlaceHolderRule place holder when Change Handler is
developed replaced with actual rules during development
ProtectRule prevents property from being changed
RequireRule requires property to be populated
RestrictRule restricts property to set of values

Refer to documentation for more details


63
Change Handlers I Validation Rules
Framework invokes getValidationRules method
on Change Handler for all validation rules
getValidationRules method must return array of
validation rule objects
To use standard rule, simply use static factory
method on rule itself for example
RequireRule.alwaysRequire() returns instance of
RequireRule class that insures entity property has value
RestrictRule.validatedMustEqualReference() returns
instance of RestrictRule class that checks if property is
equal to a specific value/reference

64
Change Handlers I Validation Rules
Validation Rule requires Property on Business
Entity (i.e. the field) to validate
Property is reference to entity field
Properties exist as constants on the business
interfaces for example
Person.properties.emailAddress refers to email address
field on Person Business Entity
Account.properties.setUpDate is setup date field on
Account entity
Properties are passed to Validation Rules as
parameters to tell rule which property to validate
65
Change Handlers I Validation Rules
Example make Email Address field on Person required
public static ValidationRule emailRequiredRule() {
return RequireRule.alwaysRequire("Person:Email is required",
"The person's email address must be specified",
Person.properties.emailAddress);
}

public ValidationRule[] getValidationRules() {


return new ValidationRule[] {emailRequiredRule()};
}
Here we see
Static method emailRequiredRule to instantiate
RequiredRule object using factory method alwaysRequire
Person.properties.email to tell rule to validate Email
Address property (i.e. field) on Person
Public method getValidationRules to provide list of rules to
framework (only one in this case)
66
Exercise 1 Change Handler Validation 1
Create Change Handler to make one of the
following fields required (Change Handler name
in parentheses)
Address line 1 on Person (CmPerson_CHandler)
Management Group on Account (CmAccount_CHandler)
Address line 2 on Premise (CmPremise_CHandler)
Location Details on Service Point
(CmServicePoint_CHandler)
Comments on Item (CmItem_CHandler)

Use online system to validate your change


handler
67
Unit Testing

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Unit Testing More About Validation
Before we delve into the topic of Testing, it helps to
understand how validation is triggered by the framework
To reiterate, validation rules are declarative; declared
in change handler, but invoked at discretion of
framework
By default, validation rules fire when Business Entity is
updated, deleted, created, etc.
Example, using setDTO to update entity will trigger
validation
Person_DTO perDTO = perEntity.getDTO();
perDTO.setEmailAddress(somebody@someplace.com);
perEntity.setDTO(perDTO);

Called eager validation because it fires immediately

69
Unit Testing More About Validation
Triggering of validation can be controlled
programmatically if needed
May be necessary where multiple entities require
validation as a coherent set of changes
An example:
Create new Person and Person Name entities,
but only validate once all entities are created
To defer validation until later, use startChanges()
before update and saveChanges() after update
NOTE: saveChanges() does not issue commit to database!

Lets take a look at the example


70
Unit Testing Example: Defer Validation
1 startChanges();
Person_DTO perDTO = (Person_DTO)this.createDTO(Person.class);
2 Person_Id perId = new Person_Id(1234567890);
perDTO.setId(perId);
Person person = perDTO.newEntity();
PersonName_DTO perNameDTO =
(PersonName_DTO) createDTO(PersonName.class);
PersonName_Id perNameId = new PersonName_Id(person,
BigInteger.ONE);
3 perNameDTO.setId(perNameId);
perNameDTO.setEntityName(Blog,Joe");
perNameDTO.setNameType(NameTypeLookup.constants.PRIMARY);
PersonName perName = perNameDTO.newEntity();
person.getNames().add(perName);
4
saveChanges();
5
1. Invokes startChanges to tell framework to suspend validation
2. Creates Person Business Entity
3. Creates PersonName Business Entity
4. Adds PersonName to Person
5. Invokes saveChanges to allow for validation on coherent set of changes
71
Unit Testing Back to Testing: JUnit
To ensure quality code, an automated unit testing
procedure is required
Reasons for automated testing
One small change can unexpectedly break other parts of system
automated tests provide early notification of these bugs
Studies show to fix bugs costs more the longer they are
undiscovered automated tests prevent this
Automated tests are useful (albeit technical) forms of functional
documentation describe to programmers expected inputs/outputs

We use JUnit at SPL for automated testing


Eclipse IDE is integrated with JUnit, so easy to create
and run tests

72
Unit Testing - JUnit
Framework contains many abstract tester
classes, one for each type of test e.g.
AbstractEntityTestCase tests Business Entities and
related Change Handlers. Also ensures all Validation
Rules in Change Handler have fired
AlgorithmImplementationTestCase tests algorithm
function
To code your own test class, must extend
appropriate one of these abstract classes
Lets see how a test is created

73
Unit Testing - JUnit
First step is to create a JUnit test class
public class CmPerson_CHandler_Test extends AbstractEntityTestCase {

protected Class getChangeHandlerClass() {


return CmPerson_CHandler.class;
}
}

This class is to test CmPerson_CHandler validation rules


1. Class name ends in _Test
2. Extends AbstractEntityTestCase to test Business Entity/Change
Handler
3. getChangeHandlerClass method returns class definition of Change
Handler being tested framework invokes this method to get class
to test

74
Unit Testing - JUnit
Now we add a method for each test case
public void testEmailRequiredRule() {

Note Our change handler only has one rule Email


Required so we only have one test case method
Remember:
1. Method name starts with test framework will execute all classes
that start with test
2. ALL rules must be violated in test - if a validation rule exists in
change handler but is not violated in test class, framework will fail
test with appropriate message

75
Unit Testing - JUnit
Lets add some code to test our email required rule
public void testEmailRequiredRule() {
Person_Id perId = new Person_Id("5775933103");
1 Person person = perId.getEntity();
2 Person_DTO goodDTO = person.getDTO();
3 goodDTO.setEmailAddress("somebody@someplace.com");
4 person.setDTO(goodDTO);
}

What this code does:


1. Fetches a person from database and instantiates Person object
2. Acquires Data Transfer Object (DTO) from Person
3. Updates email address on DTO to non-space value
4. Updates DTO on Person this triggers validation

This tests for a positive outcome (which is necessary), but we


MUST also violate the condition to properly test the validation
rule
76
Unit Testing - JUnit
So lets add some more code
public void testEmailRequiredRule() {
...
try {
Person_DTO badDTO = person.getDTO();
1 badDTO.setEmailAddress();
2 person.setDTO(badDTO);
3 fail("a validation error should have been thrown");
} catch (ApplicationException exception) {
// Make sure the correct rule was violated.
4 verifyViolatedRule(CmPerson_CHandler.emailRequiredRule(),
exception);
}
}

What this code does:


1. Instantiates a bad DTO and clears email address to violate rule
2. Updates the Persons DTO to trigger validation

77
Unit Testing - JUnit
So lets add some more code
public void testEmailRequiredRule() {
...
try {
Person_DTO badDTO = person.getDTO();
1 badDTO.setEmailAddress();
2 person.setDTO(badDTO);
3 fail("a validation error should have been thrown");
} catch (ApplicationException exception) {
// Make sure the correct rule was violated.
4 verifyViolatedRule(CmPerson_CHandler.emailRequiredRule(),
exception);
}
}

What this code does:


3. Invokes JUnit fail method if setDTO does NOT cause expected rule violation
4. Exception catch (what we expect), verifies that our rule not some other one
- caused the exception

78
Unit Testing - JUnit
Heres the complete test method
public void testEmailRequiredRule() {
Person_Id perId = new Person_Id("1648461517");
Person person = perId.getEntity();
Person_DTO goodDTO = person.getDTO();
goodDTO.setPersonOrBusiness(
PersonOrBusinessLookup.constants.PERSON);
goodDTO.setEmailAddress("somebody@someplace.com");
person.setDTO(goodDTO);
try {
Person_DTO badDTO = person.getDTO();
badDTO.setEmailAddress();
person.setDTO(badDTO);
fail("a validation error should have been thrown");
} catch (ApplicationException exception) {
// Make sure the correct rule was violated.
verifyViolatedRule(CmPerson_CHandler.emailRequiredRule(),
exception);
}
}

With this method, the JUnit test should run with no errors or failures
Error or failure would mean problem in test class or application code

79
Exercise 2 JUnit Test 1
Create a JUnit test class for your required
validation rule from exercise 1
Name your class CmXxx_CHandler_Test (Xxx is your
object name from exercise 1, e.g. Person, Premise,
Account, etc.

80
Change Handlers
Part II

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Change Handlers II Conditional Validation
In last exercise we used alwaysRequire method to
UNCONDITIONALLY require a value
Rules would not be very useful if only unconditional
validation is allowed e.g. property is ALWAYS
required/restricted/etc.
Validation usually based on some condition e.g.
Prevent dependent property from being changed if primary
property matches certain value e.g. FT freeze date/time cannot be
changed when status is frozen (ProtectRule)
Life support description on Person is required if life support flag is set
(RequiredRule)
Rules have various constructs (and factory methods) to
handle this e.g.
RequireRule.ifReferenceEqualsValue() requires property if another
property equals certain value
82
Change Handlers II Conditional Validation
Example email address required if life support flag is set
public static ValidationRule emailRequiredIfLifeSupportIsYesRule() {
return RequireRule.ifReferenceEqualsValue(
"Person:Email address is required if life support is active",
"Email address is required if life support is active",
Person.properties.emailAddress,
Person.properties.lifeSupportSensitiveLoad,
LifeSupportSensitiveLoadLookup.constants
.LIFE_SUPPORT_SENSITIVE_LOAD,
com.splwg.base.domain.StandardMessages.fieldMissing());
}
A few new things
1. Using ifReferenceEqualsValue method on RequireRule
2. emailAddress property that is required (primary property)
3. lifeSupportSensitiveLoad property to compare for value (dependent
property)

83
Change Handlers II Conditional Validation
Example email address required if life support flag is set
public static ValidationRule emailRequiredIfLifeSupportIsYesRule() {
return RequireRule.ifReferenceEqualsValue(
"Person:Email address is required if life support is active",
"Email address is required if life support is active",
Person.properties.emailAddress,
Person.properties.lifeSupportSensitiveLoad,
LifeSupportSensitiveLoadLookup.constants
.LIFE_SUPPORT_SENSITIVE_LOAD,
com.splwg.base.domain.StandardMessages.fieldMissing());
}
A few new things
4. lifeSupportSensitiveLoadLookup.constants.LIFE_SUPPORT_SENSI
TIVE_LOAD lookup value for constant Y (all valid lookup values are
generated onto lookup classes)
5. com.splwg.base.domain.StandardMessages.fieldMissing message to
display when condition is true
Note: Here we use a standard message we will create a custom
message later
84
Exercise 3 Change Handler Validation 2
Modify your Change Handler from exercise 1 to
conditionally make one of the following required
Address line 1 on Person when person type is Business
Management Group on Account when customer class is
Commercial
Address line 2 on Premise when premise type is
Apartment
Location Details on Service Point when status is
Disconnected
Comments on Item when item status is Retired
Update your JUnit test class from exercise 2 to
test conditional validation
85
Base Messages

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Message Categories
ALL application messages stored in SPL
Frameworks message repository (i.e. message
text not embedded in source code)
Messages are grouped into
categories
Use menu Admin -> M ->
Message to view/update
message categories
List here shows standard
Framework message
categories
87
Message Categories Message Text
Within each category, message text is numbered

This example shows messages for Standard category


(no 11001)
Note message number 101 (Field %1 Missing); used in
previous exercise
%1 is substitution variable to be supplied when Java
class displays message (field name in this case)

88
Message Categories Substitution Variables

Message text may contain substitution variables


Variables denoted by % followed by number e.g. %1,
%2, etc.
For example, message text
%1 field missing

will be displayed as
Bill Cycle field missing
%1

Application code must pass parameters for substitution


variables
addError(StandardMessages.FieldMissing(fieldName))

89
Base Messages Modifying
Base messages themselves may not be modified
(prevented by system)
Changes would be overwritten at next upgrade
anyway
Can override base message text with customized
version on Details tab

90
Base Messages Modifying
Customer Specific Message Text must use same
substitution variables as base
Will ALWAYS display customer specific message if
present not possible to conditionally display
base Message Text

91
Base Messages Java Definitions
Each category has own class to define message variables and
methods

For example, StandardMessages class contains


1. Category definition
2. Standard messages
92
Base Messages Runtime Definition
A message class also contains methods

Application code calls these methods to display messages at


runtime for example

addError(StandardMessages.fieldMissing("EMAILID"));

Note: description of EMAILID would be displayed in message i.e.


Email Address field missing guess how framework does it?

93
Base Messages Declarative Definition
Previous slide shows RUNTIME message definition
Remember, validation rules are declarative
We also need declarative version of message to use in
validation rules

Method returns ServerMessageTemplate


Can be used in validation rule declaration
94
Base Messages Declarative Definition
Last exercise we saw declarative version of
StandardMessages used
public static ValidationRule emailRequiredIfLifeSupportIsYesRule() {
return RequireRule.ifReferenceEqualsValue(
"Person:Email address is required if life support is active",
"Email address is required if life support is active",
Person.properties.emailAddress,
Person.properties.lifeSupportSensitiveLoad,
LifeSupportSensitiveLoadLookup.constants
.LIFE_SUPPORT_SENSITIVE_LOAD,
com.splwg.base.domain.StandardMessages.fieldMissing());
}

Not all messages require declarative versions


only those used in validation rules
Next we look at creating our own custom
messages
95
Custom Messages

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Custom Messages Creating
ONLY category 90000, Implementers
messages, may contain new custom
messages
Select category 90000 and insert new
message as shown below
% variables entered must be supplied
in classes that display the message

97
Custom Messages Java Definition
Create CustomMessages class (supplied with
this course) to contain all custom message
definitions
Specifies 90000 as message category
Placed in com.splwg.cm.domain package
Is superclass for all custom messages i.e.
MessageRepository subclasses may extend it
Lets take a closer look

98
Custom Messages Java Definition
1 package com.splwg.cm.domain;
import com.splwg.base.domain.common.message.AbstractMessageRepository;
2 import com.splwg.cm.domain.templates.MessageRepository;
3 public class CustomMessages extends AbstractMessageRepository {
4 public static final int MESSAGE_CATEGORY = 90000;
5 public static final int REQ_IF_CONDITION = 10006;
6 private static MessageRepository instance;
public CustomMessages() {
7 super(MESSAGE_CATEGORY);
}
8 static MessageRepository getInstance() {
if (instance == null) instance = new MessageRepository();
return instance;
}
}
Important class characteristics
1. In package com.splwg.cm.domain
2. Imports custom MessageRepository (to be created next)
3. Class CustomMessages Extends AbstractMessageRepository
4. Defines MESSAGE_CATEGORY 90000
5. Defines EVERY custom message (we only have one now)
99
Custom Messages Java Definition
1 package com.splwg.cm.domain;
import com.splwg.base.domain.common.message.AbstractMessageRepository;
2 import com.splwg.cm.domain.templates.MessageRepository;
3 public class CustomMessages extends AbstractMessageRepository {
4 public static final int MESSAGE_CATEGORY = 90000;
5 public static final int REQ_IF_CONDITION = 10006;
6 private static MessageRepository instance;
public CustomMessages() {
7 super(MESSAGE_CATEGORY);
}
8 static MessageRepository getInstance() {
if (instance == null) instance = new MessageRepository();
return instance;
}
}
Important class characteristics
6. Defines MessageRepository instance variable
7. Invokes superclass to establish message category at runtime
8. getInstance method to provide MessageRepository instance to framework at
runtime

100
Custom Messages MessageRepository
Next we create MessageRepository class in sub-
package
Extends CustomMessages
Only contains methods for messages relevant to
package
Static definitions for message numbers should be
in CustomMessages
Following example illustrates

101
Custom Messages MessageRepository
MessageRepository class skeleton
1 package com.splwg.cm.domain.customerinfo.person;
import com.splwg.cm.domain.CustomMessages;
2 public class MessageRepository extends CustomMessages {
3 private static MessageRepository instance;
4 private static MessageRepository getInstance() {
if (instance == null) instance = new MessageRepository();
return instance;
}
}

Important class characteristics


1. In sub-package to which it applies - customerinfo.person in this
example
2. Extends our parent CustomMessages class
3. Defines MessageRepository instance variable
4. Has getInstance method to provide approriate MessageRepository
instance to framework

102
Custom Messages Runtime Method
Lets add a runtime method for our message
1
public static ServerMessage requiredIfCondition(String fieldName1,
String fieldName2) {
2 MessageParameters parms = new MessageParameters();
3 parms.addField(fieldName1);
parms.addField(fieldName2);
4 return getInstance().getMessage(REQ_IF_CONDITION, parms);
}

Important method characteristics


1. a) Static method returns ServerMessage object type for runtime
message
b) Descriptive method name for message
c) Parameter as required by message
2. MessageParameters object for substitutions in text message
3. Adds parameters to MessageParameters object
4. Returns ServerMessage object for message number (defined in
CustomMessages class) with parameters
103
Custom Messages Using at Runtime
Setting a message at runtime
Person_Id perId = new Person_Id("1234567890");
Person person = perId.getEntity();
Person_DTO perDTO = person.getDTO();
if ((perDTO.getLifeSupportSensitiveLoad().equals(
LifeSupportSensitiveLoadLookup.constants.
LIFE_SUPPORT_SENSITIVE_LOAD))
& perDTO.getEmailAddress().equals("")) {
addError(MessageRepository.requiredIfCondition("EMAILID",
"LS_SL_FLG"));
}

Field names will be replaced by descriptions in message


requiredIfCondition method uses addField methods to set parameters

parms.addField(fieldName1);
parms.addField(fieldName2);

Causes framework to use field descriptions instead of field names


104
Custom Messages Declarative Method
Lets also add a method for our validation rule
1
public static ServerMessageTemplate requiredIfCondition(
LookupProperty prop) {
2 ServerMessageParameter[] messageParms = {
ServerMessageParameter.OFFENDING_PROPERTY_NAME,
ServerMessageParameter.createDisplayingName(prop)
};
3 return getInstance().getDeclarativeMessage(REQ_IF_CONDITION,
messageParms);
}
Important method characteristics
1. a) Returns ServerMessageTemplate object type for declarative
message
b) Descriptive method name for message
c) Parameter if required by message
2. a) Message parameter array for substitutions in text message
b) OFFENDING_PROPERTY_NAME is static reference to field
being validated in validation rule not required as parameter
105
Custom Messages Declarative Method
Lets add a method for our validation rule
1
public static ServerMessageTemplate requiredIfCondition(
LookupProperty prop) {
2 ServerMessageParameter[] messageParms = {
ServerMessageParameter.OFFENDING_PROPERTY_NAME,
ServerMessageParameter.createDisplayingName(prop)
};
3 return getInstance().getDeclarativeMessage(REQ_IF_CONDITION,
messageParms);
}
Important method characteristics
2. c) createDisplayingName gets name of LookupProperty parameter
value for substitution in message
3. Returns declarative message object for our message number and
substitution parameters

106
Custom Messages Using Declarative
Custom declarative message in validation rule
public static ValidationRule emailRequiredIfLifeSupportIsYesRule() {
return RequireRule.ifReferenceEqualsValue(
"Person:Email address is required if life support is active",
"Email address is required if life support is active",
Person.properties.emailAddress,
Person.properties.lifeSupportSensitiveLoad,
LifeSupportSensitiveLoadLookup.constants
.LIFE_SUPPORT_SENSITIVE_LOAD,
MessageRepository.requiredIfCondition(
Person.properties.lifeSupportSensitiveLoad));
}
requireIfCondition method referenced in validation rule
Parameter passes in property of field to display in message
Person.properties.emailAddress automatically set as
OFFENDING_PROPERTY_NAME so can be used in declarative
method to set field name property

107
Exercise 4 Custom Declarative Message
Create a descriptive message for exercise n-1
Update CustomMessages class for your message
Create MessageRepository class in appropriate
sub-package
Add method to MessageRepository for use in
validation rule

108
Change Handlers
Part III

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Change Handlers III Conditions
Rules can take as input one or more Conditions
Condition interface currently has following
implementations (i.e. these are conditions supported)
BetweenValues
Equals
Not
And
Or
GreaterThan / GreaterThanOrEquals
LessThan / LessThanOrEquals
Contains

(Descriptions of these conditions are documented)


Use conditions to conditionally perform validation
110
Change Handlers III Conditions
Accessible from properties, for example
1 Condition isPrimaryName = PersonName.properties.isPrimaryName.isTrue();
2 Condition greaterThan =
PersonName.properties.sequence.isGreaterThan(BigInteger.ZERO);

isTrue() and isGreaterThan() methods return Conditions


1. PersonName being checked for primary attribute
2. PersonName sequence being checked for > 0

Can also be instantiated using constructor


Condition isPerson =
new Equals(Person.properties.personOrBusiness,
PersonOrBusinessLookup.constants.PERSON);

Checks if PersonOrBusiness property is set to Person

These conditions can be passed to Validation


Rules as parameters
111
Change Handlers III Conditions
Example using Condition to make email address required if life
support flag is set
public static ValidationRule emailRequiredIfLifeSupportIsYesRule() {
1 Condition hasLifeSupport =
Person.properties.lifeSupportSensitiveLoad.
isEqualTo(LifeSupportSensitiveLoadLookup.constants.
LIFE_SUPPORT_SENSITIVE_LOAD);
2 return RequireRule.ifConditionTrue(
"Person:Email address is required if life support is active",
"Email address is required if life support is active",
Person.properties.emailAddress,
3
hasLifeSupport,
com.splwg.base.domain.StandardMessages.fieldMissing());
}
1. Condition to check if life support is on
2. ifConditionTrue method of RequireRule class
3. Condition specified in validation rule (RequireRule)

112
Exercise 5 Change Handler Validation 3
Modify Change Handler from exercise 3 to use
Condition class with RequireRule
Use your own message from previous exercise
As before, make one of following required
Address line 1 on Person when person type is Business
Management Group on Account when customer class is
Commercial
Address line 2 on Premise when premise type is
Apartment
Location Details on Service Point when status is
Disconnected
Comments on Item when item status is Retired
113
Change Handlers
Part IV

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Change Handlers IV Custom Rules
If validation too complex for declarative rule, custom rule
may be coded
Custom rule contains code to perform specific validation
i.e. if invalid condition, display error message
Class may implement one or more abstract methods
Methods correspond with events that may occur with
respect to underlying business entity
Methods are divided into 2 categories
1. Eager Validations
2. Lazy Validations

115
Custom Rule Eager Validation Methods
Eager validations fire immediately when entity
changed (via delete(), setDTO(), createEntity())
Methods
validateAdd() fires when entity added
validateChangeOnly() fires when entity changed
validateAddOrChange() fires in addition to add or change
validateDelete() fires when entity deleted
validateRegisteredChange() fires when change registered
to another object (e.g. a child)
Can be any entity that feels like notifying you of a change
Use parameter RegisteredChangeDetails method
getChangeToList() to determine if change affects you
116
Custom Rule Lazy Validation Methods
Eager validations fire after a coherent set of
changes not immediately when entity is
modified
Only one lazy validation method exists
validateSave()
Fires at the end of set of changes
Validation of child entities, for example, can be placed in
this method
Any type of change (add, change, delete, register
change) will trigger validateSave()

117
Custom Rule Class
To create and use custom rule, simply
1. Create class that extends AbstractCustomValidation
2. Provide framework with array of entity properties
associated with the custom rule framework uses this to
avoid additional validations on properties already known
to be in error
3. Implement appropriate eager / lazy methods to perform
validation
4. Reference custom rule in static validation rule method
as you would with standard declarative rule
Lets take a look at an example

118
Custom Rule MapFieldNameRequired Example
1

1. This class is actually inner class of


ScriptFieldMap_Chandler class makes sense if custom
rule specific to entity
2. Custom Rule class extends AbstractCustomValidation
3. Passes back property being validated mapFieldName

119
Custom Rule MapFieldNameRequired Example

1
2

1. Uses method validateAddOrChange for immediate (eager) validation


2. Casts Business Entity in parameter to appropriate one
ScriptFieldMap
3. If validation error found, uses addValidationError method to register
error message

120
Custom Rule MapFieldNameRequired Example

Change Handler class ScriptFieldMap_CHandler


1

1. Declares static method mapFieldNameRequired


2. Instantiates new CustomRule object for custom rule class
MapFieldNameRequired
3. getValidationRules() method provides framework list of
ALL rules
121
Exercise 6 Custom Validation Rule
Modify Change Handler from last exercise to
make Short Comment characteristic (char type
COMMENT) required for one of following
Business Entities
Person
Account
Premise
Service Point
Item

Additional notes
122
Exercise 6 Custom Validation Rule
Additional notes
Create new message
XX Short Comment characteristic is required
(substitute XX with your initials)
Create runtime message method in MessageRepository
Implement validateSave() method need to do lazy
validation when checking child entities
Characteristics are effective dated use iterator on
PersonCharacteristic to scan for COMMENT type

123
SPL Framework &
Hibernate

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


SPL Framework & Hibernate - Overview
SPLs Java Persistence Framework (JPF) uses Hibernate
for database persistence
What is Hibernate?
Object/relational mapping (ORM) tool for Java environments
ORM refers to technique of mapping data representation from object
model to relational data model with SQL-based schema
Takes care of mapping from Java classes to DB tables
Also provides data query and retrieval facilities
Significantly reduces development time otherwise spent with manual
data handling in SQL and JDBC

We have seen a lot of it already in Business Entity, DTO


topic and in JUnit tests

125
Hibernate Architecture View
Diagram shows Hibernate
between application (e.g. SPL Application
Framework) and database Persistent
PersistentObjects
Objects
Application accesses data via
Persistent Objects e.g. object
Hibernate
Person maps to CI_PER table,
Account to CI_ACCT, etc. hibernate.
properties
XML mapping

hibernate.properties file
specifies various parameters Database
e.g. database connection
XML Mapping files contain
metadata to map DB tables to
Java objects (object/relational
mapping)

126
SPL Framework & Hibernate Architecture
SessionFactory -
cache of compiled Data
DataTransfer
Transfer SPL Framework
Objects
O/R mappings Objects
Business
Business
ConnectionProvide Entities
Entities
SessionFactory
r factory & pool Session
of JDBC
ConnectionProvider
connections JDBC
Business Entities
(a.k.a. Persistent JDBC
Objects) short-
lived, single-
threaded, Database
persistent state

127
SPL Framework & Hibernate Architecture
Data Transfer
Objects (a.k.a. Data
DataTransfer
Transfer SPL Framework
Objects
Transient Objects) Objects
Business
persistent objects Business
Entities
not associated with Entities
SessionFactory
session (DTOs) Session
Session short- ConnectionProvider
JDBC
lived object,
represents
conversation JDBC
between app and
DB; wraps JDBC
connection Database

SPL Framework also provides for direct JDBC calls


128
Hibernate Background
SPL Framework wraps Hibernate, so native
Hibernate calls not used
We have already seen some of this for example
Person perEntity = perId.getEntity();

will call Hibernate to create Person object from


CI_PER database table
To provide deeper understanding, following
slides give an overview of native Hibernate
We will then compare to SPL Frameworks
implementation

129
Hibernate Persistent Objects
With Hibernate you access tables as objects
Object can be loaded from DB if identifier is known

Cat fritz = (Cat) sess.load(Cat.class, generatedId);

This instantiates object of class Cat from DB table for Cat


load() throws unrecoverable exception if row does not
exist
Use get() method to avoid exception returns null if row
not found
Cat cat = (Cat) sess.get(Cat.class, id);
if (cat==null) {
cat = new Cat();
sess.save(cat, id);
}
return cat;
130
Hibernate HQL
Hibernate Query Language (HQL) allows for SQL-like queries
Use find() method to query for objects

List cats = sess.find(


"from Cat as cat where cat.birthdate = ?",
date,
Hibernate.DATE
);
Will select all properties (columns) of Cat
Can also specify scalar queries (e.g. to retrieve one column)
Use select clause in HQL

List mates = sess.find(


"select mate from Cat as cat join cat.mate as mate " +
"where cat.name = ?",
name,
Hibernate.STRING
);

131
Hibernate Updating Persistent Objects
Persistent objects can be updated
Most straightforward load object, manipulate (using setter
methods) and flush() session
DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) );
cat.setName("PK");
sess.flush(); // changes to cat are automatically detected & persisted

For updates over multiple sessions (e.g. in online environment), use


update() method of session
// in the first session
Cat cat = (Cat) firstSession.load(Cat.class, catId);
Cat potentialMate = new Cat();
firstSession.save(potentialMate);

// in a higher tier of the application


cat.setMate(potentialMate);

// later, in a new session


secondSession.update(cat); // update cat
secondSession.update(mate); // update mate
132
Hibernate Deleting Persistent Objects
Use delete() method of session to remove
objects state from database
sess.delete(cat);

Application may still hold reference to object


delete() therefore makes persistent object
transient
May also delete many objects at once by passing
Hibernate query string to delete()

Refer to www.hibernate.org for detailed


documentation
133
Hibernate for SPL Framework
Previous slides show native use of Hibernate
persistent objects and HQL
As weve seen, internally framework uses
Hibernate for persistence
Similar to native Hibernate
Persistent Objects = Business Entities
Transient Objects = Data Transfer Objects

Much of this has been covered before, but well


review and add some new things over following
slides

134
Hibernate for SPL Framework
Business Entity / DTO
Creating new Business Entity equates to creating new
database row
Likewise, when Business Entity changed or deleted, action
performed on database
Actual inserts, updates, deletes on DB controlled by
framework
Properties on Business Entity only updated via Data
Transfer Object

135
Hibernate for SPL Framework
Business Entity / DTO
To instantiate Business Entity from DB
Person_Id perId = new Person_Id("1185477091");
Person perEntity = perId.getEntity();
or
Person perEntity = (Person)query.firstRow();

or
Query query = SessionHolder.getSession()
.createQuery("from Person");
Person perEntity = null;
QueryIterator qIter = query.iterate();
wile (qIter.hasNext()) {
perEntity = (Person)qIter.next();
...
}

136
Hibernate for SPL Framework
Business Entity / DTO
To update properties, use DTO
Person_DTO perDTO = perEntity.getDTO();
perDTO.setEmailAddress(testemail@splwg.com);
perEntity.setDTO(perDTO);

To create new Business Entity, create DTO first


Person_DTO perDTO = (Person_DTO) createDTO(Person.class);

Note: createDTO() inherited from parent GenericBusinessObject for all


Business Entity or Business Component classes (e.g. Change
Handlers)

or (to create from an Id class)


Person_Id perId = new Person_Id("1185477091");
Person_DTO perDTO = perId.newDTO();
137
Hibernate for SPL Framework
Business Entity / DTO
then create Business Entity from DTO
perDTO.setId(new Person_Id(1185477091));
perDTO.set...
Person person = perDTO.newEntity();

To delete Business Entity, use delete() method on entity


person.delete();

or, delete results of query


Query query = SessionHolder.getSession()
.createQuery("from Person");
long rowsDeleted = query.delete();

138
Hibernate for SPL Framework - HQL
HQL queries must also go through SPL Framework
Framework Query class implements subset of pure HQL
Framework HQL queries return Business Entities
Mostly same as native HQL language
Few differences in SPL Framework implementation
SELECT clause not allowed in HQL text
ORDER BY clause not allowed in HQL text
UNION catered for (not in HQL text)
Raw SQL catered for

Following slides describe SPL Frameworks


implementation of HQL
139
SPL Query SELECT clause
select clause not used in SPL Framework
Query call
Similar to Hibernate, following query valid
AlgorithmType algorithmType = ... ;
Query query = createQuery("from Algorithm algorithm +
where algorithm.algorithmType = :algorithmType");
query.bindEntity("algorithmType", algorithmType);
List algorithms = query.list();

List will contain algorithm objects for algorithm


type (i.e. Business Entities are returned)
However, unlike Hibernate, select property from
object is invalid in framework query
140
SPL Query SELECT clause
To select individual columns, specify result properties
programmatically, giving each a unique name

Query query = createQuery("from Algorithm algorithm+


where algorithm.algorithmType = :algorithmType");
query.bindEntity("algorithmType", algorithmType);
query.addResult("algorithm", "algorithm");
query.addResult("algorithmId", "algorithm.id");
List queryResults = query.list();

addResult() method on Query specifies result property


(column)
List will contain QueryResultRow objects
Each QueryResultRow will have two values keyed by
algorithm and algorithmId
141
SPL Query ORDER BY clause
order by clause in HQL not allowed by
framework
Order must be programmatically specified
Query query = createQuery("from Algorithm algorithm+
where algorithm.algorithmType = :algorithmType");
query.bindEntity("algorithmType", algorithmType);
query.addResult("algorithm", "algorithm");
query.addResult("algorithmId", "algorithm.id");
query.orderBy(algorithmId, Query.ASCENDING);
List queryResults = query.list();

List will contain QueryResultRow objects,


ordered by algorithmId

142
SPL Query Iterate Method
For large volume, better performance using
iterate() method
Query query = SessionHolder.getSession().createQuery("from Person");
Person perEntity = null;
QueryIterator qIter = query.iterate();
while (qIter.hasNext()) {
perEntity = (Person)qIter.next();
...
}

Iterator loads objects on demand


Also performs better if objects already loaded
and cached by session

143
SPL Query UNION
Hibernate does not provide for unions (does not fit in with object-
oriented principles of HQL)
However, unions can be useful
Programmatically coded for framework
Unioned queries must have identical
Result columns
Order by clauses
Max results setting

unionWith() query method performs initial union


UnionQuery union = query.unionWith(query2);

To add 3rd (or later) query, add directly to union

union.addQueryToUnion(query3);

144
SPL Query Raw SQL
May be necessary to code SQL instead of HQL
To specify performance hints
Table not mapped to Java entity
Not preferred or recommended
Instead of createQuery(), use
createPreparedStatement()
Similar to HQL Query interface, but use table and
column names instead of Java entity and
property names
This feature only mentioned here for information
not used in exercises
145
SPL Framework & Hibernate Review
Framework uses Hibernate for database access
Application code MUST use framework interfaces
for Hibernate
Most of HQL syntax the same, except for SELECT
clause, ORDER BY clause and UNION
Can bypass Hibernate and use native SQL
Weve only covered small part refer to
www.hibernate.org and SPL SDK documentation
for more details

146
Change Handlers
Part V

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Change Handlers V Cascading Changes
Weve seen up to now change handlers perform validation
on a Business Entity
Change handlers can also implement business logic
based on inserts, updates & deletes to Business Entity
i.e. to cause cascading changes to occur
For example, if a phone number changes, update
matching phone numbers for related Persons
automatically
Change handler provides for number of handle methods
Handle methods are invoked at specific events
Unlike validation, this logic fires immediately cannot be
deferred by startChanges() / saveChanges()
148
Change Handlers V Events and Methods
Following methods can be customized
Add or Copy Event
prepareToAdd()
handleAddOrChange()
handleAdd()
handleRegisteredChange()
Update Event
prepareToChange()
handleAddOrChange()
handleChange()
Delete Event
handleDelete()

149
Change Handlers V Events and Methods
prepareToAdd(DataTransferObject newDTO)
Fires before new Business Entity is added
Allows for defaulting of values or other changes on new DTO

handleAddOrChange(BusinessEntity businessEntity,
DataTransferObject oldDTO)
Fires before validation when entity added OR changed
oldDTO contains null on add event

handleAdd(BusinessEntity newBusinessEntity)
Fires before validation when entity added
Allows for cascading updates on other objects or external systems

150
Change Handlers V Events and Methods
prepareToChange(BusinessEntity unchangedEntity,
DataTransferObject newDTO)
Fires before change to DTO is submitted
Allows for defaulting of values and other changes on DTO
handleChange(BusinessEntity changedBusinessEntity,
DataTransferObject oldDTO)
Fires before validation when entity is changed
Allows for cascading updates on other objects or external systems
handleRegisteredChange(BusinessEntity changedBusnessEnty,
RegisteredChangeDetail changeDetl)
Fires when change is registered to changedBusinessEntity via
business entitys registerChange method
Can relate to entity list being changed or some other type of change
(i.e. class that implements Change interface)
151
Change Handlers V Events and Methods
handleDelete(DataTransferObject oldDTO)
Fires before validation when entity is deleted

Notes:
1. These are not preferred places for validation
validation should be done using validation rules

Lets now take a look at an example

152
Change Handlers V handleAdd example
Create an alert when new account is added
/**
1
* @ChangeHandler (entityName = account)
*/
2 public class CmAccount_CHandler extends AbstractChangeHandler {
3 public void handleAdd(BusinessEntity newBusinessEntity) {
4 Account account = (Account) newBusinessEntity;
5 AccountAlerts acctAlerts = account.getAlerts();
6
AccountAlert_DTO acctAlertDTO = acctAlerts.newChildDTO();
7
acctAlerts.add(acctAlertDTO,
new AlertType_Id("PP EXEMPT"),
new Date(2001, 1, 1));
}
}
1. Specifies entity type in annotations (dont forget to do this!)
2. Class name ends in _CHandler extends AbstractChangeHandler
3. Implements handleAdd method newBusinessEntity references
entity being added
153
Change Handlers V handleAdd example
Create an alert when new account is added
/**
1
* @ChangeHandler (entityName = account)
*/
2 public class CmAccount_CHandler extends AbstractChangeHandler {
3 public void handleAdd(BusinessEntity newBusinessEntity) {
4 Account account = (Account) newBusinessEntity;
5 AccountAlerts acctAlerts = account.getAlerts();
6
AccountAlert_DTO acctAlertDTO = acctAlerts.newChildDTO();
7
acctAlerts.add(acctAlertDTO,
new AlertType_Id("PP EXEMPT"),
new Date(2001, 1, 1));
}
}
4. Casts and assigns newBusinessEntity to Account object
5. Gets alerts entity list (AccountAlerts) for the account will be empty,
since its new account
6. Creates new alert DTO by using entity lists newChildDTO method
154
Change Handlers V handleAdd example
Create an alert when new account is added
/**
1
* @ChangeHandler (entityName = account)
*/
2 public class CmAccount_CHandler extends AbstractChangeHandler {
3 public void handleAdd(BusinessEntity newBusinessEntity) {
4 Account account = (Account) newBusinessEntity;
5 AccountAlerts acctAlerts = account.getAlerts();
6
AccountAlert_DTO acctAlertDTO = acctAlerts.newChildDTO();
7
acctAlerts.add(acctAlertDTO,
new AlertType_Id("PP EXEMPT"),
new Date(2001, 1, 1));
}
}
Question: how else could we create the DTO?
7. Adds partially completed DTO to entity list passes in additional
parameters required for entity list

Framework will add row when transaction commits


155
Change Handlers V Cascading Changes
Previous example shows cascading change to child
entity (alerts) of Business Entity (account)
Child entity lists acquired from Business Entity via get
methods (e.g. getAlerts())
To add new child entity, use entity list add methods
To remove child entity, use entity list remove methods
Inserts/deletes of other entities (not child entity lists)
requires more explicit code i.e. getDTO, setDTO calls

Lets look at an example

156
Change Handlers V handleChange Example
Update premise when account is changed
1 public void handleChange(BusinessEntity changedEntity,
DataTransferObject oldDTO) {
2 Account account = (Account) changedEntity;
3 if (account.getMailingPremiseId() != null) {
4 Premise premise = account.getMailingPremiseId().getEntity();
5 Premise_DTO premiseDTO = premise.getDTO();
6 premiseDTO.setAddress4(account.getAlertInformation());
7 premise.setDTO(premiseDTO);
}
}
1. Implements handleChange method changedEntity references
account entity being changed; oldDTO is DTO before change
2. Casts and assigns changedEntity to Account object
3. Mailing premise Id is optional (note, on CI_ACCT table mailing
premise Id is space; on Business Entity null)
4. Gets Premise object referenced by mailing premise Id

157
Change Handlers V handleChange Example
Update premise when account is changed
1 public void handleChange(BusinessEntity changedEntity,
DataTransferObject oldDTO) {
2 Account account = (Account) changedEntity;
3 if (account.getMailingPremiseId() != null) {
4 Premise premise = account.getMailingPremiseId().getEntity();
5 Premise_DTO premiseDTO = premise.getDTO();
6 premiseDTO.setAddress4(account.getAlertInformation());
7 premise.setDTO(premiseDTO);
}
}
5. Gets DTO for Premise to modify row
6. Updates value on Premise DTO address line 4 in this case is set to
accounts alert information (Comment on account page)
7. Updates Premise Business Entity using setDTO() method this
results in row update

158
Exercise 7 Cascading Change Handler
Modify your Change Handler from last exercise to
create one of the following
(All create a characteristic type of Short Comment i.e.
COMMENT)
Person Characteristic when new Person added
Account Characteristic when new Account added
Premise Characteristic when new Premise added
Service Point Characteristic when new SP added
Item Characteristic when new Item added

Update your JUnit test class to test

159
Algorithms
Part I

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Algorithms - Overview
Where system requires customization, SPL provides for
customizable algorithms (a.k.a plug-ins)
Base algorithms exist, but can be cloned and modified
Like user exits, but
Unlike Change Handlers, more related to business functions and
events
Also, unlike Change Handlers, use configurable (soft) parameters
For example
In CC&B world, if CSR requests customers recommended deposit
amount, system calls deposit recommendation algorithm to calculate
amount
If base version of algorithm not appropriate, new algorithm can be
coded to replace base on
At upgrades, custom algorithms will not be overwritten
161
Algorithms - Overview
Some more examples where algorithms are used
Validating the format of a phone number entered by a user
Validating the format of a latitude/longitude geographic
code entered by a user.
Calculating late payment charges in SPL CC&B
Calculating the recommended deposit amount in SPL
CC&B
Constructing your GL account during the interface of
financial transactions to your GL in SPL CC&B
And many other functions...
Lets take a look at how algorithms work
internally
162
Algorithms - Overview
Algorithms are defined in 2 places
1. Database tables
2. SPL Framework (Java classes / COBOL programs)

Online Admin menu used to define database components


1. Algorithm Types
2. Algorithms
3. Event / activity to which algorithm applies (e.g. FT freeze, phone
number validation, etc.)

SPL Framework requires implementation class and


various generated artifacts
Lets take a look at the online definitions first

163
Algorithm Database Model
1 CI_ALG_TYPE CI_ALG Customized Entity
PK ALG_TYPE_CD PK ALG_CD

PGM_NAME FK1 ALG_TYPE_CD FK1 ALG_CD


ALG_ENTITY_FLG VERSION
PGM_TYPE_FLG

CI_ALG_PARM
CI_ALG_TYPE_PRM PK,FK2 ALG_CD
PK,FK1 ALG_TYPE_CD PK EFFDT
PK SEQNO PK,FK1 SEQNO

PARM_REQ_SW ALG_PARM_VAL
FK1 ALG_TYPE_CD

Algorithm database tables


1. Algorithm Type defines
Entity e.g. Char Type Adhoc Value Validation, SA Type
SA Creation, etc.
Program name
Program type JAVA or COBOL
164
Algorithm Database Model
1 CI_ALG_TYPE CI_ALG Customized Entity
PK ALG_TYPE_CD PK ALG_CD

PGM_NAME FK1 ALG_TYPE_CD FK1 ALG_CD


ALG_ENTITY_FLG VERSION
PGM_TYPE_FLG

CI_ALG_PARM
2 CI_ALG_TYPE_PRM PK,FK2 ALG_CD
PK,FK1 ALG_TYPE_CD PK EFFDT
PK SEQNO PK,FK1 SEQNO

PARM_REQ_SW ALG_PARM_VAL
FK1 ALG_TYPE_CD

Algorithm database tables


2. Algorithm Type Parameter defines
Parameters expected by algorithm program
Required / optional

165
Algorithm Database Model
1 CI_ALG_TYPE 3 CI_ALG Customized Entity
PK ALG_TYPE_CD PK ALG_CD

PGM_NAME FK1 ALG_TYPE_CD FK1 ALG_CD


ALG_ENTITY_FLG VERSION
PGM_TYPE_FLG

4 CI_ALG_PARM
2 CI_ALG_TYPE_PRM PK,FK2 ALG_CD
PK,FK1 ALG_TYPE_CD PK EFFDT
PK SEQNO PK,FK1 SEQNO

PARM_REQ_SW ALG_PARM_VAL
FK1 ALG_TYPE_CD

Algorithm database tables


3. Algorithm defines an instance of algorithm type many
algorithms may exist for one algorithm type
4. Algorithm Parameter defines parameter values for the
instance

166
Algorithm Database Model
1 CI_ALG_TYPE 3 CI_ALG 5 Customized Entity
PK ALG_TYPE_CD PK ALG_CD

PGM_NAME FK1 ALG_TYPE_CD FK1 ALG_CD


ALG_ENTITY_FLG VERSION
PGM_TYPE_FLG

4 CI_ALG_PARM Examples
2 CI_ALG_TYPE_PRM PK,FK2 ALG_CD
PK,FK1 ALG_TYPE_CD PK EFFDT Characteristic Type
PK SEQNO PK,FK1 SEQNO SA Type
PARM_REQ_SW ALG_PARM_VAL Etc.
FK1 ALG_TYPE_CD

Algorithm database tables


5. Algorithm code is specified on customized entitys
configuration table algorithm will be invoked based on
this specification
Lets look at an example

167
Algorithm Phone Format Example
Phone format - algorithm definition diagram
Algorithm Type:PHN-FMT Algorithm:PHN-FMT-US Phone Type: BUSN
Format 1 required (999) 999-9999
Format 2 optional
Format 3 optional Algorithm:PHN-FMT-UK Phone Type: BUSN_UK
Format 4 thru 9 optional 999 9999-9999
99999 999999
9999 999-9999

CI_ALG_TYPE CI_ALG Phone Type


PK ALG_TYPE_CD PK ALG_CD

PGM_NAME FK1 ALG_TYPE_CD FK1 ALG_CD


ALG_ENTITY_FLG VERSION
PGM_TYPE_FLG

CI_ALG_PARM
CI_ALG_TYPE_PRM PK,FK2 ALG_CD
PK,FK1 ALG_TYPE_CD PK EFFDT
PK SEQNO PK,FK1 SEQNO

PARM_REQ_SW ALG_PARM_VAL
FK1 ALG_TYPE_CD

168
Algorithm Phone Format Example
Admin -> Algorithm Type Phone format
1

2
3
4

1. Algorithm Type name 12 characters


2. System will ONLY allow PHN-FMT algorithm type to be specified on
Phone Type entity
Note: Java name for algorithm entity will also be required for
annotations during coding will see example shortly
3. Program type JAVA (can also be COBOL)
169
Algorithm Phone Format Example
Admin -> Algorithm Type Phone format
1

2
3
4

4. Algorithm component interface to format and validate phone


Note: for JAVA class to be specified, class must already exist as
framework component
5. At least one phone format is required

170
Algorithm Phone Format Example
Admin -> Algorithm Phone format US
1

1. Algorithm name 1st instance of algorithm type


2. Algorithm type parent definition
3. Effective dated can create multiple sequences, each with different
effective date
4. Phone format for this instance U.S. has only one phone format
171
Algorithm Phone Format Example
Admin -> Algorithm Phone format UK
1

1. Algorithm name 2nd instance of algorithm type


2. Same algorithm type as for U.S. (i.e. SAME PROGRAM)
3. U.K. has multiple phone formats
172
Algorithm Phone Format Example
Admin -> Phone Type Algorithm usage

1
2

Defines 2 types of business phones


1. U.S. phone numbers to be validated and formatted by
North American phone format algorithm
2. U.K. phone numbers to be validated and formatted by
United Kingdom phone format algorithm

173
Algorithm Phone Format Example
Main -> Person Algorithm activation
1

On Person page, Phone Type now determines


algorithm to invoke for phone number formatting
and validation

Next well see how SPL Framework components


are built to do this
174
Algorithm Spots
Call out places in system (e.g. from Person to validate phone
number) are known as algorithm spots
Each algorithm spot has interface class
Communication with algorithm takes place through interface
Interface provides abstraction between base and customization

Business Algorithm
Algorithm Spot
Component Interface Component
PhoneTypeFormat
PhoneTypeFormat PhoneTypeFormat
PhoneTypeFormat
Person
Person Phone
Phone ValidationAlgorithmSpot
ValidationAlgorithmSpot ValidationAlgComp
ValidationAlgComp

175
Algorithm Spots
Attributes of an algorithm spot interface class
Internal to framework only created by Product
Development
API to algorithm component (from base application)
Specific to algorithm entity type (or system event)
Defines hard input parameters for algorithm
Defines output parameters that can be retrieved after
algorithm has been invoked

176
Algorithm Spots
These classes form part of base code
Invoked from base at appropriate times (events)
Methods on interface related to algorithm type e.g. setPhoneValue()
only relevant to PhoneTypeFormatValidationAlgorithmSpot

interface
AdhocCharacteristicValueValidationAlgorithmSpot
+setFormatOnly() : void
+setCharacteristicType() : void
+setAdhocValue() : void
+getReformattedValue() : String
interface
+isValidAdhoc() : Boolean
AlgoritmSpot
+invoke()
interface
PhoneTypeFormatValidationAlgorithmSpot
+setPhoneValue() : void
+setPhoneType() : void
+isValidPhoneValue() : Boolean
+getPreferredFormatString() : String
+getReformattedPhoneValue() : String
177
Algorithm Components
Algorithm requires programmatic implementation
Algorithm Type specifies program name e.g.
com.splwg.base.domain.common.phoneType.
PhoneTypeFormatValidationAlgComp

This name in fact specifies another interface


generated from implementation class
Implementation class has name = interface name
+ Impl e.g.
com.splwg.base.domain.common.phoneType.
PhoneTypeFormatValidationAlgComp_Impl

Following diagram describes full Phone Type


Validation algorithm component
178
Algorithm Components Phone Type Validation
Remember
Interface is empty requires implementation to perform appropriate tasks
Implementation for algorithm spot is Algorithm Component i.e. Business
Component

interface
AlgoritmSpot
+invoke()

interface
PhoneTypeFormatValidationAlgorithmSpot
+setPhoneValue() : void V2.0.10 +
+setPhoneType() : void
+isValidPhoneValue() : Boolean
+getPreferredFormatString() : String
+getReformattedPhoneValue() : String

V2.0.6
PhoneTypeFormatValidationAlgComp_Gen
PhoneTypeFormatValidationAlgComp_Impl
interface
+getPhoneFormat1() : String
PhoneTypeFormatValidationAlgComp
+getPhoneFormat2() : String
+setPhoneValue() : void +invoke() : void
+getPhoneFormat3() : String
+setPhoneType() : void +setPhoneValue() : void
+getPhoneFormat4() : String
+isValidPhoneValue() : Boolean +setPhoneType() : void
+getPhoneFormat5() : String
+getPreferredFormatString() : String +isValidPhoneValue() : Boolean
+getPhoneFormat6() : String
+getReformattedPhoneValue() : String +getPreferredFormatString() : String
+getPhoneFormat7() : String
+getReformattedPhoneValue() : String
+getPhoneFormat8() : String
+getPhoneFormat9() : String
179
Algorithm Components Phone Type Validation
1. Implementation class (_Impl) is hand coded can be customized
2. Component interfaces generated by artifact generator customized
versions will be generated for custom impl class
3. Algorithm invoked via component interface
interface
AlgoritmSpot
+invoke()

interface
PhoneTypeFormatValidationAlgorithmSpot
+setPhoneValue() : void V2.0.10 +
+setPhoneType() : void
+isValidPhoneValue() : Boolean
+getPreferredFormatString() : String
+getReformattedPhoneValue() : String

2 V2.0.6
PhoneTypeFormatValidationAlgComp_Gen 1
3 PhoneTypeFormatValidationAlgComp_Impl
interface
+getPhoneFormat1() : String
PhoneTypeFormatValidationAlgComp
+getPhoneFormat2() : String
+setPhoneValue() : void +invoke() : void
+getPhoneFormat3() : String
+setPhoneType() : void +setPhoneValue() : void
+getPhoneFormat4() : String
+isValidPhoneValue() : Boolean +setPhoneType() : void
+getPhoneFormat5() : String
+getPreferredFormatString() : String +isValidPhoneValue() : Boolean
+getPhoneFormat6() : String
+getReformattedPhoneValue() : String +getPreferredFormatString() : String
+getPhoneFormat7() : String
+getReformattedPhoneValue() : String
+getPhoneFormat8() : String
+getPhoneFormat9() : String
180
Algorithm Components Phone Type Validation

1. Implementation class contains hand coded logic


2. _Gen class has methods for soft parameters (as specified
on Algorithm Type definition)
Note: Generated from annotations in _Impl class
interface
AlgoritmSpot
+invoke()

interface
PhoneTypeFormatValidationAlgorithmSpot
+setPhoneValue() : void V2.0.10 +
+setPhoneType() : void
+isValidPhoneValue() : Boolean
+getPreferredFormatString() : String
+getReformattedPhoneValue() : String

2 V2.0.6
PhoneTypeFormatValidationAlgComp_Gen 1
PhoneTypeFormatValidationAlgComp_Impl
interface
+getPhoneFormat1() : String
PhoneTypeFormatValidationAlgComp
+getPhoneFormat2() : String
+setPhoneValue() : void +invoke() : void
+getPhoneFormat3() : String
+setPhoneType() : void +setPhoneValue() : void
+getPhoneFormat4() : String
+isValidPhoneValue() : Boolean +setPhoneType() : void
+getPhoneFormat5() : String
+getPreferredFormatString() : String +isValidPhoneValue() : Boolean
+getPhoneFormat6() : String
+getReformattedPhoneValue() : String +getPreferredFormatString() : String
+getPhoneFormat7() : String
+getReformattedPhoneValue() : String
+getPhoneFormat8() : String
+getPhoneFormat9() : String
181
Algorithm Components Phone Type Validation

3. Generated component interface class also


contains factory class to create instance of
algorithm component well see example shortly
interface
AlgoritmSpot
+invoke()

interface
PhoneTypeFormatValidationAlgorithmSpot
+setPhoneValue() : void V2.0.10 +
+setPhoneType() : void
+isValidPhoneValue() : Boolean
+getPreferredFormatString() : String
+getReformattedPhoneValue() : String

V2.0.6
PhoneTypeFormatValidationAlgComp_Gen
3 PhoneTypeFormatValidationAlgComp_Impl
interface
+getPhoneFormat1() : String
PhoneTypeFormatValidationAlgComp
+getPhoneFormat2() : String
+setPhoneValue() : void +invoke() : void
+getPhoneFormat3() : String
+setPhoneType() : void +setPhoneValue() : void
+getPhoneFormat4() : String
+isValidPhoneValue() : Boolean +setPhoneType() : void
+getPhoneFormat5() : String
+getPreferredFormatString() : String +isValidPhoneValue() : Boolean
+getPhoneFormat6() : String
+getReformattedPhoneValue() : String +getPreferredFormatString() : String
+getPhoneFormat7() : String
+getReformattedPhoneValue() : String
+getPhoneFormat8() : String
+getPhoneFormat9() : String
182
Algorithm Implementation Class
Base versions of all algorithms provided by SPL
To create new one, easiest to duplicate
appropriate base one if exists and modify
Basic Java elements of new algorithm
_Impl class implementation class that contains logic
_Gen class implementation class for soft parameters
generated by AG
Component interface class generated by AG
Message method if required

183
Algorithm Phone Format Example
1

3
4
Annotation specifies
1. Algorithm entity i.e. where in system used corresponds with entity
defined on Algorithm Type (we will see shortly how to determine this
name)
2. Soft parameters expected correspond with Algorithm Type
parameter definitions
184
Algorithm Phone Format Example
1

3
4
Class name
3. Has Algorithm Component name (as specified on Algorithm Type) +
_Impl
4. Extends _Gen class generated by Artifact Generator

185
Algorithm Phone Format Example
Algorithm Spot interface methods that are implemented in _Impl class

These methods invoked by business component


to set hard parameters
1. Sets phone number to validate stored here for use later
2. Sets phone type ignored in this algorithm

186
Algorithm Phone Format Example
Algorithm Spot interface methods that are implemented in _Impl class

invoke() method called to validate and format phone


number
1. Sets Boolean based on validity

187
Algorithm Phone Format Example
Algorithm Spot interface methods that are implemented in _Impl class
1

These methods called from business component


after invoke() method
1. Returns true/false to indicate validity of phone number
2. Returns reformatted value
188
Algorithm Phone Format Example
Algorithm Spot interface methods that are implemented in _Impl class
1

These methods called from business component


after invoke() method
3. Returns default phone format always first one (e.g. 1st
format for U.K. 999 9999-9999)
189
Algorithm Phone Format Example
Generated artifacts based on _Impl class annotation

_Gen class has methods for soft parameters


Methods called from _Impl class to get soft parameter
values
190
Algorithm Phone Format Example
Generated artifacts based on _Impl class annotation

Component interface defines required methods


for _Impl class viewed from application
(business component)
191
Algorithm Phone Format Example
Generated artifacts based on _Impl class annotation

1
2

1. Artifact Generator also generates static Factory class in


component interface class file
2. Contains newInstance() method to create instance of
algorithm component at runtime
192
Algorithm Entity
Determines where in system algorithm is invoked e.g.
phone number validation, adhoc characteristic
validation, SA creation, etc.
Entity defined on Algorithm Type definition

Entity also defined in _Impl class annotation

Entity name must be determined before implementation


class can be created
CI_LOOKUP_VAL table contains the name
Use following query

193
Algorithm Entity Query

1 2

1. Algorithm Entity specified on Algorithm Type definition


2. algorithmEntityValue set in annotation
194
Algorithm Implementation Class Review
Steps to create new class
1. Identify algorithm entity
2. Determine entity value from CI_LOOKUP_VAL table
3. Create _Impl class and extend it from _Gen
4. Code annotation
5. Run Artifact Generator to create _Gen and component
interface classes
In Eclipse, MUST refresh project after this!
6. Edit _Impl class
Extend _Gen
Implement all methods
Code invoke() method
195
Algorithm Implementation Class Review
Steps to create new class
7. Create Algorithm Type definition Java class name will
now be in Program Name drop-down list
8. Create Algorithm definition
9. Attach algorithm to business component
10. Test

196
Exercise 8 Geographic Type Algorithm
In this exercise you will create a Geographic
Type algorithm to validate geographic type
REGION on Premise
Scenario
1. Premises may be in North America or Europe
2. Within North America, country may be U.S.A. or Canada
3. Within Europe, country may be United Kingdom or France
4. Geographic type of region must be created to allow for
region code to be specified on premise

197
Exercise 8 Geographic Type Algorithm
Scenario
5. Format of region code is W-CC
W = World Region N (North America); E (Europe)
CC = Country Code US (USA); CN (Canada); UK (UK);
FR (France)
Algorithm must validate country code for region e.g. E-FR
is valid; E-US is invalid

6. Valid region code values must be specified as soft


parameters i.e. no hardcoding of values in Java
Following are exercise notes to help guide

198
Exercise 8 Geographic Type Algorithm
Java
Algorithm Entity is Geographic Type Value Format
Rule (determine Java annotation name from this)
Name your class XXGeoTypeRegionAlgComp_Impl
Create 2 parameters
1. worldRegion, string, required
Will contain 1-digit world region code
2. countryCodes, string, required
Will contain comma-delimited string of valid country codes for
associated world region
Note: To avoid naming conflicts on the server, use a 2-digit identifier
(e.g. initials) in your Java class names and online algorithm definitions.
Denoted by XX in these exercise notes
199
Exercise 8 Geographic Type Algorithm
Online Configuration
Create Algorithm Type XXGEOREGION with necessary
parameter definitions
Create 2 Algorithm definitions
1. XXGEOREG-E
Specifies Europe and valid countries
2. XXGEOREG-N
Specifies North America and valid countries

Note: To avoid naming conflicts on the server, use a 2-digit identifier


(e.g. initials) in your Java class names and online algorithm definitions.
Denoted by XX in these exercise notes
200
Exercise 8 Geographic Type Algorithm
Online Configuration
Create 2 new Geographic Types
1. XXREG-E
Validation format algorithm is XXGEOREG-E
2. XXREG-N
Validation format algorithm is XXGEOREG-N

Test
When adding/changing a geographic type on Premise,
algorithm should validate format and content of geo type

Note: To avoid naming conflicts on the server, use a 2-digit identifier


(e.g. initials) in your Java class names and online algorithm definitions.
Denoted by XX in these exercise notes
201
Algorithms
Part II

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


Exercise 9 Adhoc Char Value Algorithm
Last exercise could not reformat region code
Geographic Type algorithm does not provide for
that
In this exercise you will create an Adhoc
Characteristic Value validation algorithm to
validate and format a new Premise Characteristic
Type of REGION
Scenario same as before except
Characteristic Type of region must be created
Country code may be entered without world region code
Algorithm will format region code into W-CC format
Will display custom error message for invalid region code
203
Exercise 9 Adhoc Char Value Algorithm
Java
Create new message constant and method for runtime
message (not declarative)
Message text should be
XX Country code %1 not valid for region %2
(Note: should contain your initials)
Use message number > 10000
Add CustomMessages constant for your message
Add method for message to MessageRepository class in
characteristicType package
Message takes 2 parameters world region code and country
code method must substitute them in message text

204
Exercise 9 Adhoc Char Value Algorithm
Java
Algorithm Entity is Char Type - Adhoc Value Validation
(determine Java annotation name from this)
Name your class XXAdhocRegionValidationAlg_Impl
Create same 2 parameters as before
invoke() method must
1. Format region code for example
CN formatted to N-CN
EFR formatted to E-FR
2. Validate it if setFormatOnly() method invoked with true
3. Display custom error message if region code invalid

205
Exercise 9 Adhoc Char Value Algorithm
Online Configuration
Create Algorithm Type XX-AV-REGION with necessary
parameter definitions
Create 2 Algorithm definitions
1. XX-AV-REG-E - specifies Europe and valid countries
2. XX-AV-REG-N - specifies North America and valid countries

Create 2 Characteristic Type definitions


1. XX-REG-E to validate European region
2. XX-REG-N to validate North American region

Both must be of type Adhoc Value


Characteristic Entity (2nd Tab) must be Premise
206
Exercise 9 Adhoc Char Value Algorithm
Online Configuration
Use Admin menu to create new message in category
90000
XX Country code %1 not valid for region %2
(place your initials in the message)

Test
When adding/changing Premise Characteristic of
region, algorithm should format region code, validate
and display custom message if invalid

207
SPL Batch
Part I

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


SPL Batch I
In this section we will look at
Brief overview of SPL batch environment
Overview of batch controls
Batch programming in Java

209
Batch Environment
Batch programs run outside of web app server,
but within SPL Framework context
SPL Framework provides access to SPL business
entities and other objects
Therefore, all programs run under Java even
COBOL
For COBOL, all SQL calls handled by SPL
Framework no direct calls to Oracle/DB2/SQL
Server

210
Batch Threading
SPL system uses threading to achieve maximum
performance
What does a threaded process do?
Determines full workload (e.g. how many accounts?)
Divides workload into n number of threads
Dispatches each thread to perform workload concurrently
For example, instead of one task billing 50000
accounts, 5 tasks each bill 10000 accounts
simultaneously naturally much faster
SPL Artifact Generator creates necessary
components for multi-threading
211
Batch Control
SPL system uses batch controls for batch
processing
Mechanism to control restartibility, program
identification, parameters, etc.
Each batch process has own batch control code
Batch control code defines
Program name
Program type (COBOL / Java)
Parameters

For example
212
Batch Control Java Example

2
3

4
5

1. Batch Control code


2. Program Type
3. Program Name
213
Batch Control Java Example

2
3

4
5

4. Batch run number of next submission


5. Check to accumulate records processed counts for all instances of
one job if job fails and restarts, will add failed + restarted
instance for total records processed
214
Batch Control Java Example

2
3

4
5

6. Non-standard parameters for batch process these parameters are


prompted for after standard parameters
Supplied at runtime using name=value pairs, e.g.
FILE-PATH=/spl/data
215
Batch Process
Background process consists of 2 types of
classes
1. BatchJob
2. ThreadWorker
BatchJob class determines work to be
processed and splits it into pieces
Each piece of work processed by instance of
ThreadWorker
Lets take a look at these two components

216
Batch Process

BatchJob determines work and divides it into manageable chunks


(ThreadWork)
Each ThreadWork consists of WorkUnits
WorkUnits represent fine-grained units of work e.g. a bill
217
Batch Process

ThreadWorker responsible for processing single ThreadWork instance


Each ThreadWorker corresponds to one batch instance row on
database used for restart after failure

218
BatchJob Class
BatchJob class contains annotation
@BatchJob (rerunnable = false, 1
2 multiThreaded = true,
3 modules={todo},
4 softParameters = { @BatchJobSoftParameter
(name=OUTPUT-DIR, type=string) },
5 toDoCreation = @ToDoCreation (
drillKeyEntity = user,
sortKeys = {lastName, firstName},
messageParameters = {firstName, lastName}
)
)
1. rerunnable indicates if job can be rerun e.g. bill print extract
2. multiThreaded tells framework if job can accept thread count > 1
3. modules contains modules program belongs to should be empty for
customizations
4. Non-standard parameters to prompt for
5. Specifies how ToDo entries should be created in case of errors
219
BatchJob Class
BatchJob class should extend <BatchJob class
Name>_Gen e.g.

public class BatchErrorToDoCreation


extends BatchErrorToDoCreation_Gen {

Method getJobWork()
Determines work (using Hibernate query) (Investigate this
statement) Query MUST return Business Entity instances not true if
createJobWorkForEntityQuery not used to return JobWork objects
Passes back instance of JobWork describing work to be done
JobWork instance contains appropriate number of ThreadWork
instances (based on runtime thread count)
Each ThreadWork instance contains same number of
ThreadWorkUnits
Convenience method exists for all this!
220
BatchJob Class
Method getThreadWorkerClass()
Passes back class name of worker class i.e. hand
coded class to perform batch work
Framework will create instance of this class for each
ThreadWork instance
Passing back class name (instead of object) allows
framework to control instantiation e.g. on different
server

221
ThreadWorker Class
Responsible for processing single ThreadWork instance
performs heavy lifting
ThreadWorker can be executed on same or different
server as BatchJob and other ThreadWorker instances
ThreadWorker class name should extend
<ThreadWorker class name>_Gen
By convention ThreadWorker class coded as static inner
class of BatchJob class
public class BatchErrorToDoCreation
extends BatchErrorToDoCreation_Gen {
... BatchJob methods ...
public static class BatchErrorToDoCreationWorker
extends BatchErrorToDoCreationWorker_Gen {
... ThreadWorker methods ...
}
}
222
ThreadWorker Class
Method createExecutionStrategy()
Tells framework how work for thread will be processed
Returns instance of ThreadExecutionStrategy, of which
following implementations currently exist
1. SingleTransactionStrategy
Process all work in single transaction (logical unit of work)
Failure results in rollback of entire threads updates
Most appropriate to jobs that CANNOT tolerate errors in middle of
run e.g. Interfaces from flat files
2. CommitEveryUnitStrategy
Processes each ThreadWorkUnit in its own transaction i.e.
issues commit after each successful transaction
Most appropriate to jobs that CAN tolerate errors

223
ThreadWorker Class
Method InitializeThreadWork(boolean)
Called by framework at start of thread run for initialization
By default does nothing
Can be overridden to open files, initialize variables, etc.
Boolean parameter indicates if has been called previously

Method executeWorkUnit(ThreadWorkUnit)
Invoked once for each ThreadWorkerUnit assigned to ThreadWorker
For example, for thread processing 1000 accounts, this method will
be called 1000 times
Performs actual work e.g. process account for billing
ThreadWorkUnit parameter has reference to Business Entity to be
processed via its getPrimaryId method

224
ThreadWorker Class
Method finalizeThreadWork()
Called at end of thread processing
Used to clean up after thread e.g. close files

These are basic building blocks for batch class


Lets look at example

225
BatchJob Example Create Batch Error ToDos
Annotation and class definition
/**
* @BatchJob (rerunnable = false,
* multiThreaded = false, 1
* modules={todo})
*/
public class CmBatchErrorToDoCreation 2
extends CmBatchErrorToDoCreation_Gen {
private static final com.splwg.shared.logging.Logger logger =
3 com.splwg.shared.logging.LoggerFactory.
getLogger(CmBatchErrorToDoCreation.class);
...
1. Annotation specifies not rerunnable, not multi-threaded,
ToDo module
2. BatchJob class extends _Gen class
3. Static definition of logger to log messages at runtime

226
BatchJob Example Create Batch Error ToDos
Methods
public JobWork getJobWork() {
1 Query errorRunQuery = createQuery("from BatchRun run +
where run.runStatus = :runStatus");
2 errorRunQuery.bindLookup("runStatus",
3 RunStatusLookup.constants.ERROR);
return createJobWorkForEntityQuery(errorRunQuery);
}

4 public Class getThreadWorkerClass() {


return CmBatchErrorToDoCreationWorker.class;
}

1. getJobWork method sets up query for work retrieves


BatchRun objects (CI_BATCH_RUN) with error status
2. Binds error status to query
3. Returns to framework JobWork object contains array of
ThreadWork objects, each with ThreadWorkerUnits
227
BatchJob Example Create Batch Error ToDos
Methods
public JobWork getJobWork() {
1 Query errorRunQuery = createQuery("from BatchRun run +
where run.runStatus = :runStatus");
2 errorRunQuery.bindLookup("runStatus",
3 RunStatusLookup.constants.ERROR);
return createJobWorkForEntityQuery(errorRunQuery);
}

4 public Class getThreadWorkerClass() {


return CmBatchErrorToDoCreationWorker.class;
}

4. getThreadWorkerClass returns name of ThreadWorker


class defined as inner class (next slide)

228
BatchJob Example Create Batch Error ToDos
Inner Thread Worker class definition
public static class CmBatchErrorToDoCreationWorker
extends CmBatchErrorToDoCreationWorker_Gen {
...
Class defined in same source file as BatchJob class i.e.
defined as inner class
Name corresponds with class name passed back from
getThreadWorkerClass method
Extends _Gen thread worker class (created by Artifact
generator)

229
BatchJob Example Create Batch Error ToDos
Inner Thread Worker methods
public ThreadExecutionStrategy createExecutionStrategy() {
// Commit on every todo. This is not expected to be a
// performance intensive process.
return new CommitEveryUnitStrategy(this);
}
createExecutionStrategy tells framework job wants to
commit after each transaction
In this case, after each ToDo has been created

230
BatchJob Example Create Batch Error ToDos
Inner Thread Worker methods
public void initializeThreadWork(
boolean initializationPreviouslySuccessful)
throws ThreadAbortedException, RunAbortedException {
// determine the ToDoType_Id that should be used by querying
// the ToDoTypes for an entry with the creation process equal
// to this one.
Query toDoTypeQuery = createQuery("from ToDoType type
where type.creationProcessId = :thisBatchControlId");
...
initializeThreadWork here determines ToDo type to be
used when creating ToDos

231
BatchJob Example Create Batch Error ToDos
Inner Thread Worker methods
1 public boolean executeWorkUnit(ThreadWorkUnit unit)
throws ThreadAbortedException, RunAbortedException {
2 BatchRun_Id errorBatchRunId = (BatchRun_Id) unit.getPrimaryId();
// get the run
3
BatchRun batchRun = errorBatchRunId.getEntity();
4 if (isNull(batchRun)) {
...
1. executeWorkUnit called for each batch run in error
2. Gets primary Id from ThreadWorkUnit parameter cast to
BatchRun_Id, as expected
3. Uses Id to get BatchRun entity
4. Creates ToDo entries
Note example does not implement finalizeThreadWork
method
232
BatchJob Creation Review
To create a new BatchJob class
1. Create annotation and run Artifact Generator (refresh Eclipse project)
2. Extend class from _Gen BatchJob class
3. Code getJobWork and getThreadWorker methods
4. Create inner ThreadWorker class - extend from _Gen ThreadWorker
class
5. Code createExecutionStrategy method
6. Code initializeThreadWork method (if needed)
7. Code executeWorkUnit method
8. Code finalizeThreadWork method (if needed)
9. Create batch control

233
Exercise 10 Batch 1
Create batch program to identify Persons
without Accounts and log their info
Name program XXPersonsNoAccount (substitute your
initials for XX)
Identify persons as follows
from Person as per where not exists (from AccountPerson ap
where ap.id.person = per)
In executeWorkUnit method display person Id and person
name (first name only) use logger.info() method for
display output should look like this
Person without Account 4470529669 French,John
Person without Account 3909447990 Reliable Energy
Person without Account 4752724309 MeterCorp
...

234
Exercise 10 Batch 1
Additional notes
ThreadWorkUnit parameter has method getPrimaryId to
get Person_Id object
From this, determine Person and PersonName for
sequence 1
Display both Person Id and Entity Name
Use StandaloneExecuter launch configuration from
Eclipse to run your job

235
SPL Batch
Part II

SPL Technical Training

2006 SPL WorldGroup. Confidential & Proprietary


SPL Batch II - ToDos
In this section we look at how to create ToDos
in batch process
Previous example (BatchErrorToDoCreation)
class does that
Runs through all batch program errors
(CI_BATCH_RUN rows with status = error) and
creates ToDo for each
ToDo table structure looks as follows

237
SPL Batch II ToDo Data Model
4 CI_MSG 5 CI_BATCH_CTRL CI_TD_MSG_PARM
C PK
PK
MESSAGE_CAT_NBR
MESSAGE_NBR
PK BATCH_CD
PK,FK1 TD_ENTRY_ID P
O FK1 TD_TYPE_CD
PROGRAM_NAME
PK SEQ_NUM
R
MSG_PARM_VAL
N O
2 CI_TD_DRLKEY_TY
F PK,FK1 TD_TYPE_CD
1 CI_TD_TYPE CI_TD_ENTRY CI_TD_DRLKEY
G
PK,FK1 TD_ENTRY_ID
I PK SEQ_NUM PK TD_TYPE_CD PK TD_ENTRY_ID
PK SEQ_NUM R
FK1 TD_TYPE_CD
G FLD_NAME
TBL_NAME
CRE_BATCH_CD
FK1 MESSAGE_CAT_NBR KEY_VALUE
A
FK1 MESSAGE_NBR
U 3 CI_TD_SRTKEY_TY FK2 BATCH_CD CI_TD_SRTKEY M
R PK,FK1 TD_TYPE_CD
PK SEQ_NUM
PK,FK1
PK
TD_ENTRY_ID
SEQ_NUM
M
E DEFAULT_SW KEY_VALUE E
D ORDER_FLG
D
Entries on left are set up in Admin menu
1. ToDo Type identifies type of ToDo
2. Drill Key Type when user selects ToDo to work, where to go
3. Sort Key Type how to sort ToDo list
4. Message for ToDo list
5. Batch Control that created ToDo
238
SPL Batch II ToDo Data Model
CI_MSG CI_BATCH_CTRL
4 CI_TD_MSG_PARM
C PK
PK
MESSAGE_CAT_NBR
MESSAGE_NBR
PK BATCH_CD
PK,FK1 TD_ENTRY_ID P
O FK1 TD_TYPE_CD
PROGRAM_NAME
PK SEQ_NUM
R
MSG_PARM_VAL
N O
CI_TD_DRLKEY_TY
F PK,FK1 TD_TYPE_CD
CI_TD_TYPE 1 CI_TD_ENTRY 2 CI_TD_DRLKEY
G
PK,FK1 TD_ENTRY_ID
I PK SEQ_NUM PK TD_TYPE_CD PK TD_ENTRY_ID
PK SEQ_NUM R
FK1 TD_TYPE_CD
G FLD_NAME
TBL_NAME FK1
CRE_BATCH_CD
MESSAGE_CAT_NBR KEY_VALUE
A
FK1 MESSAGE_NBR
U CI_TD_SRTKEY_TY FK2 BATCH_CD
3 CI_TD_SRTKEY M
R PK,FK1
PK
TD_TYPE_CD
SEQ_NUM
PK,FK1
PK
TD_ENTRY_ID
SEQ_NUM
M
E DEFAULT_SW KEY_VALUE E
D ORDER_FLG
D
Entries on right are created programmatically
1. ToDo Entry one row per ToDo entry
2. Drill Key contains key value (e.g. person Id) to use for drill down
3. Sort Key contains value to sort on (e.g. person name)
4. Message Parameter contains values for message substitution
239
Exercise 11 Batch 2
Modify previous exercises class to create ToDo entries
for Persons without Accounts
Instructor will supply template for ToDo creation
methods
Note: Substitute XX with your initials in all definitions
Create new batch control XX-TDPNA

240
Exercise 11 Batch 2
Create new message XX Person %1 has no Accounts

ToDo type - Main

241
Exercise 11 Batch 2
ToDo Type Roles

ToDo Type Sort Keys

ToDo Type Drill Keys

242
Exercise 11 Batch 2
In case of errors, run following delete statements
and re-execute batch
delete from ci_td_drlkey
where td_entry_id in (select td_entry_id from ci_td_entry
where td_type_cd = XXTDPNA');
delete from ci_td_srtkey
where td_entry_id in (select td_entry_id from ci_td_entry
where td_type_cd = XXTDPNA');
delete from ci_td_msg_parm
where td_entry_id in (select td_entry_id from ci_td_entry
where td_type_cd = XXTDPNA');
delete from ci_td_entry where td_type_cd = XXTDPNA'
Run batch program and test ToDo
Should show message with person name substituted
Should be sorted in person name ascending sequence
Should be able to drill into person from ToDo
243