Buscar

99 - Fusion Manual Técnico

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 107 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 107 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 107 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Material Técnico
1 - Ambiente de desenvolvimento (Eclipse / Maven)	5
2 – Como alterar logotipos no Fusion	16
3 - Utilizando filtros avançados em formulários relacionados	17
Exemplos de filtros NeoQL:	22
4 - Campos do tipo formula	22
a) Configurando campo do tipo fórmula	22
b) Configurando campo do tipo formula (Data)	24
c) Configurando campo do tipo formula (Texto)	26
5 - Subprocessos	27
6 - Processos de aprovação	32
a) Configurando execução múltipla	32
b) Gatilhos de aprovação (GED)	36
7 - Processo relacionado	39
8 - Decisão paralela	46
9 - Customizando o Fusion	48
9.1) Conhecendo os principais objetos do Fusion	49
a) NeoObject	49
b) InstantiableEntityInfo	49
c) EntityWrapper	49
d) PersistEngine	50
e) Persistindo os dados em um formulário.	51
f) Recuperando os dados de um formulário	52
g) NeoUser	53
9.2) Desenvolvendo adapters para Workflows	54
9.3) Incluindo adapters no modelo do processo	54
10 - Exemplo de adapters de Workflow – Persistindo dados em uma tabela externa	56
11 - Utilizando o Agendador de Tarefas	57
12 - Bloco Try...Catch	60
13 - Exemplo de utilização de REST	60
14 – SOAP	63
15 - Geração de Log	63
16 – PersistentEnginee Helper (PEHelp)	63
Métodos da classe PEHelp	64
find(...)	64
find(type, field, value)	64
querySingle(...)	65
querySingle(type)	65
querySingle(type, returnField)	65
querySingle(type, where, values)	65
querySingle(type, where, v1, v2 …, v5)	65
querySingle(type, returnField, where, values)	66
querySingle(type, returnField, where, v1, v2, …, v5)	66
query(...) e query2(...)	66
query(type, where, v1, v2 …, v5)	66
query2(type, where, values)	67
17 - Atividade Envio - Customizando Modelo de E-mail	67
a) Exemplo de Modelagem Fluxo com Atividade de Envio de E-mail	69
b) Exemplo de Modelo de E-mail	71
c) Exemplo de Modelo de E-mail com, botões e anexos	75
18 – Adapter para Gerar Reuniões via Outlook	81
19 - Ferramentas e Utilitários	86
a) Visualizando a estrutura de dados do formulário com dumpEFormTree	87
	88
b) Visualizando os dados de um Objeto com dumpNeoObject	88
c) Habilitando o log seletivo	89
d) Consultando a base com SQL	89
e) Visualizando os usuários online com activeUsers	91
20 – Check Point	91
21 – Portal	93
23 – Criar um botão de CEP consultando o site dos correios	96
24 – Gatilhos do Fusion	97
25 – Relacionamentos de tabelas do Fusion	99
26 – Guia e conversão Fusion 3.3	99
Configuração de projeto:	99
Pom.xml	100
NeoPersist	100
Entidades:	100
AbstractFolder	100
NeoDocument	102
NeoObject	103
SecurityPermission	105
QLRawFilter	106
27 – Configurar LDAP no Fusion	108
28 - RULES - Criar regras de pastas da central de tarefas	109
1 - Ambiente de desenvolvimento (Eclipse / Maven)
Para realizar desenvolvimentos no Fusion, utilizamos o framework Eclipse. Na NEOMIND, dispomos de um ambiente já pré-parametrizado para facilitar as configurações do ambiente.
Para que os procedimentos descritos neste documento funcionem perfeitamente, será necessário liberar as seguintes portas: 8100, 8200, 8300, 8400, 9000, 80 do domínio neomind.com.br.
              E também, os seguintes endereços deverão serem liberados:
	 Ferramenta
	TIPO
	URL INTERNA
	URL EXTERNA
	NEXUS
	Repositório Maven
	http://nexus.neomind.com.br:8100/nexus
	http://nexus.neomind.com.br:8100/nexus
	BAMBOO
	Compilador
	http://bamboo.neomind.com.br:8200/
	http://bamboo.neomind.com.br:8200/
	JIRA
	Chamados / GP / QA
	http://jira.neomind.com.br:8300/   
	http://jira.neomind.com.br:8300/     
	CONFLUENCE
	Documentação
	http://confluence.neomind.com.br:8400/    
	http://confluence.neomind.com.br:8400/   
	SONAR
	Testes / QA
	http://sonar.neomind.com.br:9000/
	http://sonar.neomind.com.br:9000/
	SVN
	SVN
	http://svn.neomind.com.br/svn/
	http://svn.neomind.com.br/svn/
Primeiramente, faça o download do pacote ambiente_neomind.zip e em seguida extraia o pacote baixado na unidade no caminho C:\ambiente_neomind.
	Depois necessitamos de configurar o ambiente de produção, para isso execute como administrador o arquivo _variables_jdk7.bat (para as versões 3.1 até 3.2.2) ou _variables_jdk8.bat (para as versões 3.2.3 ou superior).
	Agora podemos executar o eclipse.exe que está no diretório C:\ambiente_neomind\eclipse:
Entre na opção Windows -> Preferences e verifique as seguintes configurações (precisam estar conforme mostrados aqui):
	Maven User Settings: Global Settings e User Settings devem estar com o seguinte caminho: C:\ambiente_neomind\_util\apache-maven-3.1.1\conf\settings.xml
Maven Installations: Deverá ser apontado o caminho do Maven, então clicar em Add e informar o caminho do Maven (C:\ambiente_neomind\_util\apache-maven-3.1.1) e selecioná-lo:
Java Compiler: Para a versão 3.2.2, deverá ser configurado a versão 1.7 (superior, deverá ser usado a versão 1.8).
Caso não esteja configurado com esta versão, deverá ser configurado como abaixo:
 
Pronto ! O eclipse está configurado. Agora precisamos criar um projeto Maven novo e vazio entrando em File -> New -> Project -> Maven Project
Clique em Next e na segunda tela, mantenha as configurações como estão:
Clique em Next novamente e escolha o maven-archetype-quickstart como Archtype padrão
Clique em Next e na próxima tela, defina os parâmetros como a tela abaixo e clique em Finish:
Aguarde todo o processo de criação do projeto e você terá a seguinte estrutura de pastas:
Após estes procedimentos realizados com sucesso, entre em contato com um consultor da Neomind e peça o arquivo “pom.xml” para a versão no qual você está instalando e também a pasta “resources”, que é a pasta que possui os arquivos de configuração de acesso à base de dados chamado neo-persist.xml.
Caso você já possua algum ambiente com eclipse instalado em sua empresa, você poderá pegar de outra máquina (desde que esteja realizando uma instalação co a mesma versão do Fusion).
Substitua o arquivo pom.xml do projeto criado para o pom.xml recebido pelo consultor da Neomind ou copiado de outro ambiente. No momento desta substituição, os pacotes necessários para o funcionamento do Fusion começarão a ser baixados e dependendo da velocidade de sua internet/computador, esta baixa poderá levar muitos minutos para baixar tudo. Aguarde !
Após toda a baixa, copie a pasta resources para dentro de src -> main conforme abaixo:
Após estas etapas, edite o arquivo neo-persist.xml pelo eclipse e configure as informações de acesso ao banco de dados.
Importante: NUNCA suba mais de uma instância do Fusion sobre um mesmo banco, pois isso danificará a base de dados.
Agora chegou o momento de estruturar o projeto o eclipse. Para isso acesse as seguintes opções:
- Clique com o botão direito sobre o nome do projeto “Fusion” e clique em Maven -> Update Project e configure a tela conforme abaixo:
Aguarde a atualização e em seguida, recompile todo o projeto. Para isso clique novamente com o botão direito no projeto e clique em Run As -> Maven Build configure a tela conforme abaixo e clique em Run e aguarde a compilação e todo o projeto. Isto poderá levar alguns minutos dependendo da velocidade da internet/computador:
O próximo passo, é configurarmos no Eclipse, o Server TOMCAT. Para isso, clique na aba “Servers” e clique no link “No server are available. Click this link to create a new server ...”:
.
Clique em Tomcat v7.0 Server (para Fusion 3.2.2 ou 3.1) ou em Tomcat v8.0 Server para versões maiores que 3.2.2 do Fusion e clique em Next:
Na tela Add/Remove, passe o projeto importado para o lado direito (Configured) e clique em Finish:
		Agora podemos subir o ambiente para começar os trabalhos !
Observação: Caso algum procedimento deste falhe, deve-se entrar em contato com o suporte, pois são muitas variantes que podem implicar em problemas.
2 – Como alterar logotipos no Fusion
	Primeiramente entrar em sistemas e incluir o nome dos arquivos de imagem:
 
                                                                      Inserir somente o nome do arquivo com sua extensão.
                                                                      Ex: logo_fusion.png
Os arquivos de imagem devem estarno seguinte diretório(via eclipse):
Se o servidor não estiver rodando via eclipse, basta acessar o “workdir” configurado no server.xml do apache e acessar a pasta imagens, dentro dela criar uma pasta custom caso a mesma não exista e adicionar os arquivos de imagens que serão adicionados no sistema.
3 - Utilizando filtros avançados em formulários relacionados
Ao relacionar campos selecionáveis, é disponível a utilização dos filtros avançados. Estes filtros possibilitam que, assim que o usuário estiver preenchendo o formulário, suas opções sejam mais específicas, obedecendo regras de negócio.
O seguinte exemplo mostra a criação do formulário Cidades. Nele foram criados dois campos, Cidade e Estado, como exibe a seguinte tela:
 
 
Acesse Formulários -> Navegar e crie regristros, como exibe a seguinte tela:
 
 
Perceba que foram criadas cidades e seus estados variam entre SC, PR, SP, RJ e RS. 
Agora está na hora de criar o formulário que buscará os registros de cidades. Neste exemplo foi utilizado o formulário Cadastro. Crie um campo clicando em Novo, como na imagem a seguir:
 
 
Na criação, informe um nome e um título ao campo. No exemplo a seguir, foi criado o campo Cidade:
 
 
Role a tela e, em Tipo, selecione E-Form. Depois, selecione o formulário criado acima, o formulário Cidades. A opção selecionada em Lista não importa, apenas é obrigatório que no campo Selecionável esteja marcado como Sim.
 
Após preencher estes campos, marque Filtros Avançados, como exibe a seguinte tela:
 
 
Em Consulta NeoQL, insira um código para filtrar as opções que o usuário terá para selecionar. Este código deve ser HQL, que é a linguagem que faz consultas no Hibernate. Neste exemplo será utilizado o filtro no campo Estado, para que sejam exibidas cidades apenas do estado de SC.
 
 
Como o campo Estado pertence ao formulário relacionado, apenas deve ser inserido seu código, pois a referência é direta. Como o campo estado é do tipo texto, o termo comparativo para usar no filtro deve estar entre aspas simples. 
Clique em Ok para concluir a criação do campo e mais um Ok para concluir a criação do formulário. 
Acesse Formulários -> Navegar, encontre o formulário Cadastro e clique em Novo, como exibe a seguinte tela:
 
 
Ao clicar em Novo, preencha os campos desejados. Ao clicar no campo do tipo e-form Cidades,
 
 
Perceba que o campo Cidades só exibe cidades que são de SC, mesmo que hajam cidades cadastradas de outros estados. 
Além de um campo que pertence ao formulário relacionado, dentro da Consulta NeoQL podem ser utilizados na consulta o #user, para utilizar o usuário logado, $campo caso o campo for de subnível, e ${ } quando for filtro condicional, assim como diversos outros filtros, de acordo com suas regras de negócio.
Exemplos de filtros NeoQL:
neoId in (select h.neoId from D_cadastroHierarquia h where h.usuario.neoId = ${solicitante.neoId})
neoId in (select nu.neoId from NeoUser nu join nu.papers pa where pa.name = '<nome_do_papel_aqui>')
idunidade=( CASE WHEN ${unidadeSolicitacao} = '12956169' THEN idunidade ELSE ${unidadeSolicitacao} END  )
origemAreaAgrupadora
area.neoId = $origemAreaAgrupadora.neoId
Relacionar usuários do Fusion a um e-form externo
substring(usuario,1,12) in (select usuario from com.neomind.fusion.entity.ext.x.usuariosFuncionarios where usuario = substring(${Solicitante.code},1,12))
neoId in (select perm.neoId from D_frmParametroAprovacaoFluxo paf join paf.permissaoUso perm where perm.neoId = #user.neoId) => permissaoUso é um campo no e-form pai.
4 - Campos do tipo formula
a) Configurando campo do tipo fórmula
Na criação de formulário, em Campos clique em Novo. Será exibida a seguinte tela:
 
Selecione Tipo Fórmula no campo Tipo. 
Todos os campos são de preenchimento obrigatório. Estes estarão descritos a seguir e suas formas de preenchimento.
 
1) Fórmula: Insira a fórmula desejada. Para isso, insira o símbolo de $ antes do código do campo que deseja. 
Exemplo: $salario + $bonus, $campo1 * (1 - $campo2), entre outros.
 
2) Função Agregadora: Caso o campo Fórmula seja preenchido apenas com o código de um campo, no campo Função Agregadora é possível inserir uma função própria do Java, agregando à Fórmula. Exemplo: Ao inserir "SUM", será informado a soma de todos os registros do campo selecionado. Inserindo "Count", será informado a quantidade de registros. Existem ainda outras funções, como AVG para retornar a média aritmética, "MIN" para retornar o menor valor inserido, "MAX" para retornar o maior valor inserido, entre outras funções.
3) Número de casas decimais: Informe um valor inteiro que define o número máximo de casas após a vírgula. Exemplo: Se for um valor em dinheiro, só podem haver duas casas após a vírgula. 
A imagem a seguir exibe um exemplo de campo Tipo Fórmula.
Observação importante - Para a máscara funcionar corretamente, deve ser utilizado desta maneira: 
R$ ###,###,##0.00##
b) Configurando campo do tipo formula (Data)
O campo do tipo Fórmula (Data) dispõe ao usuário fazer cálculos com datas. 
Na criação de formulário, em Campos clique em Novo. Será exibida a seguinte tela:
 
 
Selecione Fórmula (Data) no campo Tipo. 
Todos os campos são de preenchimento obrigatório. Estes estarão descritos a seguir e suas formas de preenchimento.
 
1) Fórmula: Insira a fórmula para calcular datas ou tempo. Não esqueça que a fórmula deve estar vinculada com o Tipo de Campo. 
Caso em Tipo de Campo seja selecionado Inteiro, o valor da resposta será em numeral. Por exemplo: Inserindo a fórmula #dateDiff (${dataIda} ,${dataVolta}), o usuário visualiza a diferença entre duas datas, ou seja, o número inteiro em segundos da data de ida menos a data da volta. 
Já se em Tipo de Campo for selecionado Texto, o valor da resposta será exibida em texto. Por exemplo: Utilizando o mesmo exemplo acima, onde o campoFórmula é preenchido com #dateDiff (${dataIda} ,${dataVolta}), o usuário irá visualizar a diferença entre as duas datas em texto, como "3 meses e 12 dias e 14 horas e 30 segundos". 
O dateDiff permite calcular diferenças entre duas datas.
Fórmulas: #dateDiff( ${campoData1} ,  ${ campoData2} )
Regra: ${campoData1} > ${campoData2}
 
Atenção! A expressão dateDiff só pode ser utilizada quando o Tipo de Campo for Inteiro ou Texto.
 
Se em Tipo de Campo for selecionado Data, o valor da resposta terá que ser em data. Por exemplo: Inserindo no campo Fórmula a expressão  #dateAdd (${dataIda} ,${quantidadeDeDias}, day), o usuário irá visualizar a data da ida acrescentada do número de dias. Se em a data da ida for dia 10/05/2015 e a quantidade de dias for 5 dias, a resposta da expressão será 15/05/2015.
 
O dateAdd permite atribuir um valor a uma data. Esse valor pode ser dia, mês ou ano.
Fórmulas: #dateAdd( ${campoData1} , ${campoInteiro1}, type ) ... onde type = day/month/year
Regra: ${campoInteiro1} é do tipo número inteiro
 
Atenção! A expressão dateAdd pode ser utilizada apenas quando em Tipo de Campo for selecionada a opção Data e a expressão deve conter apenas campos do tipo Data e Inteiro.
 
Também é possível cobinar fórmulas, como nos exemplos abaixo:
 
#dateDiff ( #dateAdd( ${campoData1}, ${campoInteiro1}, month ) , ${campoData2} )
#dateDiff ( #dateAdd( ${campoData1}, ${campoInteiro1}, month ) , #dateAdd( ${campoData2}, ${campoInteiro2}, day )  )
 
Mas não se esqueça! Sempre se atente ao que foi selecionado em Tipo de Campo.
 
2) Somente dias úteis: Selecione Sim para definir se apenas os dias úteis serão considerados na fórmula. Ou seja, se a fórmula for, por exemplo, a data atual mais 20 dias, irão ser contados apenas os dias úteis. Sábados, domingos e feriados não são inclusos. Selecionando Não, serão considerados todos os dias corridos. 
3) Tipo de Campo: Como citado acima, informe como o resultado da expressão será informado ao usuário final. Escolha entre as opções Data, Inteiro ou Texto.
 
Atenção! Não é possível inserir na fórmula duas datas e selecionar no campo Tipo de Campo a opção Data.
 
A imagem a seguir exibe um exemplo de campo Tipo Fórmula (Data).c) Configurando campo do tipo formula (Texto)
O campo do tipo Fórmula (Texto) dispõe ao usuário concatenar dois ou mais campos de qualquer tipo, formando assim um texto. 
Na criação de formulário, em Campos clique em Novo. Será exibida a seguinte tela:
 
Selecione Fórmula (Texto) no campo Tipo.
 
Fórmula: Informe o texto e os campos desejados. Para inserir os campos, a fórmula deve conter o caractere $ e o código dos campos entre chaves: ${codigo}. Veja o seguinte exemplo:
Insira o seguinte texto no campo Fórmula: O endereço fornecido foi: Rua ${rua}, ${complemento}, ${numero}, ${bairro}, ${cidade}, ${estado}, ${telefone}. A data de criação é ${dataAtual}.
 
A imagem a seguir exibe um exemplo de campo Tipo Fórmula (Texto).
 
 
Para concluir a criação de seu campo, clique em Ok.
5 - Subprocessos
Subprocesso é um conjunto de atividades que pode ser detalhado dentro de um outro processo a parte, ou seja, com ele é possível chamar um processo externo ao atual. Subprocesso são representados como as tarefas, porém exibem um símbolo "+" na base inferior com um diferencial, para entender que é conjunto de tarefas. Eles são conectados ao fluxo do processo da mesma forma que as outras atividades, através de conectores de fluxo de sequência. Todo subprocesso também é um processo comum no Fusion e, assim como seu fluxo pode ser utilizado como um processo comum, ele pode também ser chamado em outros processos como um subprocesso. Subprocessos também podem ser úteis para reunir partes de fluxos que podem ser repetidas em momentos distintos do processo, caracterizando reuso. 
Por exemplo, em um processo de Criar Fatura, deve ser determinado o cliente a ser faturado. Logo após, o financeiro cria a fatura do cliente. O gateway paralelo define que ocorrerão atividades simultâneas no processo, uma para que o financeiro receba o pagamento e outra para que a expedição envie a fatura do cliente. Veja exemplo na seguinte imagem.
 
 
Um subprocesso pode ser utilizado em outros processos ou ser utilizado normalmente como um processo. No exemplo, foi chamado o processo Enviar Fatura, que possui o fluxo como exibe a seguinte imagem:
 
 
Neste processo, a expedição identifica o endereço a ser enviado. Em um gateway exclusivo, é definido se o envio da fatura será por e-mail ou pelos Correios. Se enviada por e-mail, a expedição deve criar o e-mail com a fatura e depois envia a mesma. Se no gateway for definido que o envio será pelos Correios, deve ser impressa a fatura, envelopada e entregue ao cliente. Ao terminar este processo, o fluxo segue no processo anterior.
No processo principal, o segundo gateway paralelo aguarda que todos os fluxos sejam concluídos, ou seja, o envio da fatura e o pagamento da mesma. Concluído, termina o processo.
 
Na seguinte tela é exibido os campos de preenchimento:
1 - Comum
 
 
Alguns campos são de preenchimento obrigatório e outros apenas informativos. As propriedades estão dispostas em 3 categorias. Estas estarão descritas a seguir e suas formas de preenchimento. 
1) Nome: Informe um nome ao subprocesso, geralmente é atribuído o nome do processo que está sendo chamado. 
2) Descrição: Escreva neste campo uma descrição resumida sobre a processo que está sendo chamado. 
3) Processo: Selecione o processo que será iniciado a partir do processo principal.
 	4) Campo: Selecione um campo do formulário do processo atual, este deve ser do tipo E-Form (selecionável = não e lista = não) e apontará para o formulário principal do subprocesso. Nesta configuração deve ser selecionado este campo para relacionar os processos.
 
2 - Formatação
 
 
Itens 1, 2, 3 e 4: Estas quatro propriedades estão relacionadas com a formatação do componente, permitindo alterar o visual através das propriedades: Cor de Fundo, Cor da Borda, Cor da Fonte e Tamanho da Fonte.
 
3 - Fluxo
 
 
Estes campos existem para manter a compatibilidade com versões anteriores do Fusion, pois eram eles que definiam os tipos de entrada e saída das atividades. A nova versão do BPMN 2.0 utiliza para estes casos o componente Gateway.
 
1) Tipo de Saída: Neste campo contém três opções para serem selecionadas, são elas:
Paralelo: Quando mais de um fluxo sair desta atividade e estes deverão seguir simultaneamente para as próximas atividades, ou seja, não haverá condição para seguir os fluxos, serão enviados para todos que saírem desta atividade.
Exclusivo: Quando mais de um fluxo sair desta atividade e estes possuírem condições a serem seguidos, neste caso o sistema irá testar as condições e enviar para o primeiro fluxo que retornar verdadeiro. No momento que retornar o primeiro verdadeiro o sistema não testará os demais fluxos.
Inclusivo: Quando mais de um fluxo sair desta atividade e estes possuírem condições a serem seguidos, neste caso o sistema irá testar todas as condições e enviar para todos os fluxos que retornarem verdadeiro.
 
2) Tipo de Entrada: Neste campo contém duas opções para serem selecionadas, são elas:
 
Exclusivo: quando a atividade receber um fluxo de entrada ela dará sequência ao processo.
Paralelo: quando a atividade receber todos os fluxos paralelos que estão ligados nela, então dará sequência. Neste caso a atividade ficará aguardando até que todos os fluxos paralelos cheguem até ela.
 
6 - Processos de aprovação
a) Configurando execução múltipla
Neste caso utiliza-se o conceito de execução múltipla descrito a seguir.
É importante informar que para configurar a execução múltipla, o formulário do processo precisará de um campo específico. 
Primeiramente, acesse em Formulários Dinâmicos o formulário principal de seu processo e edite-o. 
Crie um novo campo com as configurações:
- Tipo: e-form
- E-form: Consenso (o sistema disponibiliza este e-form)
- Selecionável: não
- Lista: sim
 
 
O formulário Consenso disponibilizado pelo Fusion possui os campos necessários para a configuração de Execução Múltipla, por este motivo faz-se necessária a criação deste campo. 
Para configurar a execução múltipla, selecione a atividade desejada e clique na categoria 8 - Execução Múltipla, localizada nas propriedades da atividade, conforme imagem abaixo:
 
 
Todas as propriedades são de preenchimento obrigatório, exceto o Adapter que é utilizado para criar rotinas específicas.
 
1) Execução Múltipla: para realizar a configuração selecione a opção "Sim" que habilitará os próximos campos a serem configurados. 
2) Campo Lista: este campo será a lista que armazenará as informações de todos os executores da tarefa. Selecione o campo e-form criado que aponta para o consenso.
 
3) Campo Usuário da Lista: este campo armazenará o nome do usuário que executou a tarefa. Selecione dentro da estrutura do campo Consenso o campo Usuário.
 
4) Campo Iteração da Lista: este campo armazenará a ordem que os usuários executaram a tarefa. Selecione dentro da estrutura do campo Consenso o campo Iteração.
 
5) Com consenso: neste momento não será configurado este campo. Manter selecionada a opção "Não". 
6) Adapter: caso possua alguma customização via classe Java, informe o caminho da classe neste campo. Caso contrário, não há necessidade de preenchimento do campo.
b) Gatilhos de aprovação (GED)
Além dos gatilhos comuns, que não interferem diretamente no GED, existem também gatilhos que oferecem formas dinâmicas e customizadas de unir o GED com os processos no Fusion. As ações de aprovações, opções presentes na tela de Gatilhos de Processo, dispõem ao usuário unir o GED a uma modelagem de processo no BPM Studio. Por exemplo: selecionando Aprovar Cancelamento, assim que um usuário pedir cancelamento de um documento no GED, o documento fica travado (em check out) e um processo é iniciado. 
Somente quando o processo de aprovação de cancelamento for finalizado, o documento será novamente liberado.
Diferente dos gatilhos de processos, os gatilhos de aprovação interferem diretamente no documento, pois, como é realizado o check out, o documento não fica disponível aos usuários. A seguinte tela exibe os gatilhos disponíveis:
 
 
Selecione Aprovar Cancelamentopara que seja iniciado um processo de aprovação quando um usuário pedir cancelamento de um documento. 
Selecione Aprovar Exclusão para que seja iniciado um processo de aprovação quando um usuário pedir exclusão de um documento. 
Selecionando Aprovar Cancelamento ou Aprovar Exclusão, serão exibidos os campos conforme exibe a seguinte imagem:
 
 
Alguns deles são de preenchimento obrigatório e outros apenas informativo, que estarão descritos a seguir suas formas de preenchimento.
 
1) Processo: Selecione o processo que será iniciado com a ação. Atenção! Este processo deve conter as atividades de Script Check Out e Check In. Para saber mais, acesse Atividade de Script GED Cancelar/Remover Documento. 
2) Solicitante: Selecione um usuário do sistema que ficará como solicitante do processo. Geralmente, é selecionado neste campo um gestor de área. 
3) Versão Ativa: Navegue ao campo onde está inserido o campo tipo arquivo que contém a versão ativa do documento que sofrerá a aprovação no processo.
 
Após a conclusão da criação do gatilho de processo, clique em Ok.
 
Ainda na escolha da ação, na tela de Gatilhos de Processo, existe a opção Aprovar Liberação. Selecione esta ação para que seja iniciado um processo de aprovação quando um usuário pedir liberação de um documento. Ao selecionar, são exibidos os campos conforme exibe a seguinte imagem:
 
 
1) Processo: Selecione o processo elaborado para a aprovação. Atenção! Este processo deve conter as atividades de Script Check In e Check Out. Para saber mais, acesse Atividade de Script GED Check In / Check Out. A seleção do processo é obrigatória. 
2) Solicitante: Selecione um usuário do sistema que ficará como solicitante do processo. Geralmente é selecionado neste campo um gestor de área. A seleção de um solicitante do processo é obrigatória. 
3) Versão Nova: Selecione o campo tipo e-form que aponta para o formulário de sistema 'Documento' que contém a versão nova do documento e que sofrerá a aprovação no processo. Este campo é de preenchimento obrigatório.
 
4) Versão Ativa: Selecione o campo tipo e-form que aponta para o formulário de sistema 'Documento' que contém a versão ativa do documento e que sofrerá a aprovação no processo. Este campo é de preenchimento obrigatório. 
5) Campo de Aprovadores: Selecione o campo tipo usuário que contém os usuários que devem aprovar o processo. O preenchimento deste campo não é obrigatório. 
6) Aprovadores: Mova para o campo Selecionados os aprovadores que vão analisar a aprovação de liberação do documento.
 
Após a conclusão da criação do gatilho de processo, clique em Ok.
7 - Processo relacionado
Os processos relacionados auxiliam na execução de processos que possuem ligação, mas que nem sempre precisam ser iniciados. Por exemplo: Em um processo da área da qualidade onde está sendo investigado alguma não conformidade, a qualquer momento o usuário pode iniciar um ou mais processos de investigação, iniciando um plano de ação para tomar ações imediatas e/ou preventivas. Mas a iniciação desse processo relacionado, além de não ser obrigatória, também pode ser iniciada a qualquer momento do processo, ou seja, ser iniciado na execução de qualquer tarefa. 
A configuração do processo relacionado começa criando campos nos formulários dos dois processos, o principal e o relacionado. O exemplo a seguir vai demonstrar o relacionamento entre o processo Solicitação de Bolsa de Estudos com o processo Cotação de Valores de Cursos. Para realizar a configuração no formulário do processo principal, acesse: Formulários -> Configurar 
-> Dinâmicos e clique no ícone de Editar, conforme tela abaixo:
 
Crie no processo principal, que no exemplo é o processo Solicitação de Bolsa de Estudos, um campo do tipo E-Form que chame o processo relacionado Cotação de Valores de Cursos. Em Campos, clique em Novo, conforme tela abaixo:
	Preencha os campos Nome e Título como exibe a seguinte tela:
Role a tela e selecione em Tipo a opção E-Form. Selecione o formulário do processo relacionado. Preencha os campos Selecionável e Lista com Sim. Estas configurações indicam que o processo principal poderá ter uma lista de processos relacionados.
Clique em Ok para concluir a criação do campo e novamente em Ok para concluir a edição do formulário. 
No formulário do processo relacionado, também é necessário criar um campo vinculando ele ao processo principal. Para isso, no formulário do processo relacionado, que no exemplo é o processo Cotação de Valores de Cursos, clique no ícone de Editar, como exibe a seguinte tela:
Role a tela e no campo Tipo selecione a opção E-Form. Selecione o formulário do processo principal, que no exemplo é o formulário Solicitação de Bolsa de Estudos. Preencha o campo Selecionável como Sim e o campo Lista como Não. Estas configurações indicam que o processo relacionado poderá somente ter um processo principal, ou seja, somente um processo irá iniciá-lo.
Clique em Ok para concluir a criação do campo e novamente em Ok para concluir a edição do formulário. Pronto! Já estão criados os dois campos, um no formulário do processo principal e outro no formulário do processo relacionado. 
Agora é preciso configurar no modelo do processo principal quem é seu processo relacionado. Para isso, acesse Processos  -> Configurar -> Gerenciar Modelos de Processos, e clique no processo principal, como exibe a seguinte tela:
	Ao clicar, será exibido o modelo do processo no BPM Studio. Nas configurações, clique em processos Relacionados, conforme imagem abaixo:
Crie um processo relacionado clicando em Novo, como exibe a seguinte tela:
	Ao clicar em Novo, serão exibidos os seguintes campos de configuração:
Todos os campos são de preenchimento obrigatório. Estes estão descritos a seguir e suas formas de preenchimento:
 
1) Processo: Selecione o processo relacionado. No exemplo, selecione o processo Cotação de Valores de Cursos. 
2) Síncrono: Marque Sim para que quando for iniciado um processo relacionado em uma determinada atividade, o usuário não conseguirá avançar o processo principal enquanto o relacionado não finaliza, ou seja, a tarefa passa a ser dependente do processo que foi iniciado. Marque Não para que o processo principal continue sendo executado e até finalizado mesmo que o processo relacionado ainda esteja em execução. 
3) Campo de referência do pai: Selecione o campo que foi criado no formulário principal e aponta para o formulário relacionado. Por exemplo: Ao expandir os campos do processo Solicitação de Bolsas de Estudos, selecione o campo que aponta ao processo relacionado Cotação de Valores de Cursos, como exibe a seguinte tela:
Após selecionar, clique em Ok.
 
4) Campo de referência do relacionado: Selecione o campo que foi criado no processo relacionado e aponta para o formulário principal. Por exemplo: Ao expandir os campos do processo Cotação de Valores de Cursos, selecione o campo que aponta ao processo principal Solicitação de Bolsa de Estudos, como exibe a seguinte tela:
Após selecionar, clique em Ok. 
8 - Decisão paralela
Na construção do modelo do processo surgirão cenários em que o fluxo deve seguir múltiplos caminhos, permitindo execução paralela de atividades. O componente de Decisão Paralela permite dividir o fluxo em caminhos paralelos, que serão fluxos concorrentes no modelo do processo.
 
Na imagem abaixo é exemplificado um processo de Pedidos. O cliente preenche os campos da solicitação. O Workflow segue com o setor de atendimento da empresa recebendo o pedido e separando os produtos. Neste momento acontecem duas tarefas paralelas, onde o atendimento segue embalando os produtos e o financeiro, ao mesmo tempo, emite as notas fiscais. Para que o cliente efetue o pagamento do produto, é necessário que tanto a nota fiscal quanto a embalagem do produto estejam concluídas. Para isso, é necessária a inclusão de um segundo gateway paralelo, que tem a função de aguardar a conclusão de todas as etapas anteriores para seguir adiante no processo. Por último, o cliente efetua o pagamento dos produtos.O gateway de Decisão Paralela é representado visualmente como o losango com um marcador de “+”.
 
 
Caso não seja necessário aguardar todos os fluxos, apenas ligue-os com a próxima tarefa, conforme exibe a seguinte imagem:
 
 
Para cada componente adicionado na modelagem são exibidas suas propriedades para configuração. Para a Decisão Paralela, são exibidas as propriedades abaixo:
 
1 - Comum
 
 
Alguns campos são de preenchimento obrigatório e outros apenas informativos. As propriedades estão dispostas em 2 categorias. Estas estarão descritas a seguir e suas formas de preenchimento.
 
1) Nome: Informe um nome à decisão, por exemplo "Preparar Envio". 
2) Descrição: Insira uma descrição resumida sobre o componente.
 
2 - Formatação
 
 
Itens 1, 2, 3 e 4: Estas quatro propriedades estão relacionadas com a formatação do componente, permitindo alterar o visual através das propriedades: Cor de Fundo, Cor da Borda, Cor da Fonte e Tamanho da Fonte. 
Ao concluir o preenchimento dos campos relacionado o gateway, é necessário configurar os fluxos que dele saem. No caso de um gateway paralelo, os fluxos não devem conter condições. Para saber mais sobre configuração de fluxos, acesse Fluxos.
9 - Customizando o Fusion
O Fusion ECM Suite foi desenvolvido pensando-se em escalabilidade. Como consequência cada contexto do Fusion está preparado para receber novas funcionalidades, portanto tudo que o produto padrão não contemple, pode ser desenvolvido como customização através do uso de Adapters Java. Para desenvolver adapters é necessário um ambiente de desenvolvimento com o Fusion instalado. O ambiente utilizado na Neomind é o Eclipse IDE. Também é essencial o conhecimento da linguagem de programação Java, especificamente no contexto de desenvolvimento de aplicações WEB.
9.1) Conhecendo os principais objetos do Fusion
		a) NeoObject
NeoObject é o objeto mais genérico no Fusion, todos os outros objetos estendem ele. Para obter a Id de um Objeto utilize o método getNeoId(). Também as questões de segurança do Fusion estão associadas a este objeto, vários métodos de validações de segurança são invocados a partir do NeoObject.
b) InstantiableEntityInfo
Entidades são classes que mapeiam e representam uma tabela no banco de dados.
Para obter a instância de uma entidade, um objeto do tipo InstantiableEntityInfo deve ser criado para representá-la. Para criarmos uma instância de uma entidade usamos o método createNewEntityInstance(String entityName) da classe AdapterUtils. O parâmetro do método é um objeto do tipo String que será o nome da entidade (formulário ou tabela) criado no Fusion. Lembrando que o formulário pode ser dinâmico ou externo. Este objeto é posteriormente passado como argumento dos métodos getObject() e getObjects() da classe PersitEngine, que realizam a busca na tabela(formulário).
O código abaixo exemplifica o uso da entidade para mapear a tabela (Formulário) “Produto”.
O formulário “Produto” pode tanto ser um formulário dinâmico criado no banco do Fusion quanto uma tabela externa pertencente a um sistema legado. Se “Produto” for um formulário externo, a Fonte de Dados primeiramente deve ser criada no Fusion, e posteriormente o formulário externo, sendo que o Nome do formulário será o argumento passado para o método createNewEntityInstance;
// NeoObject é inicializado com uma instâcia que da entidade Produto
NeoObject produtoFusion = AdapterUtils.createNewEntityInstance("Produto");
c) EntityWrapper
Wrappers são classes com o papel de encapsular as Entidades, abstraindo sua interface simplificando as operações de leitura e escrita dos dados no banco. No Fusion o EntityWrapper é a classe que encapsula a entidade.
A tabela abaixo descreve os métodos mais usados do EntityWrapper:
	Método
	Descrição
	findField
	Retorna um Wrapper para manipulação do campo se o campo existir, senão retorna null
	findValue
	Retorna um objeto com o valor do campo
	findValues
	Retorna uma coleção de objetos
	findGenericValue
	Retorna um objeto genérico com o valor do campo
No código abaixo primeiro criamos uma instância da entidade “Produto” e atribuímos ela a um NeoObject que representará a tabela no banco, em seguida embrulhamos ela com um wrapper instanciando a classe EntityWrapper passando para o construtor desta o argumento NeoObject contendo a entidade, encapsulando assim sua complexidade, agora todas operações de leitura e escrita no banco serão realizados através do objeto wrapper. Este método simplifica as operações de banco escondendo os detalhes de relacionamentos entre tabelas que serão controlados pelo Hibernate.
// NeoObject é inicializado com uma instâcia da entidade Produto NeoObject produtoFusion = AdapterUtils.createNewEntityInstance("Produto"); EntityWrapper wrapperProdutoFusion = new EntityWrapper(produtoFusion);
d) PersistEngine
A classe PersistEngine, existente no núcleo do Fusion, centraliza toda a comunicação com o banco de dados. É nela que os principais métodos de obtenção e atribuição de valores existentes no banco são implementados.
A tabela abaixo descreve alguns dos métodos mais usados do PersistEngine:
//instancia objeto no fusion e seta valores
NeoObject produtoFusion = AdapterUtils.createNewEntityInstance("Produto");
// cria wrapper para abstrair a Entidade que representa “eduProduto” EntityWrapper wrapperProdutoFusion = new EntityWrapper(produtoFusion);
// Atribui valores a variáveis locais String numeroProduto = “AFR – 233”; String descricao = “Montain Bike”;
//Usa o wrapper para atribuir os valores aos campos wrapperProdutoFusion.findField("codigo").setValue(numeroProduto); wrapperProdutoFusion.findField("descricao").setValue(descricao);
//persistindo os dados no banco PersistEngine.persist(produtoFusion);
	Método
	Descrição
	getConnection
	Retorna um objeto de conexão para a fonte de dados. Recebe uma String com o nome da fonte de dados como parâmetro.
	persit
	Persiste os dados no banco, recebe como parâmetro um objeto que referencia a entidade.
	getObject
	Retorna a instância de um objeto. Recebe como parâmetro um objeto classe.
	getObjects
	Retorna uma lista ou coleção de instâncias de objetos. Além do objeto representando a entidade os métodos também podem ter como parâmetro filtros, assim o resultado retornado será uma instância específica ou um subconjunto de instâncias de acordo com os critérios definidos pelos filtros.
e) Persistindo os dados em um formulário. 
No exemplo abaixo, foi criado um formulário dinâmico com o nome de “Produto” com dois campos cujos nomes são “código” e “descricao”. Depois incluímos um registro no formulário utilizando o wrapper e por último persistimos o registro usando o método persit da classe PesistEngine.
	Normalmente os passos para Ler/Escrever em formulários são: Crie uma entidade para representar o formulário (tabela)
//instancia objeto no fusion e seta valores
NeoObject produtoFusion = AdapterUtils.createNewEntityInstance("Produto");
1- Crie um wrapper para encapsular a entidade
// cria wrapper para abstrair a Entidade que representa “eduProduto” EntityWrapper wrapperProdutoFusion = new EntityWrapper(produtoFusion);
2- Use o wrapper para escrever/ler/alterar os dados no banco
3- Use o mecanismo de persistência do hibernate para persistir/remover os dados
//persistindo os dados no banco PersistEngine.persist(produtoFusion);
f) Recuperando os dados de um formulário
O código abaixo exemplifica a recuperação dos registros em um formulário. Através do método getObjects os registros encontrados no formulário “Produto” são carregados para dentro de uma lista de objetos tipo NeoObject. Em seguida usamos um looping “for” para percorrer a lista usando um iterador percorremos cada registro até o final da lista, note que utilizamos um wrapper para realizar a operação sobre a entidade (tabela), o método findField retorna o campo do objeto e o método getValue traz o valor do campo. No final usamos a classe System para mostrar os valores no console a cada iteração na lista.
// Atribui valores a variáveis locaisString numeroProduto = “AFR – 233”; String descricao = “Montain Bike”;
//Usa o wrapper para atribuir os valores aos campos wrapperProdutoFusion.findField("codigo").setValue(numeroProduto); wrapperProdutoFusion.findField("descricao").setValue(descricao);
List<NeoObject> listaProduto = (List<NeoObject>) PersistEngine.getObjects(AdapterUtils.getEntityClass("Produtos"));
for(NeoObject produto : listaProduto)
 {
//dados eform externo
EntityWrapper wrapperProdutos = new EntityWrapper(produto);
String codigo = (String) wrapperProdutos.findField("codigo").getValue(); String descricao = (String) wrapperProdutos.findField("descricao").getValue();
//mostra valores dos campos
System.out.println(codigo+"\n"); System.out.println(descricao);
//remove objeto PersistEngine.remove(produtoFusion);
}
g) NeoUser
A classe NeoUser representa a abstração de um usuário do sistema. Ela é utilizada quando uma ação específica a um usuário ou grupo de usuários deve ser realizada. Através dela, uma referência ao usuário atual do sistema é obtida, retornando um objeto, que pode ser utilizado em diversas ocasiões, como na verificação do papel do usuário.
Para obter o usuário atual logado, utilize o código apresentado abaixo.
// A variável ‘user’ recebe o objeto que representa o usuário.
NeoUser user = PortalUtil.getCurrentUser();
Para verificar o papel em que o usuário está inserido, é necessário criar o objeto que mantém a referência do usuário, conforme o código acima. O exemplo abaixo demonstra como verificar se o usuário atual está no papel Estagiário.
boolean isEstagiario = user.isInRole(SecurityManager.getInstance().getRole("Estagiário"));
Através da variável user, que representa o usuário logado, utiliza-se o método isInRole(). Este método, por fim, recebe um parâmetro contendo o nome do papel, neste caso, “Estagiário”. Se o usuário estiver neste papel, a variável isEstagiario receberá true, caso contrário, false.
9.2) Desenvolvendo adapters para Workflows
Na fase de elementos de interface, etc. podem demandar o desenvolvimento de adapters de Workflow construção do Workflow algumas funcionalidades necessárias para automatizar o processo tais como integrações, validações. Estes possuem características específicas dentro do contexto de Workflow, e devem implementar a classe AdapterInterface que possui dois métodos obrigatórios o método start() e o back() . Normalmente o código para os adapters de workflow é desenvolvido dentro destes dois métodos.
9.3) Incluindo adapters no modelo do processo
Para incluirmos um adapter de workflow no processo, precisamos inclui-lo na modelagem. O adapter é uma atividade do tipo Script, para alterarmos a atividade para o tipo Script, clique na atividade, no ícone de atalho para o tipo de atividade escolha Script.
Depois de alterado para o tipo Script a caixa de atividade mudará de cor, e também o Painel de Propriedades terá suas propriedades alteradas para o contexto de Script. No painel de propriedades preencha o campo “Descrição”, e no campo “Tipo de Script” deixe o valor padrão que é “adapter”, na propriedade “Classe Java” informe o namespace da classe Java desenvolvida. Muito cuidado com o namespace pois qualquer erro impedirá que o Adapter funcione.
Treinamento Técnico
1
A maneira mais segura de copiar o namespace no Eclipse é posicionar o cursor sobre o nome da classe e clicar com o botão direito, selecionar o item “Copy Qualified Name”, o Eclipse copiará para a área de transferência o namespace da classe. Cole na propriedade “Classe Java” no Painel de Propriedades. Assim a possibilidade de erros de digitação será anulada.
10 - Exemplo de adapters de Workflow – Persistindo dados em uma tabela externa
public class CadastraPgtoERP implements AdapterInterface { 
	@Override 
	public void start(Task origin, EntityWrapper processEntity, 
			Activity activity) 
	{ 
		// TODO Auto-generated method stub 
		StringBuffer sql = new StringBuffer(); 
		sql.append("INSERT INTO produto"); 
		sql.append(" (ProductID, Name, ProductNumber, Color , StandardCost , ListPrice, Size, Weight, SellStartDate,rowguide, ModifiedDate)"); 
		sql.append(" VALUES( ?, ?, ?, ?, ?, ?, ?, ?, ?, NEWID(), GETDATE() )");
	}
	Long productId = null; 
	String name =null; 
	String productNumber = null; 
	String color = null; 
	BigDecimal standadCost = null; 
	BigDecimal listPrice = null; 
	String size = "45"; 
	BigDecimal weight = new BigDecimal(4433.78); 
	GregorianCalendar sellStartDate = null; 
	productId = (Long) processEntity.findValue("codigo"); 
	name = (String) processEntity.findValue("nome"); 
	productNumber = (String) processEntity.findValue("productNumber"); 
	color = (String) processEntity.findValue("color"); 
	standadCost = (BigDecimal) processEntity.findValue("cost"); 
	listPrice = (BigDecimal) processEntity.findValue("listPrice"); 
	sellStartDate =(GregorianCalendar) processEntity.findValue("sellStartDate"); 
	Date x = new Date(sellStartDate.getTimeInMillis());//converte gregorian para Date 
	Connection connection = PersistEngine.getConnection("Neo Produto"); 
	PreparedStatement st = null; 
	try { 
		connection.setAutoCommit(false); 
		st = connection.prepareStatement(sql.toString()); 
		st.setLong(1, productId); 
		st.setString(2, name); 
		st.setString(3, productNumber); 
		st.setString(4, color); 
		st.setBigDecimal(5,standadCost); 
		st.setBigDecimal(6, listPrice); 
		st.setString(7, size); 
		st.setBigDecimal(8, weight); 
		st.setDate(9, x); 
		st.executeUpdate(); 
		connection.commit(); 
	} 
	catch (Exception e) { 
		e.printStackTrace(); 
		throw new WorkflowException("Erro ao Salvar os dados "+e.getMessage()); 
	} finally { 
		try { 
			st.close(); 
			connection.close(); 
		} 
		catch (Exception e) { 
			e.printStackTrace(); 
		} 
	} 
}
11 - Utilizando o Agendador de Tarefas
O Agendador de Tarefas permite a execução de tarefas automaticamente de acordo com parâmetros temporais configurados previamente. Deste modo podemos gerar tarefas para sincronizar bancos, iniciar Workflows automaticamente, limpar logs, etc. As tarefas a serem executadas devem estar contidas em um adapter java, e devem implementar a interface CustomJobAdapter . O código a ser executado estará dentro do método execute.
 
Para agendar uma tarefa clique em Novo, dê um nome e uma descrição para a tarefa, e defina o campo Habilitado para Sim. No campo Adapter informe o namespace da classe que será executada. Configure o Gatilho que executará a tarefa no painel Gatilho clique em Novo preencha os campos solicitados para repetir a execução agendada.
Exemplo de Adapter para o Agendador de Tarefas – Importador Simplificado
public class ExemploAgendadorImportaDados implements CustomJobAdapter
{
@Override
public void execute(CustomJobContext ctx)
{
// TODO Auto-generated method stub
List<NeoObject> listaProduto = (List<NeoObject>) PersistEngine.getObjects(AdapterUtils.getEntityClass("AdventureProdutos"));
for(NeoObject produto : listaProduto)
{
//dados eform externo
EntityWrapper wrapperProdutos = new EntityWrapper(produto);
String descricao = (String) wrapperProdutos.findField("name").getValue();
String numeroProduto = (String) wrapperProdutos.findField("productnumber").getValue();
//instancia objeto no fusion e seta valores
NeoObject produtoFusion = AdapterUtils.createNewEntityInstance("Produto"); EntityWrapper wrapperProdutoFusion = new EntityWrapper(produtoFusion);
wrapperProdutoFusion.findField("codigo").setValue(numeroProduto); wrapperProdutoFusion.findField("descricao").setValue(descricao);
//mostra valores dos campos a serem importados no console
System.out.println(numeroProduto+"\n"); System.out.println(descricao);
//persistindo objeto PersistEngine.persist(produtoFusion);
}
}
}
O código abaixo exemplifica a estrutura de um adapter para o agendador de tarefas. Neste exemplo os dados de uma tabela externa são importados para um formulário dinâmico do Fusion.12 - Bloco Try...Catch
Para manter um melhor controle da execução do código e otimizar o tratamento de erros, é importante que o código dos adapters seja inserido entre um ou mais blocos try...catch. A função deste bloco é isolar e tratar qualquer erro que ocorra no código, impedindo que este erro interrompa a execução de outra parte do código.
O exemplo abaixo mostra um código simples de adapter. Primeiro, um campo é lido no workflow. Se o valor dele for diferente de “Processo Judicial”, o valor é alterado. Todo o código está envolvido no bloco try...catch e, caso um erro ocorra, uma mensagem é apresentada.
public void start(Task origin, EntityWrapper wrapper, Activity activity)
{
try // início do bloco try
{
String tipoProcesso = wrapper.findValue(“TipoProcesso”);
if (!tipoProcesso.equals(“Processo Judicial”))
{
wrapper.findField(“TipoProcesso”).setValue(“Processo Judicial”);
}
}catch (Exception e) // fim do bloco try
{
// Mensagem apresentada quando o erro ocorre
System.out.println(“Erro ao executar o código do adapter!”)
}
}
13 - Exemplo de utilização de REST
A necessidade de trocar informações entre aplicações motivou diferentes abordagens para “integração de dados”. Desde soluções simples e questionáveis como utilizar um banco de dados compartilhado, ou realizar troca de arquivos até soluções mais elaboradas que utilizam objetos distribuídos. Em diversos momentos não temos somente a integração de sistemas diferentes, mas a distribuição de um único sistema em diversas partes também pode ser integrada da mesma maneira.
A solução de integração denominada Webservices, que já é relativamente simples de implementar, é a mais utilizada hoje em dia.
 package com.neomind.fusion.custom.rest;
 public class UsuarioVO {
     private String nome;
    private Long idade;
    public String getNome() {
return nome;
    }
     public void setNome(String nome) {
    this. nome = nome;
    }
    public Long getIdade() {
    return idade;
    }
  public void setIdade(Long idade) {
      this. idade = idade;
     }
}
package com.neomind.fusion.custom.rest;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import com.neomind.fusion.entity.EntityWrapper;
import com.neomind.fusion.portal.PortalUtil;
import com.neomind.fusion.security.NeoUser;
import com.neomind.fusion.custom.rest.UsuarioVO;
@Path("/main" )
public class MainService {
     //Chamada simples sem parâmetros
     @GET
     @Path("/RetornaUsuarioLogado")
     public String retornaUsuarioLogado() {
          NeoUser usuLogado = PortalUtil. getCurrentUser();
          return usuLogado.getFullName();
     }
     //Chamada recebendo um parâmetro via QueryParam
     //http://localhost:8080/fusion/services/main/RetornaCampoUsuarioQParam?nomeCampo=<campo>
     @GET
     @Path("/RetornaCampoUsuarioQParam")
     public Object RetornaCampoUsuarioQParam( @QueryParam( "nomeCampo") String nomeCampo) {
          NeoUser usuLogado = PortalUtil. getCurrentUser();
          EntityWrapper wrapper = new EntityWrapper(usuLogado);
          Object retorno = wrapper.findGenericValue(nomeCampo );
           return retorno;
     }
     //Chamada recebendo um parâmetro via PathParam
     //http://localhost:8080/fusion/services/main/RetornaCampoUsuarioPParam/<campo>
     @GET
     @Path("RetornaCampoUsuarioPParam/{nomeCampo}")
     public Object RetornaCampoUsuarioPParam(@PathParam ("nomeCampo" ) String nomeCampo) {
          NeoUser usuLogado = PortalUtil. getCurrentUser();
          EntityWrapper wrapper = new EntityWrapper(usuLogado);
          Object retorno = wrapper.findGenericValue(nomeCampo );
          return retorno;
     }    
     //Enviando um JSON
     @GET
     @Path("/RetornaCampoUsuarioJson")
     @Produces(MediaType. APPLICATION_JSON + ";charset=utf-8")
     public UsuarioVO retornaUsuarioLogadoJson() {
          NeoUser usuarioLogado = PortalUtil.getCurrentUser();
          
          UsuarioVO usuario = new UsuarioVO();
           usuario.setNome( usuarioLogado.getFullName());
           usuario.setIdade(30L);
          
           return usuario;
     }
     
     //Recebendo um JSON
     @POST
     @Path("/SalvaUsuario")
     @Produces(MediaType. APPLICATION_JSON + ";charset=utf-8")
     @Consumes(MediaType. APPLICATION_JSON + ";charset=utf-8")
     public UsuarioVO salvaUsuario(UsuarioVO usuario)
     {
           return usuario;
     }
}
14 – SOAP
	Assista o vídeo detalhado no endereço: https://www.youtube.com/watch?v=mVWnznMlihg
15 - Geração de Log
A geração de logs é muito importante para realizar a manutenção do sistema. Quando um evento inesperado ocorre, é necessário que uma informação referente a ele seja gerada. Isto é feito através da classe LogFactory, que fornece os métodos necessários para se gerar o log do evento.
O trecho de código abaixo reproduz a situação onde o valor de um campo denominado Versão é lido do e-form de um processo, através de um adapter, porém o nome do campo é passado de forma errada (Versão), gerando um erro no Fusion que será gravado no log.
//Criação do objeto log, utilizando o nome da classe atual
private static final Log log = LogFactory.getLog(NomeDaClasse.class);
public void start(Task origin, EntityWrapper wrapper, Activity activity)
{
try
{
 String versao = wrapper.findField(“Versao”).getValue();
}catch (Exception e)
{
log.error(“Erro ao ler o campo Versao no e-form!”,e);
}
}
16 – PersistentEnginee Helper (PEHelp)
       O ProcessEntityHelper, ou "pe", é uma classe denominada PEHelper e  é um poderoso recurso para buscar informações em tabelas para serem copiado em campos NeoObject sem a necessidade de criação de adapter.
Este recurso pode ser utilizado diretamente em uma copiadora de campo em um processo, cópia de valor para um campo do tipo e-form.
Exemplo: Para gravar o NeoPaper em um campo do tipo e-form "papel):
Utilizar no campo "De": $$pe.find("NeoUser", "code", "adm")
     	Também é possível utilizar em um adapter, já que o conteúdo recebido é o NeoObject.
	
	Exemplo:
...
import com.neomind.fusion.persist.PEHelper;
...
		PEHelper pe = new PEHelper();
		
		NeoObject tstFind = pe.find("NeoPaper", "code", "administrators");
		EntityWrapper myWrapper = new EntityWrapper(tstFind);
...
Métodos da classe PEHelp
find(...)
Efetua uma consulta simples no banco de dados , retornando apenas um resultado, utilizando como filtro apenas um campo.
Caso a consulta especificada retorne mais de um valor, apenas o primeiro é retornado e se nada for encontrado, null é retornado.
find(type, field, value)
· type: Nome do e-form a ser pesquisado (typeName)
· field: Campo a ser utilizado no filtro
· value: Valor ser procurado no campo especificado em field
Retorno: NeoObject do primeiro registro encontrado.
Exemplo: 
$$pe.find("NeoPaper", "code", "administrators")
querySingle(...)
Efetua uma consulta no banco de dados e retorna apenas um resultado.
Caso a consulta especificada retorne mais de um valor, apenas o primeiro é retornado e se nada for encontrado, null é retornado.
São diversas as sintaxes para utilizar este método:
querySingle(type)
· type: Nome do e-form a ser pesquisado (typeName)
Retorno: NeoObject do primeiro registro encontrado.
Exemplo: 
$$pe.querySingle("NeoPaper")
querySingle(type, returnField)
· type: Nome do e-form a ser pesquisado (typeName)
· returnField: Nome do campo que deseja receber o retorno.
Retorno: Object somente referente ao campo desejado.
Exemplo: 
$$pe. querySingle("NeoPaper",”code”)
querySingle(type, where, values)
· type: Nome do e-form a ser pesquisado (typeName)
· where: Campo a ser utilizado no filtro
· values: Lista de valores a serem procurados no campo especificado em field
Retorno: NeoObject do primeiro registro encontrado.
Exemplo: 
$$pe. querySingle("docItemOrcamento", "itemOrc.tipoOrcamento.codigo = 1’ and itemOrc.neoid in (?)", wrapper.findValues(“itemOrcServ.neoId”,0))querySingle(type, where, v1, v2 …, v5)
· type: Nome do e-form a ser pesquisado (typeName)
· where: Campo a ser utilizado no filtro
· v1 ... v5: Valor ser procurado no campo especificado em field. Podem ser passados de 1 à 5 valores únicos (não pode ser uma lista).
Retorno: NeoObject do primeiro registro encontrado.
Exemplos: 
1) $$pe.querySingle("NaturezaServFichaMed", "nro_senha = ?", wrapper.findValue("SolicitacaoInt.FichaMedicaInicial.FichaMedica.nro_senha"), ..., v5)
2) $$pe.querySingle("NeoPaper", "code = ?", (Object)new String("papel1"), ..., v5);
querySingle(type, returnField, where, values)
· type: Nome do e-form a ser pesquisado (typeName)
· returnField: Nome do campo que deseja receber o retorno.
· where: Campo a ser utilizado no filtro
· values: Lista de valores a serem procurados no campo especificado em field
Retorno: Object somente referente ao campo desejado.
Exemplo: 
$$pe. querySingle ("docIemOrcamento", “dataOrcamento”, "itemOrc.tipoOrcamento.codigo = 1’ and itemOrc.neoid in (?)", wrapper.findValues(“itemOrcServ.neoId”,0))
querySingle(type, returnField, where, v1, v2, …, v5)
· type: Nome do e-form a ser pesquisado (typeName)
· returnField: Nome do campo que deseja receber o retorno.
· where: Campo a ser utilizado no filtro
· v1 ... v5: Valor ser procurado no campo especificado em field. Podem ser passados de 1 à 5 valores únicos (não pode ser uma lista).
Retorno: NeoObject do primeiro registro encontrado.
Exemplos: 
1) $$pe.querySingle("NaturezaServFichaMed", "nro_senha = ?", wrapper.findValue("SolicitacaoInt.FichaMedicaInicial.FichaMedica.nro_senha"), ..., v5)
2) $$pe.querySingle("NeoPaper", "code = ?", (Object)new String("papel1"), ..., v5);
query(...) e query2(...)
Efetua uma consulta no banco de dados e retorna uma lista dos resultados encontrados.
Caso nada for encontrado, null é retornado.
query(type, where, v1, v2 …, v5)
· type: Nome do e-form a ser pesquisado (typeName)
· where: Campo a ser utilizado no filtro
· v1 ... v5: Valor ser procurado no campo especificado em field. Podem ser passados de 1 à 5 valores únicos (não pode ser uma lista).
Retorno: List<NeoObject> com todos os registros encontrados
Exemplos: 
1) $$pe.query("NaturezaServFichaMed", "nro_senha = ?", wrapper.findValue("SolicitacaoInt.FichaMedicaInicial.FichaMedica.nro_senha"), ..., v5)
2) $$pe.query("NeoPaper", "code = ?", (Object)new String("papel1"), ..., v5);
query2(type, where, values)
Efetua uma consulta no banco de dados e retorna uma lista dos resultados encontrados.
Caso nada for encontrado, null é retornado.
· type: Nome do e-form a ser pesquisado (typeName)
· where: Campo a ser utilizado no filtro
· values: Lista de valores a serem procurados no campo especificado em field
Retorno: List<NeoObject> com todos os registros encontrados
Exemplos: 
$$pe.query2("NaturezaServFichaMed", "nro_senha = ?", wrapper.findValues("SolicitacaoInt.FichaMedicaInicial.FichaMedica.nro_senha",0) 
17 - Atividade Envio - Customizando Modelo de E-mail
A comunicação é uma das áreas críticas dentro das organizações, mecanismos de notificação são extremamente úteis para que as metas sejam atingidas. No Fusion o envio de notificação por e-mail para as Atividades de Usuário é automático.
No entanto, quando se trata de uma Atividade de Envio é necessário configurar o envio. Ao selecionar a Atividade de Envio na caixa de atividades ela mudará de cor e as propriedades de configuração serão alteradas para o Tipo Envio.
Neste tipo de atividade a continuidade do fluxo não depende da execução da atividade para avançar. É utilizada como informativo para pessoas que não executam nenhuma tarefa no processo, mas precisam ser notificadas quando algum evento ou atividade acontece e também para notificar pessoas externas à organização, que não utilizam o Fusion.
No Painel de Propriedades o campo Enviar para participante: Indica se o e-mail vai ser enviado para o participante da Raia. Se “Sim” o e-mail de notificação será enviado para os participantes da raia (usuário/papel/grupo . Se o valor de Enviar para Participante for “Não” o campo Enviar para deve ser preenchido com um campo do tipo Usuário/Papel/Grupo, ou tipo Texto quando os destinatários não forem usuários do Fusion. Neste caso os e-mails dos destinatários devem ser separados por ponto e vírgula (;) e podem ser preenchidos em tempo de execução ou incluídos na Propriedade Valor Padrão do campo tipo Texto. Caso o e-mail deva ser enviado tanto para usuários do Fusion participantes da Raia e para pessoas que não utilizam o Fusion (parceiros de negócios). O valor do Campo Enviar para participante deve ser “sim” e o valor do campo Enviar para também deve ser preenchido.
Para que esta atividade funcione é necessário informar o Modelo do e-mail que será utilizado. Para isto, se faz necessário criar uma servlet java que renderizará o e-mail formatado. Através deste modelo poderemos informar no corpo do e-mail informações específicas da instância do processo. Por exemplo, o solicitante, data da solicitação ou qualquer campo que faça parte do formulário do processo, inclusive dados de formulários externos que sejam filhos do formulário do processo.
O nome do modelo deve ser informado juntamente com o caminho em que se encontra no servidor na pasta de instalação do Fusion. No caso de modelo de e-mail o arquivo modelo deverá ser salvo na pasta mail. As imagens usadas no corpo do e-mail devem ser salvas na pasta imagens na pasta de instalação do Fusion. No exemplo abaixo foi informado o seguinte valor no campo Modelo do E-mail: /mail/enviaEmailExemplo.jsp. Mais abaixo mostramos o código do arquivo enviaEmailExemplo.jsp.
	a) Exemplo de Modelagem Fluxo com Atividade de Envio de E-mail
No fluxo abaixo temos um exemplo simples do uso da Atividade de Envio. O fluxo inicia na tarefa “Solicitar Inclusão Novo Produto” solicitando a inclusão, em seguida é usado o componente de Decisão Paralela para dividir o fluxo notificando os participantes da Raia Notificados e ao mesmo tempo segue para aprovação. Na tarefa “Aprovar Inclusão” o gestor da área aprovará ou não a inclusão do novo produto, caso ele aprove, o fluxo seguirá para a tarefa “Incluir Produto” em seguida notificando os interessados. Caso o gestor não aprove, o fluxo seguirá para a atividade de notificação. Antes do final mais um componente de Decisão paralela é utilizado, neste caso para unir os dois fluxos novamente.
Na atividade “Notifica Solicitação” a propriedade Enviar para participantes está com o valor “Sim”, e neste caso a notificação será apenas para os usuários participantes da Raia
Na atividade “Notifica Status Final” o objetivo é notificar os participantes da Raia bem como, pessoas externas à organização, portando o campo Enviar para também está configurado, neste caso com um campo do tipo Texto cujo Valor Padrão é uma lista de e-mail separado por ponto e vírgula (;).
	b) Exemplo de Modelo de E-mail
O código abaixo exemplifica a criação do modelo de e-mail:
<%@page import="com.neomind.fusion.portal.PortalUtil"%>
<%@page import="com.neomind.fusion.common.NeoObject"%>	
<%@page import="com.neomind.fusion.persist.PersistEngine"%>
<%@ taglib uri="/WEB-INF/mail.tld" prefix="mail"%>
<%@ taglib uri="/WEB-INF/workflow.tld" prefix="wf"%>
<%@ taglib uri="/WEB-INF/portal.tld" prefix="portal"%>
<%@page import="java.util.*"%>
<%@page import="java.sql.Time"%>
<%@page import="com.neomind.util.NeoUtils"%>
<%@page import="com.neomind.fusion.entity.EntityWrapper"%>
<%@page import="com.neomind.fusion.workflow.Activity"%>
<%@page import="com.neomind.fusion.workflow.Task"%>
<%@page import="com.neomind.util.NeoCalendarUtils"%>
<%
NeoObject obj = (NeoObject)request.getAttribute("entity"); 
EntityWrapper wrapper = new EntityWrapper(obj);
String processo = (String) wrapper.findValue("wfprocess.model.name"); //NOME DO PROCESSO 
String codigo = (String)wrapper.findValue("wfprocess.code"); //CODIGO DO PROCESSO
String codigoProduto = NeoUtils.safeOutputString(wrapper.findValue("codigo"));//CODIGO DO PRODUTO String descricao = NeoUtils.safeOutputString(wrapper.findValue("descricao"));//DESCRIÇÃO 
String observacao = NeoUtils.safeOutputString(wrapper.findValue("observacao"));// OBSERVÇÃO GregorianCalendar dataSol = (GregorianCalendar) wrapper.findValue("dataSolicitacao");// PEGA A DATA NO FORMATO JAVA CALENDAR
String dataSolicitacaoTexto = NeoCalendarUtils.fullDateToString(dataSol);//CONVERTE DATA PARA STRING
String title= "Solicitação de Novo Produto" + " - " + codigo;
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<portal:baseURL url="getURLPath" />
<base href="<%= PortalUtil.getBaseURL() %>" />
</head>
<body bgcolor="#FFF1D2">
<p><mail:title title='<%=title %>' /></p>
<mail:img src="/imagens/cabecalho.jpg" width="768" height="124" />
<h3><u><%=codigo %> - <%=processo %></u></h3>
<p> <strong>Codigo Produto</strong> <%=codigoProduto%> </p>
<p> <strong>Descri&ccedil;&atilde;o do Produto :</strong> <%=descricao%></p>
<p> <strong>Observa&ccedil;&atilde;o:</strong> <%=observacao%> </p>
<p><strong>Data Solicita&ccedil;&atilde;o :</strong> <%=dataSolicitacaoTexto%></p>
<mail:img src="/imagens/rodape.jpg" width="768" height="145" />
</body>
</html>
Normalmente para criarmos um template de e-mail usamos os passos a seguir:
a) Importamos as classes necessárias
<%@page import="com.neomind.fusion.portal.PortalUtil"%>
<%@page import="com.neomind.fusion.common.NeoObject"%>
<%@page import="com.neomind.fusion.persist.PersistEngine"%>
<%@ taglib uri="/WEB-INF/mail.tld" prefix="mail"%>
<%@ taglib uri="/WEB-INF/workflow.tld" prefix="wf"%>
<%@ taglib uri="/WEB-INF/portal.tld" prefix="portal"%>
<%@page import="java.util.*"%>
<%@page import="java.sql.Time"%>
<%@page import="com.neomind.util.NeoUtils"%>
<%@page import="com.neomind.fusion.entity.EntityWrapper"%>
<%@page import="com.neomind.fusion.workflow.Activity"%>
<%@page import="com.neomind.fusion.workflow.Task"%>
<%@page import="com.neomind.util.NeoCalendarUtils"%>
	b) Usamos o método getAttribute do Objeto Request para pegarmos os dados vindos do processo, assim teremos acesso aos dados preenchidos na atividade do processo através do argumento “Entity” que representa o formulário principal do processo.
NeoObject obj = (NeoObject)request.getAttribute("Entity");
	c) Criamos um objeto wrapper para encapsular a entidade.
EntityWrapper wrapper = new EntityWrapper(obj);
	d) Atribuímos o valor dos campos provenientes do processo a variáveis locais realizando conversões de tipo quando necessário. Os valores passados para o método findValue do objeto wrapper são os nomes dos campos do formulário do processo.
String processo = (String) wrapper.findValue("wfprocess.model.name");//NOME DO PROCESSO String codigo = (String)wrapper.findValue("wfprocess.code"); //CODIGO PROCESSO
String codigoProduto = NeoUtils.safeOutputString(wrapper.findValue("codigo"));//CODIGO PRODUTO String descricao = NeoUtils.safeOutputString(wrapper.findValue("descricao"));// DESCRIÇÃO String observacao = NeoUtils.safeOutputString(wrapper.findValue("observacao"));// OBSERVÇÃO GregorianCalendar dataSol = (GregorianCalendar) wrapper.findValue("dataSolicitacao");// PEGA A DATA NO FORMATO JAVA CALENDAR
String dataSolicitacaoTexto = NeoCalendarUtils.fullDateToString(dataSol);//CONVERTE PARA STRING String title= "Solicitação de Novo Produto" + " - " + codigo;
	e) Formatamos o código HTML que será gerado pela Servlet, incluímos as variáveis locais dentro das tags jsp <% %> inseridas no código HTML para renderizar os valores dos campos do processo no corpo do e-mail.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<portal:baseURL url="getURLPath" />
<base href="<%= PortalUtil.getBaseURL() %>" />
</head>
<body bgcolor="#FFF1D2">
<p><mail:title title='<%=title %>' /></p>
<mail:img src="/imagens/cabecalho.jpg" width="768" height="124" />
<h3><u><%=codigo %> - <%=processo %></u></h3>
<p> <strong>Codigo Produto</strong> <%=codigoProduto%> </p>
<p> <strong>Descri&ccedil;&atilde;o do Produto :</strong> <%=descricao%></p>
<p> <strong>Observa&ccedil;&atilde;o:</strong> <%=observacao%> </p>
<p><strong>Data Solicita&ccedil;&atilde;o :</strong> <%=dataSolicitacaoTexto%></p>
<mail:img src="/imagens/rodape.jpg" width="768" height="145" />
</body>
</html>
A imagem abaixo ilustra como ficaria o e-mail padrão de acordo como o código acima:
	c) Exemplo de Modelo de E-mail com, botões e anexos
É possível criar e-mails com botões de aprovação e/ou reprovação diretamente no e-mail, e também com anexos. Esta forma é praticamente igual ao utilizar a opção padrão de notificação por e-mail. Porém, na forma padrão, não é possível anexar arquivos no e-mail.
Para que isso seja possível, deve-se seguir os seguintes procedimentos:
a) Criar uma classe java de nome CustomPendingTaskUtils.java conforme abaixo e em seguida, ajustar os botões desejados no método createCustomButtons e também, os campos que possuem os anexos nos métodos getHtmlDocumentList e getAttachedDoc:
package com.neomind.fusion.custom.adapters.testes;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import org.olap4j.impl.ArrayMap;
import com.neomind.fusion.common.NeoObject;
import com.neomind.fusion.doc.NeoFile;
import com.neomind.fusion.entity.EntityWrapper;
import com.neomind.fusion.persist.PersistEngine;
import com.neomind.fusion.persist.QLRawFilter;
import com.neomind.fusion.portal.PortalUtil;
import com.neomind.fusion.security.NeoGroup;
import com.neomind.fusion.security.NeoPaper;
import com.neomind.fusion.security.NeoUser;
import com.neomind.fusion.security.SecurityEntity;
import com.neomind.fusion.workflow.Activity;
import com.neomind.fusion.workflow.TaskInstanceHelper;
import com.neomind.fusion.workflow.model.EmailModelAction;
import com.neomind.fusion.workflow.model.EmailModelAction.Action;
public class CustomPendingTaskUtils
{
	public static Boolean typeOfAttach() 
	{
		//Retornar true para link no corpo do e-mail ou false para arquivos anexos
		return false;
		
	}
	
	public static List<EmailModelAction> createCustomButtons() 
	{
		List<EmailModelAction> actions = new ArrayList<EmailModelAction>();
		
		//Aprovar
		EmailModelAction emailModelActionAprove = new EmailModelAction();
		emailModelActionAprove.setName("Aprovar");
		emailModelActionAprove.setParameters("aprovador=true&motivoReprova=OK");
		emailModelActionAprove.setAction(Action.NEXT);
		actions.add(emailModelActionAprove);
		
		//Reprovar
		EmailModelAction emailModelActionReprove = new EmailModelAction();
		emailModelActionReprove.setName("Reprovar");
		emailModelActionReprove.setParameters("aprovador=false&motivoReprova=NOK");
		emailModelActionReprove.setAction(Action.NEXT);
		actions.add(emailModelActionReprove);
		
		return actions;
	}
	
	public static String getHtmlDocumentList(EntityWrapper wrapper)
	{
		String retorno = "";
		
		retorno += "<b><u>Clique nos documentos abaixo para download.</b></u><br>";
		
		//List<String> listaFieldsToAttach = new ArrayList<String>();
		ArrayMap<String, String> listaFieldsToAttach = new ArrayMap<String, String>();
		
		//Informar os campos de lista de anexos aqui
		listaFieldsToAttach.put("anexos","anexo");
		
		for (Entry<String, String> fieldToAttach : listaFieldsToAttach.entrySet())
		{
			List<NeoObject> listDocs = wrapper.findGenericValue(fieldToAttach.getKey());
			
			for (NeoObject objDoc : listDocs)
			{
				EntityWrapper wrapperDoc = new EntityWrapper(objDoc);
				
				String nomeArquivo = ((NeoFile) wrapperDoc.findGenericValue(fieldToAttach.getValue())).getName();
				
				System.out.println(nomeArquivo);
				
				NeoFile doc = (NeoFile) PersistEngine.getObject(NeoFile.class, new QLRawFilter(
						"name = '" + nomeArquivo +"'"));
					retorno += "<br><a href='" + PortalUtil.getBaseURL() + "file/download/" + doc.getNeoId() + "'>" + nomeArquivo + "</a>";	
			}
		}
		return retorno;
	}
	
	public static List getAttachedDoc(EntityWrapper wrapper)
	{
		List<String> finale = new ArrayList<String>();
		
		//List<String> listaFieldsToAttach = new ArrayList<String>();
		ArrayMap<String, String> listaFieldsToAttach = new ArrayMap<String, String>();
		
		//Informar os campos de lista de anexos aqui
		listaFieldsToAttach.put("anexos","anexo");
		
		for (Entry<String, String> fieldToAttach : listaFieldsToAttach.entrySet())
		{
			List<NeoObject> listDocs = wrapper.findGenericValue(fieldToAttach.getKey());
			
			for (NeoObject objDoc : listDocs)
			{
				EntityWrapper wrapperDoc = new EntityWrapper(objDoc);
				//File pdfFile = (new DocumentConverterHelper()).converterParaPdf(wrapperManuais.findGenericValue("file"));
				String nomeArquivo = ((NeoFile) wrapperDoc.findGenericValue(fieldToAttach.getValue())).getName();
				System.out.println(nomeArquivo);
				NeoFile doc = (NeoFile) PersistEngine.getObject(NeoFile.class, new QLRawFilter(
						"name = '" + nomeArquivo + "'"));
				if (doc != null)
					finale.add(String.valueOf((Long) doc.getNeoId()));
			}
		}
		return finale;
	}
	
	public static List<NeoUser> getUsersFromlane(Activity activity) //Pegar os usuários da raia 
	{
		Set<SecurityEntity> securityEntitySet = TaskInstanceHelper.findTaskInstance(activity).getPotentialOwners();
		
		List<NeoUser> users = new ArrayList<NeoUser>();
		for (SecurityEntity assigner : securityEntitySet)
		{
			if(assigner instanceof NeoPaper)
			{
				for(NeoUser p:((NeoPaper)assigner).getUsers())
				{
					System.out.println("Neopaper = " + p.getFullName());
					if(!users.contains(p))
						users.add(p);	
				}
			}else if(assigner instanceof NeoUser)
			{
				System.out.println("NeoUser = " + ((NeoUser) assigner).getFullName());
				if(!users.contains((NeoUser) assigner))
					users.add((NeoUser) assigner);
			}else if(assigner instanceof NeoGroup)
			{
				for(NeoUser n:((NeoGroup)assigner).getUsers())
				{
					System.out.println("Neogroup = " + n.getFullName());
					if(!users.contains(n))
						users.add(n);
				}
			}
		}
		return users;
	}
}
b) Criar uma outra classe java de nome AdapterCustomPendingTask.java
package com.neomind.fusion.custom.adapters.testes;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.neomind.fusion.entity.EntityWrapper;
import com.neomind.fusion.mail.MailEngine;
import com.neomind.fusion.security.NeoUser;
import com.neomind.fusion.workflow.Activity;
import com.neomind.fusion.workflow.Task;
import com.neomind.fusion.workflow.TaskInstanceHelper;
import com.neomind.fusion.workflow.event.ActivityEvent;
import com.neomind.fusion.workflow.event.ActivityStartEventListener;
import com.neomind.fusion.workflow.exception.ActivityException;
public class AdapterCustomPendingTask implements ActivityStartEventListener
{
	@Override
	public void onStart(ActivityEvent activityEvent) throws ActivityException {
		Activity activity = activityEvent.getActivity();
 
		Task task = TaskInstanceHelper.findTaskInstance(activity).getTask();
		EntityWrapper wrapper = activityEvent.getWrapper();
 	 	List anexos = CustomPendingTaskUtils.getAttachedDoc(wrapper);
 		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("title", "Mail customizado com botões");
		paramMap.put("texto", wrapper.findGenericValue("texto"));
		paramMap.put("attachList", anexos);
		paramMap.put("activity", activity);
		paramMap.put("task", task);			
		List<NeoUser> users = CustomPendingTaskUtils.getUsersFromlane(activity);		
		for(NeoUser user : users)
		{
			String email = user.getEmail();
			if(email != null && !email.isEmpty())
			{
				MailEngine.getInstance().sendEMail(email, "/mail/customPendingTask.jsp", paramMap);
			}
		}
	}
}
Criar o modelo de e-mail necessário para o envio, conforme abaixo:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
 pageEncoding="ISO-8859-1"%>
 
<%@page import="com.neomind.util.CustomFlags"%>
<%@page import="com.neomind.util.NeoUtils"%>
<%@page import="com.neomind.fusion.workflow.model.EmailModelAction.Action"%>
<%@page import="com.neomind.util.FormContentSimple"%>
<%@page import="com.neomind.fusion.entity.EntityInfo"%>
<%@page import="com.neomind.fusion.workflow.model.TaskFormModelSource"%>
<%@page import="com.neomind.fusion.workflow.model.EmailModelAction.Action"%>
<%@page import="com.neomind.fusion.workflow.model.EmailModelAction"%>
<%@page import="com.neomind.fusion.workflow.model.EmailModel"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@page import="java.util.GregorianCalendar"%>
<%@page import="com.neomind.fusion.portal.PortalUtil"%>
<%@page import="com.neomind.fusion.common.NeoObject"%>
<%@page import="com.neomind.fusion.entity.FieldInfoEntity"%>
<%@page import="com.neomind.fusion.i18n.I18nUtils"%>
<%@page import="java.util.Map.Entry"%>
<%@page import="java.util.Set"%>
<%@page import="java.util.HashMap"%>
<%@page import="java.util.SortedSet"%>
<%@page import="java.io.IOException"%>
<%@page import="java.io.Writer"%>
<%@page import="java.io.PrintStream"%>
<%@page import="com.neomind.fusion.entity.FieldInfo"%>
<%@page import="com.neomind.fusion.entity.form.FieldGroupPath"%>
<%@page import="com.neomind.fusion.entity.form.FieldGroupSum"%>
<%@page import="com.neomind.fusion.eform.EFormField"%>
<%@page import="com.neomind.fusion.eform.EForm"%>
<%@page import="com.neomind.fusion.entity.EntityWrapper"%>
<%@page import="com.neomind.fusion.entity.FieldPathInfo"%>
<%@page import="java.util.Collection"%>
<%@page import="com.neomind.fusion.entity.form.FieldGroup"%>
<%@page import="java.util.List"%>
<%@page import="com.neomind.fusion.entity.form.FormFieldGroup"%>
<%@page import="com.neomind.fusion.entity.form.FormModel"%>
<%@page import="com.neomind.fusion.persist.PersistEngine"%>
<%@page import="com.neomind.fusion.security.NeoUser"%>
<%@page import="com.neomind.fusion.workflow.WFProcess"%>
<%@page import="com.neomind.fusion.workflow.Task"%>
<%@page import="com.neomind.fusion.entity.FusionLink"%>
<%@page import="com.neomind.fusion.workflow.Activity"%>
<%@page import="java.util.Map"%>
<%@ taglib uri="/WEB-INF/mail.tld" prefix="mail"%>
<%@ taglib uri="/WEB-INF/portal.tld" prefix="portal"%>
<%@ taglib uri="/WEB-INF/workflow.tld" prefix="wf"%>
<%@page import="com.neomind.fusion.custom.adapters.testes.CustomPendingTaskUtils" %>
<%
	String title = (String) request.getAttribute("title");
	String texto = (String) request.getAttribute("texto");
	Activity activity = (Activity) request.getAttribute("activity");
	Task task = (Task) request.getAttribute("task");
	if(activity == null)
	{
		activity = task.getActivity();
	}
	
	//URL base do link, NÃO alterar
	String linkBase = "sbpm/";
	String neoIdBase = "";
	if(task != null)
	{
		neoIdBase = task.getNeoId() + "?";
	}	
	else 
	{
		neoIdBase = activity.getNeoId() + "?";
	}
	
	WFProcess process = activity.getProcess();
	
	//wrapper padrão, NÃO alterar
	EntityWrapper wrapper = new EntityWrapper(process.getEntity());
	
	Object oUser = request.getAttribute("user");
	NeoUser user = null;
	if (oUser instanceof NeoUser)
	{
		user = (NeoUser) oUser;
	}
	else if (oUser instanceof Long)
	{
		user = (NeoUser) PersistEngine.getObject(NeoUser.class, oUser);
	}
	else
	{
		user = task.getUser();
	}
	PortalUtil.setCurrentUser(user);
	
	SimpleDateFormat data = new SimpleDateFormat("dd/MM/yyyy - HH:mm:ss");
	String[] sData = data.format(process.getStartDate().getTime()).split("-");
%>
<jsp:include page="/mail/top.jsp" />
	<!-- mail:title equivale ao assunto do e-mail abaixo estao os links para as ações -->
	<mail:title
		title='<%= process.getCode()+" - " + I18nUtils.getString(activity.getName()) %>' />
	<p><%=I18nUtils.getString("helloUser",new Object[]{user.getFullName()})%>,</p>
	
	<wf:getActivityURL task="<%= activity %>" var="getURLTask" />
	<%
	String param0 = "<a href='" + getURLTask

Continue navegando