Friday, July 31, 2009

Grails: use a session scoped bean in a singleton bean

In my project, I had to change the scope of two of my services from the default scope (singleton) to as session scope. With grails, this is fairly easy, for a service, you simply have to add the following line in you service class:
static scope = 'session'

Now there's a problem if you use this service in a singleton scoped bean like a filter or a taglib for example. The problem is that spring will try to instantiate the singleton bean on startup, then it will try to create the service to inject it in the singleton, but as this does not occur in a session, spring cannot create the service and fails with a BeanCreationException. Anyway, even if the singleton was created within a session, the same service would be used for all sessions as the singleton wouldn't be re-injected for each session.

Fortunately, spring comes with the handy ScopedProxyFactoryBean. As its name implies, it is a proxy factory bean for scoped object. To use it, you first have to declare the service in grails-app/conf/spring/resources.groovy for an application or in the doWithSpring method of the plugin descriptor for a plugin:
sessionScopedService(SessionScopedService) { bean ->
bean.scope = 'session'
}


At the same place, declare the proxy factory bean:
sessionScopeProxy(org.springframework.aop.scope.ScopedProxyFactoryBean) {
targetBean = 'sessionScopedService'
proxyTargetClass = true
}


You can now use the sessionScopeProxy instead of the sessionScopedService in you singleton bean. It will transparently proxy to a session scoped SessionScopeService bean.

Wednesday, July 29, 2009

Grails: externalize configuration with jndi

Grails provides a very handy way to set configuration with Config.groovy file.

When developing internal applications, this solution is perfect especially with per-environment configuration.

For packaged third-party applications or complex multi-environment sites, it's harder to get a maintainable solution. Grails provides the grails.config.locations setting to load configuration from files possibly out of the application war file. The problem with this solution is to get a flexible cross-appserver cross-platform way to provide the custom config file to the application.


The solution presented here is to use jndi.

Let's say you want to provide a web service URL to an application, it will be made available to the application by the application server.

We will store the web service URL at the jndi name java:comp/env/wsUrl.

To access the value in the grails application, we will use a bit of spring magic by declaring a bean in grails-app/conf/spring/resources.groovy:

beans = {
wsUrl(org.springframework.jndi.JndiObjectFactoryBean){
jndiName = 'java:comp/env/wsUrl'
}
}


This will make the bean available with the value read from jndi, to use it, simply declare a variable named wsUrl in an injected object (controller, service...):
def wsUrl


For the development environment, if you use jetty, the value can be set by creating the web-app/WEB-INF/jetty-env.xml file with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<configure class="org.mortbay.jetty.webapp.WebAppContext">
<new id="wsUrl" class="org.mortbay.jetty.plus.naming.EnvEntry">
<arg>wsUrl</arg>
<arg>http://www.example.com/dev-ws/</arg>
<arg type="boolean">true</arg>
</new>
</configure>



If you deploy to a tomcat environment, you can set the value by creating a file conf/Catalina/localhost/<context-name>.xml in your tomcat installation containing:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Environment name="wsUrl" value="http://www.example.com/prod-ws/"
type="java.lang.String" override="true"/>
</Context>

If the parameter has to be set in multiple applications in the same tomcat instance, it can be declared in conf/server.xml file and referenced in each application .xml file with the ResourceLink tag.

Saturday, July 25, 2009

BAF: soon something to show

It has been a long time since I last blogged. I was working hard on my new project: BAF.

BAF stands for Business Application Framework. As the name implies, it is a framework for building business applications. Of course it is built on top of grails.

People working with legacy 5250 application are used to have single sign-on, security management, modular applications. BAF is about bringing that (and more in the future) to web applications.

BAF is still in development, but you can already look at the git repository.

For more information, check the BAF page.

Wednesday, June 17, 2009

Deploying on Websphere Application Server 6.1 for i5/OS

The IBM official alternative to IBM Integrated Web application server for i is websphere application server.

By default, WAS uses the classic JVM, the problem is that, since version 1.0, grails doesn't work with the classic JVM. So to deploy a grails application on WAS, the instance must run with the IBM technology for java VM.

To switch an instance to the IBM technology for java VM, run the following command under qshell:
/QIBM/ProdData/Websphere/AppServer/V61/edition/bin/enableJvm -jvm std32 -profile profile
Where edition is the WAS edition you use.
To switch all instances, you can omit the -profile profile parameter.

Once the instance is switched, you can start it and deploy your app.

The rest is WAS administration

Monday, June 15, 2009

Deploying on IBM Integrated Web Application Server for i

Starting with i5/OS V5R4, you can get the Integrated Web Application Server v7.1. It is meant as a partial replacement for Tomcat which isn't available from IBM for IBM i V6R1 and up. The Integrated Web Application Server is a small footprint J2EE web server. For small CPUs (pre-power4 or partial power5 520s) or systems very low in RAM (less than 2GB) it can be very useful.

There are a few limitations to know about:
* You can have only one DataSource, its jndi name is jdbc/ProxyDS. But you can simulate multiple DataSource (more on this below)
* The DataSource pooling is done by Apache commons pool which is considered as quite slow
* You can only access DB2 for i (local or remote)

The server creation and administration is pretty straightforward via IBM Web Administration for i5/OS.

The default memory limit is very low, so complex webapp won't run out of the box, you're likely to get StackOverflowError. To increase memory limit, edit the /www/appserver/lwi/conf/overrides/i5javaopts.javaopt file and add a line with -Xmx1024m or more.

You can create several "Database connections" which will be made available to all application through the jdbc/ProxyDS DataSource. You assign each connection a "connection ID", one can be *DEFAULT. To get a *DEFAULT connection, you simply use getConnection() on the DataSource. To get a non *DEFAULT connection, you use getConnection(connectionID,null) on the DataSource. I will make further investigation to check if GORM is able to use a non *DEFAULT connection.

Don't forget to apply the latest HTTP PTF group.

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.

Tuesday, June 9, 2009

Grails jtopen plugin 0.3 is out: user profile authentication

Release 0.3 of the grails jtopen plugin is out.

This new release features user profile authentication.

More information about how to use it in a future post.

Monday, June 8, 2009

grails jtopen plugin 0.2 is out: groovy record level access

GORM is a fantastic tool, it's especially good with tables it creates. When you have legacy tables (without generated IDs, without version field, with composite keys), it's not that good.
Of course, you can fall back to groovy sql support which is very good, but, once again, with legacy tables, SQL is not always the ideal tool.
If you spent several years coding in RPG, you probably sometimes miss the classical but so efficient traditional RPG file access, as I do. Of course it's possible to use the toolbox record level access, but it needs even more boilerplate code than bare metal JDBC.
That's where the jtopen grails plugin 0.2 new feature comes in handy: "groovy record level access".
You can now access files from groovy almost like you would do from RPG:
def file = ibmI.getFile(name:"FILE")
file.setll("KEY1","SKEY1")
def rec = file.reade("KEY1")
while(rec != null){
// Do something with rec...
rec = file.reade("KEY1")
}

Let's have a closer look:
def file = ibmI.getFile(name:"FILE")
This will create a file object, reading the file "FILE". By default, the file will be opened read only, it will be accessed by key if it has a key, otherwise, it will be accessed by arrival order.

file.setll("KEY1","SKEY1")
As the RPG SETLL opcode, this will set the cursor position with the given composite key.

def rec = file.reade("KEY1")
This will read the next record with the partial key equals to "KEY1".

while(rec != null){
// Do something with rec...
rec = file.reade("KEY1")
}
These lines will iterate through the records with the partial key equals to "KEY1".

RPG coders will be happy to have the read, readp, chain, setll, setgt, reade, readpe, write, update and delete methods that are almost identical to the RPG opcodes.

The record object returned by the read* and chain are dynamic POGO with properties from the file fields (case insensitive). For example, if your file has an ITEMCOD field, it can be accessed by rec.itemcode, rec.ItemCod or rec.ITEMCOD or even rec.iTeMcOd.

You can also use groovy iteration methods (each, eachWithIndex, collect, any...) on file objects. In this case, the iteration will process the next records from the current cursor position. It's possible to process the previous records from the current position with:
file.reverse.each { // Do something with the record }

If the file is accessed by key, it is also possible to process a subset of the file based on the key, for example:
file.setll("KEY1") // Iteration function always start from the current cursor position
file.key("KEY1").each { // Do something with the record }

To process the records in reverse order:
file.setgt("KEY1")
file.reverseKey("KEY1").each { // Do something with the record }

For the latest jtopen plugin release, please go to the plugin page.

Wednesday, June 3, 2009

Program call: a practical example

In this post, I will show a practical example of using the jtopen plugin to call a program on the AS/400.

We will create a grails service to execute commands on the AS/400.

We assume we have a grails application with the jtopen plugin installed.

We first have to set the AS/400 host, user and password. We will edit the grails-app/conf/Config.groovy file and add the three following lines:
jtopen.as400 = 'as400'
jtopen.user = 'user'
jtopen.password = 'password'
Of course, you should customize the values to your environment. As they are typically per-environement values, we will set them with the grails.serverURL variable.

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

This will create the file grails-app/services/CommandService.groovy, we will change it to:
import org.codehaus.groovy.grails.plugins.jtopen.types.*
class CommandService {
boolean transactional = false
def ibmI

def executeCommand(String command) {
def cr = ibmI.call('QCMDEXC',[
new IChar(command),
new IPacked(command.length(),15,5)] as Type[])
cr.success?:cr.messageList
}
}
And that's it!
Let's have a closer look.

import org.codehaus.groovy.grails.plugins.jtopen.types.*
We import the parameter types used to call the program.

def ibmI
This line creates a property named ibmI. It will automatically be injected with an IbmI object.

def cr = ibmI.call('QCMDEXC',[
new IChar(command),
new IPacked(command.length(),15,5)] as Type[])
Here is the heart of the service. This will call the QCMDEXC API with the two parameters it expects:
  • The command to execute as a CHAR variable
  • The command length as a (15,5) packed decimal
You can see that the QCMDEXC parameters are surrounded by [ and ] as Type[]. This is necessary because of a bug in groovy. This bug has been fixed in the groovy trunk and this circumvention shouldn't be necessary in future grails releases.

cr.success?:cr.messageList
This line makes the service return true if the command execution is successful or the array of messages returned by the command will be returned.

Now let's create a controller using this service:
grails create-controller DataArea

This will create the file grails-app/controllers/DataAreaController.groovy, change it to:
class DataAreaController {
def commandService
def create = {
def result = commandService.executeCommand("CRTDTAARA ${params.name} TYPE(*CHAR) LEN(10)")
render result==true?"Data area ${params.name} created":result.inspect()
}
}
We now start the application:
grails run-app

Now point your browser to:
http://localhost:8080/yourAppName/dataArea/create?name=grails

You should see the message "Data area grails created". On your AS/400, you should have a data area named grails in the jtopen.user user current library (or QGPL).

That's all for this example.

jtopen grails plugin 0.1.2 available

Earlier today, the jtopen grails plugin 0.1.2 was released, here's what's new:
  • A bug with IbmI bean injection was fixed
  • The IBin2 and IBin8 parameter types were added to handle 2-byte and 8-byte integers
  • The IByteArray parameter type was added. This type is useful when a parameter does not have a fixed layout that can be handled by IDataStructure

jtopen grails plugin 0.1.1 available

The 0.1.1 release is available on the grails site.

The only change is that the IbmI object is now a bean that can be injected. You must define the jtopen.as400, jtopen.user and jtopen.password variables in the Config.groovy file.

Tuesday, June 2, 2009

jtopen grails plugin 0.1 available

The first release of the jtopen plugin for grails is now available on the grails site.

Enjoy!

The grails jtopen plugin is coming

Later today I will release version 0.1 of the grails jtopen plugin.

Here is a list of what's included:
  • jtopen 6.5.1
  • injection of an AS400ConnectionPool bean
  • the IbmI class
  • easy program call
  • easy data area access
The IbmI class is a wrapper around the jtopen AS400 object and other objects from jtopen.
The jtopen classes are very well designed and give access to a wide range of functions, but its use is very verbose. The IbmI class gives a more groovy way of using some of these functions in a more natural way for CL and RPG developpers:
  • Easy program call with handling of input and output parameters
  • Easy access to character and decimal data areas
  • Possibility to use traditionnal object names (OBJECT or LIBRARY/OBJECT)
Any comment or suggestion will be appreciated.

Saturday, May 30, 2009

My first post: Why?

Welcome to the i-grails blog.
For my first post I will answer the self-asked question: Why? Why this blog? Why the AS/400? Why grails?

First, why this blog? Looks like a simple question, but I don't have simple answer. There are actually several reasons for creating this blog.
The first one could be that it seems fun. Many people nowadays blog, I hope I will enjoy it.
Next, is that because of internet and open source software I learned a lot. Communication and sharing opened so many possibilities for anyone, that's just great. I've been a consumer for many years, now it's time to be a producer too. If I can help one single person, I will be glad.
Finally, I like what I do, it's a passion, I like to talk about it, a blog is a great way to do it.

Why the AS/400? OK, we're not supposed to call it AS/400 anymore, but after so many years, I just can't switch every 6 month for the new name IBM invents, so AS/400 it will be. It can seem odd to talk about open source software and the AS/400 which is a very closed system. Well, I work with the AS/400 for almost 15 years now and it's very good at its job. Dr Frank Solstis, his team and IBM did a wonderful job by creating the IBM 38 and then the AS/400. TIMI and single-level-storage are nothing but brilliant ideas. There are lots of old applications running on AS/400 and lots of new things to do. That's my job and I like it.

Why grails? I've coded using many languages, from basic on an Apple II to grails, I've worked with RPG, C, Java and many others. For business apps, RPG is really efficient, you can produce quickly efficient and maintainable code. It is ideal for batch and 5250 programs, but whether it is a good idea or not, 5250 is not the future, the browser is. Of course you can make browser screens with RPG but I don't think it's the best way to go. Java is good, it is a clean and efficient language. There are very nice frameworks for web applications. For a multi-million $ project with lots of collaborating developers, that's probably the way to go.
That's not my world. I found Ruby on Rails, it is very efficient, fast, totally suitable for my needs. The problem is that they started from scratch, so it's perfect for use with mySql, but with an AS/400, things don't go that well. It's getting better, but not enough for me.
I then found groovy and grails: the power of Ruby on rails with the power of the java universe.

My current project is creating the grails jtopen plugin. This plugin will make the jtopen library more groovy. I'll give more information on the plugin on this blog.