Introdução

O objetivo desta API é auxiliar o desenvolvedor na construção de plugins externos.


Desenvolvendo um Plugin Externo

Para obter mais exemplos de como construir usando a Intellector API, favor contactar a equipe TOTVS Financial.

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 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.

public interface PluginInterface {
	/**
	 * Executa um plugin externo; interface
	 * <p>
	 * @param hashIn
	 * @throws InfraException
	 * @throws LayoutException
	 * @throws ConfigException
	 */
	public HashMap<String, Object> execute( HashMap<String, Object> hashIn) 
		throws InfraException, LayoutException, ConfigException;
}


Exceptions throwable - O intellector-api disponibiliza algumas exceções para serem utilizadas pelos plugins de acessos, interpretados e tratados por qualquer política compilada pelo TOTVS Intellector Server, são elas:

  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 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 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.

Todas as exceções tem overload como no exemplo abaixo, permitindo lançar o throwable da causa junto.

public class CipheringException extends Exception {
	/** 
	 * Excecao relativa a problemas de criptografia
	 * <p>
	 * @param msg mensagem para ser mostrada pela excecao
	 */
	public CipheringException(String msg) {
		super(msg);
	}

	/**
	 * Constrói uma nova exceção especificando a mensagem detalhada e a causa.
	 * Note que a mensagem detalhada associada a causa não são incorporadas
	 * automaticamente na mensagem desta exceção.
	 * <p>
	 * @param message
	 *            Mensagem detalhada (que é armazenada para posterior obtenção
	 *            pelo método {@link #getMessage()})
	 * @param cause
	 *            Causa (que é guardada para posterior recuperação pelo método
	 *            {@link #getCause()}) (Um valor nulo é permitida, e indica que
	 *            a causa é inexistente ou desconhecida.)
	 */
	public CipheringException(String message, Throwable cause) {
		super(message, cause);
	}
}


Arquivos de configuração do Plugin e para a sua geração

Criar manualmente os arquivos com o layout do plugin externo e outras informações. Um template para a criação desse arquivo se encontra no dummyplugin para facilitar a vida do desenvolvedor e, tenha em mente, ele será validado pelo Intellector IW-Editor. 

São dois os arquivos que deverão ser criados para a configuração e geração do plugin (os arquivos de exemplo estão no projeto Eclipse com fontes que são disponibilizados mais abaixo):

JSON

{
"class_name": "br.com.totvs.plugins.dummyplugin.DummyPlugin" ,
"plugin_name": "dummyplugin",
"description":"Descrição do Plugin",
"layout": {
"editable": true,
"in": [
{
"description": "cpf requerente",
"type": "String",
"name": "CPF",
"format": ""
},
{
"description": "Data de Nascimento",
"type": "Date",
"name": "DT_NASC",
"format": "ddMMyyyy"
},
{
"description": "Tem seguro",
"type": "Boolean",
"name": "TEM_SEGURO",
"format": ""
},
{
"description": "Valor do salario",
"type": "Double",
"name": "VAL_SALARIO",
"format": ""
},
{
"description": "Idade do requerente",
"type": "Integer",
"name": "IDADE",
"format": ""
}
],
"out": [
{
"id": "DUMMY",
"counter": 0,
"counter_max": 0,
"register": [
{
"description": "Teste de boolean",
"type": "Boolean",
"name": "BOOLEAN_VALUE",
"format": ""
},
{
"description": "Teste pra tipo Data",
"type": "Date",
"name": "DATE_VALUE",
"format": "ddMMyyyy"
},
{
"description": "Teste pra tipo Double",
"type": "Double",
"name": "DOUBLE_VALUE",
"format": ""
},
{
"description": "Teste pra tipo Integer",
"type": "Integer",
"name": "INTEGER_VALUE",
"format": ""
},
{
"description": "Teste pra tipo String",
"type": "String",
"name": "STRING_VALUE",
"format": ""
}
]
},
{
"id": "D100",
"counter": 0,
"counter_max": 0,
"register": [
{
"description": "Um Nome qualquer",
"type": "String",
"name": "D100_NOME",
"format": ""
},
{
"description": "Uma data de Nascimento",
"type": "Date",
"name": "D100_DTNASCIMENTO",
"format": "ddMMyyyy"
},
{
"description": "Mostra o diretorio",
"type": "String",
"name": "D100_MYDIR",
"format": ""
},
{
"description": "Qualquer string",
"type": "String",
"name": "D100_OUTRO",
"format": ""
}
]
},
{
"id": "D200",
"counter": 2,
"counter_max": 3,
"register": [
{
"description": "Simula String com contador",
"type": "String",
"name": "D200_TIPO_",
"format": ""
},
{
"description": "Simula Date com contador",
"type": "Date",
"name": "D200_DATA_",
"format": "yyyyddMM"
},
{
"description": "Simula String com contador",
"type": "String",
"name": "D200_HORA_",
"format": ""
},
{
"description": "Simula String com contador",
"type": "String",
"name": "D200_MOEDA_",
"format": ""
},
{
"description": "Simula Double com contador",
"type": "Double",
"name": "D200_VALOR_",
"format": ""
}
]
}
]
},
"properties": {
"database": "mango_d",
"usuario": "claudio",
"senha": "mariposa",
"audita": true
}
}

POM.XML

<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 -->
		<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 Plugin -->
		<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 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 plugin dummy (dummyplugin) como um template para desenvolvimento de um plugin externo. A ideia é que ele oriente o desenvolvimento de toda a estrutura necessária para a criação de um plugin de acesso, mantendo uma padronização na construção destes, evitando que o fonte de cada plugin externo tenha uma forma de implementação completamente diferente dos outros. O objetivo é facilitar desenvolvimento de novos plugins de forma fácil e rápida. Os artefatos que comporão o projeto vazio de um plugin serão:

Exemplo do MANIFEST.MF : 

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 dummyplugin