Invocando o Programa
Library a partir do PHP
Disponibilizando COMMAREA
para PHP
Quando COMMAREA for definida no programa COBOL e
ADATA tiver sido gerado, a próxima etapa será criar classes Java™
que representam a COMMAREA. Estas classes são usadas para tornar
a COMMAREA acessível a partir de scripts PHP.
Será necessário gerar as classes
Java apenas uma vez: assim que as classes estiverem disponíveis para o
CA1S, poderá ser gravada qualquer quantidade de scripts para usá-las para interação
com o programa COBOL. No entanto, se o programa COBOL for modificado de maneira que altere a forma
da COMMAREA, será necessário gerar novamente o ADATA e as classes
Java e adaptar os scripts PHP conforme necessário.
As etapas a seguir requerem
um Java SDK e assumem que os comandos java e javac estejam disponíveis
no PATH do sistema. Execute-os em sua estação de trabalho ou diretamente
no sistema CICS.
1. Gerar a origem
das classes de COMMAREA
java -cp jzos_recgen.jar com.ibm.jzos.recordgen.cobol.RecordClassGenerator genCache=false
adataFile=LIBRARY symbol=DFHCOMMAREA class=Library_Commarea package=library outputDir=.
|
Vamos descrever o propósito de cada parte do comando acima:
java -cp jzos_recgen.jar com.ibm.jzos.recordgen.cobol.RecordClassGenerator
|
Isto invoca o
JZOS Record Generator, que é um programa Java contido no
arquivo jzos_recgen.jar. Este arquivo está incluído no CA1S, e a versão mais recente
está disponível no site do IBM JZOS Batch Toolkit for z/OS SDKs no
alphaWorks (consulte
Recursos).
Esta opção assegura que o código Java
gerado não tentará armazenar em cache o valor de campos
de COMMAREA. Esta opção é necessária para que o CA1S interaja
corretamente com as classes geradas.
Isto especifica o caminho
para o arquivo ADATA obtido na seção anterior.
Isto especifica o nome da COMMAREA para a qual gerar a classe.
Isto especifica o nome da classe Java
resultante.
Isto especifica o pacote
da classe Java resultante.
Isto especifica o caminho no qual a classe Java
será gravada no sistema de arquivos.
2. Gerar a origem Java para a classe
que representa constantes COBOL
No aplicativo de biblioteca de amostra, as constantes usadas
no programa COBOL (para os nomes de operações e códigos
de resposta) são definidas em uma estrutura de dados na seção WORKING-STORAGE.
Isto significa que uma classe Java que representa estas constantes pode ser gerada e
usada a partir do PHP de forma semelhante à classe que representa a
COMMAREA, neste caso, para obter os valores das constantes definidas
quando necessário.
java -cp jzos_recgen.jar com.ibm.jzos.recordgen.cobol.RecordClassGenerator genCache=false
adataFile=LIBRARY symbol=LIBRARY-CONSTANTS class=Library_Constants package=library
outputDir=.
|
A vantagem desta abordagem é que a
reflexão de PHP pode ser usada para examinar os nomes de constantes
disponíveis, e o programador de PHP não precisa consultar diretamente
os valores definidos no COBOL. Lembre-se de que isto pode ser feito
para o aplicativo LIBRARY devido à forma de definição
das constantes, e nem sempre isso será possível, por exemplo,
quando valores codificados permanentemente estiverem integrados na origem COBOL.
Nos scripts PHP fornecidos com este artigo, é adotada uma abordagem
mista, na qual algumas destas constantes
são usadas em seus formatos literais (por exemplo, os nomes
de operações), e algumas são extraídas usando a classe Java gerada
(os códigos de resposta numéricos).
3. Compilar os arquivo de origem .java para criar arquivos
de classe Java
A origem Java gerada estará no outputDir especificado acima, na biblioteca do subdiretório (que corresponde ao nome do pacote).
Usar javac para compilar os arquivos de origem da seguinte forma:
javac -cp jzos_recgen.jar library/*
|
4. Disponibilizar os arquivos de classe para o
CA1S O diretório da biblioteca agora contém as classes compiladas.
Para que o CA1S possa usá-las, elas devem estar disponíveis no caminho de classe Java.
Se você gerou as classes em sua estação de trabalho, será necessário transferir
o diretório para o servidor (por exemplo, usando o FTP).
O caminho de classe Java é determinado pelo atributo
CLASSPATH_SUFFIX do JVMPROFILE
usado pelo CA1S. O JVMPROFILE padrão no CA1S (denominado CA1SJVMP) já está
configurado para incluir o diretório ca1s/work/classes/ no
CLASSPATH_SUFFIX:
CLASSPATH_SUFFIX=/u/p8build/ca1s/config/ini:\
/u/p8build/ca1s/p8/jars/p8api.jar:\
/u/p8build/ca1s/p8/jars/p8.jar:\
/u/p8build/ca1s/p8/jars/p8cics.jar:\
/u/p8build/ca1s/work/classes:\
/usr/lpp/db2910/classes/db2jcc.jar:\
/usr/lpp/db2910/classes/db2jcc_javax.jar:\
/usr/lpp/db2910/classes/db2jcc_license_cisuz.jar
|
Portanto, se você estiver
usando JVMPROFILE CA1SJVMP, poderá copiar
o diretório da biblioteca para ca1s/work/classes/. Como alternativa, é possível alterar
seu CLASSPATH_SUFFIX para incluir um diretório ou arquivo JAR que contenha
o diretório da biblioteca.
Observe que a estrutura de diretório que representa o nome do pacote
deve ser preservada no local do caminho de classe. Portanto, se você estiver
usando ca1s/work/classes/, copie o próprio diretório da biblioteca
de forma que as classes estejam em ca1s/work/classes/library
(e não diretamente em ca1s/work/classes/).
Por último, encerre gradualmente suas JVMs para assegurar
que as novas classes sejam selecionadas pelo CA1S.
Acessando o Programa a partir do Código PHP
O Código
A chamada de um programa
COMMAREA consiste em 3 etapas:
- Preparação da COMMAREA antes de vincular-se ao programa.
- Vínculo ao programa.
- Recuperação do resultado do link da COMMAREA.
Para ilustrar, a Listagem 3 mostra um script que invoca o programa de biblioteca
para obter uma lista de books, em seguida, imprime-os:
Listagem 3. Invocando um programa CICS Commarea a partir do PHP
<?php
// Etapa 1: criar e preparar a instância COMMAREA
java_import('library.Library_Commarea');
$COMMAREA = new Library_Commarea();
$COMMAREA->setLibRequestType('LIST');
// Etapa 2: criar a instância do programa e invocá-la usando COMMAREA
$program = new CICSProgram('LIBRARY');
try {
$program->link($COMMAREA);
} catch (CICSException $e) {
echo 'Error: ' . $e->getMessage();
return;
}
// Etapa 3: recuperar o resultado do link da COMMAREA
$totalBooks = $COMMAREA->getLibItemCount();
echo "Total number of books: $totalBooks <br/>";
for ($i=0; $i<$totalBooks; $i++) {
$book = $COMMAREA->getLibBookItem($i);
$title = $book->getBookTitle();
$author = $book->getBookAuthor();
echo "Book $i is '$title' by '$author'. <br/>";
}
?>
|
 |
Por que vejo apenas caracteres
inválidos quando acesso um script em meu navegador?
Isto pode ocorrer se o script for codificado na página de códigos incorreta. Por
padrão, o tempo de execução para PHP no CA1S é configurado para esperar scripts
na codificação UTF-8. Portanto, se você transferir scripts entre uma estação de trabalho
do Windows®
ou Linux® e seu servidor CICS, certifique-se de configurar modo "binary",
para que os scripts não sejam convertidos em uma página de códigos EBCDIC durante
a transferência. Para obter informações adicionais sobre questões de codificação e opções de
configuração no CA1S, consulte a documentação do CA1S.
|
|
Este script é fornecido no download do código de amostra como library/scripts/library.php. Se você transferir este script em seu sistema CICS
para ca1s/work/scripts/library.php e acessá-lo em seu
navegador, deverá ver uma lista de books como:
Total number of books: 18
Book 0 is 'PHP for Beginners ' by 'Rob Nicholson '.
Book 1 is 'Project Management ' by 'A N IBMer '.
Book 2 is 'Easy Z Specification' by 'Jonathan '.
Book 3 is 'REST Protocol Design' by 'Zoe, Ant & Rob '.
etc...
|
Vamos examinar detalhadamente
as três etapas no código.
Preparando a COMMAREA
java_import('library.Library_Commarea');
|
A função java_import(), que é integrada ao tempo de execução
para PHP no CA1S, carrega uma classe Java e a disponibiliza para
uso no PHP. No código acima, carregamos a classe Java que representa
a classe COMMAREA da biblioteca gerada anteriormente.
$COMMAREA = new Library_Commarea();
|
Em seguida, criamos
uma instância desta classe. Esta instância será usada como um contêiner
para os dados de entrada e saída da chamada.
$COMMAREA->setLibRequestType('LIST');
|
Por último, na terceira linha,
configuramos alguns dados de entrada na COMMAREA. O método setLibRequestType é específico da classe Java
que representa a COMMAREA do programa COBOL usado neste tutorial: ele define
a operação que desejamos executar na biblioteca, neste caso, obter
uma LISTA de todos os books. Consulte Investigando a COMMAREA Usando
Reflexão para saber como usar o PHP para descobrir todos os métodos
na classe Java.
Vinculando-se ao Programa
$program = new CICSProgram('LIBRARY');
|
Primeiro, criamos
uma instância da classe integrada CICSProgram, que representa o programa CICS
com o qual desejamos interagir.
O nome do programa CICS é especificado como o argumento do construtor,
neste caso, "LIBRARY." Se o programa precisasse ser renomeado,
este programa precisaria ser alterado.
$program->link($COMMAREA);
|
O método de link
na classe CICSProgram aciona a execução
do programa CICS. Se um único argumento de COMMAREA for fornecido,
como neste caso, ele será usado pelo programa CICS como um contêiner
para dados de entrada e de saída. Também é possível fornecer dois argumentos
de COMMAREA separados, neste caso, o primeiro argumento deverá conter
dados de entrada e os dados de saída serão gravados no segundo. Também é possível
não fornecer nenhum argumento, o que é útil nos casos em que
o programa CICS não possui entrada e saída.
Se o link falhar ou o programa vinculado
for finalizado anormalmente, o método de link lançará uma
CICSException. O método getMessage() no objeto de exceção exibe detalhes da falha,
incluindo o tipo de exceção Java subjacente. Por exemplo,
se um nome de programa inválido for especificado como o argumento para o construtor
CICSProgram o código acima será impresso:
Error: com.ibm.cics.server.InvalidProgramIdException: CICS PGMIDERR Condition
|
Recuperando Dados da COMMAREA
$totalBooks = $COMMAREA->getLibItemCount();
|
Quando link() for retornado com êxito, a COMMAREA
conterá a saída da chamada. Na etapa 3 do script PHP acima,
usamos vários métodos específicos da classe Library_Commarea para obter o número total de books,
em seguida, para iterar sobre a lista de books, imprimindo o título e autor
de cada um.
Investigando a
Commarea Usando a Reflexão PHP Configurar dados de entrada em uma COMMAREA
antes de um link e recuperar dados de saída dele posteriormente requer conhecimento
dos métodos setter e getter na classe de COMMAREA. Se você não tiver
uma lista destes métodos acessível, será simples obter uma com
reflexão PHP. Por exemplo, o seguinte script usa as classes de reflexão PHP
(consulte Recursos) para obter a lista de métodos disponíveis
da classe Library_Commarea:
Listagem 4. Usando a reflexão, parte 1
<?php
java_import('library.Library_Commarea');
$COMMAREA = new Library_Commarea();
$rc = new ReflectionObject($COMMAREA);
foreach ($rc->getMethods() as $method) {
echo $method->getName() . '<br/>';
}
?>
|
A saída do
script na Listagem 4
é:
Library_Commarea
__tostring
setLibItemCount
getLibReturnCode
setLibRequestType
setLibReturnCode
getByteBuffer
getLibRequestType
getLibBookItem
getLibItemCount
|
Além do
método Library_Commarea() (que é o
construtor) e de getByteBuffer() (que fornece acesso
ao array de bytes brutos que contém os dados de COMMAREA), todos os demais
métodos são getters e setters para campos de COMMAREA. Os usados no script
inicial são marcados em negrito.
Alguns getters retornam estruturas de dados
complexos, como o método getLibBookItem() acima,
que retorna um objeto que representa um book. A mesma técnica pode ser usada
nestas estruturas de dados para descobrir quais campos podem ser acessados.
Por exemplo, usamos aqui a função do PHP get_class_methods() de Joshua Bloch (consulte Recursos) para estabelecer quais campos
podem ser acessados em um
book:
Listando 5. Usando a reflexão, parte 2
<?php
// Etapa 1: criar e preparar a instância de COMMAREA
java_import('library.Library_Commarea');
$COMMAREA = new Library_Commarea();
$COMMAREA->setLibRequestType('LIST');
// Etapa 2: criar a instância do programa e invocar o programa usando a COMMAREA
$program = new CICSProgram('LIBRARY');
$program->link($COMMAREA);
// Investigar os campos disponíveis em um objeto book
$book = $COMMAREA->getLibBookItem(0);
print_r(get_class_methods($book));
?>
|
A saída
do script na Listagem 5
é:
Array
(
[0] => LibBookItem
[1] => getBookTitle
[2] => setBookItemRef
[3] => isBookOnloan
[4] => getBookAuthor
[5] => isBookUnlent
[6] => getByteBuffer
[7] => setBookAuthor
[8] => setBookBorrower
[9] => getBookLoanStatus
[10] => getByteBufferOffset
[11] => getBookBorrower
[12] => __tostring
[13] => getFiller_1
[14] => getBookItemRef
[15] => setBookTitle
[16] => setFiller_1
[17] => setBookLoanStatus
)
|
Resolução de Problemas do Caminho de Classe
com phpinfo()
Se aparecerem avisos ou erros sugerindo que a classe de
COMMAREA não pode ser localizada, verifique o caminho de classe Java para assegurar
que ele inclua um diretório ou arquivo JAR contendo o diretório da biblioteca (que contém as
classes geradas).
Isto pode ser feito diretamente do código php usando a função do PHP
phpinfo():
Acessar esse
script em um navegador exibirá uma grande quantidade de informações, incluindo
o caminho de classe completo:
Figura 1. Verificando o caminho de classe Java
com phpinfo()
classpath.png
Mais comumente, phpinfo() é uma ferramenta útil para investigar muitos aspectos
do ambiente PHP.
|