Questo argomento descrive come sviluppare componenti di passaggi personalizzati per i flussi di lavoro e come interagire in modo programmatico con i flussi di lavoro.
La creazione di un passaggio di flusso di lavoro personalizzato prevede le seguenti attività:
È inoltre possibile interagire con i flussi di lavoro dai programmi e dagli script.
Un componente passaggio del flusso di lavoro definisce l’aspetto e il comportamento del passaggio durante la creazione di modelli di flusso di lavoro:
Come con tutti i componenti, i componenti dei passaggi del flusso di lavoro ereditano dal componente specificato per la proprietà sling:resourceSuperType
. Il diagramma seguente mostra la gerarchia dei nodi cq:component
che costituiscono la base di tutti i componenti dei passaggi del flusso di lavoro. Il diagramma include anche i componenti Process Step, Participant Step e Dynamic Participant Step, in quanto rappresentano i punti di partenza più comuni (e di base) per lo sviluppo di componenti a passo personalizzato.
Non è necessario modificare nulla nel percorso /libs
.
Questo perché il contenuto di /libs
viene sovrascritto la prossima volta che aggiorni l’istanza (e potrebbe essere sovrascritto quando applichi un hotfix o un pacchetto di funzioni).
Il metodo consigliato per la configurazione e altre modifiche è:
/libs
in /apps
/apps
Il componente /libs/cq/workflow/components/model/step
è l'antenato comune più vicino di Process Step, Participant Step e Dynamic Participant Step, che ereditano tutti i seguenti elementi:
step.jsp
Lo script step.jsp
esegue il rendering del titolo del componente passo quando viene aggiunto a un modello.
Una finestra di dialogo con le seguenti schede:
Quando le schede della finestra di dialogo di modifica di un componente passo non corrispondono a questo aspetto predefinito, il componente passo dispone di script definiti, proprietà del nodo o schede di dialogo che ignorano queste schede ereditate.
I seguenti oggetti sono disponibili (a seconda del tipo di passaggio) negli script ECMA:
🔗 WorkItemItem
🔗 WorkflowSessionworkflowSession
🔗 WorkflowDataworkflowData
args
: con gli argomenti del processo.
sling
: per accedere ad altri servizi osgi.
jcrSession
Puoi utilizzare i metadati del flusso di lavoro per mantenere le informazioni richieste durante l’intero ciclo di vita del flusso di lavoro. Un requisito comune dei passaggi del flusso di lavoro consiste nel mantenere i dati per un utilizzo futuro nel flusso di lavoro o nel recuperare i dati persistenti.
Esistono tre tipi di oggetti MetaDataMap : per gli oggetti Workflow
, WorkflowData
e WorkItem
. Hanno tutti lo stesso scopo: memorizzare i metadati.
Un oggetto WorkItem ha una propria MetaDataMap che può essere utilizzata solo durante l'esecuzione dell'elemento di lavoro (ad esempio, step).
I metadati Workflow
e WorkflowData
vengono condivisi nell’intero flusso di lavoro. Per questi casi si consiglia di utilizzare solo la mappa dei metadati WorkflowData
.
I componenti dei passaggi del flusso di lavoro possono essere creati nello stesso modo di qualsiasi altro componente.
Per ereditare da uno dei componenti del passaggio base (esistenti), aggiungi la seguente proprietà al nodo cq:Component
:
Nome: sling:resourceSuperType
Tipo: String
Valore: Uno dei percorsi seguenti che viene risolto in un componente di base:
cq/workflow/components/model/process
cq/workflow/components/model/participant
cq/workflow/components/model/dynamic_participant
Segui la procedura seguente per specificare i valori predefiniti per i campi Titolo e Descrizione nella scheda Comune .
I valori dei campi vengono visualizzati nell'istanza del passaggio quando sono soddisfatti entrambi i seguenti requisiti:
La finestra di dialogo di modifica del passaggio memorizza il titolo e la descrizione nelle seguenti posizioni: >
./jcr:title
./jcr:description
posizioni
Questo requisito è soddisfatto quando la finestra di dialogo di modifica utilizza la scheda Comune implementata dal componente /libs/cq/flow/components/step/step
.
Il componente step o un predecessore del componente non sovrascrive lo script step.jsp
implementato dal componente /libs/cq/flow/components/step/step
.
Sotto il nodo cq:Component
, aggiungi il seguente nodo:
cq:editConfig
cq:EditConfig
Per ulteriori informazioni sul nodo cq:editConfig, vedere Configurazione del comportamento di modifica di un componente.
Sotto il nodo cq:EditConfig
, aggiungi il seguente nodo:
cq:formParameters
nt:unstructured
Aggiungi le proprietà String
dei seguenti nomi al nodo cq:formParameters
:
jcr:title
: Il valore riempie il campo Titlefield della scheda Commontab.jcr:description
: Il valore riempie il campo Descrizione della scheda Commontab.Vedere Persistenza e accesso ai dati. In particolare, per informazioni sull'accesso al valore della proprietà in fase di runtime, vedere Accesso ai valori delle proprietà della finestra di dialogo in fase di esecuzione.
La proprietà name di cq:Widget
items specifica il nodo JCR che memorizza il valore del widget. Quando i widget nella finestra di dialogo dei componenti delle fasi del flusso di lavoro memorizzano i valori sotto il nodo ./metaData
, il valore viene aggiunto al flusso di lavoro MetaDataMap
.
Ad esempio, un campo di testo in una finestra di dialogo è un nodo cq:Widget
con le seguenti proprietà:
Nome | Tipo | Valore |
---|---|---|
xtype |
String |
textarea |
name |
String |
./metaData/subject |
fieldLabel |
String |
Email Subject |
Il valore specificato in questo campo di testo viene aggiunto all'oggetto [MetaDataMap](#metadatamaps)
dell'istanza del flusso di lavoro ed è associato alla chiave subject
.
Quando la chiave è PROCESS_ARGS
, il valore è prontamente disponibile nelle implementazioni di script ECMA tramite la variabile args
. In questo caso, il valore della proprietà name è ./metaData/PROCESS_ARGS.
Ciascun componente passo base consente agli sviluppatori di modelli di flusso di lavoro di configurare le seguenti funzionalità chiave in fase di progettazione:
Per attivare il componente da utilizzare in uno scenario di flusso di lavoro specifico, configura la funzione chiave nella progettazione e rimuovere la possibilità per gli sviluppatori di modelli di modificarla.
Sotto il nodo cq:component, aggiungi il seguente nodo:
cq:editConfig
cq:EditConfig
Per ulteriori informazioni sul nodo cq:editConfig, vedere Configurazione del comportamento di modifica di un componente.
Sotto il nodo cq:EditConfig, aggiungi il seguente nodo:
cq:formParameters
nt:unstructured
Aggiungi una proprietà String
al nodo cq:formParameters
. Il nome della proprietà è determinato dal super tipo di componente:
PROCESS
PARTICIPANT
DYNAMIC_PARTICIPANT
Specifica il valore della proprietà:
PROCESS
: Il percorso dello script ECMA o del PID del servizio che implementa il comportamento del passaggio.PARTICIPANT
: ID dell'utente a cui è stato assegnato l'elemento di lavoro.DYNAMIC_PARTICIPANT
: Percorso dello script ECMA o del PID del servizio che seleziona l'utente per assegnare l'elemento di lavoro.Per rimuovere la possibilità per gli sviluppatori di modelli di modificare i valori delle proprietà, sovrascrivi la finestra di dialogo del super tipo di componente.
Personalizza il componente del passaggio partecipante per fornire le funzioni disponibili nei componenti Passaggio partecipante modulo e Passaggio partecipante finestra di dialogo :
Esegui la seguente procedura sul nuovo componente (consulta Creazione di componenti del passaggio del flusso di lavoro personalizzati):
Sotto il nodo cq:Component
, aggiungi il seguente nodo:
cq:editConfig
cq:EditConfig
Per ulteriori informazioni sul nodo cq:editConfig, vedere Configurazione del comportamento di modifica di un componente.
Sotto il nodo cq:EditConfig, aggiungi il seguente nodo:
cq:formParameters
nt:unstructured
Per presentare un modulo quando l’utente apre l’elemento di lavoro, aggiungi la seguente proprietà al nodo cq:formParameters
:
FORM_PATH
String
Per presentare una finestra di dialogo personalizzata quando l'utente completa l'elemento di lavoro, aggiungi la seguente proprietà al nodo cq:formParameters
DIALOG_PATH
String
Sotto il nodo cq:Component
, aggiungi un nodo cq:EditConfig
. Sotto che aggiungi un nodo nt:unstructured
(deve essere denominato cq:formParameters
) e a quel nodo aggiungi le seguenti proprietà:
Nome: PROCESS_AUTO_ADVANCE
Tipo: Boolean
Valore:
true
il flusso di lavoro eseguirà quel passaggio e continuerà, impostazione predefinita e consigliatafalse
, il flusso di lavoro viene eseguito e interrotto; questo richiede una maggiore movimentazione, pertanto true
è consigliatoNome: DO_NOTIFY
Boolean
Puoi utilizzare i metadati del flusso di lavoro per mantenere le informazioni richieste durante la durata del flusso di lavoro, e tra i passaggi. Un requisito comune dei passaggi del flusso di lavoro è quello di persistere dei dati per utilizzi futuri o di recuperare i dati persistenti dai passaggi precedenti.
I metadati del flusso di lavoro vengono memorizzati in un oggetto MetaDataMap
. L'API Java fornisce il metodo Workflow.getWorkflowData
per restituire un oggetto WorkflowData
che fornisce l'oggetto MetaDataMap
appropriato. Questo oggetto WorkflowData
MetaDataMap
è disponibile per il servizio OSGi o per lo script ECMA di un componente step.
Il metodo execute dell'implementazione WorkflowProcess
viene passato all'oggetto WorkItem
. Utilizzare questo oggetto per ottenere l'oggetto WorkflowData
per l'istanza di flusso di lavoro corrente. Nell'esempio seguente viene aggiunto un elemento all'oggetto del flusso di lavoro MetaDataMap
e quindi ogni elemento viene registrato. L’elemento ("mykey", "My Step Value") è disponibile per i passaggi successivi nel flusso di lavoro.
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());
}
}
La variabile graniteWorkItem
è la rappresentazione script ECMA dell'oggetto Java corrente WorkItem
. Pertanto, puoi utilizzare la variabile graniteWorkItem
per ottenere i metadati del flusso di lavoro. Il seguente script ECMA può essere utilizzato per implementare un Passaggio processo per aggiungere un elemento all'oggetto flusso di lavoro MetaDataMap
e quindi registrare ogni elemento. Questi elementi sono quindi disponibili per i passaggi successivi nel flusso di lavoro.
La variabile metaData
immediatamente disponibile per lo script di passaggio è costituita dai metadati del passaggio. I metadati del passaggio sono diversi dai metadati del flusso di lavoro.
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));
}
L’oggetto MetaDataMap
delle istanze del flusso di lavoro è utile per memorizzare e recuperare i dati per tutta la durata del flusso di lavoro. Per le implementazioni dei componenti delle fasi del flusso di lavoro, la funzione MetaDataMap
è particolarmente utile per recuperare i valori delle proprietà dei componenti in fase di esecuzione.
Per informazioni sulla configurazione della finestra di dialogo dei componenti per memorizzare le proprietà come metadati del flusso di lavoro, consulta Salvataggio dei valori delle proprietà nei metadati del flusso di lavoro.
Il flusso di lavoro MetaDataMap
è disponibile per le implementazioni di processi script Java ed ECMA:
Nelle implementazioni Java dell'interfaccia WorkflowProcess, il parametro args
è l'oggetto MetaDataMap
per il flusso di lavoro.
Nelle implementazioni di script ECMA, il valore è disponibile utilizzando le variabili args
e metadata
.
La finestra di dialogo di modifica del componente Passaggio processo include la proprietà Argomenti . Il valore della proprietà Arguments viene memorizzato nei metadati del flusso di lavoro ed è associato alla chiave PROCESS_ARGS
.
Nel diagramma seguente, il valore della proprietà Arguments è argument1, argument2
:
Il seguente codice Java è il metodo execute
per un'implementazione WorkflowProcess
. Il metodo registra il valore in args
MetaDataMap
associato alla chiave 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 viene eseguito un passaggio del processo che utilizza questa implementazione Java, il registro contiene la seguente voce:
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
Il seguente script ECMA viene utilizzato come processo per il passaggio del processo. Registra il numero di argomenti e i valori degli argomenti:
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"));
Questa sezione descrive come utilizzare gli argomenti relativi ai passaggi del processo. Le informazioni si applicano anche ai selettori dei partecipanti dinamici.
Per un altro esempio di memorizzazione delle proprietà dei componenti nei metadati del flusso di lavoro, vedi Esempio: Crea un passaggio del flusso di lavoro del logger. Questo esempio presenta una finestra di dialogo che associa il valore dei metadati a una chiave diversa da PROCESS_ARGS.
All'interno di uno script per un componente Passaggio processo, gli argomenti sono disponibili tramite l'oggetto args
.
Quando si crea un componente passaggio personalizzato, l’oggetto metaData
è disponibile in uno script. Questo oggetto è limitato a un singolo argomento stringa.
Quando i passaggi del processo vengono avviati durante il processo di un flusso di lavoro, i passaggi inviano una richiesta a un servizio OSGi o eseguono uno script ECMA. Sviluppa il servizio o lo script ECMA che esegue le azioni necessarie per il flusso di lavoro.
Per informazioni sull'associazione del componente del passaggio del processo al servizio o allo script, vedere Passaggio del processo o Sovrascrittura dell'implementazione del passaggio.
Per definire un passaggio del processo come componente del servizio OSGI (bundle Java):
Crea il bundle e distribuiscilo nel contenitore OSGI. Consulta la documentazione sulla creazione di un bundle con CRXDE Lite o Eclipse.
Il componente OSGI deve implementare l'interfaccia WorkflowProcess
con il suo metodo execute()
. Vedi il codice di esempio seguente.
Il nome del pacchetto deve essere aggiunto alla sezione <*Private-Package*>
della configurazione maven-bundle-plugin
.
Aggiungi la proprietà SCR process.label
e imposta il valore come richiesto. Questo sarà il nome in cui il passaggio del processo viene elencato quando si utilizza il componente generico Passo processo. Vedi l'esempio seguente.
Nell'editor Modelli, aggiungi il passaggio del processo al flusso di lavoro utilizzando il componente generico Process Step.
Nella finestra di dialogo di modifica (del Passaggio processo), vai alla scheda Processo e seleziona la tua implementazione del processo.
Se utilizzi gli argomenti nel codice, imposta Argomenti processo. Ad esempio: false.
Salva le modifiche, sia per il passaggio che per il modello di flusso di lavoro (nell’angolo in alto a sinistra dell’editor modelli).
I metodi java, rispettivamente le classi che implementano il metodo Java eseguibile, sono registrati come servizi OSGI, consentendo di aggiungere metodi in qualsiasi momento durante il runtime.
Il seguente componente OSGI aggiunge la proprietà approved
al nodo del contenuto della pagina quando il payload è una pagina:
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");
}
}
Se il processo ha esito negativo tre volte di fila, viene inserito un elemento nella casella in entrata dell’amministratore del flusso di lavoro.
Gli script ECMA consentono agli sviluppatori di script di implementare i passaggi del processo. Gli script si trovano nell’archivio JCR ed vengono eseguiti da lì.
Nella tabella seguente sono elencate le variabili immediatamente disponibili per l’elaborazione degli script, che forniscono accesso agli oggetti dell’API Java del flusso di lavoro.
Classe Java | Nome variabile script | Descrizione |
---|---|---|
com.adobe.granite.workflow.exec.WorkItem |
graniteWorkItem |
L'istanza del passaggio corrente. |
com.adobe.granite.workflow.WorkflowSession |
graniteWorkflowSession |
La sessione del flusso di lavoro dell’istanza del passaggio corrente. |
String[] (contiene argomenti di processo) |
args |
Argomenti del passaggio. |
com.adobe.granite.workflow.metadata.MetaDataMap |
metaData |
I metadati dell'istanza del passaggio corrente. |
org.apache.sling.scripting.core.impl.InternalScriptHelper |
sling |
Fornisce l'accesso all'ambiente di runtime Sling. |
Lo script di esempio seguente illustra come accedere al nodo JCR che rappresenta il payload del flusso di lavoro. La variabile graniteWorkflowSession
è adattata a una variabile di sessione JCR, che viene utilizzata per ottenere il nodo dal percorso di payload.
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();
}
}
Lo script seguente controlla se il payload è un'immagine ( .png
file), ne crea un'immagine in bianco e nero e la salva come nodo di pari livello.
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();
}
}
Per utilizzare lo script:
Crea lo script (ad esempio con CRXDE Lite) e salvalo nell’archivio sottostante /apps/myapp/workflow/scripts
Per specificare un titolo che identifichi lo script nella finestra di dialogo di modifica Passaggio processo , aggiungi le seguenti proprietà al nodo jcr:content
dello script:
Nome | Tipo | Valore |
---|---|---|
jcr:mixinTypes |
Name[] |
mix:title |
jcr:title |
String |
Nome da visualizzare nella finestra di dialogo di modifica. |
Modifica l'istanza Process Step e specifica lo script da utilizzare.
È possibile sviluppare i selettori dei partecipanti per i componenti Passaggio partecipante dinamico.
Quando un componente Passaggio partecipante dinamico viene avviato durante un flusso di lavoro, il passaggio deve determinare il partecipante a cui può essere assegnato l’elemento di lavoro generato. Per eseguire questa operazione, effettua una delle seguenti operazioni:
È possibile sviluppare un servizio o uno script ECMA che selezioni il partecipante in base ai requisiti del flusso di lavoro.
Per informazioni sull'associazione del componente Passaggio partecipante dinamico al servizio o allo script, consulta Passaggio partecipante dinamico o Sovrascrittura dell'implementazione del passaggio.
Per definire un passaggio partecipante come componente del servizio OSGI (classe Java):
Il componente OSGI deve implementare l'interfaccia ParticipantStepChooser
con il suo metodo getParticipant()
. Vedi il codice di esempio seguente.
Crea il bundle e distribuiscilo nel contenitore OSGI.
Aggiungi la proprietà SCR chooser.label
e imposta il valore come richiesto. Sarà il nome in cui è elencato il selettore dei partecipanti, utilizzando il componente Passaggio partecipante dinamico. Vedi l'esempio:
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";
}
}
Nell’editor Modelli , aggiungi il passaggio del partecipante dinamico al flusso di lavoro utilizzando il componente generico Passaggio partecipante dinamico .
Nella finestra di dialogo di modifica, seleziona la scheda Selezione partecipanti e seleziona l’implementazione del selettore.
Se utilizzi gli argomenti nel codice, imposta Argomenti processo. Per questo esempio: /content/we-retail/de
.
Salva le modifiche, sia per il passaggio che per il modello di flusso di lavoro.
È possibile creare uno script ECMA che seleziona l'utente a cui è assegnato l'elemento di lavoro generato da Participant Step. Lo script deve includere una funzione denominata getParticipant
che non richiede argomenti e restituisce un String
che contiene l'ID di un utente o di un gruppo.
Gli script si trovano nell’archivio JCR ed vengono eseguiti da tale archivio.
Nella tabella seguente sono elencate le variabili che forniscono accesso immediato agli oggetti Java del flusso di lavoro negli script.
Classe Java | Nome variabile script |
---|---|
com.adobe.granite.workflow.exec.WorkItem |
graniteWorkItem |
com.adobe.granite.workflow.WorkflowSession |
graniteWorkflowSession |
String[] (contiene argomenti di 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";
}
}
}
Crea lo script (ad esempio con CRXDE Lite) e salvalo nell’archivio sottostante /apps/myapp/workflow/scripts
Per specificare un titolo che identifichi lo script nella finestra di dialogo di modifica Passaggio processo , aggiungi le seguenti proprietà al nodo jcr:content
dello script:
Nome | Tipo | Valore |
---|---|---|
jcr:mixinTypes |
Name[] |
mix:title |
jcr:title |
String |
Nome da visualizzare nella finestra di dialogo di modifica. |
Modifica l'istanza Passaggio partecipante dinamico e specifica lo script da utilizzare.
I pacchetti del flusso di lavoro possono essere passati a un flusso di lavoro per l’elaborazione. I pacchetti di flussi di lavoro contengono riferimenti a risorse come pagine e risorse.
I seguenti passaggi del processo di flusso di lavoro accettano pacchetti di flusso di lavoro per l’attivazione in massa di pagine:
Puoi sviluppare passaggi del flusso di lavoro per ottenere le risorse del pacchetto ed elaborarle. I seguenti membri del pacchetto com.day.cq.workflow.collection
consentono di accedere ai pacchetti del flusso di lavoro:
ResourceCollection
: Classe del pacchetto del flusso di lavoro.ResourceCollectionUtil
: Utilizzare per recuperare gli oggetti ResourceCollection.ResourceCollectionManager
: Crea e recupera le raccolte. Un’implementazione viene distribuita come servizio OSGi.Il seguente esempio di classe Java illustra come ottenere le risorse del pacchetto:
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;
}
}
Un modo semplice per iniziare a creare un passaggio personalizzato è quello di copiare un passaggio esistente da:
/libs/cq/workflow/components/model
Ricrea il percorso sotto /apps; ad esempio:
/apps/cq/workflow/components/model
Le nuove cartelle sono di tipo nt:folder
:
- apps
- cq
- workflow (nt:folder)
- components (nt:folder)
- model (nt:folder)
Questo passaggio non si applica all’editor di modelli dell’interfaccia classica.
Quindi inserisci il passaggio copiato nella cartella /apps; ad esempio:
/apps/cq/workflow/components/model/myCustomStep
Ecco il risultato del nostro esempio personalizzato passo:
Poiché nell’interfaccia utente standard non vengono visualizzati sulla scheda solo il titolo e non i dettagli, details.jsp
non è necessario come per l’editor dell’interfaccia classica.
Applica le seguenti proprietà al nodo:
/apps/cq/workflow/components/model/myCustomStep
Proprietà di interesse:
sling:resourceSuperType
Deve ereditare da un passaggio esistente.
In questo esempio ereditiamo dal passaggio di base in cq/workflow/components/model/step
, ma puoi utilizzare altri super tipi come participant
, process
, ecc.
jcr:title
È il titolo visualizzato quando il componente è elencato nel browser dei passaggi (pannello laterale sinistro dell’editor del modello di flusso di lavoro).
cq:icon
Utilizzato per specificare un'icona Corallo per il passaggio.
componentGroup
Deve essere uno dei seguenti:
Ora puoi aprire un modello di flusso di lavoro per la modifica. Nel browser dei passaggi è possibile filtrare per vedere Il mio passaggio personalizzato:
Trascinando Il mio passaggio personalizzato sul modello viene visualizzata la scheda:
Se non è stato definito alcun cq:icon
per il passaggio, viene eseguito il rendering di un’icona predefinita utilizzando le prime due lettere del titolo. Esempio:
Dopo Creazione del passaggio di base, definisci il passaggio Configura come segue:
Configura le proprietà sul nodo cq:editConfig
come segue:
Proprietà di interesse:
cq:inherit
Se è impostato su true
, il componente del passaggio eredita le proprietà dal passaggio specificato in sling:resourceSuperType
.
cq:disableTargeting
Impostate come richiesto.
Configura le proprietà sul nodo cq:formsParameter
come segue:
Proprietà di interesse:
jcr:title
Imposta il titolo predefinito sulla scheda del passaggio nella mappa del modello e nel campo Titolo della finestra di dialogo di configurazione Personalizzato - Proprietà passaggio.
Puoi anche definire proprietà personalizzate.
Configura le proprietà sul nodo cq:listeners
.
Il nodo cq:listener
e le relative proprietà consentono di impostare gestori eventi che reagiscono agli eventi nell’editor modelli dell’interfaccia touch; come il trascinamento di un passaggio su una pagina modello o la modifica di proprietà di un passaggio.
Proprietà di interesse:
afterMove: REFRESH_PAGE
afterdelete: CQ.workflow.flow.Step.afterDelete
afteredit: CQ.workflow.flow.Step.afterEdit
afterinsert: CQ.workflow.flow.Step.afterInsert
Questa configurazione è essenziale per il corretto funzionamento dell'editor. Nella maggior parte dei casi questa configurazione non deve essere modificata.
Tuttavia, l’impostazione di cq:inherit
su true (sul nodo cq:editConfig
, vedi sopra) consente di ereditare questa configurazione, senza dover includerla esplicitamente nella definizione del passaggio. Se non è presente alcuna ereditarietà, è necessario aggiungere questo nodo con le seguenti proprietà e valori.
In questo esempio, l’ereditarietà è stata attivata in modo da poter rimuovere il nodo cq:listeners
e il passaggio continuerà a funzionare correttamente.
Ora puoi aggiungere un’istanza del passaggio a un modello di flusso di lavoro. Quando Configura il passaggio viene visualizzata la finestra di dialogo:
Il markup per un passaggio personalizzato viene rappresentato nel .content.xml
del nodo principale del componente. Il campione .content.xml
utilizzato per questo esempio:
/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"/>
L'esempio _cq_editConfig.xml
utilizzato in questo esempio:
<?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>
L'esempio _cq_dialog/.content.xml
utilizzato in questo esempio:
<?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>
Osserva i nodi comuni e di processo nella definizione della finestra di dialogo. Questi vengono ereditati dal passaggio del processo che abbiamo utilizzato come supertipo per il passaggio personalizzato:
sling:resourceSuperType : cq/workflow/components/model/process
Le finestre di dialogo dell’editor modelli dell’interfaccia classica continueranno a funzionare con l’editor dell’interfaccia touch standard.
AEM dispone di strumenti di modernizzazione se desideri aggiornare le finestre di dialogo dei passaggi dell’interfaccia classica alle finestre di dialogo dell’interfaccia utente standard. Dopo la conversione ci sono ancora alcuni miglioramenti manuali che possono essere fatti alla finestra di dialogo per alcuni casi.
Nei casi in cui una finestra di dialogo aggiornata è vuota, è possibile esaminare le finestre di dialogo in /libs
che hanno funzionalità simili come esempi di come fornire una soluzione. Esempio:
/libs/cq/workflow/components/model
/libs/cq/workflow/components/workflow
/libs/dam/components
/libs/wcm/workflow/components/autoassign
/libs/cq/projects
Non devi modificare nulla in /libs
, ma utilizzarli semplicemente come esempi. Se desideri sfruttare uno dei passaggi esistenti, copiali in /apps
e modificali in tale punto.