Genexus 9 vs. Funções externas Java

 

Buenas…

Demorei um pouco, mas estou de volta. Hoje quero falar um pouco sobre funções externas, mais especificamente utilizando GeneXus 9, já que a versão X nos possibilita fazer isso de forma transparente…

Resumidamente, o que se deve fazer é:

1) Personalizar uma classe externa, para que o genexus consiga chamar o método execute() de forma transparente;
2) Compilar a classe externa na mesma package da aplicação;
3) Adicionar o call() no objeto genexus;

Vamos aos detalhes:

1)  Personalizar a classe externa:

Crie uma classe externa java, a que eu montei é uma classe para compactação de arquivos utilizando métodos nativos do java (Olhar no final desse post). O grande segredo aqui são 3 coisas:

  1. Ter um construtor específico que serve para o genexus utilizá-lo quando for instanciar o objeto.
  2. Ter um método execute(), que o genexus irá utilizar para realizar a chamada de fato.
  3. Ter um package name compatível com a aplicação, pois facilita a compilação tanto da classe externa quanto da aplicação genexus, visto que para essa última a classe já está automaticamente adicionada.

 

2) Compilar a classe externa:

Para compilar a classe externa é necessário colocá-la no mesmo diretório onde estão as demais classes geradas da aplicação (normalmente dentro do diretório da KB\diretório do modelo\web, levar em conta que se estiver utilizando um package name terá mais um ou dois subdiretórios dentro de web\). Após feito isso, utiliza-se o mesmo método que o genexus utiliza para compilá-las, ou seja:

  1. Abrir um prompt do DOS e posicioná-lo na pasta web\ do modelo da KB. Como o exemplo feito na minha KB:
    • Iniciar, Executar, CMD ;
    • D: ;
    • Cd D:\Projetos\MinhaKB\Data002\Web;
  2. Configurar a variável CLASSPATH do Java (disponível no menu de execução do GeneXus):
    • SET CLASSPATH=gxclassr.zip;GxUtils.jar;.;
  3. Executar:
    • callmake.bat “C:\Program Files\ARTech\GeneXus\GeneXus90\gxjava\GXJMake.exe” “C:\Program Files\Java\jdk1.6.0_16\bin\javac.exe” gxzip com\genexus\ -O

sendo

    • c:\Program Files\ARTech\GeneXus\GeneXus90 o caminho onde está o genexus 9 na minha máquina e
    • c:\Program Files\Java\Jdk1.6.0_16\ o caminho onde está o JDK.
    • gxzip: o nome da minha classe externa (arquivo .java)
    • com\genexus: o “package name” da minha aplicação.

E, finalmente,

 

3) Adicionar a chamada ao genexus

Essa é a parte mais simples, localize o evento onde deseja-se adicionar a chamada e inclua:

  • &Origem (string) = caminho absoluto de uma pasta ou arquivo a ser compactados;
    • Se for um arquivo, o .zip conterá somente esse arquivo.
    • Se for uma pasta, o .zip conterá todos os arquivos na pasta citada, com exceção de:
      • subpastas;
      • arquivos com extensão .zip, .7z e .jar
  • &Destino (String) = caminho absoluto para o arquivo .zip a ser gerado, se já existir será sobrescrito;
  • Call(‘gxzip’,&Origem, &Destino)

 

Bom, por hoje é só, espero ter sido claro como a água do rio Tietê e discreto como um elefante em uma loja de cristais… hehehe

Qualquer coisa não exite em não me chamar…

Um abraço e boa noite…

/*
               File: GXZip
        Description: Classe para compactação
             Author: Sandro M. Vianna
         Created on: 29/09/2010 16:24:55.75

*/

package com.genexus ;
import java.io.*;
import java.util.zip.*;
import com.genexus.*;

public class  gxzip {

    static final int BUFFER = 2048;

        //Esse construtor vazio é para ser utilizado pelo método main()
	public gxzip()
	{
	}

        //Aqui está o primeiro segredo, é necessário ter um construtor com exatamente esses parâmetros,
        //para que o genexus consiga "enxergar" como uma classe dele
	public gxzip(int remoteHandle, ModelContext context)
	{
	}

    //Deixei o método main para que a classe possa ser chamada pela linha de comandos,
    //Mas é completamente opcional...
    public static void main(String[] args) {
        if (args.length != 2) {
            System.out.println(
   "Usar: java gxzip <arquivos> <novo arquivo compactado> ");
            return;
        }
        try {
            String filename = args[0];
            String zipfilename = args[1];
            gxzip list = new gxzip( );
            list.doZip(filename,zipfilename);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

        //Aqui está o segundo segredo, esse método será utilizado no comando call() do gx
        //Aqui se está recebendo duas strings, apesar de serem recebidas como array de string.
        //Se utiliza sempre o indice 0
        public static void execute(String[] gxFiles, String[] gxZipFile ) {
	  try {
	    String filename = gxFiles[0];
            String zipfilename = gxZipFile[0];
            gxzip list = new gxzip( );
            list.doZip(filename,zipfilename);
	  } catch (Exception e) {
            e.printStackTrace();}
	}

        //Esse é o método que realiza de fato a compactação, é chamado tanto do método main() quanto do execute()
	public void doZip(String filename,String zipfilename) {
            try {
		File ft = new File(filename);
		String entryname, foldername = null;
		final String zipfile = zipfilename;

		if (ft.isFile()){
			//Obtenho o nome do arquivo e da pasta
			//int index = filename.lastIndexOf('\\')+1;
			//String entryname = filename.substring(index);
			//String foldername = filename.substring(0,index-1);
			entryname = ft.getName();
			foldername = ft.getParent();
		}else{
			entryname = "";
			foldername = filename;
			int index = filename.lastIndexOf('\\')+1;
			if (index == filename.trim().length()) foldername = foldername.substring(0,index-1);
		}

		//Obtenho os arquivos contidos na pasta
		File f = new File(foldername);
		String files[] = null;

		//Filtros para não carregar subpastas, arquivos compactados, e o próprio .zip
		FilenameFilter filter = new FilenameFilter() {
			public boolean accept(File f, String name) {
			File ftemp = new File(f.getPath()+'\\'+name);
			return !ftemp.isDirectory() &&
				!name.endsWith(".zip") &&
				!name.endsWith(".7z") &&
				!name.endsWith(".jar") &&
				!name.equals(zipfile);
				}
		};

		//Se foi configurado um nome de arquivo como origem, carrego somente ele na listagem
		if (entryname.length() > 0)
		{
			files = new String[1];
			files[0] = entryname;
		}else{
			//Senão, carrego a todos arquivos na pasta.
			files = f.list(filter);
                }

                byte[] buf = new byte[BUFFER];
		BufferedInputStream origin = null;
		ZipOutputStream s = new ZipOutputStream((OutputStream)new FileOutputStream(zipfilename));

                for (int i=0; i<files.length; i++) {

	        	FileInputStream fis = new FileInputStream(foldername+'\\'+files[i]);
         		origin = new BufferedInputStream(fis, BUFFER);
			s.setLevel(6);
			ZipEntry entry = new ZipEntry(files[i]);
			s.putNextEntry(entry);
			int count;
			while((count = origin.read(buf, 0, BUFFER)) != -1) {
				s.write(buf, 0, count);
			}
			origin.close();
		}
		s.finish();
		s.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Anúncios

Um comentário sobre “Genexus 9 vs. Funções externas Java

  1. Bom dia.

    Voce citou que o Genexus X consegue fazer isso de forma transparente. Caso voce tenha alguma documentação ou possa postar um passo-a-passo como fez com o 9 eu agradeço, pois estou tendo muita dificuldade em realizar a chamada no X.
    Obrigado.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s