Activiti: пример создания workflow

На форуме прозвучала просьба написать пример воркфлоу на activiti с подробными объяснениями. Попытаюсь просьбу исполнить. Пишу в этом блоге впервые, прошу строго не судить.

Надо знать, что с введением в альфреску activiti общие принципы написания бизнесс-процессов кардинально не изменились. Изменился лишь язык описания процессов (всю документацию по activiti можно найти здесь) и некоторые мелочи в локализации. Поэтому прежде стоит прочитать предыдущие статьи здесь на форуме:

Пример создания workflow в ECM Alfresco

Создание workflow. Продолжение

Давайте имплементируем следующий сценарий:

1. Регистратор загружает документ-директиву и инициирует процесс, передавая документ начальнику некоего подразделения.

2. Начальник знакомится с содержанием документа-директивы, формирует поручение и отправляет поручение на исполнение, выбирая исполнителя.

3. Исполнитель выполняет поручение, добавляет к документам акт об исполнении и возвращает начальнику на рассмотрение.

4. Начальник утверждает исполнение, и процесс заканчивается. Иначе -  начальник возвращает исполнителю поручение на доработку, и процесс возвращается к шагу 3.

Получится вот такой маршрут для документа:

 

Итак, создаем модель процесса DirectiveWorkflowModel.xml:

 

<?xml version="1.0" encoding="UTF-8"?>
<!-- Описание модели бизнес-процесса -->
<model name="dir:workflowmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
 
	<!-- Импорт необходимых описаний -->
	<imports>
		<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d" />
		<import uri="http://www.alfresco.org/model/bpm/1.0" prefix="bpm" />
		<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
	</imports>
 
	<!-- Описываем пространство имен для нашего процесса -->
	<namespaces>
		<namespace uri="http://www.somecompany.ru/model/workflow/1.0" prefix="dir" />
	</namespaces>
 
	<types>
		<!-- Подача директивы -->
		<type name="dir:start">
			<!-- Наследуем от bpm:startTask -->
			<parent>bpm:startTask</parent>
			<!-- Указываем обязательные аспекты -->
			<mandatory-aspects>
				<!-- Начальник подразделения -->
				<aspect>bpm:assignee</aspect>
			</mandatory-aspects>
		</type>
 
		<!-- Ознакомление с директивой и передача на исполнение -->
		<type name="dir:inspection">
			<!-- Наследуем от bpm:workflowTask -->
			<parent>bpm:workflowTask</parent>
 
			<!-- Доступ к документам пакета -->
			<overrides>
				<!-- Документ может быть добавлен -->
				<property name="bpm:packageActionGroup">
					<default>add_package_item_actions</default>
				</property>
				<!-- Документ может быть отредактирован -->
				<property name="bpm:packageItemActionGroup">
					<default>edit_package_item_actions</default>
				</property>
			</overrides>
				<!-- Указываем обязательные аспекты -->
				<mandatory-aspects>
					<!-- Исполнитель -->
					<aspect>dir:performer</aspect>
				</mandatory-aspects>
		</type>
 
		<!-- Исполнение поручения -->
		<type name="dir:perform">
			<parent>bpm:workflowTask</parent>
			<!-- Доступ к документам пакета -->
			<overrides>
				<!-- Документ может быть добавлен -->
				<property name="bpm:packageActionGroup">
					<default>add_package_item_actions</default>
				</property>
				<!-- Документ может быть отредактирован -->
				<property name="bpm:packageItemActionGroup">
					<default>edit_package_item_actions</default>
				</property>
			</overrides>
		</type>
 
		<!-- Проверка исполнения -->
		<type name="dir:approve">
			<!-- Наследуем от bpm:activitiOutcomeTask -->
			<!-- Новый объект, появился с введением activiti в альфреско -->
			<parent>bpm:activitiOutcomeTask</parent>
			<!-- Свойства -->
			<properties>
				<!-- Утвердить исполнение или же отправить на доработку -->
				<property name="dir:appOutcome">
					<type>d:text</type>
					<default>reject</default>
					<constraints>
						<constraint name="dir:propAppOutcome" type="LIST">
							<parameter name="allowedValues">
								<list>
									<!-- Утвердить -->
									<value>approve</value>
									<!-- Отправить на доработку -->
									<value>reject</value>
								</list>
							</parameter>
							<parameter name="caseSensitive">
								<value>true</value>
							</parameter>
						</constraint>
					</constraints>
				</property>
			</properties>
			<!-- Доступ к документам пакета -->
			<overrides>
				<!-- Документ может быть добавлен -->
				<property name="bpm:packageActionGroup">
					<default>add_package_item_actions</default>
				</property>
				<!-- Документ может быть отредактирован -->
				<property name="bpm:packageItemActionGroup">
					<default>edit_package_item_actions</default>
				</property>
			</overrides>
		</type>
	</types>
 
	<aspects>
		<aspect name="dir:performer">
			<associations>
				<association name="dir:performer">
					<source>
						<mandatory>true</mandatory>
						<many>false</many>
					</source>
					<target>
						<class>cm:person</class>
						<mandatory>true</mandatory>
						<many>false</many>
					</target>
				</association>
			</associations>
		</aspect>
	</aspects>
</model>

 

Помещаем модель в ALFRESCO_HOME/tomcat/shared/classes/alfresco/extension/model/

Создаем процесс DirectiveProcess.xml:

 

<?xml version="1.0" encoding="UTF-8" ?>
 
<!-- Объявление необходимых пространств имен -->
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn"
	xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"
	xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema"
	expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
 
	<!-- Начало описания процесса -->
	<process id="PerformDirective" name="Исполнение внешних директив">
 
		<!-- Начальный узел процесса -->
		<startEvent id="start"	activiti:formKey="dir:start" />
 
		<!-- Переход от старта к задаче ознакомления с директивой -->
		<sequenceFlow id='flow1' sourceRef='start' targetRef='inspection' />
 
		<!-- Ознакомление с директивой и передача на исполнение -->
		<userTask id="inspection" name="Ознакомиться с документом и передать на исполнение."	
			activiti:formKey="dir:inspection" >
			<extensionElements>
				<!-- Скрипт при создании задачи -->
				<!-- Устанавливаем срок исполнения и приоритет, если те не указаны -->
				<!-- Запоминаем начальника -->
				<activiti:taskListener event="create" 
					class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
					<activiti:field name="script">
						<activiti:string>
							if (typeof bpm_workflowDueDate != 'undefined') task.dueDate = bpm_workflowDueDate
							if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
							execution.setVariable('manager', bpm_assignee.properties.userName);
						</activiti:string>
					</activiti:field>
				</activiti:taskListener>
				<!-- Скрипт при закрытии задачи -->
				<!-- Запоминаем исполнителя -->
				<activiti:taskListener event="complete" 
					class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
					<activiti:field name="script">
						<activiti:string>
							var performer = task.getVariable('dir_performer');
							execution.setVariable('performer', performer.properties.userName);
						</activiti:string>
					</activiti:field>
				</activiti:taskListener>
			</extensionElements>
			<!-- Задача для начальника -->
			<humanPerformer>
				<resourceAssignmentExpression>
					<formalExpression>${bpm_assignee.properties.userName}</formalExpression>
				</resourceAssignmentExpression>
			</humanPerformer>
		</userTask>
 
		<!-- Переход от ознакомления с директивой к исполнениию -->
		<sequenceFlow id='flow2' sourceRef='inspection' targetRef='perform' />
 
		<!--Исполнение поручения -->
		<!-- Второй способ обозначить владельца задачи - через activiti:assignee -->
		<!-- Задача для исполнителя -->
		<userTask id="perform" name="Исполнение поручения."	activiti:formKey="dir:perform" 
			activiti:assignee="${performer}" >
			<extensionElements>
				<!-- Скрипт при создании задачи -->
				<!-- Устанавливаем срок исполнения и приоритет, если те не указаны -->
				<activiti:taskListener event="create" 
					class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
					<activiti:field name="script">
						<activiti:string>
							if (typeof bpm_workflowDueDate != 'undefined') task.dueDate = bpm_workflowDueDate
							if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
						</activiti:string>
					</activiti:field>
				</activiti:taskListener>
			</extensionElements>
		</userTask>
 
		<!-- Переход от исполнениия к проверке исполнения -->
		<sequenceFlow id='flow3' sourceRef='perform' targetRef='approve' />
 
		<!-- Проверка исполнения -->
		<!-- Задача для начальника -->
		<userTask id="approve" name="Проверить исполнение поручения."	activiti:formKey="dir:approve"
			activiti:assignee="${manager}" >
			<extensionElements>
				<!-- Скрипт при создании задачи -->
				<!-- Устанавливаем срок исполнения и приоритет, если те не указаны -->
				<activiti:taskListener event="create" 
					class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
					<activiti:field name="script">
						<activiti:string>
							if (typeof bpm_workflowDueDate != 'undefined') task.dueDate = bpm_workflowDueDate
							if (typeof bpm_workflowPriority != 'undefined') task.priority = bpm_workflowPriority;
						</activiti:string>
					</activiti:field>
				</activiti:taskListener>
				<!-- Скрипт при закрытии задачи -->
				<!-- Устанавливаем результат -->
				<activiti:taskListener event="complete" 
					class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
					<activiti:field name="script">
						<activiti:string>
							execution.setVariable('dir_appOutcome', task.getVariable('dir_appOutcome'));
						</activiti:string>
					</activiti:field>
				</activiti:taskListener>
			</extensionElements>
		</userTask>
 
		<!-- Переход от проверки исполнения к развилке -->
		<sequenceFlow id='flow4' sourceRef='approve' targetRef='decision' />
 
		<!-- Развилка: вернуться ли к исполнению или же окончить процесс -->
		<exclusiveGateway id="decision" name="Decision" /> 
 
		<!-- Исполнение не утверждено: вернуться к задаче исполнения -->
		<sequenceFlow id='flow5' sourceRef='decision' targetRef='perform' >
			<conditionExpression xsi:type="tFormalExpression">${dir_appOutcome == 'reject'}</conditionExpression>
		</sequenceFlow>
 
		<!-- Исполнение утверждено: окончить процесс -->
		<sequenceFlow id='flow6' sourceRef='decision' targetRef='end' />
 
		<!-- Конец процесса -->
		<endEvent id="end" />
 
	</process>
</definitions>

 

Помещаем процесс в ALFRESCO_HOME/tomcat/shared/classes/alfresco/extension/workflows/

Локализуем бизнес-процесс (dirWorkflow_ru_RU.properties):

PerformDirective.workflow.title=Обработка внешних директив
PerformDirective.workflow.description=Ознакомиться с директивой и исполнить ее
 
listconstraint.dir_propAppOutcome.approve=Утвердить исполнение
listconstraint.dir_propAppOutcome.reject=Послать на доработку
 
PerformDirective.node.inspection.transition.title=Направить на исполнение
PerformDirective.node.inspection.transition.description=Направить на исполнение
 
PerformDirective.node.perform.transition.title=Передать на утверждение
PerformDirective.node.perform.transition.description=Передать на утверждение
 

 

Помещаем локализацию в ALFRESCO_HOME/tomcat/shared/classes/alfresco/extension/messages/

Настраиваем вэб-клиент (web-client-config-custom.xml):

<alfresco-config>
 
	<config evaluator="string-compare" condition="Languages">
		<languages>
			<language locale="ru_RU">Russian</language>
		</languages>
	</config>
 
	<!--  Отображение  бизнес процессов -->
 
	<!-- Подача директивы -->
	<config evaluator="node-type" condition="dir:start" replace="true">
		<property-sheet>
			 <!-- Разделитель -->
      <separator name="sep1" display-label-id="general" component-generator="HeaderSeparatorGenerator" />
      <!-- Описание процесса -->
      <show-property name="bpm:workflowDescription" component-generator="TextAreaGenerator" />
      <!-- Выбор начальника -->
      <show-association name="bpm:assignee" />
		</property-sheet>
	</config>
 
	<!-- Ознакомление с директивой и передача на исполнение -->
	<config evaluator="node-type" condition="dir:inspection" replace="true">
		<property-sheet>
			 <!-- Разделитель -->
      <separator name="sep1" display-label-id="general" component-generator="HeaderSeparatorGenerator" />
      <!-- Описание процесса -->
      <show-property name="bpm:workflowDescription" component-generator="TextAreaGenerator" />
      <!-- Комментарий -->
      <show-property name="bpm:comment" component-generator="TextAreaGenerator" />
      <!-- Выбор исполнителя -->
      <show-association name="dir:performer" />
		</property-sheet>
	</config>
 
	<!-- Исполнение поручения -->
	<config evaluator="node-type" condition="dir:perform" replace="true">
		<property-sheet>
			 <!-- Разделитель -->
      <separator name="sep1" display-label-id="general" component-generator="HeaderSeparatorGenerator" />
      <!-- Описание процесса -->
      <show-property name="bpm:workflowDescription" component-generator="TextAreaGenerator" />
      <!-- Комментарий -->
      <show-property name="bpm:comment" component-generator="TextAreaGenerator" />
		</property-sheet>
	</config>
 
	<!-- Проверка исполнения -->
	<config evaluator="node-type" condition="dir:approve" replace="true">
		<property-sheet>
			 <!-- Разделитель -->
      <separator name="sep1" display-label-id="general" component-generator="HeaderSeparatorGenerator" />
      <!-- Описание процесса -->
      <show-property name="bpm:workflowDescription" component-generator="TextAreaGenerator" />
      <!-- Комментарий -->
      <show-property name="bpm:comment" component-generator="TextAreaGenerator" />
      <show-property name="dir:appOutcome" />
		</property-sheet>
	</config>
 
</alfresco-config>

 

Помещаем вэб-клиент в ALFRESCO_HOME/tomcat/shared/classes/alfresco/extension

Создаем загрузчик (dir-workflow-context.xml):

<?xml version='1.0' encoding='UTF-8'?>
 
<!-- Описание моделей и процессов для загрузки -->
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
 
<beans>
 
  <!-- Регистрируем ресурсы -->
  <bean id="dir.workflowBootstrap" parent="workflowDeployer">
    <property name="workflowDefinitions">
      <list>
        <props>
          <!-- Тип процесса -->
          <prop key="engineId">activiti</prop>
          <!-- Путь -->
          <prop key="location">alfresco/extension/workflows/DirectiveProcess.xml</prop>
          <!-- MIME -->
          <prop key="mimetype">text/xml</prop>
          <!-- Загружать каждый раз -->
          <prop key="redeploy">true</prop>
        </props>
      </list>
    </property>
 
    <!-- Локализация -->
    <property name="labels">
      <list>
        <value>alfresco.extension.messages.dirWorkflow</value>
      </list>
    </property>
 
    <!-- Список моделей для загрузки -->
    <property name="models">
        <list>
            <value>alfresco/extension/model/DirectiveWorkflowModel.xml</value>
        </list>
    </property>
 
  </bean>
 
</beans>
<!-- Конец описания -->

 

И помещаем его в ALFRESCO_HOME/tomcat/shared/classes/alfresco/extension

Настраиваем пользовательский интерфейс для share (web-extension/share-config-custom.xml):

<!-- Настройки интерфейса -->
<alfresco-config>
 
	<!-- Этим элементом можно включить режим отладки -->
	<config replace="true">
		<flags>
			<client-debug>false</client-debug>
			<client-debug-autologging>false</client-debug-autologging>
		</flags>
	</config>
 
	<!-- Отображение информации при просмотре бизнес-процесса -->
	<config evaluator="string-compare" condition="activiti$PerformDirective">
		<forms>
			<form>
				<!-- Список видимых полей -->
				<field-visibility>
					<show id="bpm:workflowDescription"/>
					<show id="bpm:assignee"/>
					<show id="packageItems" />
				</field-visibility>
				<appearance>
					<!-- Блоки -->
					<set id="" appearance="title" label-id="workflow.set.general" />
					<set id="assignee" appearance="title" label-id="dir_assignee" />					
					<set id="items" appearance="title" label-id="dir_items" />
					<!-- Отображение полей -->
					<field id="bpm:workflowDescription" label-id="dir_description">
						<control template="/org/alfresco/components/form/controls/textarea.ftl">
							<control-param name="style">width: 95%</control-param>
						</control>
					</field>
					<field id="bpm:assignee" label-id="dir_assign_to" set="assignee" />
					<field id="packageItems" set="items" label-id="dir_pitems" />
				</appearance>
			</form>
		</forms>
	</config>
 
	<!-- Начальный узел процесса -->
	<config evaluator="task-type" condition="dir:start">
		<forms>
			<form>
				<!-- Список видимых полей -->
				<field-visibility>
					<show id="bpm:workflowDescription"/>
					<show id="bpm:assignee"/>
					<show id="packageItems" />
				</field-visibility>
				<appearance>
					<!-- Блоки -->
					<set id="" appearance="title" label-id="workflow.set.general" />
					<set id="assignee" appearance="title" label-id="dir_assignee" />					
					<set id="items" appearance="title" label-id="dir_items" />
					<!-- Отображение полей -->
					<field id="bpm:workflowDescription" label-id="dir_description">
						<control template="/org/alfresco/components/form/controls/textarea.ftl">
							<control-param name="style">width: 95%</control-param>
						</control>
					</field>
					<field id="bpm:assignee" label-id="dir_assign_to" set="assignee" />
					<field id="packageItems" set="items" label-id="dir_pitems" />
				</appearance>
			</form>
		</forms>
	</config>
 
	<!-- Ознакомление с директивой и передача на исполнение -->
	<config evaluator="task-type" condition="dir:inspection">
		<forms>
			<form>
				<!-- Список видимых полей -->
				<field-visibility>
					<show id="bpm:workflowDescription"/>
					<show id="bpm:comment"/>
					<show id="dir:performer"/>
					<show id="transitions" />
					<show id="packageItems" />
				</field-visibility>
				<appearance>
					<!-- Блоки -->
					<set id="" appearance="title" label-id="workflow.set.general" />
					<set id="assignee" appearance="title" label-id="dir_assignee" />
					<set id="trans" appearance="" />
					<set id="items" appearance="title" label-id="dir_items" />
					<!-- Отображение полей -->
					<field id="bpm:workflowDescription" label-id="dir_description">
						<control template="/org/alfresco/components/form/controls/textarea.ftl">
							<control-param name="style">width: 95%</control-param>
						</control>
					</field>
					<field id="bpm:comment" label-id="dir_comment" />
					<field id="dir:performer" label-id="dir_performer" set="assignee" />
					<field id="transitions" set="trans" />
					<field id="packageItems" set="items" label-id="dir_pitems" />
				</appearance>
			</form>
		</forms>
	</config>
 
	<!--Исполнение поручения -->
	<config evaluator="task-type" condition="dir:perform">
		<forms>
			<form>
				<!-- Список видимых полей -->
				<field-visibility>
					<show id="bpm:workflowDescription"/>
					<show id="bpm:comment"/>
					<show id="transitions" />
					<show id="packageItems" />
				</field-visibility>
				<appearance>
					<!-- Блоки -->
					<set id="" appearance="title" label-id="workflow.set.general" />
					<set id="trans" appearance="" />
					<set id="items" appearance="title" label-id="dir_items" />
					<!-- Отображение полей -->
					<field id="bpm:workflowDescription" label-id="dir_description">
						<control template="/org/alfresco/components/form/controls/textarea.ftl">
							<control-param name="style">width: 95%</control-param>
						</control>
					</field>
					<field id="bpm:comment" label-id="dir_comment" />
					<field id="transitions" set="trans" />
					<field id="packageItems" set="items" label-id="dir_pitems" />
				</appearance>
			</form>
		</forms>
	</config>
 
	<!--Проверка исполнения -->
	<config evaluator="task-type" condition="dir:approve">
		<forms>
			<form>
				<!-- Список видимых полей -->
				<field-visibility>
					<show id="bpm:workflowDescription"/>
					<show id="bpm:comment"/>
					<show id="dir:appOutcome" />
					<show id="packageItems" />
				</field-visibility>
				<appearance>
					<!-- Блоки -->
					<set id="" appearance="title" label-id="workflow.set.general" />
					<set id="items" appearance="title" label-id="dir_items" />
					<!-- Отображение полей -->
					<field id="bpm:workflowDescription" label-id="dir_description">
						<control template="/org/alfresco/components/form/controls/textarea.ftl">
							<control-param name="style">width: 95%</control-param>
						</control>
					</field>
					<field id="bpm:comment" label-id="dir_comment" />
					<field id="dir:appOutcome" label-id="workflow.field.outcome" >
						<control template="/org/alfresco/components/form/controls/workflow/activiti-transitions.ftl" />
					</field>
					<field id="packageItems" set="items" label-id="dir_pitems" />
				</appearance>
			</form>
		</forms>
	</config>
 
</alfresco-config>

 


Помещаем вэб-клиент в ALFRESCO_HOME/tomcat/shared/classes/alfresco/web-extension

Локализуем метки интерфейса (dir_ru_RU.properties):

dir_assignee=Назначить ответственного
dir_assign_to=Начальник подразделения
dir_performer=Исполнитель
dir_items=Документы
dir_pitems=Директивы и пр. документы
dir_description=Описание
dir_comment=Комментарий
 

 

Помещаем локализацию в ALFRESCO_HOME/tomcat/shared/classes/alfresco/web-extension/messages/

Конфигурируем Spring bean для локализации интерфейса (custom-slingshot-application-context):

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
 
<beans>
 
   <bean id="dir.resources" class="org.springframework.extensions.surf.util.ResourceBundleBootstrapComponent">
      <property name="resourceBundles">
         <list>
            <value>alfresco.web-extension.messages.dir</value>
         </list>
      </property>
   </bean>
 
</beans>

 

Записываем его в ALFRESCO_HOME/tomcat/shared/classes/alfresco/web-extension

После рестарта альфрески заходим в localhost:8080/share, где в списке процессов мы видим наш процесс "Обработка внешних директив (Ознакомиться с директивой и исполнить ее)"

Updated

Вот так выглядит бизнес-процесс исполнения директив:

 

4250
Прикрепленные файлыРазмер
workflows.zip10.63 кб
start.png47.79 кб
inspection.png52.53 кб
perform.png53.14 кб
approve.png54.17 кб
diagram1.png10.99 кб

Комментарии

Angelina аватар
Кроме добавления в самой модели, надо добавить вырисовку в интерфейсе, т е надо произвести правки в web-client-config-custom.xml для вырисовки в репозитории и в share-config-custom.xml для вырисовки процесса на рабочем столе
Angelina аватар
Кроме добавления в самой модели, надо добавить вырисовку в интерфейсе, т е надо произвести правки в web-client-config-custom.xml для вырисовки в репозитории и в share-config-custom.xml для вырисовки процесса на рабочем столе
Да, в эти файлы изменения я тоже внес. При чем bpm:workflowDescription и packageItems отображаются.

Кусочек модели:
        <type name="wf:start">
            <!-- Наследуем от bpm:startTask -->
            <parent>bpm:startTask</parent>
            <mandatory-aspects>
               <aspect>bpm:assignee</aspect>
            </mandatory-aspects>           
        </type>


share-config-custom.xml:

	<config evaluator="string-compare" condition="activiti$Approval">
		<forms>
			<form>
				<field-visibility>
					<show id="bpm:workflowDescription"/>
					<show id="bpm:assignee"/>
					<show id="packageItems" />
				</field-visibility>
				<appearance>
					<set id="" appearance="title" label-id="workflow.set.general" />
					<set id="assignee" appearance="title" label-id="wf_assignee" />					
					<set id="items" appearance="title" label-id="wf_items" />
					<field id="bpm:workflowDescription" label-id="wf_description">
						<control template="/org/alfresco/components/form/controls/textarea.ftl">
							<control-param name="style">width: 95%</control-param>
						</control>
					</field>
					<field id="bpm:assignee" label-id="wf_assign_to" set="assignee" />
					<field id="packageItems" set="items" label-id="wf_pitems" />
				</appearance>
			</form>
		</forms>
	</config>

	<config evaluator="task-type" condition="wf:start">
		<forms>
			<form>
				<field-visibility>
					<show id="bpm:workflowDescription"/>
					<show id="bpm:assignee"/>
					<show id="packageItems" />
				</field-visibility>
				<appearance>
					<set id="" appearance="title" label-id="workflow.set.general" />
					<set id="assignee" appearance="title" label-id="wf_assignee" />					
					<set id="items" appearance="title" label-id="wf_items" />
					<field id="bpm:workflowDescription" label-id="wf_description">
						<control template="/org/alfresco/components/form/controls/textarea.ftl">
							<control-param name="style">width: 95%</control-param>
						</control>
					</field>
					<field id="bpm:assignee" label-id="wf_assign_to" set="assignee" />
					<field id="packageItems" set="items" label-id="wf_pitems" />
				</appearance>
			</form>
		</forms>
	</config>

Процесс:
 

  <process id="Approval" name="Approval" isExecutable="true">
    <startEvent id="startevent" name="Start" activiti:initiator="wf:start"></startEvent>
    <userTask id="approve" name="Approve" activiti:assignee="${performer}" activiti:formKey="wf:approve"></userTask>
    <endEvent id="end" name="End"></endEvent>
    <exclusiveGateway id="exclusivegateway1" name="Exclusive Gateway" default="endProcess"></exclusiveGateway>
    <sequenceFlow id="flow2" sourceRef="approve" targetRef="exclusivegateway1"></sequenceFlow>
    <sequenceFlow id="endProcess" sourceRef="exclusivegateway1" targetRef="end">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[<conditionExpression xsi:type="tFormalExpression">${wf_propAppOutcome == 'approve'}</conditionExpression>]]></conditionExpression>
    </sequenceFlow>
    <userTask id="execution" name="Execute" activiti:formKey="wf:execution">
      <extensionElements>
        <activiti:taskListener event="complete" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
          <activiti:field name="script">
            <activiti:string>var performer = task.getVariable('wf_performer');
execution.setVariable('performer', performer.properties.userName);</activiti:string>
          </activiti:field>
        </activiti:taskListener>
      </extensionElements>
    </userTask>
    <sequenceFlow id="flow7" sourceRef="startevent" targetRef="execution"></sequenceFlow>
    <sequenceFlow id="flow8" sourceRef="execution" targetRef="approve"></sequenceFlow>
    <sequenceFlow id="toExecution" name="Доработка" sourceRef="exclusivegateway1" targetRef="execution">
      <conditionExpression xsi:type="tFormalExpression"><![CDATA[<conditionExpression xsi:type="tFormalExpression">${wf_propAppOutcome == 'reject'}</conditionExpression>]]></conditionExpression>
    </sequenceFlow>
  </process>


 

Angelina аватар
Хм... вроде, на первый взгляд,все правильно, должно отображаться...

А лог ничего не пишет?
Нет. В логе все хорошо. Может я правда не там смотрю?
Я так понимаю лог для share: Alfresco/share.log
для эксплорера: Alfresco/alfresco.log

У меня подозрение, что это связано с моделью. Что изначально я в модели не добавил аспект. Правда, я так понимаю, после обновления модели и рестарта томката все должно было быть хорошо.


Angelina аватар
Да, чтобы появились изменения в модели (если, опять же, модель задеплоена через контекст, а не через интерфейс репозитория) и конфигах, альфреску надо обязательно рестартовать. Также уже поднятые процессы всегда идут по старым сценариям (хотя но это не Ваш случай)

Не знаю за модель (обычно описание процесса не обновляется, если редеплой в контексте не указан как true), но просмотрела внимательнее Ваше описание процесса. Вопрос: а где он используется затем - этот assignee? Заодно, откуда Вы берете перформера? Одно дело в скрипте считать assignee и задать его значение performer-у, но у Вас нигде ничего такого нет. Или я ошибаюсь?

А логи пишутся в следующих файлах:
- под Линуксом в файле ALFRESCO_HOME/tomcat/logs/catalina.out
- под Виндовсом в файлах ALFRESCO_HOME/tomcat/logs/много_букав_stdout_дата.log и ALFRESCO_HOME/tomcat/logs/много_букав_stderr_дата.log

Просто странно: если косится шаре-конфиг, то часто просто нереально зайти на стол бывает. Такой вопрос, может, прозвучать странно: а Вы уверены, что деплоете на ту альфреску, под которой затем заходите? Ну, например, у Вас есть несколько серверов, задеплоили на одну, а смотрите другую. Если все происходит локально, то вопрос, конечно, снимается.

Пока выверите все же описание процесса (момент инициации перформера) и прочитайте логи.
Angelina аватар
А еще, если честно, мне не нравится Ваш namespace с префиксом. Он созвучен существующему альфресковскому. Вполне возможно, что у Вас просто стандартный неймспейс налагается на Ваш в конфиге.
Все. Разобрался.
Ошибка была здесь:
    <startEvent id="startevent" name="Start" activiti:initiator="wf:start"></startEvent>
Диаграмму рисовал через Activiti Disigner и не в то поле вколбасил wf:start.
Ангелина, еще вопросик у меня остался. В activiti:formKey указывается тип задания, соответственно при отрисовке формы можно использовать атрибуты данного типа, и значения введенные на форме будут сохраняться в объект задания. При необходимости обратиться к какому-либо атрибуту объекта можно, например, в обработчике в скрипте.  Я все правильно понимаю?
activiti:formKey обязательно указывать?
И еще в activiti:formKey может быть указано что-то отличное от типа?


Angelina аватар
Да, все правильно: все свойства задания и аспекты хранятся в объекте задания и с ними можно работать через JavaScript APi. Кроме того, в каждом задании есть набор стандартный свойств и аспектов. Например, тот же срок исполнения - dueDate, status и пр.

В самом посте есть пара простых примеров:
task.dueDate = bpm_workflowDueDate
здесь срок исполнения задания устанавливается равным сроку исполнения процесса

Или же этот пример:
execution.setVariable('dir_appOutcome', task.getVariable('dir_appOutcome'));
Здесь, наоборот, значение свойства dir:Outcom задания сажается в другую переменную (которая просто по совпадению созвучна со свойством)

Здесь Вы найдете API для работы. Кроме того, Альфреско хранит историю процессов, которую можно изъять и через Java. Также через скрипт Вы можете работать и со свойствами самого процесса.

В самой активити атрибут activiti:formKey необязателен и его роль - указывать на шаблон вырисовки в форме. Но также он может содержать ключ генерации шаблона, как в случае с Альфреской, указывающий какой алгоритм/трансформацию использовать при этом. Именно поэтому в процессах под Альфреско мы указываем этот ключ. Таким образом, указывая ключ (а это ключ типа в Альфреско) Альфреско подставляет свои стандартные шаблоны вырисовок полей и форм в соответствии с типами полей и пр. Но при этом Вы всегда можете через тот же конфиг подставить и свой шаблон - формы или же поля.

Спасибо большое за помощь!
Angelina аватар
Была рада быть полезной :)
Добрый день.

помогите пожалуйста разобраться. Сделал все по инструкции, но после рестарта Alfrecso в браузере получаю следующее:
A problem has occurred. 
This page could not be rendered: 
user/admin/dashboard 
Please notify your system administrator.

Убрал все исправления, которые сделал по инструкции. Сделал рестарт. НО ошибка та же.

Подскажите, в какую сторону смотреть?
заранее всем благодарен за помощь.
Angelina аватар
Такая ошибка возникает, когда или вэб клиент, или же шаре конфиг неправильные. Обычно это проблемы синтаксиса.

Я Вам посоветую все xml-файлы процесса редактировать в XML редакторах. Тогда Вы сразу увидите ошибку.
Angelina аватар
Скачайте workflows.zip, приатаченынй к теме и попробуйте с этими сорсами задеплоить процесс
Пытаюсь создать БП из задач Создание -->  Согласование --> Утверждение. В задаче Создание выбираю согласующих лиц(не обязательное поле) и утверждающее лицо(обязательное поле). И никак не могу сообразить, как мне сделать условие, при котором, если согласующие не указаны, то БП после Создания переходит сразу к задаче Утверждения.

Создала элемент exclusiveGateway и из него 2 стрелочки с условиями
1 approve(к задаче утверждения)  -->  ${typeof mwf_admiter != 'undefined'}
2 admit(к задаче согласования)  -->  ${typeof mwf_admiter == 'undefined'}
Но не работает, ругается
org.activiti.engine.ActivitiException: Exception while invoking TaskListener: Exception while invoking TaskListener: 07190545 Failed to execute supplied script: unterminated string literal (AlfrescoJS#5)

Писала условие ${mwf_admiter == null} ${mwf_admiter == void}. И ничего.
Может я что-то не правильно делаю?
Заранее спасибо

Angelina аватар
У Вас синтаксическая ошибка где-то в скрипте.

Какого типа у Вас  переменная? Могу посоветовать использовать отладочную печать, т е в процеду complete  в соответствующей задаче (или же прямо в стартовой процедуре, если переменная именно там инициализируется) внести строчку  logger.warn("Согласующий="+mwf_admiter).  Там же можно вывести и тип переменной. Попробуйте так, посмотрите, что у Вас происходит и где именно падает точно.
 Спасибо большое, с помощью логов разобралась. Очень помогли с места сдвинуться.
 Подскажите, пожалуйста, хочу в бизнесс-процесс подклюсить скрипт, который лежит по адресу
 Alfresco\tomcat\shared\classes\alfresco\extension\scripts\wf_script.js
Пытаюсь это сделать с помощью
     <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
          <activiti:field name="script">
               <activiti:string>

                    &lt;import resource="classpath:alfresco/extension/scripts/wf_script.js"&gt;;

                    ..........
               </activiti:string>
          </activiti:field>
     </activiti:taskListener>
Процесс не запускается - "Не удалось начать бизнес-процесс". Запускаю в share, и логов об ошибке в alfresco.log не показывает.
Если запустить без строчки в скрипте, то все работает и запускается.
Angelina аватар
Попробуйте завернуть элемент import  в CDATA

Или же сделайте следующее:
- загрузите скрипт в репозиторий в Scripts;
- заверните элемент импорт в CDATA так:
<script>
              <expression>
                 <![CDATA[                 
                    <import resource="/Company Home/Data Dictionary/Scripts/wf_script.js">
                 ]]>
              </expression>
              <variable name="theresult" access="write" />
            </script>

 Спасибо большое.

Вариант не работает
       <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
          <activiti:field name="script">
               <activiti:string>

           <![CDATA[

                    <import resource="classpath:alfresco/extension/scripts/wf_script.js">
           ]]>

                    ..........
               </activiti:string>
          </activiti:field>
     </activiti:taskListener>

Вариант работает
       <activiti:taskListener event="create" class="org.alfresco.repo.workflow.activiti.tasklistener.ScriptTaskListener">
          <activiti:field name="script">
               <activiti:string>

                    &lt;import resource="/Company Home/Data Dictionary/Scripts/wf_script.js"&gt;;

                    ..........
               </activiti:string>
          </activiti:field>
     </activiti:taskListener>
 

 
Добрый день.

Какого типа объект можно отправлять по БП? 
Можно ли запустить folder по БП?
Angelina аватар
Простите, вопрос непонятен. Вы имеете в виду, какого рода документы можно цеплять к процессу для дальнейшего документооборота или же что-то другое?  И что значит запустить фолдер? Имеется в виду, автоматические некие изменения на папках при неких правилах?
Нет. Я как раз имею ввиду, что я хочу по процессу запустить не документ, а фолдер, например.
Сейчас через интерфейс я могу при запуске процесса выбрать только документ. 
На сколько я понял, это ограничение интерфейса, а не движка?
Angelina аватар
Вы знаете, никогда не пробовала передавать папки. Боюсь, ничего не могу сказать по этому вопросу. Но, думаю, это вопрос не движка. Думаю, это вопрос элементов управления альфрески, которые и обеспечивают "цепляние" документов в интерфейсе процессов. Т е теоретически, думаю, возможно, предварительно описав в модели папку, нарисовать шаблон на фримаркере и указать его в шаре конфиге в задачах

На всякий случай, продублируйте вопрос в форуме. Может быть, кто-то уже сделал такую вещь
Добрый день! Ангелина подскажите для версии 4.2f  бизнес-процесс подойдет ?
Angelina аватар
Должна подойти