Professional Documents
Culture Documents
Framework
HTT
P
Oracle
Servlets/XSLT Services Persistent
JavaScript/ DB2/UDB
Entities
XSLT Caches Data Service
Objects Hibernate MSSQL
Session State (Java/COBOL)
JDBC
HTT
P
Oracle
Servlets/XSLT Services Persistent
JavaScript/ DB2/UDB
Entities
XSLT Caches Data Service
Objects Hibernate MSSQL
Session State (Java/COBOL)
JDBC
3
Logical Architecture
HTT
P
Oracle
Servlets/XSLT Services Persistent
JavaScript/ DB2/UDB
Entities
XSLT Caches Data Service
Objects Hibernate MSSQL
Session State (Java/COBOL)
JDBC
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
HTT
P
Oracle
Servlets/XSLT Services Persistent
JavaScript/ DB2/UDB
Entities
XSLT Caches Data Service
Objects Hibernate MSSQL
Session State (Java/COBOL)
JDBC
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
HTT
P
Oracle
Servlets/XSLT Services Persistent
JavaScript/ DB2/UDB
Entities
XSLT Caches Data Service
Objects Hibernate MSSQL
Session State (Java/COBOL)
JDBC
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
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
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
Person
CI_PER
CI_PER
Page
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
+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
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
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
+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();
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();
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);
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();
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();
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
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
49
Eclipse IDE Menu Bar
51
Eclipse CM1 Project
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
57
Change Handlers
Part I
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
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);
}
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!
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 {
74
Unit Testing - JUnit
Now we add a method for each test case
public void testEmailRequiredRule() {
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);
}
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);
}
}
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
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
88
Message Categories Substitution Variables
will be displayed as
Bill Cycle field missing
%1
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
addError(StandardMessages.fieldMissing("EMAILID"));
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
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;
}
}
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);
}
parms.addField(fieldName1);
parms.addField(fieldName2);
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
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
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
119
Custom Rule MapFieldNameRequired Example
1
2
120
Custom Rule MapFieldNameRequired Example
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
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
129
Hibernate Persistent Objects
With Hibernate you access tables as objects
Object can be loaded from DB if identifier is known
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
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);
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
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();
...
}
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
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
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
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
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
159
Algorithms
Part I
163
Algorithm Database Model
1 CI_ALG_TYPE CI_ALG Customized Entity
PK ALG_TYPE_CD PK ALG_CD
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
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
165
Algorithm Database Model
1 CI_ALG_TYPE 3 CI_ALG Customized Entity
PK ALG_TYPE_CD PK ALG_CD
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
166
Algorithm Database Model
1 CI_ALG_TYPE 3 CI_ALG 5 Customized Entity
PK ALG_TYPE_CD PK ALG_CD
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
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_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
2
3
4
170
Algorithm Phone Format Example
Admin -> Algorithm Phone format US
1
1
2
173
Algorithm Phone Format Example
Main -> Person Algorithm activation
1
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
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
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
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
186
Algorithm Phone Format Example
Algorithm Spot interface methods that are implemented in _Impl class
187
Algorithm Phone Format Example
Algorithm Spot interface methods that are implemented in _Impl class
1
1
2
193
Algorithm Entity Query
1 2
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
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
Test
When adding/changing a geographic type on Premise,
algorithm should validate format and content of geo type
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
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
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
2
3
4
5
2
3
4
5
216
Batch Process
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.
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
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);
}
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
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
241
Exercise 11 Batch 2
ToDo Type Roles
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