A dummy's approach to making a simple DSL for headless interaction with a 5250 emulator.
This project was used to reinforce my limited knowledge of Groovy and learn how to make a Domain Specific Language (DSL). Additionally, 5250 emulator automation seemed like a fascinating topic to screw around with.
Possible applications could be basic automated tasks/testing and general screen scraping.
My coworker (Ryan Eberly) sparked the motivation for this project, he has an awesome 5250 testing project built around TN5250J called Terminal Driver.
I think I could have taken this project a lot further (this is a super shallow implementation), but for now I am satisfied with it; Time to move onto the next "shiny".
- Get and set cursor position
- Enter strings at position
- Scrape screen for string or list of strings
- Scrape screen contents to text file
- Check screen position for string
- Press command keys F1-F24 and other keys ENTER, TAB, ESCAPE, PAGEUP, PAGEDOWN, etc.
- Download TN5250J jar and place in libs/
A simple example to showcase various operations the DSL can perform
final config = new JsonSlurper().parse(new File(this.getClass().getResource('/config.json').toURI()))
final List<String> qrpgleMembers = []
Dsl5250.eval{
environment{
outputPath = 'out'
host = config['host']
user = config['user']
password = config['password']
}
stages{
stage('LOGIN'){
steps{env->
position 6,53
send env.user
capture()
position 7,53
send env.password,true // true -> masks text in log
press Key.ENTER
waitms 2500
if(check('Display Program Messages',1,28) || check('Display Messages',1,33)){
press Key.ENTER
waitms 1000
}
capture()
waitms 1000
}
}
stage('DSPLIBL'){
steps{
send 20,7,'DSPLIBL'
press Key.ENTER
waitms 1000
capture()
cmd 12
waitms 1000
}
}
stage('EXTRACT'){
steps{
def system = extract(2,72,10) // testing extract method (row, col, length)
println "system - $system"
position 20,7
send 'WRKMBRPDM BOLIB/QRPGLESRC'
press Key.ENTER
waitms 1000
while(!(check('You have reached the bottom of the list.',24,2))){
capture()
qrpgleMembers.addAll(extract(11,7,10,8).collect{i-> i.replaceAll('\\s','')}.findAll{i-> i.length() > 0})
press Key.PG_DOWN
waitms 1000
}
cmd 3
waitms 1000
}
}
stage('LOGOFF'){
steps{
position 20,7
send 'SIGNOFF'
press Key.ENTER
waitms 1000
capture()
}
}
}
}
println 'BOLIB/QRPGLESRC\n' + qrpgleMembers
I took a few other approaches before the current implementation, skim through them in dev/approaches. Here is the outline:
- JNA and EHLAPI32.dll - failed
- JRuby and EHLAPI32.dll - failed
- JNA and Win32 Programming - barely worked...abandoned
- TN5250J - current
- Set and get field by name
- Smarter field traversing - next,prev,first,last
- HOD macro generation
- Image screenshots
- clean build -
gradlew clean shadowjar
- run -
gradlew run