Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
V2 for Developers
Agenda
10. Messages
11. Change Handlers Part III – Conditions
12. Change Handlers Part IV – Custom Validation Rule
13. Change Handlers Part V – Cascading Changes
14. Algorithms Part I – Validation
15. Algorithms Part II – Validation & Formatting
16. SPL Batch Part I – Simple Batch
HTTP
HTML
JavaScript/
XSLT
Session State
Web Browser
HTTP
HTML Presentation Business Data Access
Servlets/XSLT Services Persistent
JavaScript/
Entities
XSLT Caches Data Service
Objects Hibernate
Session State (Java/COBOL)
JDBC
HTTP
HTML Presentation Business Data Access
Servlets/XSLT Services Persistent
JavaScript/
Entities
XSLT Caches Data Service
Objects Hibernate
Session State (Java/COBOL)
JDBC
HTTP
HTML Presentation Business Data Access
Servlets/XSLT Services Persistent
JavaScript/
Entities
XSLT Caches Data Service
Objects Hibernate
Session State (Java/COBOL)
JDBC
HTTP
HTML Presentation Business Data Access
Servlets/XSLT Services Persistent
JavaScript/
Entities
XSLT Caches Data Service
Objects Hibernate
Session State (Java/COBOL)
JDBC
HTTP
HTML Presentation Business Data Access
Oracle
Servlets/XSLT Services Persistent
JavaScript/ DB2
Entities
XSLT Caches Data Service
Objects Hibernate MSSQL
Session State (Java/COBOL)
JDBC
• Database
– Framework supports …
• Oracle
• DB2
• Microsoft SQL Server.
splbatch.sh / cmd
(command line)
Scheduler
Etc.
Submission
• Batch Processing
– A scheduler or the command-line is used to invoke the splbatch script
(the scheduler can be a 3rd party or SPL’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
Batch Control Business Data Access
(command line) Oracle
Standalone Data Service Persistent
Scheduler Executor Objects Entities DB2
(Java/COBOL) MSSQL
Batch Process Hibernate
Etc.
JDBC
• 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)
COBOL App
Java Service
JDBC
Business Objects Data Access
Hibernate JDBC DB
1 2 3 Search Service
Page Service List Service
• Page service names end with “P” – e.g. the Person service
is CILCPERP, Account service is CILCACCP, etc.
List Service
Java List
Service
Search Service
Java Search
Service
COBOL App
Java Service
JDBC
Business Objects Data Access
Hibernate JDBC DB
Child
JVM
COBOL App
Java Service
JDBC
Business Objects Data Access
Hibernate JDBC DB
Child
JVM
COBOL App
Java Service
JDBC
Business Objects Data Access
Hibernate JDBC DB
Page Row
Maintenance Maintenance
Person Person
Page Row
Person
CI_PER
Page
COBOL App
Java Service
JDBC
Business Objects Data Access
Hibernate JDBC DB
COBOL App
Java Service
JDBC
Business Objects Data Access
Hibernate JDBC DB
+createDTO()
Person_Gen PersonName_Gen
-id -id
-address1 CI_PER_NAME -entityName
CI_PER
+getId() +getId()
+getAddress() PK,FK1 PER_ID +getEntityName()
PK PER_ID PK SEQ
Person_Impl ADDRESS1 ENTITY_NAME PersonName_Impl
PersonName
Person Interface
Interface
+createDTO()
Person_Gen PersonName_Gen
-id -id
-address1 CI_PER_NAME -entityName
CI_PER
+getId() +getId()
+getAddress() PK,FK1 PER_ID +getEntityName()
PK PER_ID PK SEQ
Person_Impl ADDRESS1 ENTITY_NAME PersonName_Impl
PersonName
Person Interface
Interface
Person_Id Person_Gen
Person_DTO
-id PersonNames_Impl
-address1 «interface»
PersonNames
+getId()
+getAddress() +add()
+remove()
«interface»
Person
+getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()
Person_Id Person_Gen
Person_DTO
-id PersonNames_Impl
-address1 «interface»
PersonNames
+getId()
+getAddress() +add()
+remove()
«interface»
Person
+getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()
Person_Id Person_Gen
Person_DTO
-id PersonNames_Impl
-address1 «interface»
PersonNames
+getId()
+getAddress() +add()
+remove()
«interface»
Person
+getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()
Person_Gen
-id
-address1
+getId()
+getAddress()
«interface»
Person
+getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()
AbstractBusinessEntity
+setDTO()()
Person : Person_Impl
PER_ID ADDRESS1 …
id = 1550000001
address1 = Easy Street 1550000001 Easy Street …
Person : Person_Impl
PER_ID ADDRESS1 …
id = 1550000001
address1 = Easy Street 1550000001 Easy Street …
Person : Person_Impl
7804500002 Penny Lane …
id = 7804500002 …
address1 = Penny Lane
«interface»
Person
More about Ids and DTOs in a +getId() Person_Impl
minute…
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()
Person_Gen
-id
-address1
+getId()
+getAddress()
«interface»
Person
More about Ids and DTOs in a minute… +getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()
Person_DTO
Person_DTO
StringId
Person_Id
StringId
Person_Id
– Sequentially retrieved
– Removed
– Added
PersonNames_Impl
«interface»
PersonNames
+add()
+remove()
PersonNames_Impl
«interface»
PersonNames
+add()
+remove()
«interface»
Person
+getId() Person_Impl
+getAddress1()
+getInfo() +getInfo()
+getDTO()()
+setDTO()()
Here’s an example:
/**
@SampleAnnotation (
simpleString = value,
complexString = "A string with spaces",
boolean = true,
arrayOfStrings = {abc, def, "g h i" },
fkAnnotation = @NestedAnnotation ( property = value ),
arrayOfAnnotations = { @ChildAnnotation (name=first),
@ChildAnnotation (name=second)}
)
*/
public class ExampleClass {
....
}
1. Java-doc comments
2. Annotation name
3. Property-value pairs – strings and Booleans
4. Array of annotations
Sy
st
em
D
at
a
Project
Dev DB
Sy
st
em
D
at
a
Project
Dev DB
Sy
st
em
D
at
a
Project
Dev DB
Sy
st
em
D
at
a
Project
Dev DB
Sy
st
em
D
at
a
Project
Dev DB
A development workstation …
1. Is created as an image of the project repository initially
2. Is where a developer codes and tests customizations for a project –
unit-tested code is submitted back to the project repository
Sy
st
em
D
at
a
Project
Dev DB
Sy
st
em
D
at
a
Project
Dev DB
– source contains the Java source code – the source is created and edited
using Eclipse
– sourcegen is where the artifact generator places the generated Java
classes
– target is where the Java compiler places the compiled Java classes (the
.class files)
• These folders are all updated from Eclipse – you should not
have to manually update them from Windows
1. applications\root\WEB-INF\lib
2. standalone\lib
• This folder contains all the jar files for the online application server
• Included here are the framework jars …
– spl-base-2.0.10.jar
– spl-shared-2.0.10.jar
• … and the product jars, for example for CC&B …
– spl-ccb-2.0.5.jar
• … and many others
• This folder will also house your cm.jar file, which contains all your
customization class files (programs)
• We will see in the next topic how to create this jar file from Eclipse
• This standalone folder contains all the jar files for the batch server
and remote COBOL JVMs
• It contains mostly the same jar files as the online app server folder,
including the framework and product ones mentioned earlier
• You need to also place your cm.jar file in this folder to run your
Java batch programs
• Enter the
SPLSDKCommon
folder name under your
SPL environment folder
in the root directory
text box
• Make sure that only the
Training project is
selected
• Make sure that the
“Copy projects into
workspace” box is
unchecked!
• Click Finish
• Once the project has been fully imported, you should see the
Training project defined in your Package Explorer view
• You will recognize the folders from the ones discussed under the
SDK section – these folders are “linked” to the appropriate
folders in your SPL environment folder – right-click and view the
folder properties to find its actual location on the file system
/**
* @ChangeHandler (entityName = characteristicType)
*/
public class CmCharacteristicType_CHandler
extends AbstractChangeHandler {
...
}
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)
1 startChanges();
Person_DTO perDTO = (Person_DTO)this.createDTO(Person.class);
Person_Id perId = new Person_Id(“1234567890”);
perDTO.setId(perId);
2 Person person = perDTO.newEntity();
PersonName_DTO perNameDTO =
(PersonName_DTO) createDTO(PersonName.class);
PersonName_Id perNameId = new PersonName_Id(person,
BigInteger.ONE);
3 perNameDTO.setId(perNameId);
perNameDTO.setEntityName(“Blog,Joe");
perNameDTO.setNameType(NameTypeLookup.constants.PRIMARY);
4 PersonName perName = perNameDTO.newEntity();
person.getNames().add(perName);
5 saveChanges();
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)
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
All 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
addError(StandardMessages.FieldMissing(fieldName))
addError(StandardMessages.fieldMissing("EMAILID"));
• 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 …
1 package com.splwg.cm.domain;
import com.splwg.base.domain.common.message.AbstractMessageRepository;
2 import com.splwg.cm.domain.templates.MessageRepository;
3 public class CustomMessages extends AbstractMessageRepository {
4 public static final int MESSAGE_CATEGORY = 90000;
5 public static final int REQ_IF_CONDITION = 10006;
private static MessageRepository instance;
public CustomMessages() {
super(MESSAGE_CATEGORY);
}
static MessageRepository getInstance() {
if (instance == null) instance = new MessageRepository();
return instance;
}
}
1 package com.splwg.cm.domain.customerinfo.person;
import com.splwg.cm.domain.CustomMessages;
public class MessageRepository extends CustomMessages {
2 private static MessageRepository instance;
3 private static MessageRepository getInstance() {
4 if (instance == null) instance = new MessageRepository();
return instance;
}
}
parms.addField(fieldName1);
parms.addField(fieldName2);
All 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(…)
Condition isPerson =
new Equals(Person.properties.personOrBusiness,
PersonOrBusinessLookup.constants.PERSON);
All 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
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 …
All 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
Optional
• 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 validation
Note: 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
Optional (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
• As indicated by the JDBC block on the right, the SPL Framework also
provides for direct JDBC calls if needed
• This instantiates an object of class Cat from the DB table for Cat
• The load() method throws an unrecoverable exception if the row does
not exist
• Use the get() method to avoid the exception – instead, it returns a null
if the row is not found, as shown below
• This can be an inefficient model since it requires a SQL select and SQL
update in the same session
• The following slide shows a different approach …
• In this example …
– A existing Cat object, cat, is instantiated from a database row through the
session load method – a new Cat, potentialMate, is also created
– cat is then modified in some other part of the application - it’s mate is set to the
new potentialMate object
– In a second session, cat it is updated on the database – this does the update
directly, instead of first selecting the object
sess.delete(cat);
or …
Person perEntity = (Person)query.firstRow();
or …
perDTO.setId(new Person_Id(“1185477091”));
perDTO.set...
Person person = perDTO.newEntity();
person.delete();
… or you can delete the results of a query using the delete method
on Query
Query query = SessionHolder.getSession()
.createQuery("from Person");
long rowsDeleted = query.delete();
• To add a third (or later) query, you add it directly to the union
union.addQueryToUnion(query3);
• 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
• 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
7. It adds the partially completed DTO to the account’s alert entity list –
the additional parameters are required for the entity list
The framework will add the row when the transaction commits
All 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
CI_ALG_PARM
CI_ALG_TYPE_PRM PK,FK2 ALG_CD
PK,FK1 ALG_TYPE_CD PK EFFDT
PK SEQNO PK,FK1 SEQNO
PARM_REQ_SW ALG_PARM_VAL
FK1 ALG_TYPE_CD
CI_ALG_PARM
2 CI_ALG_TYPE_PRM PK,FK2 ALG_CD
PK,FK1 ALG_TYPE_CD PK EFFDT
PK SEQNO PK,FK1 SEQNO
PARM_REQ_SW ALG_PARM_VAL
FK1 ALG_TYPE_CD
PARM_REQ_SW ALG_PARM_VAL
FK1 ALG_TYPE_CD
CI_ALG_PARM Examples
CI_ALG_TYPE_PRM PK,FK2 ALG_CD
PK EFFDT
Characteristic Type
PK,FK1 ALG_TYPE_CD
PK SEQNO PK,FK1 SEQNO SA Type
PARM_REQ_SW ALG_PARM_VAL Etc.
FK1 ALG_TYPE_CD
CI_ALG_PARM
CI_ALG_TYPE_PRM PK,FK2 ALG_CD
PK,FK1 ALG_TYPE_CD PK EFFDT
PK SEQNO PK,FK1 SEQNO
PARM_REQ_SW ALG_PARM_VAL
FK1 ALG_TYPE_CD
2
3
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. The U.K. has multiple phone formats – the algorithm will validate
a U.K. phone number against all of these formats
1
2
Business Algorithm
Algorithm Spot
Component Interface Component
PhoneTypeFormat PhoneTypeFormat
Person Phone ValidationAlgorithmSpot ValidationAlgComp
«interface»
PhoneTypeFormatValidationAlgorithmSpot
+setPhoneValue() : void
+setPhoneType() : void
+isValidPhoneValue() : Boolean
+getPreferredFormatString() : String
+getReformattedPhoneValue() : String
PhoneTypeFormatValidationAlgComp_Gen
PhoneTypeFormatValidationAlgComp_Impl
«interface»
+getPhoneFormat1() : String
PhoneTypeFormatValidationAlgComp
+getPhoneFormat2() : String
+setPhoneValue() : void +invoke() : void
+getPhoneFormat3() : String
+setPhoneType() : void +setPhoneValue() : void
+getPhoneFormat4() : String
+isValidPhoneValue() : Boolean +setPhoneType() : void
+getPhoneFormat5() : String
+getPreferredFormatString() : String +isValidPhoneValue() : Boolean
+getPhoneFormat6() : String
+getReformattedPhoneValue() : String +getPreferredFormatString() : String
+getPhoneFormat7() : String
+getReformattedPhoneValue() : String
+getPhoneFormat8() : String
+getPhoneFormat9() : String
«interface»
PhoneTypeFormatValidationAlgorithmSpot
+setPhoneValue() : void
+setPhoneType() : void
+isValidPhoneValue() : Boolean
+getPreferredFormatString() : String
+getReformattedPhoneValue() : String
PhoneTypeFormatValidationAlgComp_Gen
PhoneTypeFormatValidationAlgComp_Impl
«interface»
PhoneTypeFormatValidationAlgComp
2
+getPhoneFormat1() : String
+getPhoneFormat2() : String 1
+invoke() : void
3
+setPhoneValue() : void
+setPhoneType() : void
+getPhoneFormat3() : String
+setPhoneValue() : void
+getPhoneFormat4() : String
+isValidPhoneValue() : Boolean +setPhoneType() : void
+getPhoneFormat5() : String
+getPreferredFormatString() : String +isValidPhoneValue() : Boolean
+getPhoneFormat6() : String
+getReformattedPhoneValue() : String +getPreferredFormatString() : String
+getPhoneFormat7() : String
+getReformattedPhoneValue() : String
+getPhoneFormat8() : String
+getPhoneFormat9() : String
«interface»
PhoneTypeFormatValidationAlgorithmSpot
+setPhoneValue() : void
+setPhoneType() : void
+isValidPhoneValue() : Boolean
+getPreferredFormatString() : String
+getReformattedPhoneValue() : String
2
PhoneTypeFormatValidationAlgComp_Gen 1
PhoneTypeFormatValidationAlgComp_Impl
«interface»
+getPhoneFormat1() : String
PhoneTypeFormatValidationAlgComp
+getPhoneFormat2() : String
+setPhoneValue() : void +invoke() : void
+getPhoneFormat3() : String
+setPhoneType() : void +setPhoneValue() : void
+getPhoneFormat4() : String
+isValidPhoneValue() : Boolean +setPhoneType() : void
+getPhoneFormat5() : String
+getPreferredFormatString() : String +isValidPhoneValue() : Boolean
+getPhoneFormat6() : String
+getReformattedPhoneValue() : String +getPreferredFormatString() : String
+getPhoneFormat7() : String
+getReformattedPhoneValue() : String
+getPhoneFormat8() : String
+getPhoneFormat9() : String
«interface»
PhoneTypeFormatValidationAlgorithmSpot
+setPhoneValue() : void
+setPhoneType() : void
+isValidPhoneValue() : Boolean
+getPreferredFormatString() : String
+getReformattedPhoneValue() : String
PhoneTypeFormatValidationAlgComp_Gen
3 PhoneTypeFormatValidationAlgComp_Impl
«interface»
+getPhoneFormat1() : String
PhoneTypeFormatValidationAlgComp
+getPhoneFormat2() : String
+setPhoneValue() : void +invoke() : void
+getPhoneFormat3() : String
+setPhoneType() : void +setPhoneValue() : void
+getPhoneFormat4() : String
+isValidPhoneValue() : Boolean +setPhoneType() : void
+getPhoneFormat5() : String
+getPreferredFormatString() : String +isValidPhoneValue() : Boolean
+getPhoneFormat6() : String
+getReformattedPhoneValue() : String +getPreferredFormatString() : String
+getPhoneFormat7() : String
+getReformattedPhoneValue() : String
+getPhoneFormat8() : String
+getPhoneFormat9() : String
3
4
• 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
1
2
All 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
Optional (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”)
Optional (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);
All Students
• Java Requirements
– Create a new message constant and method for a runtime message (not
declarative)
• The message text should be
Country code %1 not valid for region %2 (XX)
(Where XX are your initials)
• Use a message number > 10000
• Add a CustomMessages constant for your message
• Add a method for the message to your MessageRepository class in
the com.splwg.cm.domain.common.characteristicType package
The message takes 2 parameters – world region code and country
code – the method must substitute them when setting up the
message for display
Online Configuration
– Create Algorithm Type XX-AV-REGION with the necessary parameter
definitions (the Algorithm Entity is “Characteristic Type – Adhoc Value
Validation”
– Create 2 Algorithm definitions
1. XX-AV-REG-E - specifies Europe and its valid countries
2. XX-AV-REG-N - specifies North America and its valid countries
– Create 2 Characteristic Type definitions …
1. XX-REG-E to validate the European region
2. XX-REG-N to validate the North American region
Both must be of type “Adhoc Value”
The Characteristic Entity (2nd Tab) must be “Premise”
– Create a new message in category 90000
“Country code %1 not valid for region %2 (XX)”
(Where XX are your initials)
2
3
4
5
2
3
4
5
4. The batch run number (for this batch control) of the next submission
5. 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
2
3
4
5
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
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
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 tables on the left are populated via the Admin menu
4. Message specifies the message to show in the ToDo list
5. Batch Control contains the batch control of the job that created the
ToDo
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
Thank You