Páginas filhas
  • Intellector 9 - API - Criação de Plugin

Versões comparadas

Chave

  • Esta linha foi adicionada.
  • Esta linha foi removida.
  • A formatação mudou.

...

Nem preciso explicar que esse framework nasceu da necessidade de padronizar o desenvolvimento dos primeiros plugins de acessos e execuções de políticas, embora essa característica fosse evidente desde o princípio. Na realidade, queríamos "forçar" qualquer desenvolvedor de plugins de acesso para o TOTVS Intellector a seguir o pattern que fosse operacional na chamada da política ao acesso plugin desenvolvido, como exceções lançadas, etc., e tivesse uma luz no fim do túnel, com algumas artifícios que ajudassem, pois quanto problemas e dúvidas melhor. Ele é um framework de abstração para operações como chamadas HTTPS com certificados, as vezes bem complexas, e, acreditem, não é tão trivial lidar com sopa de letrinhas esquisitas. Mas nada de ficar assustado, abaixo veremos cada característica desse framework.

  • Interface Plugin - Interface de acessos externosplugins externos. Arremessa as exceções 'InfraException' para problemas de infraestrutura, como unknown host (conexões e suas configurações, erros de autenticação, logins e passwords, jks, etc);'LayoutException' para problemas relacionados aos layouts, registros e tipos do acesso plugins e, 'ConfigException' se for detectado qualquer anomalia na configuração do acessoplugin. Atualmente um único método precisa ser implementado, oexecute(). É interessante observar as HashMap de entrada/saída:

...

  1. CipheringException - Classe Exception para tratamento das exceptions de ciphering (criptografia);
  2. ConfigException - Exceção gerada sempre que há um erro na configuração do acesso plugin externo, como por exemplo, arquivos de configuração não localizados, certificados não localizados, etc.;
  3. InfraException - Exceção gerada sempre que há um erro na execução do acesso plugin externo, como por exemplo, host não localizado, erros na conexão, autenticação, etc.;
  4. LayoutException - Exceção gerada sempre que há um erro na configuração dos layouts, como por exemplo, arquivos de configuração não localizados, layouts configurados de forma errada, etc.;
  5. PolicyException - Exceção gerada sempre que há um erro na política de controle de acessos de usuários na publicação de políticas, layouts de políticas, autenticação no site e execução de políticas.

...

Bloco de código
languagehtml/xml
linenumberstrue
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>grouo-id</groupId>
	<artifactId>dummyplugin</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<description>Dummy para exemplificar plugins externos</description>

	<properties>
		<!-- nome da package e classe - FQN -->
		<main-class>br.com.totvs.plugins.dummyplugin.DummyPlugin</main-class>
		<!-- Nome do Plugin de acesso -->
		<pluginname>dummyplugin</pluginname>
		<description>Dummy para exemplificar plugins externos</description>
		<!-- chave de acesso ao dado na persistencia -->
		<primarykey>CPF</primarykey>
		<pkdescription>CPF do adquirente</pkdescription>
		<!-- Caminho para o Layout do AcessoPlugin -->
		<layoutpath>resources/dummyplugin.json</layoutpath>
		
		<!-- P - plugin /  L - lib para plugin -->
		<pluginlib>P</pluginlib>
	</properties>

	<distributionManagement>
		<repository>
			<id>releases</id>
			<url>http://repo.com:8081/nexus/content/repositories/releases</url>
		</repository>
		<snapshotRepository>
			<id>snapshots</id>
			<url>http://repo.com:8081/nexus/content/repositories/snapshots</url>
		</snapshotRepository>
	</distributionManagement>

	<build>
		<sourceDirectory>src</sourceDirectory>
		<resources>
			<resource>
				<directory>src</directory>
				<excludes>
					<exclude>**/*.java</exclude>
				</excludes>
			</resource>
			<resource>
				<directory>resources</directory>
				<includes>
					<include>**/*.*</include>
				</includes>
				<targetPath>resources</targetPath>
			</resource>
		</resources>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.5.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<version>3.0.2</version>
				<configuration>
					<archive>
						<manifest>
							<addClasspath>false</addClasspath>
							<mainClass>${main-class}</mainClass>
						</manifest>
						<manifestSections>
							<manifestSection>
								<name>Intellector Entries</name>
								<manifestEntries>
									<Implementation-Plugin>${pluginname}</Implementation-Plugin>
									<Implementation-Layout>${layoutpath}</Implementation-Layout>
									<Implementation-Description>${description}</Implementation-Description>
									<primarykey>${primarykey}</primarykey>
									<pkdescription>${pkdescription}</pkdescription>
									<Plugin-Lib>${pluginlib}</Plugin-Lib>
								</manifestEntries>
							</manifestSection>
						</manifestSections>
					</archive>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-source-plugin</artifactId>
				<version>2.2.1</version>
				<executions>
					<execution>
						<id>attach-sources</id>
						<phase>verify</phase>
						<goals>
							<goal>jar-no-fork</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
			<plugin>
				<artifactId>maven-clean-plugin</artifactId>
				<version>3.0.0</version>
				<executions>
					<execution>
						<!-- Aqui estou forçando um clean toda vez que o maven install for 
							executado. -->
						<id>auto-clean</id>
						<phase>initialize</phase>
						<goals>
							<goal>clean</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
		</plugins>
		<pluginManagement>
			<plugins>
				<!--This plugin's configuration is used to store Eclipse m2e settings 
					only. It has no influence on the Maven build itself. -->
				<plugin>
					<groupId>org.eclipse.m2e</groupId>
					<artifactId>lifecycle-mapping</artifactId>
					<version>1.0.0</version>
					<configuration>
						<lifecycleMappingMetadata>
							<pluginExecutions>
								<pluginExecution>
									<pluginExecutionFilter>
										<groupId>org.apache.maven.plugins</groupId>
										<artifactId>maven-clean-plugin</artifactId>
										<versionRange>[2.5,)</versionRange>
										<goals>
											<goal>clean</goal>
										</goals>
									</pluginExecutionFilter>
									<action>
										<ignore></ignore>
									</action>
								</pluginExecution>
							</pluginExecutions>
						</lifecycleMappingMetadata>
					</configuration>
				</plugin>
			</plugins>
		</pluginManagement>
	</build>
	<dependencies>
		<dependency>
			<groupId>iw-server</groupId>
			<artifactId>iw-server-api</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>iw-server</groupId>
			<artifactId>iw-server-beans</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>
</project>

...

E o dummyaccess não é tão dummy assim...

O acesso plugin dummy estará sempre sendo submetido a melhorias, por isso, procure sempre por uma versão atualizada, pois ele terá várias versões, que ao longo do nosso desenvolvimento são taggeds. Talvez exista uma que seja mais adequado a sua necessidade.

Desenvolvendo...

Importar o acesso plugin dummy (dummyaccessdummyplugin) como um template para desenvolvimento de um acesso plugin externo. A ideia é que ele oriente o desenvolvimento de toda a estruturanecessária para a criação de um plugin de acesso, mantendo uma padronização na construção destes, evitando que o fonte de cada acesso plugin externo tenha uma forma de implementação completamente diferente dos outros. O objetivo é facilitar desenvolvimento de novos acessos de plugins de forma fácil e rápida. Os artefatos que comporão o projeto vazio de um plugin serão:

    • No arquivo JSON:
      • Definir as
    Arquivo de
      • propriedades com os dados de configuração do
    acesso
      • plugin externo, caso existam. Como não se sabe inicialmente quais são esses dados,
    criar um
      • definir no arquivo JSON de exemplo
    com
      • as propriedades mais comuns: protocolo (HTTP, HTTPS, TCP, etc), host, porta e objeto no servidor; atualmente só http/servlet é suportado
    ;
  • Artefatos necessários para a criação de uma funcionalidade no site do Intellector Server que permitirá a configuração do arquivo de propriedades pelo administrador do sistema;
  • As estruturas das classes Java que deverão ser programadas para cada acesso externo:
  • As classes, se for o caso, de implementação do acesso externo, para que o desenvolvedor possa programar o acesso externo propriamente dito;
  • Um XML com
      • . Essas propriedades poderão ser configuradas na interface do Intellector na edição do plugin.
        • "properties": {
          "database": "mango_d",
          "usuario": "user",
          "senha": "senha",
          "audita": true
          }
      • Definir os dados de entrada para chamada do
    acesso
      • plugin de acordo com o layout pré estabelecido pelo órgão e, que receberá o layout montado pela classe anterior e fará o acesso e retornará a classe com o layout de saída;
    • As estruturas das classes Java que deverão ser programadas para cada plugin externo:
    • As classes, se for o caso, de implementação do plugin externo, para que o desenvolvedor possa programar o plugin externo propriamente dito;
    • Uma classe que fará o parser do retorno do órgão externo e montará o VO com as variáveis de resposta, que será chamada pela classe que efetuou o acesso;
    Colocar todos os arquivos de propriedades e layouts dentro de uma pasta, para que seja retirado do JAR depois. Essa lista deve ficar no arquivo de manifesto, i.e. 
    • Parametrizar no arquivo POM.XML as propriedades necessárias para correta geração do plugin. Essas confiogurações serã utilizadas para, por exemplo, a geração do META-INF/MANIFEST.MF
     com uma tag específica (Implementation-FileList - veja exemplo); os arquivos importados ficarão no diretório apontado pela variável de ambiente descrita pela tag 'Implementation-Datadir' no MANIFEST.MF e, esse local deve ter permissão de escrita para o owner do application server;
    • .
      • <main-class> : classe principal do plugin, ou seja, a classe a ser instanciada pelo Intellector Server. 
      • <pluginname> : nome do plugin
      • <description> : uma descrição do plugin
      • <primarykey> : chave a ser usada para a persistência da execução do plugin. Normalmente é uma das variáveis de entrada do plugin e será usada como referência do uso de cache.
      • <pkdescription>: descrição da chave
      • <layoutpath>: caminho para o arquivo json de configuração do plugin.
      • <pluginlib> : indicação se é um plugin ou uma lib para uso por outros plugins.  P - plugin / L - lib para plugin
    Para configuração do plugin de acesso no "Intellector Data Dir", deverá ser informado no arquivo de manifesto, i.e. META-INF/MANIFEST.MF, o nome do acesso, na tag 'Implementation-Plugin'. Na Instalação do plugin, no Intellector, será criada um diretório com esse nome no "Intellector Data Dir".
    • Para consultar o plugin de acesso é necessário determinar as chaves primárias para que futuramente o plugin de acesos seja armazenado em uma base de dados, portanto as variáveis primarykey e pkdescription deverão ser informados no arquivo de manifesto, i.e. META-INF/MANIFEST.MF, sendo o campo primarykey as chaves no HashMap de entrada do
    acesso
    • plugin mais importantes da consulta separados por ',' para que sejam consultados na funcionalidade Consultar Resultados de Plugin
    de Acesso e
    • e o campo pkdescription um nome mais amigável para que seja listado na funcionalidade também separado por ',' na mesma sequência descrita no campo primarykey;
    • Criar um novo projeto no Eclipse, tendo como base/exemplo o 
    acessodummy
    • dummyplugin no diretório base de onde os artefatos foram gerados.

Exemplo do MANIFEST.MF (nesse caso, um do SERASA): 

Bloco de código
languagehtml/xml
linenumberstrue
Manifest-Version: 1.0
 Main-Class: br.com.tools.acessos.serasa.SerasaPF
 Class-Path: .
 Version-Info: teste-10
 Implementation-Vendor: Tools Servicos
 Implementation-Plugin: serasapf
 Implementation-Layout: serasapf
 Implementation-Datadir: serasapf.datadir
 Implementation-FileList: 
  resources/https.properties,
  resources/layout_p002.xml,
  resources/layout_p006.xml,
  resources/layoutPF_b49c.xml,
  resources/layoutPJ_b49c.xml,
  resources/serasa.properties,
  resources/serasapf.xml,
  resources/serasapj.xml
 primarykey: CPF, DTNASCIMENTO,
 pkdescription: CPF, Data de Nascimento,
Downloads
    • É obrigatório informar no layout de saída nas variáveis  XXX e  YYYY a string que foi enviada no request e a string que foi retornada do request. Caso o plugin não tenha essas informações deixe-as vazias.
      • hashOut.put("LPT__PLUGIN_ENVIO", "STRING REQUEST");
      • hashOut.put("LPT__PLUGIN_RETORNO", "STRING RETORNO");

Exemplo do MANIFEST.MF : 

Bloco de código
languagehtml/xml
linenumberstrue
Manifest-Version: 1.0
Built-By: ricart.monachesi
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_202
Main-Class: br.com.totvs.plugins.dummyplugin.DummyPlugin

Name: Intellector Entries
Implementation-Description: Dummy para exemplificar plugins externos
Plugin-Lib: P
pkdescription: CPF do adquirente
Implementation-Plugin: dummyplugin
Implementation-Layout: resources/dummyplugin.json
primarykey: CPF
Downloads

Baixe dummyplugin.7z o template do dummypluginBaixe aqui o template do accessdummy