Ampliação da funcionalidade do fluxo de trabalho
- Aplica-se a:
- Experience Manager 6.5
- Tópicos:
- Desenvolvimento
Criado para:
- Desenvolvedor
Este tópico descreve como desenvolver componentes de etapa personalizados para seus workflows e, em seguida, como interagir programaticamente com workflows.
A criação de uma etapa de fluxo de trabalho personalizada envolve as seguintes atividades:
- Desenvolva o componente da etapa do fluxo de trabalho.
- Implemente a funcionalidade da etapa como um serviço OSGi ou um script ECMA.
Você também pode interagir com seus fluxos de trabalho a partir de seus programas e scripts.
Componentes da etapa do fluxo de trabalho - Noções básicas
Um componente da etapa do fluxo de trabalho define a aparência e o comportamento da etapa ao criar modelos de fluxo de trabalho:
- A categoria e o nome da etapa no sidekick do fluxo de trabalho.
- A aparência da etapa em modelos de fluxo de trabalho.
- A caixa de diálogo de edição para configurar propriedades do componente.
- O serviço ou script que é executado no tempo de execução.
Assim como em todos os componentes, os componentes da etapa do fluxo de trabalho herdam do componente especificado para a propriedade sling:resourceSuperType
. O diagrama a seguir mostra a hierarquia dos nós cq:component
que formam a base de todos os componentes da etapa do fluxo de trabalho. O diagrama também inclui os componentes da Etapa do processo, da Etapa de participante e da Etapa de participante dinâmica, pois esses são os pontos de partida mais comuns (e básicos) para o desenvolvimento de componentes de etapa personalizados.
/libs
./libs
é substituído na próxima vez que você atualizar sua instância (e pode ser substituído quando você aplicar um hotfix ou pacote de recursos).- Recrie o item necessário (isto é, como ele existe em
/libs
em/apps
- Fazer alterações em
/apps
O componente /libs/cq/workflow/components/model/step
é o ancestral comum mais próximo das Etapa de Processo, Etapa de Participante e Etapa de Participante Dinâmica, que herdam os seguintes itens:
-
step.jsp
O script
step.jsp
renderiza o título do componente da etapa quando ele é adicionado a um modelo. -
Uma caixa de diálogo com as seguintes guias:
- Comum: para editar o título e a descrição.
- Avançado: para editar propriedades de notificação por email.
NOTE
Quando as guias da caixa de diálogo de edição de um componente da etapa não corresponderem a essa aparência padrão, o componente da etapa terá scripts definidos, propriedades do nó ou guias de caixa de diálogo que substituem essas guias herdadas.
Scripts ECMA
Os seguintes objetos estão disponíveis (dependendo do tipo de etapa) nos scripts ECMA:
-
WorkflowSession workflowSession
-
DadosFluxoDeTrabalho DadosFluxoDeTrabalho
-
args
: matriz com os argumentos do processo. -
sling
: para acessar outros serviços osgi. -
jcrSession
MetaDataMaps
Você pode usar metadados de fluxo de trabalho para manter as informações necessárias durante a vida útil do fluxo de trabalho. Um requisito comum de etapas do fluxo de trabalho é criar dados persistentes para uso futuro no fluxo de trabalho ou recuperar os dados persistentes.
Há três tipos de objetos MetaDataMap - para objetos Workflow
, WorkflowData
e WorkItem
. Todos têm a mesma finalidade: armazenar metadados.
Um item de trabalho tem seu próprio MetaDataMap que só pode ser usado enquanto esse item de trabalho (por exemplo, etapa ) estiver em execução.
Os mapeamentos de metadados Workflow
e WorkflowData
são compartilhados em todo o fluxo de trabalho. Nesses casos, é recomendável usar apenas o mapa de metadados WorkflowData
.
Criação de componentes de etapa de fluxo de trabalho personalizados
Os componentes da etapa do fluxo de trabalho podem ser criados da mesma maneira que qualquer outro componente.
Para herdar de um dos componentes da etapa base (existentes), adicione a seguinte propriedade ao nó cq:Component
:
-
Nome:
sling:resourceSuperType
-
Tipo:
String
-
Valor: um dos seguintes caminhos que são resolvidos para um componente base:
cq/workflow/components/model/process
cq/workflow/components/model/participant
cq/workflow/components/model/dynamic_participant
Especificando o Título e a Descrição Default para Instâncias da Etapa
Use o procedimento a seguir para especificar valores padrão para os campos Título e Descrição na guia Comum.
-
A caixa de diálogo de edição da etapa armazena o título e a descrição nos seguintes locais: >
-
./jcr:title
-
./jcr:description
locaisEsse requisito é atendido quando a caixa de diálogo de edição usa a guia Comum que o componente
/libs/cq/flow/components/step/step
implementa. -
O componente de etapa ou um ancestral do componente não substitui o script
step.jsp
que o componente/libs/cq/flow/components/step/step
implementa.
-
Abaixo do nó
cq:Component
, adicione o seguinte nó:- Nome:
cq:editConfig
- Tipo:
cq:EditConfig
NOTE
Para obter mais informações sobre o nó cq:editConfig, consulte Configurando o Comportamento de Edição de um Componente. - Nome:
-
Abaixo do nó
cq:EditConfig
, adicione o seguinte nó:- Nome:
cq:formParameters
- Tipo:
nt:unstructured
- Nome:
-
Adicionar propriedades
String
dos seguintes nomes ao nócq:formParameters
:jcr:title
: O valor preenche o campo Título da guia Comum.jcr:description
: O valor preenche o campo Descrição da guia Comum.
Salvar valores de propriedade nos metadados de fluxo de trabalho
A propriedade name de cq:Widget
itens especifica o nó JCR que armazena o valor do widget. Quando os widgets na caixa de diálogo dos componentes da etapa do fluxo de trabalho armazenam valores abaixo do nó ./metaData
, o valor é adicionado ao fluxo de trabalho MetaDataMap
.
Por exemplo, um campo de texto em uma caixa de diálogo é um nó cq:Widget
que tem as seguintes propriedades:
xtype
String
textarea
name
String
./metaData/subject
fieldLabel
String
Email Subject
O valor especificado neste campo de texto é adicionado ao objeto [MetaDataMap](#metadatamaps)
da instância de fluxo de trabalho e está associado à chave subject
.
PROCESS_ARGS
, o valor está prontamente disponível nas implementações de script ECMA por meio da variável args
. Nesse caso, o valor da propriedade de nome é ./metaData/PROCESS_ARGS.
Substituição da implementação da etapa
Cada componente da etapa base permite que os desenvolvedores de modelo de fluxo de trabalho configurem os seguintes recursos principais em tempo de design:
- Etapa do Processo: O serviço ou script ECMA a ser executado no tempo de execução.
- Etapa do participante: a ID do usuário ao qual foi atribuído o item de trabalho gerado.
- Etapa dinâmica do participante: o serviço ou script ECMA que seleciona o ID do usuário atribuído ao item de trabalho.
Para focalizar o componente para uso em um cenário de fluxo de trabalho específico, configure o recurso principal no design e remova a capacidade dos desenvolvedores de modelo de alterá-lo.
-
Abaixo do nó cq:component, adicione o seguinte nó:
- Nome:
cq:editConfig
- Tipo:
cq:EditConfig
Para obter mais informações sobre o nó cq:editConfig, consulte Configurando o Comportamento de Edição de um Componente.
- Nome:
-
Abaixo do nó cq:EditConfig, adicione o seguinte nó:
- Nome:
cq:formParameters
- Tipo:
nt:unstructured
- Nome:
-
Adicione uma propriedade
String
ao nócq:formParameters
. O supertipo de componente determina o nome da propriedade:- Etapa do processo:
PROCESS
- Etapa do participante:
PARTICIPANT
- Etapa dinâmica do participante:
DYNAMIC_PARTICIPANT
- Etapa do processo:
-
Especifique o valor da propriedade:
PROCESS
: O caminho para o script ECMA ou o PID do serviço que implementa o comportamento da etapa.PARTICIPANT
: a identificação do usuário ao qual o item de trabalho foi atribuído.DYNAMIC_PARTICIPANT
: o caminho para o script ECMA ou o PID do serviço que seleciona o usuário para atribuir o item de trabalho.
-
Para remover a capacidade dos desenvolvedores de modelo de alterar os valores de propriedade, substitua a caixa de diálogo do supertipo de componente.
Adicionar Forms e caixas de diálogo às etapas do participante
Personalize o componente da etapa do participante para fornecer recursos encontrados nos componentes da Etapa de participante do formulário e da Etapa de participante da caixa de diálogo:
- Apresente um formulário ao usuário quando ele abrir o item de trabalho gerado.
- Apresentar uma caixa de diálogo personalizada ao usuário quando ele concluir o item de trabalho gerado.
Execute o seguinte procedimento no novo componente (consulte Criação de Componentes de Etapa de Fluxo de Trabalho Personalizado):
-
Abaixo do nó
cq:Component
, adicione o seguinte nó:- Nome:
cq:editConfig
- Tipo:
cq:EditConfig
Para obter mais informações sobre o nó cq:editConfig, consulte Configurando o Comportamento de Edição de um Componente.
- Nome:
-
Abaixo do nó cq:EditConfig, adicione o seguinte nó:
- Nome:
cq:formParameters
- Tipo:
nt:unstructured
- Nome:
-
Para apresentar um formulário quando o usuário abrir o item de trabalho, adicione a seguinte propriedade ao nó
cq:formParameters
:- Nome:
FORM_PATH
- Tipo:
String
- Valor: o caminho que é resolvido para o formulário
- Nome:
-
Para apresentar uma caixa de diálogo personalizada quando o usuário concluir o item de trabalho, adicione a seguinte propriedade ao nó
cq:formParameters
- Nome:
DIALOG_PATH
- Tipo:
String
- Valor: o caminho que é resolvido para a caixa de diálogo
- Nome:
Configurar o comportamento do tempo de execução da etapa do fluxo de trabalho
Abaixo do nó cq:Component
, adicione um nó cq:EditConfig
. Abaixo, adicione um nó nt:unstructured
(deve se chamar cq:formParameters
) e, a esse nó, adicione as seguintes propriedades:
-
Nome:
PROCESS_AUTO_ADVANCE
-
Tipo:
Boolean
-
Valor:
- quando definido como
true
, o fluxo de trabalho executará essa etapa e continuará. isso é padrão e também é recomendado - quando
false
, o fluxo de trabalho será executado e interrompido; isso requer manipulação extra; portanto,true
é recomendado
- quando definido como
-
-
Nome:
DO_NOTIFY
- Tipo:
Boolean
- Value: indica se as notificações por email devem ser enviadas para as etapas de participação do usuário (e presume que o servidor de email esteja configurado corretamente)
- Tipo:
Persistência e acesso a dados
Dados persistentes para etapas de fluxo de trabalho subsequentes
Você pode usar metadados de fluxo de trabalho para manter as informações necessárias durante a vida útil do fluxo de trabalho - e entre etapas. Um requisito comum de etapas do fluxo de trabalho é criar dados persistentes para uso futuro ou recuperar os dados persistentes de etapas anteriores.
Os metadados do fluxo de trabalho são armazenados em um objeto MetaDataMap
. A API Java fornece o método Workflow.getWorkflowData
para retornar um objeto WorkflowData
que forneça o objeto MetaDataMap
apropriado. Este objeto WorkflowData
MetaDataMap
está disponível para o serviço OSGi ou script ECMA de um componente de etapa.
Java
O método execute da implementação WorkflowProcess
recebeu o objeto WorkItem
. Use este objeto para obter o objeto WorkflowData
para a instância de fluxo de trabalho atual. O exemplo a seguir adiciona um item ao objeto de fluxo de trabalho MetaDataMap
e registra cada item. O item ("mykey", "My Step Value") está disponível para etapas subsequentes no workflow.
public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) throws WorkflowException {
MetaDataMap wfd = item.getWorkflow().getWorkflowData().getMetaDataMap();
wfd.put("mykey", "My Step Value");
Set<String> keyset = wfd.keySet();
Iterator<String> i = keyset.iterator();
while (i.hasNext()){
Object key = i.next();
log.info("The workflow medata includes key {} and value {}",key.toString(),wfd.get(key).toString());
}
}
Script ECMA
A variável graniteWorkItem
é a representação de script ECMA do objeto Java WorkItem
atual. Portanto, você pode usar a variável graniteWorkItem
para obter os metadados do fluxo de trabalho. O script ECMA a seguir pode ser usado para implementar uma Etapa do Processo para adicionar um item ao objeto de fluxo de trabalho MetaDataMap
e registrar cada item. Esses itens ficam disponíveis nas etapas subsequentes do fluxo de trabalho.
metaData
que está imediatamente disponível para o script de etapa são os metadados da etapa. Os metadados da etapa são diferentes dos metadados do fluxo de trabalho.var currentDateInMillis = new Date().getTime();
graniteWorkItem.getWorkflowData().getMetaDataMap().put("hardcodedKey","theKey");
graniteWorkItem.getWorkflowData().getMetaDataMap().put("currentDateInMillisKey",currentDateInMillis);
var iterator = graniteWorkItem.getWorkflowData().getMetaDataMap().keySet().iterator();
while (iterator.hasNext()){
var key = iterator.next();
log.info("Workflow metadata key, value = " + key.toString() + ", " + graniteWorkItem.getWorkflowData().getMetaDataMap().get(key));
}
Acessando Valores de Propriedade da Caixa de Diálogo no Tempo de Execução
O objeto MetaDataMap
de instâncias de fluxo de trabalho é útil para armazenar e recuperar dados durante toda a vida útil do fluxo de trabalho. Para implementações de componentes de etapa de fluxo de trabalho, o MetaDataMap
é especialmente útil para recuperar valores de propriedade de componente em tempo de execução.
O fluxo de trabalho MetaDataMap
está disponível para implementações de processo de script Java e ECMA:
-
Em implementações Java da interface WorkflowProcess, o parâmetro
args
é o objetoMetaDataMap
do fluxo de trabalho. -
Em implementações de script ECMA, o valor está disponível usando as variáveis
args
emetadata
.
Exemplo: Recuperação de Argumentos do Componente de Etapa do Processo
A caixa de diálogo de edição do componente Etapa do Processo inclui a propriedade Argumentos. O valor da propriedade Arguments é armazenado nos metadados do fluxo de trabalho e está associado à chave PROCESS_ARGS
.
No diagrama a seguir, o valor da propriedade Arguments é argument1, argument2
:
Java
O código Java a seguir é o método execute
para uma implementação WorkflowProcess
. O método registra o valor no args
MetaDataMap
que está associado à chave PROCESS_ARGS
.
public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) throws WorkflowException {
if (args.containsKey("PROCESS_ARGS")){
log.info("workflow metadata for key PROCESS_ARGS and value {}",args.get("PROCESS_ARGS","string").toString());
}
}
Quando uma etapa do processo que usa essa implementação Java é executada, o log contém a seguinte entrada:
16.02.2018 12:07:39.566 *INFO* [JobHandler: /var/workflow/instances/server0/2018-02-16/model_855140139900189:/content/we-retail/de] com.adobe.example.workflow.impl.process.LogArguments workflow metadata for key PROCESS_ARGS and value argument1, argument2
Script ECMA
O seguinte script ECMA é usado como o processo para a Etapa do processo. Ele registra o número de argumentos e os valores do argumento:
var iterator = graniteWorkItem.getWorkflowData().getMetaDataMap().keySet().iterator();
while (iterator.hasNext()){
var key = iterator.next();
log.info("Workflow metadata key, value = " + key.toString() + ", " + graniteWorkItem.getWorkflowData().getMetaDataMap().get(key));
}
log.info("hardcodedKey "+ graniteWorkItem.getWorkflowData().getMetaDataMap().get("hardcodedKey"));
log.info("currentDateInMillisKey "+ graniteWorkItem.getWorkflowData().getMetaDataMap().get("currentDateInMillisKey"));
Scripts e Argumentos do Processo
Em um script para um componente Etapa do processo, os argumentos estão disponíveis por meio do objeto args
.
Ao criar um componente de etapa personalizado, o objeto metaData
está disponível em um script. Esse objeto é limitado a um único argumento de string.
Desenvolvimento de implementações de etapas do processo
Quando as etapas do processo são iniciadas durante o processo de um workflow, as etapas enviam uma solicitação para um serviço OSGi ou executam um script ECMA. Desenvolva o serviço ou script ECMA que executa as ações exigidas pelo seu fluxo de trabalho.
Implementando uma etapa do processo com uma classe Java
Para definir uma etapa do processo como um componente de serviço OSGI (pacote Java):
-
Crie o pacote e implante-o no contêiner OSGI. Consulte a documentação sobre a criação de um pacote com CRXDE Lite ou Eclipse.
NOTE
O componente OSGI precisa implementar a interfaceWorkflowProcess
com seu métodoexecute()
. Consulte o código de exemplo abaixo.NOTE
O nome do pacote precisa ser adicionado à seção<*Private-Package*>
da configuraçãomaven-bundle-plugin
. -
Adicione a propriedade SCR
process.label
e defina o valor conforme necessário. Esse será o nome com o qual a etapa do processo será listada ao usar o componente genérico Etapa do processo. Veja o exemplo abaixo. -
No editor Modelos, adicione a etapa do processo ao fluxo de trabalho usando o componente genérico Etapa do processo.
-
Na caixa de diálogo de edição (da Etapa do processo), vá para a guia Processo e selecione a implementação do processo.
-
Se você usar argumentos em seu código, defina os Argumentos do processo. Por exemplo: falso.
-
Salve as alterações para a etapa e o modelo de fluxo de trabalho (canto superior esquerdo do editor de modelo).
Os métodos java, respectivamente, as classes que implementam o método Java executável são registrados como serviços OSGI, permitindo que você adicione métodos a qualquer momento durante o tempo de execução.
O seguinte componente OSGI adiciona a propriedade approved
ao nó de conteúdo da página quando a carga é uma página:
package com.adobe.example.workflow.impl.process;
import com.adobe.granite.workflow.WorkflowException;
import com.adobe.granite.workflow.WorkflowSession;
import com.adobe.granite.workflow.exec.WorkItem;
import com.adobe.granite.workflow.exec.WorkflowData;
import com.adobe.granite.workflow.exec.WorkflowProcess;
import com.adobe.granite.workflow.metadata.MetaDataMap;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.osgi.framework.Constants;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
/**
* Sample workflow process that sets an <code>approve</code> property to the payload based on the process argument value.
*/
@Component
@Service
public class MyProcess implements WorkflowProcess {
@Property(value = "An example workflow process implementation.")
static final String DESCRIPTION = Constants.SERVICE_DESCRIPTION;
@Property(value = "Adobe")
static final String VENDOR = Constants.SERVICE_VENDOR;
@Property(value = "My Sample Workflow Process")
static final String LABEL="process.label";
private static final String TYPE_JCR_PATH = "JCR_PATH";
public void execute(WorkItem item, WorkflowSession session, MetaDataMap args) throws WorkflowException {
WorkflowData workflowData = item.getWorkflowData();
if (workflowData.getPayloadType().equals(TYPE_JCR_PATH)) {
String path = workflowData.getPayload().toString() + "/jcr:content";
try {
Session jcrSession = session.adaptTo(Session.class);
Node node = (Node) jcrSession.getItem(path);
if (node != null) {
node.setProperty("approved", readArgument(args));
jcrSession.save();
}
} catch (RepositoryException e) {
throw new WorkflowException(e.getMessage(), e);
}
}
}
private boolean readArgument(MetaDataMap args) {
String argument = args.get("PROCESS_ARGS", "false");
return argument.equalsIgnoreCase("true");
}
}
Utilização do ECMAScript
Os scripts ECMA permitem que os desenvolvedores de script implementem etapas de processo. Os scripts estão no repositório JCR e são executados nele.
A tabela a seguir lista as variáveis que estão imediatamente disponíveis para processar scripts, fornecendo acesso aos objetos da API Java do workflow.
com.adobe.granite.workflow.exec.WorkItem
graniteWorkItem
com.adobe.granite.workflow.WorkflowSession
graniteWorkflowSession
String[]
(contém argumentos de processo)args
com.adobe.granite.workflow.metadata.MetaDataMap
metaData
org.apache.sling.scripting.core.impl.InternalScriptHelper
sling
O exemplo de script a seguir demonstra como acessar o nó JCR que representa a carga do fluxo de trabalho. A variável graniteWorkflowSession
é adaptada a uma variável de sessão JCR, que é usada para obter o nó do caminho da carga.
var workflowData = graniteWorkItem.getWorkflowData();
if (workflowData.getPayloadType() == "JCR_PATH") {
var path = workflowData.getPayload().toString();
var jcrsession = graniteWorkflowSession.adaptTo(Packages.javax.jcr.Session);
var node = jcrsession.getNode(path);
if (node.hasProperty("approved")){
node.setProperty("approved", args[0] == "true" ? true : false);
node.save();
}
}
O script a seguir verifica se a carga é uma imagem (arquivo .png
), cria uma imagem em preto-e-branco dela e a salva como um nó irmão.
var workflowData = graniteWorkItem.getWorkflowData();
if (workflowData.getPayloadType() == "JCR_PATH") {
var path = workflowData.getPayload().toString();
var jcrsession = graniteWorkflowSession.adaptTo(Packages.javax.jcr.Session);
var node = jcrsession.getRootNode().getNode(path.substring(1));
if (node.isNodeType("nt:file") && node.getProperty("jcr:content/jcr:mimeType").getString().indexOf("image/") == 0) {
var is = node.getProperty("jcr:content/jcr:data").getStream();
var layer = new Packages.com.day.image.Layer(is);
layer.grayscale();
var parent = node.getParent();
var gn = parent.addNode("grey" + node.getName(), "nt:file");
var content = gn.addNode("jcr:content", "nt:resource");
content.setProperty("jcr:mimeType","image/png");
var cal = Packages.java.util.Calendar.getInstance();
content.setProperty("jcr:lastModified",cal);
var f = Packages.java.io.File.createTempFile("test",".png");
var tout = new Packages.java.io.FileOutputStream(f);
layer.write("image/png", 1.0, tout);
var fis = new Packages.java.io.FileInputStream(f);
content.setProperty("jcr:data", fis);
parent.save();
tout.close();
fis.close();
is.close();
f.deleteOnExit();
}
}
Para usar o script:
-
Crie o script (por exemplo, com CRXDE Lite) e salve-o no repositório abaixo de
//apps/workflow/scripts/
-
Para especificar um título que identifique o script na caixa de diálogo de edição Etapa do processo, adicione as seguintes propriedades ao nó
jcr:content
do script:NomeTipoValorjcr:mixinTypes
Name[]
mix:title
jcr:title
String
O nome a ser exibido na caixa de diálogo de edição. -
Edite a instância Etapa do Processo e especifique o script a ser usado.
Desenvolvendo seletores de participantes
Você pode desenvolver seletores de participantes para componentes da Etapa dinâmica de participantes.
Quando um componente Etapa dinâmica de participante é iniciado durante um fluxo de trabalho, a etapa precisa determinar o participante ao qual o item de trabalho gerado pode ser atribuído. Para fazer isso, siga um destes procedimentos:
- envia uma solicitação a um serviço OSGi
- executa um script ECMA para selecionar o participante
Você pode desenvolver um serviço ou script ECMA que selecione o participante de acordo com os requisitos do seu fluxo de trabalho.
Desenvolvendo um seletor de participantes usando uma classe Java
Para definir uma etapa do participante como um componente de serviço OSGI (classe Java):
-
O componente OSGI precisa implementar a interface
ParticipantStepChooser
com seu métodogetParticipant()
. Consulte o código de exemplo abaixo.Crie o pacote e implante-o no contêiner OSGI.
-
Adicione a propriedade SCR
chooser.label
e defina o valor conforme necessário. Esse será o nome com que seu seletor de participantes será listado, usando o componente Etapa dinâmica de participante. Veja o exemplo:package com.adobe.example.workflow.impl.process; import com.adobe.granite.workflow.WorkflowException; import com.adobe.granite.workflow.WorkflowSession; import com.adobe.granite.workflow.exec.ParticipantStepChooser; import com.adobe.granite.workflow.exec.WorkItem; import com.adobe.granite.workflow.exec.WorkflowData; import com.adobe.granite.workflow.metadata.MetaDataMap; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Property; import org.apache.felix.scr.annotations.Service; import org.osgi.framework.Constants; /** * Sample dynamic participant step that determines the participant based on a path given as argument. */ @Component @Service public class MyDynamicParticipant implements ParticipantStepChooser { @Property(value = "An example implementation of a dynamic participant chooser.") static final String DESCRIPTION = Constants.SERVICE_DESCRIPTION; @Property(value = "Adobe") static final String VENDOR = Constants.SERVICE_VENDOR; @Property(value = "Dynamic Participant Chooser Process") static final String LABEL=ParticipantStepChooser.SERVICE_PROPERTY_LABEL; private static final String TYPE_JCR_PATH = "JCR_PATH"; public String getParticipant(WorkItem workItem, WorkflowSession workflowSession, MetaDataMap args) throws WorkflowException { WorkflowData workflowData = workItem.getWorkflowData(); if (workflowData.getPayloadType().equals(TYPE_JCR_PATH)) { String path = workflowData.getPayload().toString(); String pathFromArgument = args.get("PROCESS_ARGS", String.class); if (pathFromArgument != null && path.startsWith(pathFromArgument)) { return "admin"; } } return "administrators"; } }
-
No editor Modelos, adicione a etapa de participante dinâmico ao fluxo de trabalho usando o componente genérico Etapa de participante dinâmico.
-
Na caixa de diálogo de edição, selecione a guia Seletor de participantes e selecione a implementação do seletor.
-
Se você usar argumentos no código, defina os Argumentos do processo. Para este exemplo:
/content/we-retail/de
. -
Salve as alterações para a etapa e o modelo de fluxo de trabalho.
Desenvolvendo um seletor de participantes usando um script ECMA
Você pode criar um script ECMA que selecione o usuário atribuído ao item de trabalho gerado pela Etapa de participante. O script deve incluir uma função chamada getParticipant
que não requer argumentos e retorna um String
que contém a ID de um usuário ou grupo.
Os scripts estão no repositório JCR e são executados nele.
A tabela a seguir lista as variáveis que fornecem acesso imediato aos objetos Java do workflow nos scripts.
com.adobe.granite.workflow.exec.WorkItem
graniteWorkItem
com.adobe.granite.workflow.WorkflowSession
graniteWorkflowSession
String[]
(contém argumentos de processo)args
com.adobe.granite.workflow.metadata.MetaDataMap
metaData
org.apache.sling.scripting.core.impl.InternalScriptHelper
sling
function getParticipant() {
var workflowData = graniteWorkItem.getWorkflowData();
if (workflowData.getPayloadType() == "JCR_PATH") {
var path = workflowData.getPayload().toString();
if (path.indexOf("/content/we-retail/de") == 0) {
return "admin";
} else {
return "administrators";
}
}
}
-
Crie o script (por exemplo, com CRXDE Lite) e salve-o no repositório abaixo de
//apps/workflow/scripts
-
Para especificar um título que identifique o script na caixa de diálogo de edição Etapa do processo, adicione as seguintes propriedades ao nó
jcr:content
do script:NomeTipoValorjcr:mixinTypes
Name[]
mix:title
jcr:title
String
O nome a ser exibido na caixa de diálogo de edição. -
Edite a instância Etapa dinâmica de participante e especifique o script a ser usado.
Lidar com pacotes de fluxo de trabalho
Pacotes de fluxo de trabalho podem ser passados para um fluxo de trabalho para processamento. Os pacotes de fluxo de trabalho contêm referências a recursos como páginas e ativos.
Você pode desenvolver etapas de fluxo de trabalho que obtêm os recursos do pacote e os processam. Os seguintes membros do pacote com.day.cq.workflow.collection
fornecem acesso aos pacotes de fluxo de trabalho:
ResourceCollection
: classe do pacote de fluxo de trabalho.ResourceCollectionUtil
: use para recuperar objetos ResourceCollection.ResourceCollectionManager
: cria e recupera coleções. Uma implementação é implantada como um serviço OSGi.
O exemplo de classe Java a seguir demonstra como obter recursos de pacote:
package com.adobe.example;
import java.util.ArrayList;
import java.util.List;
import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.collection.ResourceCollection;
import com.day.cq.workflow.collection.ResourceCollectionManager;
import com.day.cq.workflow.collection.ResourceCollectionUtil;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.exec.WorkflowData;
import com.day.cq.workflow.exec.WorkflowProcess;
import com.day.cq.workflow.metadata.MetaDataMap;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Reference;
import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
@Component
@Service
public class LaunchBulkActivate implements WorkflowProcess {
private static final Logger log = LoggerFactory.getLogger(LaunchBulkActivate.class);
@Property(value="Bulk Activate for Launches")
static final String PROCESS_NAME ="process.label";
@Property(value="A sample workflow process step to support Launches bulk activation of pages")
static final String SERVICE_DESCRIPTION = Constants.SERVICE_DESCRIPTION;
@Reference
private ResourceCollectionManager rcManager;
public void execute(WorkItem workItem, WorkflowSession workflowSession) throws Exception {
Session session = workflowSession.getSession();
WorkflowData data = workItem.getWorkflowData();
String path = null;
String type = data.getPayloadType();
if (type.equals(TYPE_JCR_PATH) && data.getPayload() != null) {
String payloadData = (String) data.getPayload();
if (session.itemExists(payloadData)) {
path = payloadData;
}
} else if (data.getPayload() != null && type.equals(TYPE_JCR_UUID)) {
Node node = session.getNodeByUUID((String) data.getPayload());
path = node.getPath();
}
// CUSTOMIZED CODE IF REQUIRED....
if (path != null) {
// check for resource collection
ResourceCollection rcCollection = ResourceCollectionUtil.getResourceCollection((Node)session.getItem(path), rcManager);
// get list of paths to replicate (no resource collection: size == 1
// otherwise size >= 1
List<String> paths = getPaths(path, rcCollection);
for (String aPath: paths) {
// CUSTOMIZED CODE....
}
} else {
log.warn("Cannot process because path is null for this " + "workitem: " + workItem.toString());
}
}
/**
* helper
*/
private List<String> getPaths(String path, ResourceCollection rcCollection) {
List<String> paths = new ArrayList<String>();
if (rcCollection == null) {
paths.add(path);
} else {
log.debug("ResourceCollection detected " + rcCollection.getPath());
// this is a resource collection. the collection itself is not
// replicated. only its members
try {
List<Node> members = rcCollection.list(new String[]{"cq:Page", "dam:Asset"});
for (Node member: members) {
String mPath = member.getPath();
paths.add(mPath);
}
} catch(RepositoryException re) {
log.error("Cannot build path list out of the resource collection " + rcCollection.getPath());
}
}
return paths;
}
}
Exemplo: Criação de uma etapa personalizada
Uma maneira fácil de começar a criar sua própria etapa personalizada é copiar uma etapa existente do:
/libs/cq/workflow/components/model
Criação da etapa básica
-
Recrie o caminho em /apps; por exemplo:
/apps/cq/workflow/components/model
As novas pastas são do tipo
nt:folder
:- apps - cq - workflow (nt:folder) - components (nt:folder) - model (nt:folder)
NOTE
Esta etapa não se aplica ao editor de modelo de interface clássica. -
Em seguida, coloque a etapa copiada na pasta /apps; por exemplo, como:
/apps/cq/workflow/components/model/myCustomStep
Este é o resultado de nosso exemplo de etapa personalizada:
CAUTION
Como na interface do usuário padrão, somente o título e não os detalhes não são exibidos no cartão,details.jsp
não é necessário, pois era para o editor de interface do usuário clássico. -
Aplique as seguintes propriedades ao nó:
/apps/cq/workflow/components/model/myCustomStep
Propriedades de interesse:
-
sling:resourceSuperType
Deve herdar de uma etapa existente.
Neste exemplo, estamos herdando da etapa base em
cq/workflow/components/model/step
, mas você pode usar outros supertipos comoparticipant
,process
e assim por diante. -
jcr:title
É o título exibido quando o componente é listado no navegador de etapas (painel lateral esquerdo do editor de modelo de fluxo de trabalho).
-
cq:icon
Usado para especificar um ícone Coral para a etapa.
-
componentGroup
Deve ser um dos seguintes:
- Fluxo de trabalho de colaboração
- Fluxo de trabalho DAM
- Fluxo de trabalho dos formulários
- Projetos
- WCM fluxo de trabalho
- Fluxo de trabalho
-
-
Agora é possível abrir um modelo de fluxo de trabalho para edição. No navegador de etapas, você pode filtrar para ver Minha Etapa Personalizada:
Arrastar Minha etapa personalizada para o modelo exibe o cartão:
Se nenhum
cq:icon
tiver sido definido para a etapa, um ícone padrão será renderizado usando as duas primeiras letras do título. Por exemplo:
Definir a caixa de diálogo Configurar etapa
Depois de Criar a Etapa Básica, defina a caixa de diálogo Configurar da seguinte maneira:
-
Configure as propriedades no nó
cq:editConfig
da seguinte maneira:Propriedades de interesse:
-
cq:inherit
Quando definido como
true
, seu componente de etapa herdará propriedades da etapa especificada emsling:resourceSuperType
. -
cq:disableTargeting
Defina conforme necessário.
-
-
Configure as propriedades no nó
cq:formsParameter
da seguinte maneira:Propriedades de interesse:
-
jcr:title
Define o título padrão no cartão de etapas no mapa de modelos e no campo Título da caixa de diálogo de configuração Meu Personalizado - Propriedades da Etapa.
-
Você também pode definir suas próprias propriedades personalizadas.
-
-
Configure as propriedades no nó
cq:listeners
.O nó
cq:listener
e suas propriedades permitem definir manipuladores de eventos que reagem a eventos no editor de modelo de interface habilitada para toque; como arrastar uma etapa para uma página de modelo ou editar propriedades de uma etapa.Propriedades de interesse:
afterMove: REFRESH_PAGE
afterdelete: CQ.workflow.flow.Step.afterDelete
afteredit: CQ.workflow.flow.Step.afterEdit
afterinsert: CQ.workflow.flow.Step.afterInsert
Essa configuração é essencial para o funcionamento adequado do editor. Na maioria dos casos, essa configuração não deve ser alterada.
No entanto, definir
cq:inherit
como verdadeiro (no nócq:editConfig
, veja acima) permite que você herde essa configuração, sem precisar incluí-la explicitamente na definição da etapa. Se nenhuma herança estiver em vigor, será necessário adicionar esse nó com as seguintes propriedades e valores.Neste exemplo, a herança foi ativada para que pudéssemos remover o nó
cq:listeners
e a etapa ainda funcionará corretamente. -
Agora é possível adicionar uma instância da etapa a um modelo de fluxo de trabalho. Quando você Configurar a etapa, verá a caixa de diálogo:
Exemplo de marcação usada neste exemplo
A marcação para uma etapa personalizada será representada no .content.xml
do nó raiz do componente. A amostra .content.xml
usada para este exemplo:
/apps/cq/workflow/components/model/myCustomStep/.content.xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="https://sling.apache.org/jcr/sling/1.0" xmlns:cq="https://www.day.com/jcr/cq/1.0" xmlns:jcr="https://www.jcp.org/jcr/1.0"
cq:icon="bell"
jcr:primaryType="cq:Component"
jcr:title="My Custom Step"
sling:resourceSuperType="cq/workflow/components/model/process"
allowedParents="[*/parsys]"
componentGroup="Workflow"/>
A amostra _cq_editConfig.xml
usada neste exemplo:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="https://www.day.com/jcr/cq/1.0" xmlns:jcr="https://www.jcp.org/jcr/1.0" xmlns:nt="https://www.jcp.org/jcr/nt/1.0"
cq:disableTargeting="{Boolean}true"
cq:inherit="{Boolean}true"
jcr:primaryType="cq:EditConfig">
<cq:formParameters
jcr:primaryType="nt:unstructured"
jcr:title="My Custom Step Card"
SAMPLE_PROPERY="sample value"/>
<cq:listeners
jcr:primaryType="cq:EditListenersConfig"
afterdelete="CQ.workflow.flow.Step.afterDelete"
afteredit="CQ.workflow.flow.Step.afterEdit"
afterinsert="CQ.workflow.flow.Step.afterInsert"
afterMove="REFRESH_PAGE"/>
</jcr:root>
A amostra _cq_dialog/.content.xml
usada neste exemplo:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="https://sling.apache.org/jcr/sling/1.0" xmlns:cq="https://www.day.com/jcr/cq/1.0" xmlns:jcr="https://www.jcp.org/jcr/1.0" xmlns:nt="https://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="My Custom - Step Properties"
sling:resourceType="cq/gui/components/authoring/dialog">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/tabs">
<items jcr:primaryType="nt:unstructured">
<common
cq:hideOnEdit="true"
jcr:primaryType="nt:unstructured"
jcr:title="Common"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"/>
<process
cq:hideOnEdit="true"
jcr:primaryType="nt:unstructured"
jcr:title="Process"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"/>
<mycommon
jcr:primaryType="nt:unstructured"
jcr:title="Common"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
<items jcr:primaryType="nt:unstructured">
<columns
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<title
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Title"
name="./jcr:title"/>
<description
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
fieldLabel="Description"
name="./jcr:description"/>
</items>
</columns>
</items>
</mycommon>
<advanced
jcr:primaryType="nt:unstructured"
jcr:title="Advanced"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
<items jcr:primaryType="nt:unstructured">
<columns
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<email
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/checkbox"
fieldDescription="Notify user via email."
fieldLabel="Email"
name="./metaData/PROCESS_AUTO_ADVANCE"
text="Notify user via email."
value="true"/>
</items>
</columns>
</items>
</advanced>
</items>
</content>
</jcr:root>
sling:resourceSuperType : cq/workflow/components/model/process
-
Nos casos em que uma caixa de diálogo atualizada está vazia, você pode ver caixas de diálogo no
/libs
que tenham funcionalidade semelhante a exemplos de como fornecer uma solução. Por exemplo: -
/libs/cq/workflow/components/model
-
/libs/cq/workflow/components/workflow
-
/libs/dam/components
-
/libs/wcm/workflow/components/autoassign
-
/libs/cq/projects
Não edite nada em
/libs
, apenas use-os como exemplos. Se quiser usar qualquer uma das etapas existentes, copie-as para/apps
e edite-as lá.