Sunday, June 14, 2009

Practical example: jtopen and webservice

At my job we are currently prototyping a monitoring solution. We use a packaged solution to monitor our Unix and Windows servers, our telecom equipments and our AS/400s.

For the AS/400, we want to check verify that our scheduler is up. The way to determine if it's running is to see if a given data area is locked. If it is locked, the scheduler is running. The question was: how to check this from the monitoring box? The first solution was to create a telnet script that would connect to the AS/400, and check if the data area is locked. Of course, this is not the good way to go, this should be considered as a last resort. The second solution was to create a java program on the monitoring package that would use jtopen (the library, not the plugin) to try to lock the data area. This would work but we would be tied between the monitoring solution program and the scheduler (think about updates...). The third solution was to use a web service. The monitoring solution is able to call a web service and take action depending on the result. With grails, creating the web service is so simple a monkey could do it (even I did it!).

The first step is to create a new grails application:
grails create-app monitor

Then we install the jtopen plugin:
grails install-plugin jtopen

For web service, there are several plugins available. I decided to go with xfire plugin, it is the simplest for me:
grails install-plugin xfire

We then create a new service:
grails create-service scheduler

We then instruct xfire to expose the service:
static expose = ['xfire']

We define an ibmI object that will be injected:
def ibmI

We then define the service method:
boolean isSchedulerActive(){
def cr = ibmI.execute("ALCOBJ OBJ((DTAARA *DTAARA *SHRRD)) WAIT(0)")
if(cr.success){
ibmI.execute("DLCOBJ OBJ((DTAARA *DTAARA *SHRRD))")
false
} else {
if(cr.messageList[0].ID == "CPF1002"){
true
} else {
throw new RuntimeException("Unexpected message "+cr.messageList[0].toString())
}
}
}

And that's it!
Let's give a closer look at the method:

def cr = ibmI.execute("ALCOBJ OBJ((DTAARA *DTAARA *SHRRD)) WAIT(0)")
This will try to allocate the data area, returning immediately if the lock can't be locked.

if(cr.success){
ibmI.execute("DLCOBJ OBJ((DTAARA *DTAARA *SHRRD))")
false
}
If the command ran successfully, it means that the data area was not locked. We immediately unlock the data area to avoid being bugged by a ghost lock and return false.

else {
if(cr.messageList[0].ID == "CPF1002"){
true
} else {
throw new RuntimeException("Unexpected message "+cr.messageList[0].toString())
}
}
If the command did not run successfully, we check the message ID returned by the command processor. If the message is a CPF1002, it means that the data area was already locked, meaning the scheduler is active, so we return true. If we have another message, then something went wrong and we throw an exception.

We just have to specify the as/400 host name, user and password in Config.groovy and that's it.

You can take your favorite soap client (I use Mac SOAP Client) and point it to the wsdl which is created by the xfire plugin at: http://localhost:8080/monitor/services/scheduler?wsdl and test the isSchedulerActive method.

And that's all. No boiler plate code, no infinite xml file to write, just strait to the code.

In a next post, I will talk about deployement.

5 comments:

  1. Hi Damien,

    This blog is awesome. I am new to groovy and grails. I was looking around for a way to connect to the AS400 until I found your plugin.

    i am trying to follow your example above but got stuck from this point:

    We then instruct xfire to expose the service:
    static expose = ['xfire']
    (can you tell me where do key this code in?)

    We define an ibmI object that will be injected:
    def ibmI
    (can you tell me where do key this code in?)


    We then define the service method:
    boolean isSchedulerActive(){
    def cr = ibmI.execute("ALCOBJ OBJ((DTAARA *DTAARA *SHRRD)) WAIT(0)")
    if(cr.success){
    ibmI.execute("DLCOBJ OBJ((DTAARA *DTAARA *SHRRD))")
    false
    } else {
    if(cr.messageList[0].ID == "CPF1002"){
    true
    } else {
    throw new RuntimeException("Unexpected message "+cr.messageList[0].toString())
    }
    }
    }
    (can you tell me where do key this code in?)


    regards,
    (newbie)

    ReplyDelete
  2. I'm glad that you find this blog useful.

    All the code you're asking for should go in the service class body you're creating.

    ReplyDelete
  3. hi damien,

    can you show me an example on how to create a grails web application that retrieves data from the as400?

    thank you.

    Regards,
    ben

    ReplyDelete
  4. hi Damien,
    This looks interesting. Now I'm writing in Java and have certain hassle with dataareas. Our ERP app (written in RPG) uses dataareas to keep last recordnumbers (PKey) for certain tables we also use in Java apps. So we not only need to check the dataaraea to be locked or not, we have to implement a lock-read-increment-write-unlock cycle instead. Do you have any idea how this could work? We found and used the dataarea class in jt400.jar (IBM toolbox for java) for read and write but found no locking functionality..
    Regards, Stephan

    ReplyDelete
  5. Hi Damien and Stephan,

    Did you find a solution to your problem Stephan? I have the same issue that you describe.

    Thanks, Sam

    ReplyDelete