283
Java Application Development Oracle Utilities Framework

Java Application Development

Embed Size (px)

Citation preview

Page 1: Java Application Development

Java Application Development

Oracle Utilities Framework

Page 2: Java Application Development

2

Day 1 Agenda

• Logical Architectural Overview• OLTP• Batch

• History• Version V1.x• Version V2.x

• Development, Extension and Customization Overview• The Artifact Generator• Entities

• Entity Classes• Entity CRUD• Querying Entities

Page 3: Java Application Development

Logical Architectural Overview

Page 4: Java Application Development

4

Logical Web Architecture

• Information is presented in HTML and JavaScript (no Java applets) through Internet Explorer 6.0

• The browser communicates with the Web App Server via HTTP

HTML

JavaScript/XSLT

Session State

HT

TP

Web Browser

Page 5: Java Application Development

5

Logical Web Architecture

• The Web App Server is divided into logical tiers:• Presentation services• Business logic• Data access

HTML

JavaScript/XSLT

Session State

Presentation

Servlets/XSLT

Caches

Data Access

Persistent Entities

Hibernate

JDBC

Business

Services

Data Service Objects (Java/COBOL)

HT

TP

Web Browser Web Application Server

Page 6: Java Application Development

6

Logical Web Architecture

• In the Presentation Layer …• Java servlets handle the inbound HTTP requests from the browser

• Various static data – e.g. control tables, language-specific messages and labels – are cached

• XSL/T technology is used to create the HTML

• The servlets invoke the data service objects in the business layer as required

HTML

JavaScript/XSLT

Session State

Presentation

Servlets/XSLT

Caches

Data Access

Persistent Entities

Hibernate

JDBC

Business

Services

Data Service Objects (Java/COBOL)

HT

TP

Web Browser Web Application Server

Page 7: Java Application Development

7

Logical Web Architecture

• In the Business Layer …• Data service objects are invoked from the presentation layer• These services ultimately perform the business functions• The service objects themselves are Java, but the business logic

could be implemented in Java or COBOL, or a combination• The data access objects are used to communicate with the

database

HTML

JavaScript/XSLT

Session State

Presentation

Servlets/XSLT

Caches

Data Access

Persistent Entities

Hibernate

JDBC

Business

Services

Data Service Objects (Java/COBOL)

HT

TP

Web Browser Web Application Server

Page 8: Java Application Development

8

Logical Web Architecture

• In the Data Access Layer …• The Hibernate Object Relational Model (ORM) framework is used for

database access and persistence

• The Java Database Connectivity API (JDBC) is used directly (i.e. Hibernate is bypassed) for SQL statements from COBOL

• All database calls are routed through the framework’s data access layer – application programs do not issue direct calls to database

HTML

JavaScript/XSLT

Session State

Presentation

Servlets/XSLT

Caches

Data Access

Persistent Entities

Hibernate

JDBC

Web Browser Web Application Server

Business

Services

Data Service Objects (Java/COBOL)

HT

TP

Page 9: Java Application Development

9

Logical Web Architecture

• Database• Framework supports …

• Oracle

• DB2

• Microsoft SQL Server.

HTML

JavaScript/XSLT

Session State

Presentation

Servlets/XSLT

Caches

Data Access

Persistent Entities

Hibernate

JDBC

Web Browser Web Application Server

Business

Services

Data Service Objects (Java/COBOL)

HT

TP

Oracle

DB2

MSSQL

Database

Page 10: Java Application Development

10

Logical Batch Architecture

• Batch Processing• A scheduler or the command-line is used to invoke the splbatch script

(the scheduler can be a 3rd party OUF’s “cdxcronbatch” scheduler)

• splbatch starts a batch instance of the framework

• The framework controls all batch execution

• Once initialized, splbatch prompts for the batch code of the batch process to execute

splbatch.sh / cmd(command line)

Scheduler

Etc.

splbatch.sh / cmd(command line)

Scheduler

Etc.

Submission

Page 11: Java Application Development

11

Logical Batch Architecture

• Batch Processing• The Standalone Executor invokes the Java/COBOL batch

process, based on the supplied batch control code• The business layer components perform the business functions

(same as online)• The data access layer is used to communicate with the database

(same as online)

splbatch.sh / cmd(command line)

Scheduler

Etc.

splbatch.sh / cmd(command line)

Scheduler

Etc.

Batch Control

Standalone Executor

Batch Process

Data Access

Persistent Entities

Hibernate

JDBC

Submission Batch Server

Business

Data Service Objects (Java/COBOL)

Oracle

DB2

MSSQL

Database

Page 12: Java Application Development

12

Embedded Batch Architecture (option)

• Starting with FW 2.1.0 batch processing can optionally take place on the Web Application Server:

• A scheduling daemon polls for jobs submitted by the online• The local business tier executes the work

Batch Control

Standalone Executor

Batch Process

Data Access

Persistent Entities

Hibernate

JDBC

Web Application Server

Business

Data Service Objects (Java/COBOL)

Oracle

DB2

MSSQL

Database

Page 13: Java Application Development

13

Servers<BizTalk><Body> <AccountInfo> <Request docTynfo"> <Account> <company>99ny> <accountId>5ntId> <area>001</area> </Account> </Request> </AccountInfo> </Body></BizTalk>

XML: Web Services Integration

Real timeinterfaces:

CRM, MS Office,Web Self Service, etc.

DBMS

UI

…etc…

Mass recordIntegration

Outside Agents

Meter data

Billable Charges

ERP / GL

<BizTalk><Body> <AccountInfo> <Request docTynfo"> <Account> <company>99ny> <accountId>5ntId> <area>001</area> </Account> </Request> </AccountInfo> </Body></BizTalk>

<BizTalk><Body> <AccountInfo> <Request docTynfo"> <Account> <company>99ny> <accountId>5ntId> <area>001</area> </Account> </Request> </AccountInfo> </Body></BizTalk>

<BizTalk><Body> <AccountInfo> <Request docTynfo"> <Account> <company>99ny> <accountId>5ntId> <area>001</area> </Account> </Request> </AccountInfo> </Body></BizTalk>

Staging

<BizTalk><Body> <AccountInfo> <Request docTynfo"> <Account> <company>99ny> <accountId>5ntId> <area>001</area> </Account> </Request> </AccountInfo> </Body></BizTalk>

<BizTalk><Body> <AccountInfo> <Request docTynfo"> <Account> <company>99ny> <accountId>5ntId> <area>001</area> </Account> </Request> </AccountInfo> </Body></BizTalk>

<BizTalk><Body> <AccountInfo> <Request docTynfo"> <Account> <company>99ny> <accountId>5ntId> <area>001</area> </Account> </Request> </AccountInfo> </Body></BizTalk>

Mass XML Integration

XML Staging

XAIMPL

Integration Architecture

Page 14: Java Application Development

History

Page 15: Java Application Development

Version 1.x

Page 16: Java Application Development

16

Page Server(Servlet/JSP)

V1.x Technical Architecture Web Server to App Server

Handles service

distribution

WebApplication

Server

BusinessApplication

Server

DatabaseServer

Data Page Conduit

(EJB)

XML

Jolt

WebLogic

TuxedoBusiness Object Conduit

Contains• Tuxedo commun.• Flattener / expander

Business Object

(COBOL)

Tuxedo

Page 17: Java Application Development

17

PersonCI_PER

NameCI_PER_NAME

IDCI_PER_ID

PhoneCI_PER_PHONE

CharCI_PER_CHAR

The entities that hold person information

3 Types Of Programs Involved With The Maintenance Of Objects

• Let’s use an example of the programs used to maintain the person object:

PersonPage

PersonRow

NameList

IDList

PhoneList

Char.List

NameRow

IDRow

PhoneRow

Char.Row

Page programs orchestrate the calls to the various row and list programs

List programs access and updates the rows in a collection. Note, we only update rows that have been changed. You will also find inter-row validation here

Row programs perform validation and updates on a specific row

Page programs perform inter-record validation after row validation / update, but prior to commit

Page 18: Java Application Development

18

PersonPage

PersonRow

NameList

IDList

PhoneList

Char.List

NameRow

IDRow

PhoneRow

Char.Row

PersonWrapper

Issues the rollback and commit so that other programs can call the page program

Where’s The Commit / Rollback

• Tuxedo doesn’t call the page program, it calls the page program’s wrapper• The commit / rollback is issued by the page’s wrapper (the program that

Tuxedo invokes)

Tuxedo

Page 19: Java Application Development

Version 2.x

Transition to Java

Page 20: Java Application Development

20

Transition Strategies

• Persistence• Java persistence layer based on Hibernate that interoperates with

existing COBOL Row program persistence.

• Services• Java service implementation as an alternative to COBOL Page,

List, Search services• A service dispatcher that dispatches service requests

implemented in either Java or COBOL

• Business Interoperability• Business logic implemented in Java, COBOL or scripts can call

each other, usually without knowing the implementation technology of the called code.

Page 21: Java Application Development

21

Business Interoperability

• Expand COBOL• Preprocesses COBOL code to make JNI calls to Java hosting it’s

execution

• AbstractCobolProgram• A Java program that wraps a COBOL program so it can be called

from Java. Typically, COBOL copybooks are processed and a Java API is generated to make programming calls to COBOL easy.

• JavaToCobolGateway/CIPZCTJN• Generalized facility to call arbitrary static Java methods from

COBOL by passing COBOL copybook structures

• Database Session• One consistent session is shared among Java, COBOL and

scripting participants in a business transaction

Page 22: Java Application Development

22

Native Execution Hosting

Native Business

Objects

J2EE Web Application Server

Java Business

Objects

Primary ChildJVM

Non-TCP Communication

Protocol

Failover ChildJVM(s)

Page 23: Java Application Development

Development, Extension and Customization

Page 24: Java Application Development

24

Resources

• Wiki• http://sf-morpheus.splwg.com/ccb• The “CookBook” is the best place to start for most things• Walk-through: look at the wiki

• Product documentation• //documentation/User Doc (Multi Product)

• JavaDocs• Generally, the code is well commented and JavaDocs show up in Eclipse

quite easily.

• Use cases• How are classes used by other classes• Junit tests

• A fantastic resource for discovering how a developer intended a class to be used

• A fantastic resource for discovering that the developer misunderstood the requirements or didn’t test his or her code

Page 25: Java Application Development

25

The Application Stack

• The running system is really a composite of stacked applications configured at runtime• Example: base, ccb, mtm, cm

• Applications initialize the lower application in the stack and then overlay higher applications

• Applications are developed by independent teams:• May not change applications lower on the stack• May not depend on applications higher on the stack

Page 26: Java Application Development

26

Perforce Locations

• Each application has it’s own root node in depot• Example: FW, C1, O2

• Within each version of the application (2.1.0, 2.2.0, etc) there are three important folders: modules, projects, tools

• Modules• Code that makes up the deliverable application• “lib” includes jar dependencies from third parties or lower

applications on the stack• “source” includes application source and tests• “dist” includes other resources/executables from third parties or

lower applications on the stack (I.e. COBOL object code)

Page 27: Java Application Development

27

Perforce Locations (cont)

• Projects• Represents files configuring the development process• Eclipse projects are configured here• Wiring for the Maven build• Configuration of the shared development servers

• Tools• Contains software needed to develop• Eclipse• Tomcat• Ant• Java

Page 28: Java Application Development

28

Introduction to Eclipse

• Walk-through• See project structure• Typical sync

• Perforce sync

• Artifact generator build

• Refresh

• Launch Tomcat

• Look at Perforce integration

Page 29: Java Application Development

29

Package Structures

• com.splwg.base.api.*• Framework APIs that applications may code against

• com.splwg.shared.*• Classes that are shared between the runtime application and the

build-time code (I.e. the Artifact Generator)• Includes some very useful classes:

• Logger

• StringUtilities

• ApplicationException

• com.splwg.mtm.domain.*• Domain logic for the “mtm” application• Typically a new package for each Maintenance Object

Page 30: Java Application Development

The Artifact Generator

An Introduction

Page 31: Java Application Development

31

What is the Artifact Generator

• We generate both Java source and XML documents via a stand-along Java program called the “Artifact Generator”

• The Artifact generator:• Parsed Java source files to extract

• Knowledge of public methods and variables

• Comments so that they can helpfully be added to generated business interfaces

• Annotations embedded in comments that define metadata coupled to the code

• COBOL source to build up Java representations of the COBOL programs and copybooks for COBOL-Java interoperability

• Database Metadata to understand the structure of Tables, Fields and Constraints

Page 32: Java Application Development

32

Why do we generate artifacts?

• To create classes that Humans can code to• Business Interfaces with proper “getters” and “setters”• Helpful methods on abstract superclasses specific to the class

that someone is coding

• To capture details only available from the source code at build time because the source code is not available at runtime• Example: the structure of COBOL copybooks

Page 33: Java Application Development

Entities

Page 34: Java Application Development

34

What are Entities?

• Entity Classes • Classes wired into the Hibernate Object-Relational Mapping

framework to provide persistence

• Entity Objects • Instances of Entity Classes representing rows on the database

• Entity Layer• The layer logically between the database and the service layer• Contains families of classes that facilitate the basic CRUD of rows

on the database

Page 35: Java Application Development

35

Entity Layer Classes

• Walk-through: Take a look at “Currency” in FW• Hand-coded persistence classes

• Entity “Impl” (Currency_Impl) defines basic persistence• Change Handler (Currency_CHandler) defines validation and

cascading changes• Message Repository (MessageRepository) defines new messages

used by this package

• Hand-coded maintenance (service layer) classes• List Maintenance (CurrencyListMaintenance) defines a service

callable via the online• Entity Code Description Query (CurrencyCodeDescriptionQuery)

defines a service that returns descriptions of the rows, ostensibly for caching

Page 36: Java Application Development

36

Generated Entity Layer Classes

• Business Interface (Currency) • Defines the interface that client objects should talk to

• ID (Currency_ID) • Defines a prime key class

• Data Transfer Object (Currency_DTO) • Defines a transient data structure holding the properties of the entity

• Entity “Gen” (Currency_Gen) • Defines the abstract superclass of the “Impl”. Mostly this give

convenient accessors to program business methods on the “Impl”.

• Language classes (Currency_Language and Currency_LanguageId) • Provides language support

• POJO (Currency_POJO and others)• Provides support for the HQL query tool. Not used by the running

system.

Page 37: Java Application Development

37

Generated Entity Configuration Files

• Hibernate Mappings (*.hbm.xml)• Loaded at runtime to wire up Hiberate

• Info Data (*.info.xml)• Provides runtime metadata about the entity for the framework

• packageMetaInfo.xml• Bootstrapping metadata used by the framework to discover and

wire up the package

Page 38: Java Application Development

38

Prerequisite Database Metadata

• Some metadata data needs to be defined in framework tables before the artifact generator is run• Table, Field, TableField and Contraint defines the structure of the

tables that the entities must map to• Lookups need to be defined because classes are generated which

allow Java code to directly reference lookup values• Maintenance Objects values drive

• Validations in the artifact generator that prevent incorrect parent-child relationships from being defined and other issues

• Maintenance generation using the “MO Wizard” which we’ll discuss later.

Page 39: Java Application Development

Working with Entities

Page 40: Java Application Development

40

Inside Business Entities• In general, a Business Entity class exists for each table in

the system• The example here illustrates the Person and Person Name

tables and their related classes

+createDTO()

AbstractBusinessEntity

+getId()+getAddress()

-id-address1

Person_Gen

Person_Impl

+getId()+getEntityName()

-id-entityName

PersonName_Gen

PersonName_Impl

Person InterfacePersonName

Interface

CI_PER

PK PER_ID

ADDRESS1

CI_PER_NAME

PK,FK1 PER_IDPK SEQ

ENTITY_NAME

Page 41: Java Application Development

41

Business Entity related classes are divided into 3 categories:1. Framework

2. Generated

3. Hand-coded

Business Entity and Related Classes

+createDTO()

AbstractBusinessEntity

+getId()+getAddress()

-id-address1

Person_Gen

+getInfo()

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

«interface»Person

AbstractDataTransferObject

Person_DTO

StringId

Person_Id

AbstractEntityList

+add()+remove()

PersonNames_Impl

«interface»SimpleEntityList

«interface»PersonNames

Page 42: Java Application Development

42

• The goal of the 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

Business Entity and Related Classes

+createDTO()

AbstractBusinessEntity

+getId()+getAddress()

-id-address1

Person_Gen

+getInfo()

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

«interface»Person

AbstractDataTransferObject

Person_DTO

StringId

Person_Id

AbstractEntityList

+add()+remove()

PersonNames_Impl

«interface»SimpleEntityList

«interface»PersonNames

Page 43: Java Application Development

43

• Let’s look at how the classes below are used• Business Entities• Data Transfer Objects (DTOs)• String Ids• Entity Lists

Business Entity and Related Classes

+createDTO()

AbstractBusinessEntity

+getId()+getAddress()

-id-address1

Person_Gen

+getInfo()

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

«interface»Person

AbstractDataTransferObject

Person_DTO

StringId

Person_Id

AbstractEntityList

+add()+remove()

PersonNames_Impl

«interface»SimpleEntityList

«interface»PersonNames

Page 44: Java Application Development

44

• The Java programs typically do not call the database directly; they use the Business Entities where possible

• For example, to fetch a Person from the database

Person_Id perId = new Person_Id("1185477091");Person perEntity = perId.getEntity();

Working with Business Entities

AbstractBusinessEntity

+getId()+getAddress()

-id-address1

Person_Gen

+getInfo()

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

«interface»Person

Page 45: Java Application Development

45

Query query = createQuery("from Person");Person perEntity = null;QueryIterator qIter = query.iterate();while (qIter.hasNext()) {

perEntity = (Person)qIter.next();...

}

• To fetch multiple persons from the databaseWorking with Business Entities

AbstractBusinessEntity

+getId()+getAddress()

-id-address1

Person_Gen

+getInfo()

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

«interface»Person

This is an early introduction to our Java Persistence Framework (JPF) & Hibernate. JPF & Hibernate are discussed in detail later, but we will see more references to them over the following slides

Page 46: Java Application Development

46

• The framework creates instances of Business Entities when fetching data – for examplePerson perEntity = perId.getEntity();

or

Person perEntity = (Person)qIter.next();

will create a new instance of Person• Therefore: An instance (object) of a Business Entity class

represents a row in a database table

Working with Business Entities

PER_ID ADDRESS1 …

1550000001 Easy Street …

7804500002 Penny Lane …

id = 1550000001address1 = Easy Street

Person : Person_Implid = 1550000001address1 = Easy Street

Person : Person_Impl

id = 7804500002address1 = Penny Lane

Person : Person_Implid = 7804500002address1 = Penny Lane

Person : Person_Impl

Page 47: Java Application Development

47

Working with Business Entities• Creating a new instance of a Business Entity creates a new

database row (when the transaction commits)• Likewise, when changing or deleting an instance, the

database row is updated or deleted (when the transaction commits)

• The database commit happens at the framework’s discretion – the application code has no direct control over it

PER_ID ADDRESS1 …

1550000001 Easy Street …

7804500002 Penny Lane …

id = 1550000001address1 = Easy Street

Person : Person_Implid = 1550000001address1 = Easy Street

Person : Person_Impl

id = 7804500002address1 = Penny Lane

Person : Person_Implid = 7804500002address1 = Penny Lane

Person : Person_Impl

Page 48: Java Application Development

48

• A Business Entity has “getters” (get methods) for retrieval of its propertiesExample

Person perEntity = (Person)query.firstRow();String emailAddress = perEntity.getEmailAddress();

Will retrieve a person’s email address

• Most getters are specific to an object (e.g. emailAddress on Person), but there are common ones• getId() retrieves identifier (Account Id,

Person Id, Premise Id, etc.) depending on the object• getDTO() retrieves an instance of a Data Transfer

Object (DTO) for the Business Entity

Getting Entity Properties

AbstractBusinessEntity

+getId()+getAddress()

-id-address1

Person_Gen

+getInfo()

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

«interface»PersonMore about Ids and DTOs in a

minute…

Page 49: Java Application Development

49

• A Business Entity does not have “setters” for its properties

• Properties can only be updated via a DTO• A Business Entity has a setDTO() method to register a

modified DTO and thus update the database

Setting Entity Properties

AbstractBusinessEntity

+getId()+getAddress()

-id-address1

Person_Gen

+getInfo()

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

«interface»Person

More about Ids and DTOs in a minute…

Page 50: Java Application Development

50

String emailAddress = perDTO.getEmailAddress();...perDTO.setEmailAddress(emailAddress);

Person perEntity = (Person)query.firstRow();Person_DTO perDTO = perEntity.getDTO();

AbstractDataTransferObject

Person_DTO

• Data Transfers Objects (DTOs) are transient (temporary / non-persistent) holders of Business Entity properties

• They are acquired via the Business Entity getDTO() method, for example

• Use the DTO “getters” and “setters” (get/set methods) to retrieve or update properties, for example:

Data Transfer Objects

Page 51: Java Application Development

51

• Updating a DTO property (via “setter” method) does not update the entity (database object) automatically

• A Business Entity has the setDTO method to update a modified DTO, for example

This effectively updates the database, but the database update & commit happen at the discretion of the framework

Data Transfer Objects

AbstractDataTransferObject

Person_DTO

Person perEntity = (Person)query.firstRow();Person_DTO perDTO = perEntity.getDTO();perDTO.setEmailAddress(“[email protected]”);perEntity.setDTO(perDTO);

Page 52: Java Application Development

52

String Ids

• Simple string keys (e.g. Person Id) are defined as objects in the framework

• An ID is retrieved from a DTO or Business Entity, e.g.Person_Id perId = perDTO.getId();or

Person_Id perId = perEntity.getId();

• Use the getIdValue() method to get the value of the IdString perIdString = perId.getIdValue(); StringId

Person_Id

Page 53: Java Application Development

53

String Ids

• An Id object can also be used to retrieve a Business Entity, for example

Person_Id perId = new Person_Id("6785704944");Person perEntity = perId.getEntity();Person_DTO perDTO = perEntity.getDTO();...

StringId

Person_Id

Page 54: Java Application Development

54

Entity Lists

AbstractEntityList

+add()+remove()

PersonNames_Impl

«interface»SimpleEntityList

«interface»PersonNames

• Entity lists reference collections of entities, such as person names, phone numbers, characteristics, etc.

• They are retrieved from a Business Entity, e.g.

Person_Id perId = new Person_Id("1185477091"); Person perEntity = perId.getEntity();PersonNames perNames = perEntity.getNames();

• Elements in an entity list can be:• Sequentially retrieved• Removed• Added

Page 55: Java Application Development

55

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();

...}

AbstractEntityList

+add()+remove()

PersonNames_Impl

«interface»SimpleEntityList

«interface»PersonNames

Page 56: Java Application Development

56

Creating an Entity

• To create a new Business Entity, you create the DTO first

… or you create an empty DTO from an “Id” class …

… and then create the Business Entity from the DTO

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

Person_Id perId = new Person_Id("1185477091");Person_DTO perDTO = perId.newDTO();

Note: createDTO() is inherited from the parent GenericBusinessObject class for all Business Entity or Business Component classes (e.g. Change Handlers)

perDTO.setId(new Person_Id(“1185477091”));perDTO.set...Person person = perDTO.newEntity();

Page 57: Java Application Development

57

Deleting an Entity

To delete a Business Entity, you use the delete method on the entity …

… or you can delete the results of a query using the delete method on Query

person.delete();

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

Page 58: Java Application Development

58

Hibernate for SPL Framework - HQL• HQL queries must also go through the SPL Framework• The framework Query class implements a subset of pure

HQL• The framework HQL queries return Business Entities• It is mostly the same as the native HQL language, except

for a few differences …• The SELECT clause is not allowed in the framework’s HQL text• The ORDER BY clause is not allowed in the framework’s HQL text• UNIONs are catered for in the framework’s HQL (native HQL does

not allow it)• The framework caters for raw SQL statements

• The following slides describe the framework’s implementation of HQL

Page 59: Java Application Development

Querying Entities

Page 60: Java Application Development

60

Selecting Entities

• The SELECT clause is not used in a framework Query call• Similar to Hibernate, the following query is valid

• In this example, the List will contain the algorithm objects selected for the algorithm type (i.e. Business Entities are returned)

AlgorithmType algorithmType = ... ;Query query = createQuery("from Algorithm algorithm “+ “where algorithm.algorithmType = :algorithmType");query.bindEntity("algorithmType", algorithmType);List algorithms = query.list();

Page 61: Java Application Development

61

Specifying Results

• To select individual columns, you specify the “result” properties programmatically, giving each a unique name

• The addResult method on the Query object specifies a result property (column) to select

• Now the List will contain QueryResultRow objects• Each QueryResultRow will have two values, keyed by

“algorithm” and “algorithmId”

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();

Page 62: Java Application Development

62

Ordering Results

• The ORDER BY clause in HQL is not allowed by the framework

• Instead, the order must be programmatically specified …

• The List will contain QueryResultRow objects, ordered by “algorithmId”

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();

Page 63: Java Application Development

63

Using Query Iterators

• For a large volume query, instead of using a List, better performance can be gained using the iterate method on Query

• This is more efficient because the iterator loads objects on demand

• It also performs better if the objects have already been loaded and cached by the session

Query query = createQuery("from Person");Person perEntity = null;QueryIterator qIter = query.iterate();while (qIter.hasNext()) {

perEntity = (Person)qIter.next();...

}

Page 64: Java Application Development

64

Union Queries

• Hibernate does not provide for unions (it does not fit in with the object-oriented principles of HQL)

• However, unions can be useful so the framework allows you to programmatically code a union

• Unioned queries must have identical …• Result columns• Order by clauses• Max results settings

• The unionWith() method of the Query class performs the initial union

• To add a third (or later) query, you add it directly to the union

UnionQuery union = query.unionWith(query2);

union.addQueryToUnion(query3);

Page 65: Java Application Development

65

Please note that this is not a recommended or preferred means of accessing the database

Raw SQL• It may be necessary to code SQL instead of HQL• Potential reasons are …

• To specify performance hints• A table is not mapped to a Java entity

• Instead of createQuery(), you use the JDBC-like createPreparedStatement() method on the session object

• The text is similar to the HQL Query text, but you use the table and column names instead of the Java entity and property names

• This feature is only mentioned here for information – we do not cover it in the exercises

Page 66: Java Application Development

66

Extending Business Entities

• Entities can be extended by applications “higher” on the application stack. For example, the “cm” application can extend “ccb” entities.

• The BusinessEntity annotation has a special parameter to define this: extendedInterfaceName

• Only new business methods can be added. Existing ones may not be overridden or removed.

• Walk-through: User_Impl in CCB

Page 67: Java Application Development

67

COBOL-Backed Entities

• There are complex COBOL row programs in the CCB application that maintain table data

• So not to duplicate this logic between COBOL and Java, these row programs are “wrapped” by BusinessEntity classes.

• These classes can be interacted with just like any other entity: queried, changed, etc

• The persistence mechanism has been changed though so that rather than Hibernate persisting changes, the COBOL programs are called instead

• Walk-through: ServiceAgreement in CCB

Page 68: Java Application Development

End of Day 1

Page 69: Java Application Development

69

Day 2 Agenda

• Change Handlers-Standard Validations

Page 70: Java Application Development

Change Handlers

Standard Validations

Page 71: Java Application Development

71

Change Handlers• The way to change an entity’s response to changes in it’s

state is by creating Change Handlers• Validations disallow inappropriate modification• Cascading changes allow one change to cause another

• One or more Change Handlers may exist for a Business Entity – the framework will call all of them

• The Business Entity is specified in the annotations – it tells the framework which entity to attach the Change Handler to at runtime

• A Change Handler extends the AbstractChangeHandler framework class

• A Change Handler class name MUST end in “_CHandler” for the artifact generator to recognize it as such

Page 72: Java Application Development

72

Example Change Handler

/** * @ChangeHandler (entityName = characteristicType) */public class CmCharacteristicType_CHandler extends AbstractChangeHandler {

...}

• In this example …• The annotation specifies a Change Handler for Business Entity

“Characteristic Type”• It extends AbstractChangeHandler• The class name ends in “_CHandler”

Page 73: Java Application Development

73

Change Handlers

• Change Handlers add event-driven logic to entities (similar to COBOL row user exits)

• They can perform 2 things:1. Validate data changes

2. Cause cascading changes

• We’ll take a look at validation first

Page 74: Java Application Development

74

Change Handlers – Validation Rules• The framework uses Validation Rules to determine how to

validate a Business Entity at runtime• The Validation Rules for a Business Entity are declared in

a Change Handler• The declarative style means the programmer specifies

WHAT to validate, not HOW or WHEN• A number of standard rules exist that require minimal

programming, but custom rules can be coded if needed• Custom rules require programming – these contain the

step-by-step logic of HOW to validate• Validation rules are “side-effect free”, which means …

• They cannot change the persistent state of the system (can’t update)

• It insures all validations are performed on a complete set of changes

Page 75: Java Application Development

75

Change Handlers – Validation Rules• The following standard rules exist

• AllowAndRequireRule – both allows and requires a property to be populated

• AllowRule – allows a value to be populated• CustomRule – creates a rule out of a Custom Validation class (to

implement logic not handled by any of the above)• NotAllowRule – one or more properties are not allowed• PlaceHolderRule – this is a “place holder” when a Change

Handler is developed – they are replaced with the actual rules during development

• ProtectRule – prevents a property from being changed• RequireRule – requires a property to be populated• RestrictRule – restricts a property to a set of values

• Refer to the SDK documentation for more details on these rules

Page 76: Java Application Development

76

Change Handlers – Validation Rules

• The framework invokes the getValidationRules method on a Change Handler for all the validation rules for a Business Entity

• The getValidationRules method must return an array of validation rule objects

• To use a standard rule, simply use the static “factory” method on the rule itself – for example• RequireRule.alwaysRequire() returns an instance of the

RequireRule class that insures an entity property has a value• RestrictRule.validatedMustEqualReference() returns an instance

of the RestrictRule class that checks if a property is equal to a specific value/reference

Page 77: Java Application Development

77

Change Handlers – Validation Rules

• A Validation Rule requires a Property on the Business Entity (i.e. the “field”) to validate

• A property is a reference to an 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 the setup date field on the

Account entity

• Properties are passed to the Validation Rules as parameters to tell a rule which property to validate

Page 78: Java Application Development

78

Change Handlers – Validation Rules

Here we see …• Static method emailRequiredRule to instantiate a RequiredRule object

using factory method alwaysRequire• Person.properties.email to tell the rule to validate the Email Address

property (i.e. “field”) on Person• Public method getValidationRules to provide a list of the rules to the

framework (only one in this case)

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()}; }

Example – make Email Address field on Person required

Page 79: Java Application Development

79

Exercise 1 – Change Handler Validation 1All Students• Create a Person change handler in the java folder of your project …

• Place it in package com.splwg.cm.domain.customerinfo.person

• Name it CmPerson_CHandler

• Add validation rule address1RequiredRule to make address line 1 required

OptionalNote: this exercise is very similar to the above, but will lead to a more challenging exercise 3

• Create a Premise change handler …• Place it in package com.splwg.cm.domain.customerinfo.premise

• Name it CmPremise_CHandler

• Add a validation rule to make city required

Test• Use the online system to test your change handler

Page 80: Java Application Development

80

When do Rules Fire?• 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

a change handler, but invoked at the discretion of the framework

• By default, validation rules “fire” when a Business Entity is updated, deleted, created, etc.

• For example, using setDTO to update an entity will trigger the validation for it, as seen here …

• This is called “eager” validation because it fires immediately

Person_DTO perDTO = perEntity.getDTO();perDTO.setEmailAddress(“[email protected]”);perEntity.setDTO(perDTO);

Page 81: Java Application Development

81

When do Rules Fire?• The triggering of validation can be controlled

programmatically if needed• It may be necessary where multiple entities require

validation as a “coherent” set of changes• To illustrate this, consider the example of validating a new

Person and Person Name, but only once the entities have been created – i.e. to defer validation until both entities are created

To defer validation until later, use framework method startChanges() before the update and saveChanges() after the update

• Let’s take a look at the code for this example …

NOTE: saveChanges() does not issue commit to database!

Page 82: Java Application Development

82

Example: Defer Validation

1. Invokes startChanges to tell the framework to suspend validation

2. Creates a new Person Business Entity

3. Creates a PersonName Business Entity for the new Person

4. Adds PersonName to Person

5. Invokes saveChanges to allow for validation on the “coherent” set of changes

startChanges();

Person_DTO perDTO = (Person_DTO)this.createDTO(Person.class);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);perNameDTO.setId(perNameId);perNameDTO.setEntityName(“Blog,Joe");perNameDTO.setNameType(NameTypeLookup.constants.PRIMARY);PersonName perName = perNameDTO.newEntity();

person.getNames().add(perName);

saveChanges();

1

2

3

45

Page 83: Java Application Development

JUnit Testing

Page 84: Java Application Development

84

JUnit Testing• To ensure quality code, an automated unit testing

procedure is required• The reasons for automated testing are …

• One small change can unexpectedly break other parts of the system – automated tests provide early notification of these bugs

• Studies show that to fix bugs costs more the longer they are undiscovered – automated tests prevent this

• Automated tests are useful (albeit technical) forms of functional documentation – they describe to the programmers the expected inputs/outputs

• We use JUnit for automated testing• The Eclipse IDE is integrated with JUnit, making it easy to

create and run tests• JUnit test are part of our continuous build process.

Page 85: Java Application Development

85

JUnit Testing

• The framework contains many abstract “tester” classes, one for each type of test – for example• AbstractEntityTestCase tests a Business Entity and its related

Change Handlers. It also ensures all the Validation Rules in the Change Handler have fired

• AlgorithmImplementationTestCase tests an algorithm function

• When coding your own test class, you must extend the appropriate abstract “tester” class

• The root of many tester class is ContextTestCase which can be used to test most things that require general framework services

Page 86: Java Application Development

86

JUnit Tests are Safe

… or should be…• The transaction logic in the tester classes is “hotwired”.

Whenever you use the session provided within the tester class:• All your changes get rolled back at the end of the test, pass or fail• If you do data setup, it gets rolled back

• Other resource cleanup (like temporary files) should be cleaned up by overriding “tearDown()” method

• Let’s see how a test is created …

Page 87: Java Application Development

87

Creating a JUnit Test Class

First step is to create a JUnit test class

This class is to test CmPerson_CHandler validation rules1. The class name ends in “_Test”

2. It extends AbstractEntityTestCase – to test a Business Entity/Change Handler

3. The getChangeHandlerClass method returns the class definition of the Change Handler being tested – the framework invokes this method to get the name of the class to test

public class CmPerson_CHandler_Test extends AbstractEntityTestCase {

protected Class getChangeHandlerClass() { return CmPerson_CHandler.class; } }

Page 88: Java Application Development

88

Creating a JUnit Test CasesNow we add a method for each test case …

Remember:1. The method name must start with “test” – the framework will

execute all classes that start with “test”

2. ALL the rules must be violated in the test - if a validation rule exists in the change handler but is not violated in the test class, the framework will fail the test

3. The objective is to have all test cases complete successfully (no failures)

public void testEmailRequiredRule() {

}

Note Our change handler only has one rule – “Email Required” – so we only have one test case method

Page 89: Java Application Development

89

Fleshing out a JUnit Test CaseLet’s add some code to test our “email required” rule …

What this code does is …1. Fetches a person from the database and instantiates a Person

object2. Acquires a Data Transfer Object (DTO) from Person3. Updates the email address on the DTO to a non-space value4. Modifies the DTO on Person, which triggers validation

This tests for a positive outcome (which is necessary), but we MUST also violate the condition to properly test the validation rule …

public void testEmailRequiredRule() { Person_Id perId = new Person_Id("5775933103");

Person person = perId.getEntity();

Person_DTO goodDTO = person.getDTO();

goodDTO.setEmailAddress("[email protected]");

person.setDTO(goodDTO);}

1

2

3

4

Page 90: Java Application Development

90

Fleshing out a JUnit Test Case (cont)So let’s add some more code …

What this code does is …1. Instantiates a “bad” DTO and clears the email address to violate the rule

2. Updates the Person’s DTO to trigger validation

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

public void testEmailRequiredRule() { ... try { Person_DTO badDTO = person.getDTO(); badDTO.setEmailAddress(null);

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); }}

1

2

3

4

Page 91: Java Application Development

91

The Complete Test Case

Here’s the complete test method …

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

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("[email protected]"); person.setDTO(goodDTO); try { Person_DTO badDTO = person.getDTO(); badDTO.setEmailAddress(null); 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); }}

Page 92: Java Application Development

92

Exercise 2 – JUnit Test 1All Students• Create a JUnit test class for your Person validation rule from exercise 1 in the

test folder of your project …• Place it in package com.splwg.cm.domain.customerinfo.person• Name your class CmPerson_CHandler_Test• Add a method to test your validation rule

Optional• Create a JUnit test class for your Premise validation rule from exercise 1

Test• From Eclipse, right-click on your test class and select Run As -> JUnit Test

Page 93: Java Application Development

The Continuous Build

Page 94: Java Application Development

94

The Continuous Build

• Servers have been dedicated to continuously build and test our applications• Every 10 minutes or so, the build server looks for committed

changes in the appropriate Perforce location. If none are found, the build waits another 10 minutes and polls again.

• When changes are found it does the following: • Downloads all changes

• Removes all artifacts, class files and other remnants from the last build

• Generates all artifacts

• Compiles all code

• Runs all tests

• If the build was unsuccessful it sends emails to everyone who committed changes since the last successful build.

Page 95: Java Application Development

95

When you “break the build”

• If a developer thinks the problem is his/her fault, it is customary to: • Send a note to other developers on the list so they don't waste

time on the problem • Fix the problem, test it locally, commit changes to Perforce and

hope the build is appeased.

• If no developer confesses to the problem, some collaboration may be required. It may also require some discussion with the "build master“.

Page 96: Java Application Development

96

How not to break the build

• Make sure everything compiles• Make sure your changelists are complete• Run as many tests as you can. Run all appearing related

to the changes made.• When you need to commit code you know is broken or

untested, disable the test as follows:

protected void testSendingEmails() { disableTest( "This test needs to be reworked so it doesn't hit the real oracle

email server and spam real people. This should be more like the other email tests that hit an embedded server.",

"Brian Conlon", new Date(2008, 04, 29));

Page 97: Java Application Development

Conditional Validation

Page 98: Java Application Development

98

Conditional Validation• In the last exercise we used the alwaysRequire method to

UNCONDITIONALLY require a value• Rules would not be very useful if only unconditional

validation was allowed• Validation is usually based on some condition, for

example1. Prevent a “dependent” property from being changed if the

“primary” property matches a certain value – e.g. FT freeze date/time cannot be changed when the status is frozen (ProtectRule)

2. The life support description on Person is required if the life support flag is set (RequiredRule)

• Rules have various constructs (and factory methods) to handle this, for example• RequireRule.ifReferenceEqualsValue() requires a property if

another property equals a certain value

Page 99: Java Application Development

99

Conditional Validation (cont)Example – email address required if life support flag is setpublic 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());}

1

2

Here we introduce a few new things …1. Using the ifReferenceEqualsValue factory method on RequireRule

2. The property that is required (“primary” property) - emailAddress

3. The property to compare for a value (“dependent” property) – lifeSupportSensitiveLoad

3

Page 100: Java Application Development

100

Conditional Validation (cont)Example – email address required if life support flag is setpublic 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());}

Here we introduce a few new things …4. The value to compare the dependent property (no. 3) to –

LIFE_SUPPORT_SENSITIVE_LOAD is the lookup value for constant “Y” (all valid lookup values are generated onto “lookup” classes)

5. The message to display when the condition is true - com.splwg.base.domain.StandardMessages.fieldMissing

Note: Here we use a standard message – we will create a custom message later

4

5

3

Page 101: Java Application Development

101

Exercise 3 – Conditional ValidationAll Students• Modify your Person change handler from exercise 1 …

• Change the validation rule to make address line 1 required only if the person type is “Business”

• Rename the validation rule to indicate that it’s conditional – e.g. address1RequiredIfBusinessRule

Optional• Modify your Premise change handler from exercise 1 …

• Change the validation rule to make city required only if the county is not equal to constant value “San Francisco”

• Rename the validation rule to indicate that it’s conditional – e.g. cityRequiredIfCountyNotSFRule

Test• Update your JUnit test class from exercise 2 to test the conditional

validation

Page 102: Java Application Development

Base Messages

Page 103: Java Application Development

103

Message Categories• ALL application messages are stored in the framework’s

message repository (the message text is not embedded in the source code)

• Messages are grouped into categories

• Use menu Admin -> M -> Message to view/update the message categories

• The list here shows the standard message categories

Page 104: Java Application Development

104

• Within each category, the message text is numbered

• This example shows messages for “Standard” category 11001

• Note message number 101 (“ %1 field missing”); we used it in the previous exercise

• “%1” is a substitution variable to be supplied when the Java class displays the message (field name in this case)

• A message may contain up to 9 substitution variables

Message Categories – Message Text

Page 105: Java Application Development

105

• Message text may contain substitution variables• Variables are denoted by % followed by a number from 1

to 9 – e.g. %1, %2, etc.• For example, the message text

%1 field missing

will be displayed as

Bill Cycle field missing

%1

• The application code must pass the values for the substitution variables when the message is displayed

Message Categories – Substitution Variables

addError(StandardMessages.FieldMissing(fieldName))

Page 106: Java Application Development

106

• Base message text may not be modified (it is prevented by the system) - changes would be overwritten at the next upgrade anyway

• However, you can ADD customized message text for a base message on the Details tab

Base Messages – Modifying …

Page 107: Java Application Development

107

• The Customer Specific Message Text must use the same substitution variables as the base one

Base Messages – Modifying …

The framework will ALWAYS display the customer specific message if present – it is not possible to conditionally display the base Message Text if custom text for it exists

Page 108: Java Application Development

108

Base Messages – Java Definitions• Each category has its own class to define message variables and

methods

• For example, the StandardMessages class contains …1. The category number definition for the standard messages

2. All the standard message numbers

1

2

Page 109: Java Application Development

109

Base Messages – Runtime Definition• A message class also contains methods …

• The application code calls these methods to display messages at runtime – for example

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

Page 110: Java Application Development

110

Base Messages – Runtime Definition

Note: in this case, the language-dependent description of EMAILID would be displayed in the message – in English, “Email Address field missing”

• As can be seen here, runtime message methods return objects of type ServerMessage

Page 111: Java Application Development

111

Base Messages – Declarative Definition• The previous slide shows a RUNTIME message definition• Remember, validation rules are declarative• We therefore also need a declarative version of the

message to use in the validation rules

• This methods returns a ServerMessageTemplate object to use in the validation rule declaration

Page 112: Java Application Development

112

Base Messages – Declarative Definition• In the last exercise we used the declarative version of

StandardMessages.fieldMissing

• fieldMissing has a runtime AND declarative message method, but not all messages require both versions• Those used in validation rules require declarative ones; those

displayed from other “runtime” code (e.g. algorithms) require runtime versions

• We’ll see in a moment how to use a runtime message …

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());}

Page 113: Java Application Development

Custom Messages

Page 114: Java Application Development

114

Custom Messages – Creating …

• Over the following slides, we’ll look at creating and using a custom message in Java

• The custom message text we will work with is

“%1 required if %2 is activated”

The validation that references this messages will therefore be a conditional validation

Remember this text – you could even write it down to refer to as we step through the slides

• First, let’s look at creating the message online …

Page 115: Java Application Development

115

This is all that is required in the online to create a new message

Custom Messages – Creating …• ONLY category 90000, Implementer’s

messages, may contain new custom messages

• To create a new message, you select category 90000 and insert a new message as shown below

% variables here must be supplied in the classes that display the message

Page 116: Java Application Development

116

Custom Messages – Java Definition• On the Java side, these are the basic initial setup rules for

creating custom messages …1. Create a CustomMessages class (supplied with this course) to

contain all your custom message definitions

2. CustomMessages must extend AbstractMessageRepository

3. In CustomMessages, specify 90000 as the message category

4. In CustomMessages, define all your custom message numbers

5. Place CustomMessages in the com.splwg.cm.domain package

6. In each individual sub-package under package cm, you create a MessageRepository class for the message methods specific to that sub-package – Note: common message methods are placed in the CustomMessages class

7. Each MessageRepository extends CustomMessages and contains the runtime and declarative methods for that sub-package

• Let’s take a closer look …

Page 117: Java Application Development

117

Custom Messages – Java Definition

• These are the important class characteristics …1. It is in package com.splwg.cm.domain2. It imports our custom MessageRepository (to be created next)3. Class CustomMessages extends AbstractMessageRepository4. It defines MESSAGE_CATEGORY 900005. It defines EVERY custom message (for now, we only have one)

package com.splwg.cm.domain;

import com.splwg.base.domain.common.message.AbstractMessageRepository; import com.splwg.cm.domain.templates.MessageRepository;

public class CustomMessages extends AbstractMessageRepository {

public static final int MESSAGE_CATEGORY = 90000;

public static final int REQ_IF_CONDITION = 10006;

private static MessageRepository instance; public CustomMessages() {

super(MESSAGE_CATEGORY); } static MessageRepository getInstance() { if (instance == null) instance = new MessageRepository(); return instance; } }

1

23

4

5

Page 118: Java Application Development

118

Custom Messages – Java Definition

• These are the important class characteristics …6. It defines a MessageRepository instance variable (see point 8)7. It invokes the superclass to establish the message category at runtime8. The getInstance method is a private method that provides the

MessageRepository instance to the to the message methods in the class

6

7

8

package com.splwg.cm.domain;

import com.splwg.base.domain.common.message.AbstractMessageRepository; import com.splwg.cm.domain.templates.MessageRepository;

public class CustomMessages extends AbstractMessageRepository {

public static final int MESSAGE_CATEGORY = 90000;

public static final int REQ_IF_CONDITION = 10006;

private static MessageRepository instance;

public CustomMessages() { super(MESSAGE_CATEGORY); } private static MessageRepository getInstance() { if (instance == null) instance = new MessageRepository(); return instance; } }

Page 119: Java Application Development

119

Custom Messages – MessageRepository• Next we create the MessageRepository class in the sub-

package under package cm• It must extend the CustomMessages class• It only contains the methods for the messages relevant to

the sub-package• All static definitions for the message numbers should be in

CustomMessages• Let’s look at the example …

Page 120: Java Application Development

120

Custom Messages – MessageRepository

• These are the important class characteristics …1. It is in the sub-package to which it applies - customerinfo.person in

this example2. It extends the parent CustomMessages class3. It defines a MessageRepository instance variable4. It has a getInstance method to provide the MessageRepository

instance – i.e. an instance of itself - to the message methods that follow

package com.splwg.cm.domain.customerinfo.person; import com.splwg.cm.domain.CustomMessages;

public class MessageRepository extends CustomMessages {

private static MessageRepository instance;

private static MessageRepository getInstance() { if (instance == null) instance = new MessageRepository(); return instance; } }

1

2

3

4

MessageRepository class

Page 121: Java Application Development

121

Custom Messages – Runtime Method

• The important method characteristics are …1. a) The method is static

b) It returns a ServerMessage object type for a runtime messagec) It has a descriptive method name based on the message it handlesd) The parameters correspond with the % variables in the message

public static ServerMessage requiredIfCondition(String fieldName1, String fieldName2) {

MessageParameters parms = new MessageParameters();

parms.addField(fieldName1);

parms.addField(fieldName2);

return getInstance().getMessage(REQ_IF_CONDITION, parms); }

Let’s add a runtime method for our message in the MessageRepository class

1

Page 122: Java Application Development

122

Custom Messages – Runtime Method

• The important method characteristics are …2. It defines a MessageParameters object to carry the substitution

values for the message3. It adds the substitution values (the parameters) to the

MessageParameters object4. It returns a ServerMessage object as instantiated by the getMessage

method, based on the supplied message number and parameters –the message number is defined in class CustomMessages

Let’s add a runtime method for our message in the MessageRepository class

2

4

3

public static ServerMessage requiredIfCondition(String fieldName1, String fieldName2) {

MessageParameters parms = new MessageParameters();

parms.addField(fieldName1);

parms.addField(fieldName2);

return getInstance().getMessage(REQ_IF_CONDITION, parms); }

Page 123: Java Application Development

123

Custom Messages – Using at Runtime

• As seen on the previous slide, the requiredIfCondition method uses the addField method to set the parameters …

• The MessageParameters.addField method uses the language-dependent descriptions of the fields to replace the % markers in the message

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")); }

Here we see how to set a message at runtime

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

Page 124: Java Application Development

124

Custom Messages – Declarative Method

• The important method characteristics are …1. a) The method is static

b) It returns a ServerMessageTemplate object type for a declarative messagec) It has a descriptive method name based on the message it handlesd) It has a reference to the parameters if the message contains % substitution variables

public static ServerMessageTemplate requiredIfCondition( LookupProperty prop) { ServerMessageParameter[] messageParms = { ServerMessageParameter.OFFENDING_PROPERTY_NAME, ServerMessageParameter.createDisplayingName(prop) };

return getInstance().getDeclarativeMessage(REQ_IF_CONDITION, messageParms); }

Let’s also add a declarative method for our validation rule

1

Page 125: Java Application Development

125

Custom Messages – Declarative Method

• The important method characteristics are …2. a) It has a message parameter array for the substitutions in the text

messageb) OFFENDING_PROPERTY_NAME is a static reference to the field being validated in the validation rule – we substitute this name into

the message’s 1st parameterc) createDisplayingName gets the name of the LookupProperty value which we substitute into the message’s 2nd parameter

Let’s also add a declarative method for our validation rule

public static ServerMessageTemplate requiredIfCondition( LookupProperty prop) { ServerMessageParameter[] messageParms = { ServerMessageParameter.OFFENDING_PROPERTY_NAME, ServerMessageParameter.createDisplayingName(prop) };

return getInstance().getDeclarativeMessage(REQ_IF_CONDITION, messageParms); }

2

Page 126: Java Application Development

126

Custom Messages – Declarative Method

• The important method characteristics are …3. It returns a declarative message object based on the message

number and substitution parameters

Let’s also add a declarative method for our validation rule

3

public static ServerMessageTemplate requiredIfCondition( LookupProperty prop) { ServerMessageParameter[] messageParms = { ServerMessageParameter.OFFENDING_PROPERTY_NAME, ServerMessageParameter.createDisplayingName(prop) };

return getInstance().getDeclarativeMessage(REQ_IF_CONDITION, messageParms); }

Page 127: Java Application Development

127

Custom Messages – Using DeclarativeUsing the custom declarative message in a 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));}

1. Person.properties.emailAddress is automatically set as the OFFENDING_PROPERTY_NAME, so it does not need to be passed to the declarative method as a parameter – as seen on the previous slide, we use this name to substitute the 1st message parameter

2. We now reference our custom requiredIfCondition method in the validation rule

3. The parameter we pass in is the property of the field to substitute the message’s 2nd parameter

1

2

3

Page 128: Java Application Development

128

Exercise 4 – Custom Declarative MessageAll Students• Use the online system to create a descriptive message for the Person

validation rule in exercise 3• Each student should use a unique message number when working on a

shared database – the instructor can assign message numbers, starting at message number 10001

• Use your initials in the message to distinguish it

• Create the message with 2 parameters – the offending field name and the field name used in the comparison

• For example: “%1 is required if %2 is BUSINESS (XX)” – where XX are your initials

• Update the CustomMessages class and add a constant for your new message number – e.g. REQUIRED_IF_ BUSINESS

• Copy the supplied MessageRepository template to your person sub-package and add a method for use in the validation rule – e.g. requiredIfBusiness(…)

Page 129: Java Application Development

129

Exercise 4 – Custom Declarative MessageAll Students (continued) • Update your validation rule from exercise 3 to reference the new

message

Optional• Perform the above steps to create a descriptive message for your

Premise validation rule …• Start at message number 20001

• For added complexity, create a 3rd message parameter in which you specify the string value (constant) that the county is compared to

For example: “%1 required if %2 not %3 (XX)” – where XX are your initials

(see attached note)

Test• Use the online system to validate that the new message is displayed

Page 130: Java Application Development

Condition Objects

Page 131: Java Application Development

131

Change Handlers – Conditions• Rules can take as input one or more Conditions• The Condition interface currently has the following

implementations (i.e. these are the supported conditions)• BetweenValues• Equals• Not• And• Or• GreaterThan / GreaterThanOrEquals• LessThan / LessThanOrEquals• Contains

(Descriptions of these conditions are documented)• You use conditions to conditionally perform validation

Page 132: Java Application Development

132

• Conditions can be instantiated from factory methods on certain properties

The isTrue() and isGreaterThan() methods instantiate a Condition object1. PersonName is being checked for a “primary” attribute2. PersonName sequence is being checked for > 0

• Conditions can also be instantiated using a constructor

This checks if the PersonOrBusiness property is set to “Person”

• A Condition object such as this can be used in a Validation Rule to cause conditional validation

Condition isPrimaryName = PersonName.properties.isPrimaryName.isTrue(); Condition greaterThan = PersonName.properties.sequence.isGreaterThan(BigInteger.ZERO);

12

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

Change Handlers – Conditions

Page 133: Java Application Development

133

Example – using a Condition to make email address required if life support flag is set public static ValidationRule emailRequiredIfLifeSupportIsYesRule() {

Condition hasLifeSupport = Person.properties.lifeSupportSensitiveLoad. isEqualTo(LifeSupportSensitiveLoadLookup.constants. LIFE_SUPPORT_SENSITIVE_LOAD);

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, hasLifeSupport, com.splwg.base.domain.StandardMessages.fieldMissing()); }

1. This is the Condition to check if life support is on

2. We use the ifConditionTrue method of the RequireRule class

3. The ifConditionTrue method requires the Condition as a parameter, which in this case is the condition created in point 1

1

3

2

Change Handlers – Conditions

Page 134: Java Application Development

134

Exercise 5 – Change Handler ConditionsAll Students• Modify your Person change handler from exercise 3 …

• Introduce a Condition in your validation rule to make address line 1 required if the person type is “Business” (same validation as in exercise 3)

• Change the validation rule to use the Condition

Optional• Modify your Premise change handler from exercise 3 …

• Introduce a Condition in your validation rule to make city required if the county is not equal to “San Francisco” (same validation as in exercise 3)

• Change the validation rule to use the Condition

Test• Run the JUnit test class from exercise 3 to test• Startup the online system and test that your validation rule works the

same as in exercise 4

Page 135: Java Application Development

Custom Rules

Page 136: Java Application Development

136

Change Handlers – Custom Rules• If validation is too complex for a declarative rule, a custom

rule may be coded• A custom rule contains code to perform the specific

validation – in other words, “if invalid condition, display error message”

• A custom rule class may implement one or more abstract methods

• The methods correspond with “events” that may occur with respect to the underlying business entity

• The methods are divided into 2 categories …1. Eager Validations

2. Lazy Validations

Page 137: Java Application Development

137

Custom Rule – Eager Validation Methods• Eager validations fire immediately when an entity is

changed by way of a delete(), setDTO() or createEntity())• The “event” methods that can be implemented by a

custom rule class are …• validateAdd() fires when a business entity is added• validateChangeOnly() fires when a business entity is changed• validateAddOrChange() fires when a business entity is added or

changed (in addition to an add or change event)• validateDelete() fires when a business entity is deleted• validateRegisteredChange() fires when a change is registered to

another object (e.g. a child) - this can be any business entity that feels like notifying you of a change

A parameter passed to this method, RegisteredChangeDetail, can be queried (via its getChangeToList() method) to determine if the change affects you

Page 138: Java Application Development

138

Custom Rule – Lazy Validation Methods• Lazy validations fire after a “coherent set of changes”

have been made – this is in contrast to eager validations that fire immediately when an entity is modified

• Only one lazy validation method exists …

validateSave()It fires at the “end of” a set of changes

Validation of child entities, for example, can therefore be placed in this method

All types of changes (add, change, delete or register change) will trigger a validateSave()

Page 139: Java Application Development

139

Custom Rule Class• These are the basic steps to create and use a custom rule

…1. Create a class that extends AbstractCustomValidation – this class

could be an inner class of your Change Handler if the custom validation rule is specific to the Business Entity being validated

2. In your new class, provide the framework with an array of entity properties associated with the custom rule – the framework uses this to avoid additional validations on properties already known to be in error

3. In you new class, implement the appropriate eager and/or lazy methods to perform the validation

4. Reference the custom rule in your static validation rule method, as you would with a standard declarative rule

• Let’s take a look at an example …

Page 140: Java Application Development

140

Custom Rule MapFieldNameRequired Example

1. This class is an “inner class” of the ScriptFieldMap_CHandler class – this is not required, but it makes sense if the custom rule is specific to a Business Entity

2. The custom rule class extends AbstractCustomValidation

3. It passes back to the framework the property(s) being validated – in this case mapFieldName

1

3

2

Page 141: Java Application Development

141

Custom Rule MapFieldNameRequired Example

1. It overrides abstract method validateAddOrChange for immediate (eager) validation – this validation code will get fired on either an add or a change event

2. It casts the generic Business Entity object in the parameter to the type of Business Entity being validated – in this case ScriptFieldMap

3. If a validation error is found, the addValidationError method registers the error message with the framework

1

2

3

Page 142: Java Application Development

142

Custom Rule MapFieldNameRequired Example

1. In the Change Handler class, it declares a static method mapFieldNameRequired – as a standard, the name ties in with the custom rule class name of MapFieldNameRequired

2. The Change Handler instantiates and returns a new CustomRule object for custom rule class MapFieldNameRequired

3. The getValidationRules() method provides the framework the list of ALL the rules in this Change Handler – custom and standard ones

1

3

Change Handler class – ScriptFieldMap_CHandler

2

Page 143: Java Application Development

143

Exercise 6 – Custom Validation RuleAll Students• Modify (or copy) your Person change handler from exercise 5 and

make the Short Comment characteristic (characteristic type “COMMENT”) required …• Create a new message “Short Comment characteristic is required (XX)”

(where XX are your initials) – the instructor can assign a unique message number to each student

• Create a runtime message method in your MessageRepository class

• Override the validateSave method – remember, you need to do “lazy validation” when checking child entities

• Characteristics are effective dated – use an iterator on PersonCharacteristic to scan for the “COMMENT” type

Test• Create cm.jar and startup the online system to test …

• On a shared database, each student should test using a different person

Page 144: Java Application Development

144

Exercise 6 – Custom Validation RuleOptional• Create a JUnit test class for your custom validation rule and in your

testShortCommentRequiredRule() method …• Create a PersonCharacteristic_Id object for the “COMMENT”

characteristic for your Person_Id• Because this is for an existing Person on the database, remove any

existing Short Comment characteristic before continuing with the steps below to test the validationNote: This remove could trigger validation on the Person, which at this stage you want to avoid. See if you can come up with the solution.

• Create a PersonCharacteristic_DTO object from the PersonCharacteristic_Id

• Set the adhoc characteristic value to something – e.g. “Test comment”• Create a new PersonCharacteristic object from the

PersonCharacteristic_DTO• Add the new PersonCharacteristic object to your collection of

characteristics All the steps up to this point perform the “positive” validation – i.e. they test that your validation rule does NOT get violated

Page 145: Java Application Development

145

Exercise 6 – Custom Validation RuleOptional (continued)

• Test that the rule gets violated by removing the newly created PersonCharacteristic object from the collection of characteristics – this should cause an application exception to be thrown

Page 146: Java Application Development

Cascading Changes

Page 147: Java Application Development

147

Change Handlers – Cascading Changes• Up to now we’ve seen change handlers performing

validation on a Business Entity• Change handlers can also implement business logic based

on inserts, updates & deletes to a Business Entity – i.e. to cause “cascading changes” to occur

For example, if a phone number for a Person changes, update matching phone numbers for related Persons automatically

• Change handlers provide for a number of “handle” methods

• Handle methods are invoked when specific events occur• Unlike validation, this logic fires immediately – it cannot be

deferred by the startChanges or saveChanges method calls

Page 148: Java Application Development

148

The following methods can be implemented to provide customized functionality …

• For an Add or Copy Event• prepareToAdd()• handleAddOrChange()• handleAdd()• handleRegisteredChange()

• For an Update Event• prepareToChange()• handleAddOrChange()• handleChange()

• For a Delete Event• handleDelete()

Change Handlers – Cascading Changes

Page 149: Java Application Development

149

Events and MethodsLet’s take a closer look at the methods …• prepareToAdd(DataTransferObject newDTO)

• This method fires before a new Business Entity is added• It allows you to default values and perform other changes on a new

DTO before the add

• handleAddOrChange(BusinessEntity businessEntity,

DataTransferObject oldDTO)• This fires before validation when a entity is added OR changed• The oldDTO object contains a null on an add event

• handleAdd(BusinessEntity newBusinessEntity)• This fires before validation when an entity is added• It allows for cascading updates on other objects or external

systems

Page 150: Java Application Development

150

Events and Methods• prepareToChange(BusinessEntity unchangedEntity,

DataTransferObject newDTO)• This fires before a change to a DTO is submitted

• You can use this to default values and perform other changes on a DTO before the change

• handleChange(BusinessEntity changedBusinessEntity, DataTransferObject oldDTO)• This fires before validation when an entity is changed

• It allows for cascading updates on other objects or external systems

Page 151: Java Application Development

151

Events and Methods• handleRegisteredChange(BusinessEntity changedBusnessEnty,

RegisteredChangeDetail changeDetl)• This fires when a change is “registered” to the

changedBusnessEnty object via the business entity’s registerChange method

• For example, it can be fired when a child list associated with the Business Entity has been changed

• The RegisterChangeDetail object specifies the details of the change

• handleDelete(DataTransferObject oldDTO)• This fires before validation when an entity is deleted

Let’s now take a look at an example …

Important … these are not preferred places for validation – validation should be done using validation rules

Page 152: Java Application Development

152

handleAdd example• Create an alert when a new account is added /** * @ChangeHandler (entityName = account) */ public class CmAccount_CHandler extends AbstractChangeHandler {

public void handleAdd(BusinessEntity newBusinessEntity) { Account account = (Account) newBusinessEntity; AccountAlerts acctAlerts = account.getAlerts(); AccountAlert_DTO acctAlertDTO = acctAlerts.newChildDTO(); acctAlerts.add(acctAlertDTO, new AlertType_Id("PP EXEMPT"), getSystemDateTime().getDate()); } }

12

3

1. It specifies the entity type in annotations (don’t forget to do this!)2. The class name ends in “_CHandler” and extends

AbstractChangeHandler3. It implements the handleAdd method; the newBusinessEntity object is

a reference to the entity being added

Page 153: Java Application Development

153

handleAdd example (cont)• Create an alert when a new account is added /** * @ChangeHandler (entityName = account) */ public class CmAccount_CHandler extends AbstractChangeHandler {

public void handleAdd(BusinessEntity newBusinessEntity) { Account account = (Account) newBusinessEntity;

AccountAlerts acctAlerts = account.getAlerts();

AccountAlert_DTO acctAlertDTO = acctAlerts.newChildDTO();

acctAlerts.add(acctAlertDTO, new AlertType_Id("PP EXEMPT"), getSystemDateTime().getDate()); } }

4

5

6

7

4. It casts newBusinessEntity to an Account object5. It gets the alerts entity list (AccountAlerts) for the account – this will be empty since it’s a

new account6. It creates a new alert DTO by using the entity list’s newChildDTO method7. It adds the partially completed DTO to the account’s alert entity list – the additional

parameters are required for the entity listThe framework will add the row when the transaction commits

Page 154: Java Application Development

154

Change Handlers – Cascading Changes

• The previous example shows a “cascading change” to a child entity (Alerts) of a Business Entity (Account)

• The basic rules when working with child entities are …• Child entity lists are acquired from a Business Entity via the

appropriate getter methods (e.g. getAlerts())• To add a new child entity, use the entity list’s add methods• To remove a child entity, use the entity list’s remove methods

Page 155: Java Application Development

155

Change Handlers – Cascading Changes

• When inserting and deleting entities that are NOT child entities of the business entity being customized, more explicit code is required

• In this case the getDTO and setDTO method calls need to be used

Let’s look at an example …

Page 156: Java Application Development

156

Change Handlers V – handleChange Example

1. It implements the handleChange method – the changedEntity object is a reference to the account entity being changed; oldDTO is the DTO before the change was made

2. It casts changedEntity to an Account object

3. It checks if the mailing premise Id is populated on the account – mailing premise Id is an optional foreign key reference (Note, on the CI_ACCT table the mailing premise Id is a space, but on the Business Entity object it is a null)

public void handleChange(BusinessEntity changedEntity, DataTransferObject oldDTO) { Account account = (Account) changedEntity; if (account.getMailingPremiseId() != null) { Premise premise = account.getMailingPremiseId().getEntity(); Premise_DTO premiseDTO = premise.getDTO(); premiseDTO.setAddress4(account.getAlertInformation()); premise.setDTO(premiseDTO); } }

• Update the related premise when an account is changed

1

234567

Page 157: Java Application Development

157

Change Handlers V – handleChange Example

4. It gets the Premise object referenced by the mailing premise Id field

5. It gets DTO for the Premise to modify the row

6. It updates the value on the Premise DTO – address line 4 in this case is set to the account’s alert information (i.e. the “Comment” field on the account page)

7. It updates the Premise Business Entity using the setDTO() method, which ultimately causes the row to be updated

public void handleChange(BusinessEntity changedEntity, DataTransferObject oldDTO) { Account account = (Account) changedEntity; if (account.getMailingPremiseId() != null) { Premise premise = account.getMailingPremiseId().getEntity(); Premise_DTO premiseDTO = premise.getDTO(); premiseDTO.setAddress4(account.getAlertInformation()); premise.setDTO(premiseDTO); } }

• Update the related premise when an account is changed

1

234567

Page 158: Java Application Development

158

Exercise 7 – Cascading Change HandlerAll Students• Change your Person Change Handler from the previous exercise

automatically add a Short Comment characteristic (characteristic type “COMMENT”) whenever a new Person is added

Test• Create cm.jar and startup the online system to test• Add a new person and verify that the Short Comment characteristic

was added by your Change Handler

Optional• Create a JUnit test class that adds a new person and verifies that the

Short Comment characteristic was automatically added. In this exercise, a completely new person, with all its required collections of names and Id numbers, must be created. In your test method …• Suspend validation until all the data has been added

• Create a new Person_Id object

Page 159: Java Application Development

159

Exercise 7 – Cascading Change HandlerOptional (continued)

• Create a new Person_DTO object

• Set the following required fields on the Person_DTO …• PersonOrBusiness• LifeSupportSensitiveLoad• LanguageId

• Create a new Person object from the DTO

• Create a PersonName_DTO object (use the getNames() method on the Person object)

• Set the following required fields on the PersonName_DTO …• EntityName• IsPrimaryName• NameType

• Add the name to the Names collection on the Person object (use sequence 1)

Page 160: Java Application Development

160

Exercise 7 – Cascading Change HandlerOptional (continued)

• Create a PersonId_DTO object (use the getIds() method on the Person object)• Set the following required fields on the PersonId_DTO …

• IsPrimaryId

• PersonIdNumber

• Add the Id to the Ids collection on the Person object for Id Type “SSN” (Social Security Number)

• Enable validation at this point (i.e. remove the suspension)• Verify that the short comment characteristic was added by getting a

PersonCharacteristic object for the expected “COMMENT” characteristic – if a null object is returned, fail the test as follows …

assertNotNull("Short Comment characteristic does not exist",perChar);

Page 161: Java Application Development

Services and Maintenance Classes

Page 162: Java Application Development

162

Services• Services expose business functionality via predefined

request and response data structures• Services may be invoked

• from outside the application JVM (I.e. a browser)• from from within the application (I.e. by a service script).

• These are the data access and update services• Many services are implemented by either Java classes or

COBOL programs. The implementations are called “maintenances”.

Page 163: Java Application Development

163

Services• Each service has an XML metainfo document describing

its structure• For integration, the framework automates the mapping of

string-based browser data to a service’s data structure using this metainfo XML (the XAI class covers this)

• The Service Dispatcher routes the service requests to the Java or COBOL service …

Page 164: Java Application Development

164

Services - Service Dispatcher• The Service Dispatcher acts as conduit to the business

objects from the presentation layer• A service invocation represents a database transaction • It invokes a Java or COBOL service

PresentationPresentation ServiceDispatcher

ServiceDispatcher

DBDBHibernateHibernate

JDBCJDBC

JDBCJDBC

COBOL SvcWrapper

COBOL SvcWrapper

COBOL AppCOBOL App

Java Maintenance

Business Objects Data Access

Page 165: Java Application Development

165

Service Dispatching• The Service Dispatcher is commonly invoked from a Web

servlet• It invokes the appropriate service for the Web request,

which could be one of the following1. Page service2. List service3. Search service

Service DispatcherService Dispatcher Dispatched ServiceDispatched Service

Page ServicePage Service List ServiceList Service Search ServiceSearch Service1 2 3

Page 166: Java Application Development

166

Page Services• This is a “top level” application service• It orchestrates the display and update of all data for a root object and

all its child objects – e.g. Person, Person Name, Person Phone, Person Id, etc.

• The data is displayed on a single tab menu – across one or more child tab pages

• Page service names end with “P” – e.g. the Person service is CILCPERP, Account service is CILCACCP, etc.

Page 167: Java Application Development

167

Page Service Dispatching• A Page service invoked in one of seven modes (actions)• Each service class determines if the maintenance service

is implemented in COBOL or Java and uses the appropriate calling mechanism to invoke it

Page ServicePage Service

ChangeChange CopyCopy DefaultDefault DeleteDelete ReadReadAddAdd

Java PageAdd Service

Java PageAdd Service

Cobol Page Add Service

Cobol Page Add Service

… same for all modes

Cobol SvcWrapper

Cobol SvcWrapper

ValidateValidate

Page 168: Java Application Development

168

List Services • This defines a list of objects• It could contain nested lists• It is used for list-oriented data – e.g. Customer Contacts

• List service names end in “L” – e.g. CILCPCCL for Customer Contact list

• They do not support database updates

Page 169: Java Application Development

169

List Service Dispatching• A List service class is invoked in single mode (“List”) from

the Service Dispatcher• It determines if the underlying list service is implemented

in COBOL or Java and uses the appropriate calling mechanism to invoke it

List ServiceList Service

Java ListService

Java ListService

Cobol ListService

Cobol ListService

Cobol SvcWrapper

Cobol SvcWrapper

Page 170: Java Application Development

170

Search Services• These are used to support ad-hoc user searches• The results are similar to list services• The input is set of criteria and a search mode

• Search service names end in “S” – e.g. CILCPERS for Person search

Page 171: Java Application Development

171

Search Service Dispatching• A Search service class is invoked in single mode

(“Search”) from the Service Dispatcher• It determines if underlying search service implemented in

COBOL or Java and uses the appropriate calling mechanism to invoke it

Search ServiceSearch Service

Java SearchService

Java SearchService

Cobol SearchService

Cobol SearchService

Cobol SvcWrapper

Cobol SvcWrapper

Page 172: Java Application Development

Java Maintenance Classes

Page 173: Java Application Development

173

Java Maintenance Classes

• Important forms of maintenances:• PageMaintenances are general purpose and can conceivably do

anything. However, whatever that is must be coded by the implementer.

• EntityPageMaintenance performs the CRUD for an MO• EntityListPageMaintenance performs CRUD on a collection of

entities without a single common maintained parent• SearchServices can perform searches based on varying input

fields

Page 174: Java Application Development

174

PageMaintenances

• Remember, these are the generic ones• Use the @PageMaintenance annotation

• Define the “body” based on the needs for request and response• Declare actions that make sense

• Supported actions are then implemented by overriding action methods, like “add” in the case of a service that adds data to the system or “read” when it just returns existing data.

• Walk-through: EmailService

Page 175: Java Application Development

175

EntityPageMaintenances

• Provide CRUD for MOs • The actions interact with the Entities in the MO• Use the @EntityPageMaintenance annotation

• For new MOs there is a wizard that creates a skeletal structure based on metadata.

• This should be a single root object. That is we are maintaining a single entity instance that my have children. To maintain lists, the @EntityListPageMaintenance is more appropriate

Page 176: Java Application Development

176

EntityPageMaintenances

• @EntityPageMaintenance values• Important root values:

• “service” defines the name of the service• “entity” defines the entity being maintained• “body” is always a data element containing an array of “contents”.

• @RowField should be used for the entity being maintained• @ListFields reference lists• @DataFields can be used to specify “loose fields”• @FieldGroup can be used to group fields together

• Lists• An array of lists is kept that may be referenced by name by @ListField

annotations in the root node of the annotation or other lists• The individual lists have bodies like in the root element discussed above.• Filters may be applied using HQL snippets which bind values in the

implmentation class

• Walk-through: FactMaintenance

Page 177: Java Application Development

177

EntityListPageMaintenances

• Use the @EntityListPageMaintenance annotation• These are typically very simple implementations• A @ListField will be used to define the maintained list in the root

body of the annotation• The reference list will refer to a @RowField corresponding to the

entity being maintained• orderBy” will specify ordering

• Walk-through: CurrencyMaintenance, LanguageListMaintenance

Page 178: Java Application Development

178

Search Services

• Use the @SearchService annotation• Provide some number of different search criteria that can be used

via the @SearchCriteria annotation. Importantly,• “hql” defines how the rows are retrieved

• “orderBy” specifies the order

• “fields” specifies the values that the search is based on

• “returnValus” specifies the values return be a search result row and includes HQL snippets to extract these values from the query result object

• Walk-through: BatchControlSearch

Page 179: Java Application Development

The Eclipse MO Wizard

Page 180: Java Application Development

180

The Eclipse MO Wizard

• An Eclipse plug-in was written to create default implementation classes, with annotations based on MO metadata definitions. This “wizard” will create:• Entity “Impl” classes for each entity in the MO• An EntityPageMaintenance class

• The user chooses the names for the class files, the package and file location and the wizard does the rest

Page 181: Java Application Development

Running the Wizard From Eclipse

Page 182: Java Application Development

End of Day 2

Page 183: Java Application Development

Business Components

Page 184: Java Application Development

184

Business Components

• Business Components are classes that provide two important features• A place to put reusable business logic without the other

responsibilites that come with other types of application classes (like entities, change handers, etc).

• Provide a lightweight replacement strategy that allows customers to fully replace some system logic without all of the formality and configuration of new plugin spots.

Page 185: Java Application Development

185

Adding a Business Component

• Use the @BusinessComponent annotation• With this simple anotation, the artifact generator will process the

business component and create business interface class.• customizationReplaceable

• Specify “customizationReplaceable” to indicate if a customer may replace this component. Setting this value to “true” also has the affect of treating the component as a customization whether or not it was actually provided by the base package or not.

• customizationCallable• Specify if the component is “customizationCallable”. This can be set

to true to allow customers to call methods on the business component but not replace the component

…more…

Page 186: Java Application Development

186

Adding a Business Component

• Use the @BusinessComponent annotation• replacementComponent

• In the case where the component is replacing a component defined in an application lower on the application stack, setting the “replacementComponent” attribute to “true” will cause the component to be the replacement component for any replaceable components where this component implements the same business interface as the component being repaced.

• Extend GenericBusinessComponet

Page 187: Java Application Development

Algorithms

Page 188: Java Application Development

188

Algorithms - Overview• Where the system requires a customization, we provide for

customizable algorithms (a.k.a plug-ins)• Base algorithms exist, but can be cloned and modified• They are like “user exits”, but …

• Unlike Change Handlers, they are more related to the business functions and events

• Also, unlike Change Handlers, they use configurable (“soft”) parameters

• For example …• In the CC&B world, if a CSR requests a customers recommended

deposit amount, the system calls a “deposit recommendation algorithm” to calculate the amount

• If the base version of the algorithm is not appropriate for your business, a new algorithm can be coded to replace or supplement the base one

Page 189: Java Application Development

189

Algorithms - Overview• At upgrades, custom algorithms will not be overwritten• Here are a few more examples where algorithms are used

• Validating the format of a phone number entered by the user• Validating the format of a latitude/longitude geographic code

entered by the user.• Calculating late payment charges in CC&B• Calculating the recommended deposit amount in CC&B• In CC&B, constructing your GL account during the interface of a

financial transaction to your GL• Etc.

• Let’s take a look at how algorithms work internally …

Page 190: Java Application Development

190

Algorithms - OverviewAlgorithms are defined in 2 places …

Database tables• The online Admin menu is used to define the database components,

which are …• Algorithm Types

• Algorithms

• The event or activity to which the algorithm applies (e.g. FT freeze, phone number validation, etc.)

The OU Framework• The framework requires the “implementation” class – the program

that contains the logic – and various generated artifacts (we will only be looking at Java, not COBOL)

Let’s take a look at these definitions more closely, database components first and then the framework classes …

Page 191: Java Application Development

191

CI_ALG_TYPE

PK ALG_TYPE_CD

PGM_NAMEALG_ENTITY_FLGPGM_TYPE_FLG

CI_ALG

PK ALG_CD

FK1 ALG_TYPE_CDVERSION

CI_ALG_TYPE_PRM

PK,FK1 ALG_TYPE_CDPK SEQNO

PARM_REQ_SW

CI_ALG_PARM

PK,FK2 ALG_CDPK EFFDTPK,FK1 SEQNO

ALG_PARM_VALFK1 ALG_TYPE_CD

Customized Entity

FK1 ALG_CD

Algorithm Database Model

• These are the tables that define an algorithm1. Algorithm Type defines …

• The entity – e.g. Char Type – Adhoc Value Validation, SA Type – SA Creation, etc.

• The program name

• The program type – JAVA or COBOL

1

Page 192: Java Application Development

192

Algorithm Database Model

• These are the tables that define an algorithm2. Algorithm Type Parameter defines …

• The parameters expected by the algorithm program

• For each parameter, whether it is required or optional

CI_ALG_TYPE

PK ALG_TYPE_CD

PGM_NAMEALG_ENTITY_FLGPGM_TYPE_FLG

CI_ALG

PK ALG_CD

FK1 ALG_TYPE_CDVERSION

CI_ALG_TYPE_PRM

PK,FK1 ALG_TYPE_CDPK SEQNO

PARM_REQ_SW

CI_ALG_PARM

PK,FK2 ALG_CDPK EFFDTPK,FK1 SEQNO

ALG_PARM_VALFK1 ALG_TYPE_CD

Customized Entity

FK1 ALG_CD

1

2

Page 193: Java Application Development

193

CI_ALG_TYPE

PK ALG_TYPE_CD

PGM_NAMEALG_ENTITY_FLGPGM_TYPE_FLG

CI_ALG

PK ALG_CD

FK1 ALG_TYPE_CDVERSION

CI_ALG_TYPE_PRM

PK,FK1 ALG_TYPE_CDPK SEQNO

PARM_REQ_SW

CI_ALG_PARM

PK,FK2 ALG_CDPK EFFDTPK,FK1 SEQNO

ALG_PARM_VALFK1 ALG_TYPE_CD

Customized Entity

FK1 ALG_CD

Algorithm Database Model

• These are the tables that define an algorithm3. Algorithm defines an “instance” of the algorithm type – many

algorithms may exist for one algorithm type

4. Algorithm Parameter defines the parameter values for the instance

4

1

2

3

Page 194: Java Application Development

194

CI_ALG_TYPE

PK ALG_TYPE_CD

PGM_NAMEALG_ENTITY_FLGPGM_TYPE_FLG

CI_ALG

PK ALG_CD

FK1 ALG_TYPE_CDVERSION

CI_ALG_TYPE_PRM

PK,FK1 ALG_TYPE_CDPK SEQNO

PARM_REQ_SW

CI_ALG_PARM

PK,FK2 ALG_CDPK EFFDTPK,FK1 SEQNO

ALG_PARM_VALFK1 ALG_TYPE_CD

Customized Entity

FK1 ALG_CD

Algorithm Database Model

• These are the tables that define an algorithm5. The algorithm code is specified on the customized entity’s

configuration table – the algorithm will be invoked based on this specification

• Let’s look at an example …

5

Examples

Characteristic TypeSA Type

Etc.

4

1

2

3

Page 195: Java Application Development

195

Algorithm Phone Format ExamplePhone format - algorithm definition diagram

Algorithm Type:PHN-FMT

CI_ALG_TYPE

PK ALG_TYPE_CD

PGM_NAMEALG_ENTITY_FLGPGM_TYPE_FLG

CI_ALG

PK ALG_CD

FK1 ALG_TYPE_CDVERSION

CI_ALG_TYPE_PRM

PK,FK1 ALG_TYPE_CDPK SEQNO

PARM_REQ_SW

CI_ALG_PARM

PK,FK2 ALG_CDPK EFFDTPK,FK1 SEQNO

ALG_PARM_VALFK1 ALG_TYPE_CD

Phone Type

FK1 ALG_CD

Format 1 – requiredFormat 2 – optionalFormat 3 – optional

Algorithm:PHN-FMT-US(999) 999-9999

Format 4 thru 9 – optional Algorithm:PHN-FMT-UK999 9999-999999999 999999

9999 999-9999

Phone Type: BUSN

Phone Type: BUSN_UK

Page 196: Java Application Development

196

Algorithm Phone Format ExampleAdmin -> Algorithm Type – Phone format

1. Algorithm Type name – 12 characters

2. The Algorithm Entity determines where the system will allow this algorithm to be specified – in this case, the PHN-FMT algorithm type may only be specified on the Phone Type entity

3. The Program Type here is JAVA (it can also be COBOL)

2

3

4

1

5

Page 197: Java Application Development

197

Algorithm Phone Format ExampleAdmin -> Algorithm Type – Phone format

4. This is the algorithm component interface to format and validate the phone number

Note: for the JAVA class to be specified, the class must already exist as a framework component

5. This specifies that at least one phone format is required

2

3

4

1

5

Page 198: Java Application Development

198

Algorithm Phone Format ExampleAdmin -> Algorithm – Phone format US

1. This is the algorithm name – i.e. the 1st “instance” of the algorithm type

2. The Algorithm Type that this algorithm corresponds to

3. The effective date

4. The phone format for this instance – only one for the U.S.

3

1

4

2

Page 199: Java Application Development

199

Algorithm Phone Format ExampleAdmin -> Algorithm – Phone format UK

1. This is the algorithm name - i.e. the 2nd “instance” of the algorithm type

2. It has the same algorithm type as for the U.S. (i.e. it is the SAME PROGRAM that formats U.S. and U.K. phone numbers)

1

3

2

Page 200: Java Application Development

200

Algorithm Phone Format ExampleAdmin -> Algorithm – Phone format UK

3. The U.K. has multiple phone formats – the algorithm will validate a U.K. phone number against all of these formats

1

3

2

Page 201: Java Application Development

201

Algorithm Phone Format ExampleAdmin -> Phone Type – Algorithm usage

1

2

• This defines 2 types of business phones1. U.S. phone numbers are to be validated and formatted by the

“North American phone format” algorithm, as defined on the previous slides

2. U.K. phone numbers are to be validated and formatted by the “United Kingdom phone format” algorithm, as defined on the previous slides

Page 202: Java Application Development

202

Algorithm Phone Format ExampleMain -> Person – Algorithm activation

1

2

• On the Person page, Phone Type now determines the algorithm to invoke for the phone number formatting and validation

In this topic we have so far looked at defining the database entries required for an algorithm definition – next we’ll see how the framework components are built to support these definitions …

Page 203: Java Application Development

203

Algorithm Spots• The “call out” places in the system (e.g. from Person to validate phone

number) are known as algorithm spots• Each algorithm spot has an interface class• Communication with an algorithm takes place through the interface• An interface provides abstraction between the base and the

customization

Business Component

Algorithm ComponentAlgorithm Spot

Interface

Person Phone Person Phone PhoneTypeFormatValidationAlgComp

PhoneTypeFormatValidationAlgComp

PhoneTypeFormatValidationAlgorithmSpot

PhoneTypeFormatValidationAlgorithmSpot

Page 204: Java Application Development

204

Algorithm Spots• The attributes of an algorithm spot interface class are …

• The API to the algorithm component (from the base application)• It is specific to the algorithm entity type (or system “event”)• It defines the hard input parameters for an algorithm – these are the

parameters associated with a specific event• It defines the output parameters that can be retrieved after the

algorithm has been invoke• Algorithm spots also specify the schema defined for a plug-in script

Page 205: Java Application Development

205

Algorithm Spots• These classes form part of the base code• They are invoked from the base code at appropriate times (events)• The methods on the interface are related to the algorithm type – for

example, setPhoneValue() is only relevant to PhoneTypeFormatValidationAlgorithmSpot

+invoke()

«interface»AlgoritmSpot

+setFormatOnly() : void+setCharacteristicType() : void+setAdhocValue() : void+getReformattedValue() : String+isValidAdhoc() : Boolean

«interface»AdhocCharacteristicValueValidationAlgorithmSpot

+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

«interface»PhoneTypeFormatValidationAlgorithmSpot

Page 206: Java Application Development

206

Adding Algorithm Spots

• Algorithm spots reference an AlgorithmEntityLookup value so a new lookup value must be added to correspond to the new spot

• Add an interface that defines the spot using the @AlgorithmSpot annotation. Properties include• algorithmEntity—One or more AlgorithmEntity values corresponding

to the lookup value described above• calledFromCobol—A boolean attribute that lets the framework know if

inbound call support is to be supported from COBOL• implementableInCobol—A boolean attribute that lets the framework

know if it must be able to call an algorithm implemented in COBOL• Extend the AlgorithmSpot interface• Wire up the call to the spot by accessing the AlgorithmComponent via

Algorithm.getAlgorithmComponent(…)

Example: See TimelineZoneAlgorithmSpot in FW

Page 207: Java Application Development

207

Supporting Plug-in Scripts

• Algorithms may also be implemented in Plug-in Scripts• In these cases, the Java signature gets interpreted by the

framework at runtime to generate the “parm” schema defining the parameters passed in and out of the plug-in script when invoked

• The framework needs to be able to figure out how to make XML out of the input parameters and make output parameter objects out of the output parameters. This cannot be done with every possible interface. The spot developer must help!

• Simple JavaBean compliant getters an setters should be used where• “set” methods represent values sent into the algorithm• “get” methods represent values returned

Page 208: Java Application Development

208

Supporting Plug-in Scripts

• Collections on the signature should have generic type information so the framework knows the class of the elements that it may contain.

• The ArtifactGenerator checks spot compatability with scripting and will issue an error if the spot cannot be used by the framework for plug-in scripts

• For unusable spots, there are two approaches• For new spots, the spots should be reworked to comply with

framework requirements• Some spots have been shipped before the plug-in spot technology

was created and were unknowingly non-complient. These spots cannot be reworked because they have been deployed to customers. Therefore a “BeanAdapter” class is necessary.• Please see the Wiki for more information on BeanAdapters

Page 209: Java Application Development

209

Algorithm Components• An algorithm requires a programmatic implementation• The Algorithm Type definition carries the program name,

for examplecom.splwg.base.domain.common.phoneType. PhoneTypeFormatValidationAlgComp

This name in fact specifies another interface which is generated from the implementation class

• The implementation class name = the interface name + “Impl”, for examplecom.splwg.base.domain.common.phoneType. PhoneTypeFormatValidationAlgComp_Impl

• The following diagram describes the full Phone Type Validation algorithm component …

Page 210: Java Application Development

210

Algorithm Components – Phone Type Validation

• Remember …• An interface is “empty” – it requires an implementation to perform

appropriate tasks• The implementation for an algorithm spot is an Algorithm

Component – i.e. Business Component

+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

«interface»PhoneTypeFormatValidationAlgorithmSpot

+getPhoneFormat1() : String+getPhoneFormat2() : String+getPhoneFormat3() : String+getPhoneFormat4() : String+getPhoneFormat5() : String+getPhoneFormat6() : String+getPhoneFormat7() : String+getPhoneFormat8() : String+getPhoneFormat9() : String

PhoneTypeFormatValidationAlgComp_Gen

+invoke() : void+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

PhoneTypeFormatValidationAlgComp_Impl

+invoke()

«interface»AlgoritmSpot

+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

«interface»PhoneTypeFormatValidationAlgComp

Page 211: Java Application Development

211

+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

«interface»PhoneTypeFormatValidationAlgorithmSpot

+getPhoneFormat1() : String+getPhoneFormat2() : String+getPhoneFormat3() : String+getPhoneFormat4() : String+getPhoneFormat5() : String+getPhoneFormat6() : String+getPhoneFormat7() : String+getPhoneFormat8() : String+getPhoneFormat9() : String

PhoneTypeFormatValidationAlgComp_Gen

+invoke() : void+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

PhoneTypeFormatValidationAlgComp_Impl

+invoke()

«interface»AlgoritmSpot

+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

«interface»PhoneTypeFormatValidationAlgComp

Algorithm Components – Phone Type Validation

12

3

1. The implementation class (…_Impl) is hand-coded – it can be customized

2. The component interface is generated by the artifact generator – a customized version will be generated for a custom “impl” class

3. An algorithm is invoked via its component interface

Page 212: Java Application Development

212

1. The implementation class contains the hand-coded logic

2. The _Gen class has the methods for the “soft” parameters (as specified on the Algorithm Type definition)Note: These are generated from the annotations in the “_Impl” class

+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

«interface»PhoneTypeFormatValidationAlgorithmSpot

+getPhoneFormat1() : String+getPhoneFormat2() : String+getPhoneFormat3() : String+getPhoneFormat4() : String+getPhoneFormat5() : String+getPhoneFormat6() : String+getPhoneFormat7() : String+getPhoneFormat8() : String+getPhoneFormat9() : String

PhoneTypeFormatValidationAlgComp_Gen

+invoke() : void+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

PhoneTypeFormatValidationAlgComp_Impl

+invoke()

«interface»AlgoritmSpot

+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

«interface»PhoneTypeFormatValidationAlgComp

Algorithm Components – Phone Type Validation

12

Page 213: Java Application Development

213

3. The generated component interface class also contains a “factory” class to create an instance of an algorithm component – we’ll see an example of this shortly

+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

«interface»PhoneTypeFormatValidationAlgorithmSpot

+getPhoneFormat1() : String+getPhoneFormat2() : String+getPhoneFormat3() : String+getPhoneFormat4() : String+getPhoneFormat5() : String+getPhoneFormat6() : String+getPhoneFormat7() : String+getPhoneFormat8() : String+getPhoneFormat9() : String

PhoneTypeFormatValidationAlgComp_Gen

+invoke() : void+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

PhoneTypeFormatValidationAlgComp_Impl

+invoke()

«interface»AlgoritmSpot

+setPhoneValue() : void+setPhoneType() : void+isValidPhoneValue() : Boolean+getPreferredFormatString() : String+getReformattedPhoneValue() : String

«interface»PhoneTypeFormatValidationAlgComp

Algorithm Components – Phone Type Validation

3

Page 214: Java Application Development

214

Algorithm Implementation Class• The base versions of all algorithms are provided• To create a new one, it is easiest to duplicate the

appropriate base one if it exists and modify it• The basic Java elements of a new algorithm are:

• An “_Impl” class, the hand-coded implementation class that contains the logic

• A “_Gen” class, the implementation class for the “soft” parameters, generated by the artifact generator

• A component interface class, generated by the AG• A message method, if required

Page 215: Java Application Development

215

Algorithm Phone Format Example

• This Impl class’s annotation specifies …1. The soft parameters expected by the algorithm – these correspond with

the Algorithm Type parameter definitions

2. Has an Algorithm Component name (as specified on the Algorithm Type) + “_Impl”

1

234

Page 216: Java Application Development

216

Algorithm Phone Format Example

• The class name …3. Extends the “_Gen” class – the “_Gen” class is generated by the

Artifact Generator

4. Implements the base Algorithm Spot class for the algorithm type

1

234

Page 217: Java Application Development

217

Algorithm Phone Format Example

• These methods are invoked by the business component to set the hard parameters1. This sets the phone number to validate – it is stored here for use later

2. This sets the phone type – this method here is empty because it is ignored in this algorithm

Algorithm Spot interface methods that are implemented in _Impl class …

1

2

Page 218: Java Application Development

218

Algorithm Phone Format Example

• The invoke() method is called to validate and format the phone number1. This sets a Boolean based on the validity of the phone number

Algorithm Spot interface methods that are implemented in _Impl class …

1

Page 219: Java Application Development

219

Algorithm Phone Format ExampleAlgorithm Spot interface methods that are implemented in _Impl class …

• These methods are called from the business component after the invoke() method1. This returns a true/false to indicate the validity of the phone number

(you may have noted that this Boolean is the one set in the invoke method)

2. This returns the reformatted value, also formatted in invoke()

1

2

3

Page 220: Java Application Development

220

Algorithm Phone Format ExampleAlgorithm Spot interface methods that are implemented in _Impl class …

• These methods are called from the business component after the invoke() method3. This returns the default phone format – in this case it is always the first

one (e.g. 1st format for U.K. – “999 9999-9999”)

1

2

3

Page 221: Java Application Development

221

Algorithm Phone Format ExampleGenerated artifacts that are based on the _Impl class annotation …

• The _Gen class has the methods for the soft parameters

• The _Impl class calls these methods to get the soft parameter values, as set on the Algorithm definition

Page 222: Java Application Development

222

Algorithm Phone Format ExampleGenerated artifacts that are based on the _Impl class annotation …

• The component interface defines the required methods for the _Impl class as viewed from the application (the business component)

Page 223: Java Application Development

223

Algorithm Phone Format ExampleGenerated artifacts that are based on the _Impl class annotation …

1. The Artifact Generator also generates a static Factory class in the component interface class file

2. It has the newInstance method to create an instance of the algorithm component at runtime

12

Page 224: Java Application Development

224

Algorithm Implementation Class Review• The steps to create a new algorithm class are …

1. Determine the Algorithm Spot interface name – the Javadocs could be used for this

2. Create the “_Impl” class, implementing the appropriate Algorithm Spot interface

3. Add default implementations for all the Algorithm Spot methods (e.g. using the Eclipse Source, Override/implement Methods… menu item)

4. Code the annotation

5. Run the Artifact Generator to create the “_Gen” and component interface classes

In Eclipse, you MUST refresh the project after this!

Page 225: Java Application Development

225

Algorithm Implementation Class Review• The steps to create a new algorithm class are …

6. Edit the “_Impl” class and …• Extend the “_Gen” class on the class definition• Store the required instances variables in the appropriate set… methods (these

instance variables will be referenced in the invoke() method)• Code the invoke() method – this contains the main logic• Return the value(s) in the get… methods as required by the Algorithm spot

7. Create the cm.jar file and shutdown and restart the application server – this is necessary for the Java class to be visible when creating the Algorithm Type definition (next step)

8. Create the Algorithm Type definition – the Java class name will now be in the Program Name drop-down list AND will automatically insert the Algorithm Type parameters from your annotation specification

NOTE: This is the reason for creating the Java impl class BEFORE adding the Algorithm Type and Algorithm definitions in the UI

Page 226: Java Application Development

226

Algorithm Implementation Class Review• The steps to create a new algorithm class are …

9. Create the Algorithm definition

10. Attach the algorithm to the business component

11. Test

Page 227: Java Application Development

227

Exercise 8 – Geographic Type AlgorithmAll Students• In this exercise you will create a Geographic Type algorithm to

validate geographic type “REGION” on Premise• Consider the following scenario …

1. Premises may be in North America or Europe

2. Within North America, the country may be U.S.A. or Canada

3. Within Europe, the country may be United Kingdom or France

4. A geographic type of “region” must be created to allow for the region code to be specified on Premise

5. The format of region code is W-CC, where …• W = World Region – “N” (North America); “E” (Europe)• CC = Country Code – “US” (USA); “CN” (Canada); “UK” (UK); “FR” (France)

The algorithm must validate that the country code falls within its region – for example E-FR is valid; E-US is invalid

Page 228: Java Application Development

228

Exercise 8 – Geographic Type AlgorithmAll Students (continued)

6. The valid region code values must be specified as soft parameters – i.e. no hardcoding of values in Java are allowed

• Java Requirements• The Algorithm Spot to implement is GeoTypeFormatValidationAlgorithmSpot• Name your class CmGeoTypeRegionAlgComp_Impl in package

com.splwg.cm.domain.common.geographicType• Create 2 parameters …

1. worldRegion, string, required

This will contain the 1-digit world region code

2. countryCodes, string, required

This will contain a comma-delimited string of valid country codes for their associated world region code

Page 229: Java Application Development

229

Exercise 8 – Geographic Type Algorithm• Online Configuration

• Create Algorithm Type XXGEOREGION (where XX are your initials) …• The Algorithm Entity is “Geographic Type – Value Format Rule”• Program Type is “Java”• Program Name should be CmGeoTypeRegionAlgComp

• Create two Algorithm definitions …1. XXGEOREG-E (where XX are your initials)

Specifies Europe and its valid countries

2. XXGEOREG-N (where XX are your initials)

Specifies North America and its valid countries

• Create two new Geographic Type definitions, using the following values for Type, Description and Format Algorithm respectively …1. XXREG-E, “Region Europe (XX)”, XXGEOREG-E (where XX are your initials)

2. XXREG-N, “Region North America (XX)”, XXGEOREG-N (where XX are your initials)

Page 230: Java Application Development

230

Exercise 8 – Geographic Type Algorithm• Online Configuration (continued)

• From your browser, use URL http://localhost:6800/flushDropdownCache.jsp to delete the drop-down cache on the server, and then clear the browser cache by deleting your “temporary internet files” to make the new Geographic Types known to the Premise Geographic Data page(Note: “localhost” and “6800” above refer to the server name and port of your web application server – it may be named differently in your specific case)

Test• When adding or changing a Geographic Type on Premise, the

algorithm should validate the format and content of geo type and display the generic message “Premise Geographic Value format incorrect” if invalid

OptionalThe JUnit test class for this exercise should check all possible combinations of invalid world regions and country codes, but we will only check two conditions – one valid and one invalid

Page 231: Java Application Development

231

Exercise 8 – Geographic Type AlgorithmOptional (continued)• Code a JUnit test class for your algorithm (the class must extend

AlgorithmImplementationTestCase) and in the test method – e.g. testGeoTypeRegion …• Similar to previous exercises, create a Premise object from an existing

premise on the database

• Create a new GeographicType_Id object for one of the geographic types you defined (e.g. “XXREG-E” or “XXREG-N”)

• Create a PremiseGeographicLocation_Id object for the Premise_Id (as instantiated above) and GeographicType_Id

• Suspend validation for the following steps

• Create a new PremiseGeographicLocation_DTO from the Id above

• On the DTO, set the value of GeographicValue (e.g. “E-UK”)

• Add the new GeographicLocation (via the DTO) to the collection of GeographicLocations for the Premise (note: the add method can also accept the DTO with the GeographicType_Id (e.g. “XXREG-E”)

Page 232: Java Application Development

232

Exercise 8 – Geographic Type AlgorithmOptional (continued)

• Remove the suspension to validate that the data currently entered is valid – an application error is not expected at this point

• Remove the existing PremiseGeographicLocation from the collection of GeographicLocations

• Set the GeographicValue to an invalid value (e.g. “E-US”)• Re-add the PremiseGeographicLocation object to the GeographicLocations

location which should trigger the validation• Catch the ApplicationError and use the following statement to verify that the correct

error was thrown …assertServerMessage(e, 3, 33901);

Page 233: Java Application Development

Creating Algorithm Spots

Page 234: Java Application Development

234

Creating Algorithms Spots

Page 235: Java Application Development

Batch

Page 236: Java Application Development

236

SPL Batch I• In this section we will look at …

• A brief overview of the SPL batch environment• An overview of batch controls• Batch programming in Java

Page 237: Java Application Development

237

Batch Environment• Batch programs run outside of the web app server, but still

within the context of the framework• The framework provides access to the business entities and

other objects• Therefore, ALL programs run under Java – even COBOL• For COBOL, all SQL calls are handled by the framework –

there are no direct calls from COBOL to Oracle/DB2/SQL Server (e.g. via PRO*Cobol)

Page 238: Java Application Development

238

Batch Threading• The system uses threading to achieve maximum

performance• What does a threaded process do?

• It determines the full workload (e.g. how many accounts?)• It divides the workload into n number of threads• It dispatches each thread to perform the workload – the workloads

are executed concurrently

• For example, instead of one task billing 50000 accounts, 5 tasks can each bill 10000 accounts simultaneously – this is naturally much faster

• The Artifact Generator creates the necessary components for multi-threading and the batch framework facilitates its execution

Page 239: Java Application Development

239

Batch Control• Batch controls are used in batch processing to control

restartibility, program identification, parameters, etc.• Each batch process has its own batch control code• A batch control code defines …

• The program name• The program type (COBOL / Java)• The batch parameters

• For example …

Page 240: Java Application Development

240

Batch Control – Java Example

1. The Batch Control code

2. The Program Type

3. The Program Name

1

23

4

6

5

Page 241: Java Application Development

241

Batch Control – Java Example

4. The batch run number (for this batch control) of the next submission5. Check this to accumulate the “records processed” counts for all instances

of one job – if the job fails and restarts, it will add the “failed” + “restarted” instances for the total records processed – should be unchecked for programs that work with flat files

1

23

4

6

5

Page 242: Java Application Development

242

Batch Control – Java Example

6. These are the non-standard parameters for the batch process – these parameters are prompted for after the standard parametersThey are supplied at runtime using name=value pairs, for exampleFILE-PATH=/spl/data

1

23

4

6

5

Page 243: Java Application Development

243

Batch Process Overview• A background process consists of 2 types of classes …

1. A BatchJob

2. A ThreadWorker

• The BatchJob class determines the work to be processed and splits it into chunks based on a thread count

• Each “chunk” of work is processed by an instance of ThreadWorker

• Let’s take a look at these two components …

Page 244: Java Application Development

244

Batch Process Overview

• BatchJob determines the work and divides it into manageable chunks (ThreadWork)

• Each ThreadWork consists of WorkUnits• WorkUnits represent fine-grained units of work – e.g. one bill

Page 245: Java Application Development

245

Batch Process Overview

• The ThreadWorker is responsible for processing a single ThreadWork instance

• Each ThreadWorker corresponds to one batch instance row on the database, which is used for restart after failure

Page 246: Java Application Development

246

The BatchJob Class• The BatchJob class consists of an annotation and a number

of standard methods that the framework uses to invoke and communicate with a batch process

• Let’s take a look at these components of a BatchJob class …

Page 247: Java Application Development

247

BatchJob Class Annotation

1. rerunnable indicates if the job can be re-run – e.g. bill print extract can be re-run

2. multiThreaded tells the framework if job can be submitted in multiple threads – i.e. if it will accept a thread count > 1

3. modules contains the modules the program belongs to – this should be empty for customizations

@BatchJob (rerunnable = false,

multiThreaded = true,

modules={todo},

softParameters = { @BatchJobSoftParameter (name=OUTPUT-DIR, type=string) },

toDoCreation = @ToDoCreation ( drillKeyEntity = user, sortKeys = {lastName, firstName}, messageParameters = {firstName, lastName} ) )

12

3

4

5

• A BatchJob class annotation looks as follows …

Page 248: Java Application Development

248

BatchJob Class Annotation

4. These are the non-standard parameters to prompt for when the job starts

5. This specifies how the “ToDo” entries should be created if application errors are found

• A BatchJob class annotation looks as follows …

@BatchJob (rerunnable = false,

multiThreaded = true,

modules={todo},

softParameters = { @BatchJobSoftParameter (name=OUTPUT-DIR, type=string) },

toDoCreation = @ToDoCreation ( drillKeyEntity = user, sortKeys = {lastName, firstName}, messageParameters = {firstName, lastName} ) )

12

3

4

5

Page 249: Java Application Development

249

BatchJob Class Definition• The BatchJob class must extend class

“<BatchJob class Name>_Gen”, for example

• The _Gen class is generated by the artifact generator based on the BatchJob annotation

public class BatchErrorToDoCreation extends BatchErrorToDoCreation_Gen {

Page 250: Java Application Development

250

BatchJob Class Public Methods• The following standard public methods must exist in a

BatchJob class …• Method getJobWork()

• This method determines the workload (using a Hibernate query) –• It passes back to the framework an instance of JobWork,

describing the work to be done

The JobWork instance contains the appropriate number of ThreadWork instances (based on the runtime thread count)

Each ThreadWork instance contains the same number of ThreadWorkUnits

The good news: a convenience framework method exists to handle this for you!

Page 251: Java Application Development

251

BatchJob Class Public Methods• Method getThreadWorkerClass()

• This method passes back to the framework the class name of the “worker” class – i.e. the hand-coded class that will perform the batch work

• The framework will create an instance of this class for each ThreadWork instance – i.e. each thread

• Passing back the class name (instead of an object) allows the framework to control the instantiation of the ThreadWorker classes so that they can be executed anywhere, even on different servers

Page 252: Java Application Development

252

The ThreadWorker Class• The ThreadWorker class is responsible for processing a single

ThreadWork instance – in other words, it performs the “heavy lifting”• A ThreadWorker can be executed on the same, or a different, server

as its associated BatchJob and other ThreadWorker instances• A ThreadWorker class must extend the artifact-generated class

“<ThreadWorker class name>_Gen” (the example below illustrates)• By convention a ThreadWorker class is coded as a static inner class

in its parent BatchJob class

public class BatchErrorToDoCreation extends BatchErrorToDoCreation_Gen {

... BatchJob methods ...

public static class BatchErrorToDoCreationWorker extends BatchErrorToDoCreationWorker_Gen {

... ThreadWorker methods ...

}}

Page 253: Java Application Development

253

ThreadWorker Class Public Methods• The following standard public methods are implemented

in a ThreadWorker class …

Page 254: Java Application Development

254

ThreadWorker Class Public Methods• Method createExecutionStrategy()

• This methods tells the framework how the work for thread will be processed

• It returns to the framework an instance of ThreadExecutionStrategy, of which the following implementations currently exist … SingleTransactionStrategy

This tells the framework to process all work in single transaction (logical unit-of-work)

Failure results in a rollback of the entire thread’s updates

It is most appropriate for jobs that CANNOT tolerate errors in the middle of a run, for example interfaces from flat files

CommitEveryUnitStrategy

This tells the framework to process each ThreadWorkUnit (e.g. one bill) in its own transaction and to issue a commit after each successful completion

Page 255: Java Application Development

255

ThreadWorker Class Public Methods• Method createExecutionStrategy()

• ThreadExecutionStrategy implementations continued… StandardCommitTransactionStrategy

This tells the framework to process up to a configurable number of work units within the same transaction to increase performance. If an error occurs, the previously successful units are reprocessed and the record and error skipped after logging the error.

It is most appropriate for jobs with high performance demands that must also tolerate errors.

Page 256: Java Application Development

256

ThreadWorker Class Public Methods• Method InitializeThreadWork(boolean)

• This is called by the framework at the start of a thread run to perform initialization

• By default it does nothing, but can be overridden to open files, initialize variables, etc.

• A Boolean parameter indicates if it was called previously

• Method executeWorkUnit(ThreadWorkUnit)• This is invoked once for each ThreadWorkerUnit assigned to a

ThreadWorker• For example, for a thread processing 1000 accounts, this method

will be called 1000 times• It performs the actual work, for example to process an account for

billing• The ThreadWorkUnit parameter is a reference to the Business

Entity to be processed – you use this parameter’s getPrimaryId method to get the business entity’s Id object

Page 257: Java Application Development

257

ThreadWorker Class Public Methods• Method finalizeThreadWork()

• This method is called at the end of thread processing• It can be used to clean up after a thread, for example to close files

These are the basic building blocks for a batch classLet’s take a look at a complete example that creates ToDos for batch runs that ended in error …

Page 258: Java Application Development

258

BatchJob Example – Create Batch Error ToDos

/** * @BatchJob (rerunnable = false, * multiThreaded = false, * modules={todo}) */public class CmBatchErrorToDoCreation extends CmBatchErrorToDoCreation_Gen {

private static final Logger logger = LoggerFactory.getLogger(CmBatchErrorToDoCreation.class);...

1. The BatchJob annotation specifies this job is not rerunnable, not multi-threaded and a “ToDo” module (remember, for a custom batch class, modules should be empty – i.e. {})

2. The class extends its associated _Gen class

3. This is a static definition of the Log4j logger to log messages at runtime (Note: You really should not log application messages to the system log, but for these exercises we will)

1

2

3

• The annotation and class definition

Page 259: Java Application Development

259

BatchJob Example – Create Batch Error ToDos

1. The getJobWork method sets up query for the work – this query retrieves BatchRun objects (CI_BATCH_RUN) that have an error status

2. It sets the runStatus bind variable in the query to the lookup constant ERROR

• The BatchJob methods public JobWork getJobWork() { Query errorRunQuery = createQuery("from BatchRun run “+ “where run.runStatus = :runStatus");

errorRunQuery.bindLookup("runStatus", RunStatusLookup.constants.ERROR);

return createJobWorkForEntityQuery(errorRunQuery); }

public Class getThreadWorkerClass() { return CmBatchErrorToDoCreationWorker.class; }

1

2

3

4

Page 260: Java Application Development

260

BatchJob Example – Create Batch Error ToDos

3. By passing the query to the convenience method createJobWorkForEntity, it returns to the framework a JobWork object which will contain an array of ThreadWork objects, each with ThreadWorkerUnits

4. The getThreadWorkerClass method returns to the framework the name of the ThreadWorker class – this class is defined as an inner class (as we’ll see on the next slide)

• The BatchJob methods

public JobWork getJobWork() { Query errorRunQuery = createQuery("from BatchRun run “+ “where run.runStatus = :runStatus");

errorRunQuery.bindLookup("runStatus", RunStatusLookup.constants.ERROR);

return createJobWorkForEntityQuery(errorRunQuery); }

public Class getThreadWorkerClass() { return CmBatchErrorToDoCreationWorker.class; }

1

2

3

4

Page 261: Java Application Development

261

BatchJob Example – Create Batch Error ToDos

public static class CmBatchErrorToDoCreationWorker extends CmBatchErrorToDoCreationWorker_Gen { ...

• The class is defined in the same source file as the BatchJob class and is therefore an “inner” class

• This is the class whose name is passed back to the framework in the getThreadWorkerClass method – as seen on the previous slide

• It extends its associated _Gen thread worker class, which is created by the artifact generator

• The inner ThreadWorker class definition

Page 262: Java Application Development

262

BatchJob Example – Create Batch Error ToDos

public ThreadExecutionStrategy createExecutionStrategy() {

// Commit on every todo. This is not expected to be a // performance intensive process. return new CommitEveryUnitStrategy(this); }

• createExecutionStrategy passes back to the framework an object of type CommitEveryUnitStrategy, which tells the framework that the job wants to commit after each transaction

• A “transaction” in this case is after each ToDo has been created

• Inner ThreadWorker method createExecutionStrategy

Page 263: Java Application Development

263

BatchJob Example – Create Batch Error ToDos

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 the ToDo type to be used by the executeWorkUnit method (next slide) when it creates the ToDos

• Inner ThreadWorker method initializeThreadWork

Page 264: Java Application Development

264

BatchJob Example – Create Batch Error ToDos

public boolean executeWorkUnit(ThreadWorkUnit unit) throws ThreadAbortedException, RunAbortedException {

BatchRun_Id errorBatchRunId = (BatchRun_Id) unit.getPrimaryId();

// get the run BatchRun batchRun = errorBatchRunId.getEntity(); ... createToDo(batchRun); ...

1. executeWorkUnit is called for each batch run in error, based on the initial query

2. It gets the primary Id from the ThreadWorkUnit object parameter and casts it to a BatchRun_Id class

3. It uses the Id object to get the BatchRun entity object for which the ToDo is to be created

4. It creates the ToDo entry

• Inner ThreadWorker method executeWorkUnit

1

2

3

4

Page 265: Java Application Development

265

BatchJob Example – Create Batch Error ToDos

• Inner ThreadWorker method finalizeThreadWork

This example does not implement the finalizeThreadWork method

public void finalizeThreadWork() throws ThreadAbortedException, RunAbortedException { }

Page 266: Java Application Development

266

BatchJob Creation Review

• Before we get to the exercise, let’s review how to create a new BatchJob class …1. Create the class file and code the annotation

2. Run the Artifact Generator to create the _Gen classes (you must refresh the Eclipse project after the AG has run)

3. Extend the class from the _Gen BatchJob class

4. Code the getJobWork and getThreadWorkerClass methods

5. Create the inner ThreadWorker class - extend it from the _Gen ThreadWorker class

6. Code the createExecutionStrategy method

7. Code the initializeThreadWork method (if needed)

8. Code the executeWorkUnit method

9. Code the finalizeThreadWork method (if needed)

10. Create the batch control

Page 267: Java Application Development

267

Exercise 10 – Batch 1All Students• Create a batch program to identify Persons without Accounts and display

their details on the log …• Name the program CmPersonsNoAccount in package com.splwg.cm.domain.batch• Identify the persons as follows …

• In the executeWorkUnit method, the ThreadWorkUnit parameter has a method getPrimaryId to get the Person_Id object – from this, determine the Person and the “primary” PersonName

• Display both the Person Id and the Entity Name on the log using the logger.info(…) method – the output should look like this …

from Person as per where not exists (from AccountPerson ap where ap.id.person = per)

Person without Account: 4470529669 French,JohnPerson without Account: 3909447990 Reliable Energy...

Page 268: Java Application Development

268

Exercise 10 – Batch 1All Students (continued)

• Add a new batch control using the online Admin menu – use batch code XXPNOA (where XX are your initials)

Test• Use the Batch - Training launch configuration from Eclipse to run

your job

The following run parameters should be specified:• Batch Code: Your batch code (e.g. XX-PNOA)

• Batch Thread Number: 1

• Batch Thread Count: 1

• User ID: SPL

• User Password: spladmin

• Language Code: ENG

Take the defaults for all the other parameters (i.e. hit Enter when prompted)

Page 269: Java Application Development

Batch II

Page 270: Java Application Development

270

SPL Batch II - ToDo’s

• In this section we look at how to create “ToDos” in a batch process

• FYI: The previous example (CmBatchErrorToDoCreation) class does that

It runs through all the batch program errors (CI_BATCH_RUN rows with status = “error”) and creates a ToDo for each

• The ToDo table structure looks as follows …

Page 271: Java Application Development

271

CI_TD_ENTRY

PK TD_ENTRY_ID

FK1 TD_TYPE_CD

CI_TD_TYPE

PK TD_TYPE_CD

CRE_BATCH_CDFK1 MESSAGE_CAT_NBRFK1 MESSAGE_NBRFK2 BATCH_CD

CI_TD_DRLKEY

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

KEY_VALUE

CI_TD_SRTKEY

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

KEY_VALUE

CI_TD_MSG_PARM

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

MSG_PARM_VAL

CI_TD_SRTKEY_TY

PK,FK1 TD_TYPE_CDPK SEQ_NUM

DEFAULT_SWORDER_FLG

CI_TD_DRLKEY_TY

PK,FK1 TD_TYPE_CDPK SEQ_NUM

FLD_NAMETBL_NAME

CI_MSG

PK MESSAGE_CAT_NBRPK MESSAGE_NBR

FK1 TD_TYPE_CD

CI_BATCH_CTRL

PK BATCH_CD

PROGRAM_NAME

SPL Batch II – ToDo Data Model

CONFIGURED

PROGRAMMED

1

54

2

3

• The tables on the left are populated via the Admin menu1. ToDo Type identifies the type of ToDo

2. Drill Key Type identifies which page to jump to when the user selects a ToDo to “work” on

3. Sort Key Type determines how the ToDo list is sorted

Page 272: Java Application Development

272

CI_TD_ENTRY

PK TD_ENTRY_ID

FK1 TD_TYPE_CD

CI_TD_TYPE

PK TD_TYPE_CD

CRE_BATCH_CDFK1 MESSAGE_CAT_NBRFK1 MESSAGE_NBRFK2 BATCH_CD

CI_TD_DRLKEY

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

KEY_VALUE

CI_TD_SRTKEY

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

KEY_VALUE

CI_TD_MSG_PARM

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

MSG_PARM_VAL

CI_TD_SRTKEY_TY

PK,FK1 TD_TYPE_CDPK SEQ_NUM

DEFAULT_SWORDER_FLG

CI_TD_DRLKEY_TY

PK,FK1 TD_TYPE_CDPK SEQ_NUM

FLD_NAMETBL_NAME

CI_MSG

PK MESSAGE_CAT_NBRPK MESSAGE_NBR

FK1 TD_TYPE_CD

CI_BATCH_CTRL

PK BATCH_CD

PROGRAM_NAME

SPL Batch II – ToDo Data Model

CONFIGURED

PROGRAMMED

1

54

2

3

• The tables on the left are populated via the Admin menu4. Message specifies the message to show in the ToDo list

5. Batch Control contains the batch control of the job that created the ToDo

Page 273: Java Application Development

273

CI_TD_ENTRY

PK TD_ENTRY_ID

FK1 TD_TYPE_CD

CI_TD_TYPE

PK TD_TYPE_CD

CRE_BATCH_CDFK1 MESSAGE_CAT_NBRFK1 MESSAGE_NBRFK2 BATCH_CD

CI_TD_DRLKEY

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

KEY_VALUE

CI_TD_SRTKEY

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

KEY_VALUE

CI_TD_MSG_PARM

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

MSG_PARM_VAL

CI_TD_SRTKEY_TY

PK,FK1 TD_TYPE_CDPK SEQ_NUM

DEFAULT_SWORDER_FLG

CI_TD_DRLKEY_TY

PK,FK1 TD_TYPE_CDPK SEQ_NUM

FLD_NAMETBL_NAME

CI_MSG

PK MESSAGE_CAT_NBRPK MESSAGE_NBR

FK1 TD_TYPE_CD

CI_BATCH_CTRL

PK BATCH_CD

PROGRAM_NAME

SPL Batch II – ToDo Data Model

CONFIGURED

PROGRAMMED

• The tables on the right are populated programmatically1. ToDo Entry has one row per ToDo entry and a foreign key to

the ToDo Type

2. Drill Key contains the key value (e.g. person Id) to use for the navigational “drill down” when the user selects the ToDo to “work” on

1

4

2

3

Page 274: Java Application Development

274

CI_TD_ENTRY

PK TD_ENTRY_ID

FK1 TD_TYPE_CD

CI_TD_TYPE

PK TD_TYPE_CD

CRE_BATCH_CDFK1 MESSAGE_CAT_NBRFK1 MESSAGE_NBRFK2 BATCH_CD

CI_TD_DRLKEY

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

KEY_VALUE

CI_TD_SRTKEY

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

KEY_VALUE

CI_TD_MSG_PARM

PK,FK1 TD_ENTRY_IDPK SEQ_NUM

MSG_PARM_VAL

CI_TD_SRTKEY_TY

PK,FK1 TD_TYPE_CDPK SEQ_NUM

DEFAULT_SWORDER_FLG

CI_TD_DRLKEY_TY

PK,FK1 TD_TYPE_CDPK SEQ_NUM

FLD_NAMETBL_NAME

CI_MSG

PK MESSAGE_CAT_NBRPK MESSAGE_NBR

FK1 TD_TYPE_CD

CI_BATCH_CTRL

PK BATCH_CD

PROGRAM_NAME

SPL Batch II – ToDo Data Model

CONFIGURED

PROGRAMMED

• The tables on the right are populated programmatically3. Sort Key contains the value(s) to sort on (e.g. person name)

4. Message Parameter contains the values for message substitution

1

4

2

3

Page 275: Java Application Development

275

Exercise 11 – Batch 2

All Students• Modify the previous exercise’s class to create ToDo entries for Persons

without Accounts …• The ToDo creation methods to populate the right-sided tables as described on the

previous slide have too much complexity for this course, so the instructor will supply a template for the ToDo creation methods – you can simply copy and paste those into your class

• The supplied methods are …• public void initializeThreadWork

• private boolean toDoAlreadyExists

• private void createToDo

• private void addDrillKeyValue

• private void addSortKeyValue

• private void addMessageParameter

Page 276: Java Application Development

276

Exercise 11 – Batch 2All Students (continued)

• In your executeWorkUnit method …• As in the previous exercise, determine the Person_Id and PersonName_Id values

• Using the supplied method, determine if the ToDo already exists and, if so, write a message to the system log indicating such and return with a Boolean of true

• Optionally, write a message to the system log to show the person id and name being added to the ToDo

• Use the supplied method to create the ToDo entry

• Follow the instructions over the following slides to add the configuration data for the batch control, message and ToDo

Important note: Over the following slides, all the examples specify names that contain XX. To avoid overwriting another student’s definitions, substitute XX in all cases with your own 2-digit initials

Page 277: Java Application Development

277

Exercise 11 – Batch 2All Students (continued)• Create new batch control XX-TDPNA

• Create new message “Person %1 has no Accounts (XX)”

Page 278: Java Application Development

278

Exercise 11 – Batch 2All Students (continued)• Create new ToDo type XXTDPNA – Main tab

• ToDo Type XXTDPNA – Roles tab

Page 279: Java Application Development

279

Exercise 11 – Batch 2All Students (continued)• ToDo Type XXTDPNA – Sort Keys tab

• ToDo Type XXTDPNA – Drill Keys tab

Page 280: Java Application Development

280

Exercise 11 – Batch 2Test• Use the Batch - Training launch configuration from Eclipse to run your job

• Verify in the online system that it created a ToDo entry for each Person identified as not having an Account …• It should show the message with person name substituted• It should be sorted in person name ascending sequence• You should be able to drill into a person from the ToDo list

• With this exercise we do not create a JUnit test class, but it can be done in one of two ways …1. Extending the BatchJobTestCase class and implementing abstract methods

2. Calling the submitBatchJob(SubmissionParameters) method in any ContextTestCase - this allows testing a mix of one or more background process and other business logic to be tested

In both cases, the database does not get updated

Page 281: Java Application Development

281

Exercise 11 – Batch 2

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'

Test (continued)Note: When testing your batch class and an error occurs, run the following delete statements before re-executing your batch class – these statements will delete all previously created ToDo entries to prepare for the re-run

Page 282: Java Application Development

End of day 4

Page 283: Java Application Development

283