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

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

 

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

Комментарии

Aviriel аватар

А где же в конце красивый скриншот открытой картинки модели процесса на странице деталей бизнес-процесса?;)

Angelina аватар

Не подумала. :(

Добавила скрины каждого этапа-задачи в share.

 

Aviriel аватар

 Здорово. Я имела в виду что-то типа http://www.alvexcore.com/img/ru/about/alvex-workflow-activiti.png, но можно и так :)

Angelina аватар

Да, поняла, это будет полезно. Хорошо. Сделаю вечером обязательно.

З.Ы. Я вообще работаю в vi и jEdit, поэтому у меня со схемами напряженка. :) Вечерком у меня под рукой все инструменты будут

 

Aviriel аватар

 Ок. Сама всегда все делаю в vi, хотя до activiti вообще еще не добралась, и не знаю, как там что рисовать.

Здравствуйте! У меня, пожалуй, обратная проблема - не могу удалить процесс на activiti. Alfresco-4.0.d. Создала свой процесс в /shared/extention, не могла сначала ничего изменить в нём (после перезагрузки ничего не менялось), потом решила совсем удалить, но не получается! Не могли бы подсказать, как это правильно сделать?

Angelina аватар

Для того, чтобы при обновлении файла процесса в share/extension обновлялся сам воркфлоу, надо обратить внимание на конфигурацию воркфлоу. Проверьте внимательно в файле *-workflow-context часть, описывающую файл процесса. У меня вот эта часть:

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

Обратите внимание на значение ключа redeploy

 <prop key="redeploy">true</prop>

Что означает перезагрузку при обновлении файла. Может быть у Вас это описано так

 <prop key="redeploy">false</prop>

 

Измените false на true, и тогда при каждом рестарте альфрески процесс будет перезагружаться

Кроме того, может быть, Вы просто копируете файл процесса. Но просто перезаписать файл процесса в шаре не перезагружает вокрфлоу. Если Вы деплоете воркфлоу таким образом, то после обновления файла Вы должны рестартовать сам сервер. Чтобы обновлять воркфлоу без перезагрузки сервера, Вы должны пользоваться интерфейсом самого альфрески для деплоймента процесса и модели.

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

Но Вы можете пойти другим путем: Вы можете не удалять файлы, а вернуть их на место и спрятать сам воркфлоу вот таким образом Если Вы используете activity, то префикс jbpm в <workflow name="jbpm$doc:testAppRej"/> меняется на activity, а doc:testAppRej на имя Вашего процесса. Пример:

<workflow name="activiti$activitiReview"/>

 

Angelina аватар

Если Вы все же хотите совсем убрать процесс из системы, то, как я и сказала, недостаточно лишь удалить его файлы. Надо зайти в администраторскую консоль (http://localhost:8080/alfresco/faces/jsp/admin/workflow-console.jsp). В ней Вы можете увидеть все воркфлоу, набрав:

show definitions all

А чтобы "раздеплоить" воркфлоу, наберите:

undeploy definition <workflow definition name>

 

 

Огромное спасибо за обстоятельный ответ! Буду пробовать.

Angelina аватар

Не за что! Надеюсь, получится.

Кстати, здесь на портале у Фуфлера есть коммент на ту же тему. Посмотрите здесь, в последних комментариях.

 

Kogda pitayus propisat chto libo v workflow console poluchayu 3to. Xotya ya udalil vse org.alfresco.service.namespace.NamespaceException: Namespace prefix dir is not mapped to a namespace URI
Angelina аватар
Я боюсь, что у Вы что-то сделали неправильно при undeploy. У Вас эта ошибка если возникает - означает. что система ищет и не находит модель. ЧТобы больше так не ругалось, можно просто задеплоить через интерфейс модель с данным неймспейсом или же все почистить в самой базе, а затем переиндексировать все.

Но, вообще, я бы посоветовала при таком раскладе, когда уже непонятно, из-за чего там перекосилось, переставить альфреску, отработать Ваш новый воркфлоу (без деплоя моего) и потом уже, когда все заработает, ставить альвексю А то сейчас уже замылена картина
 Я так и думал ) спасибо большое за уделенное время ))
Переставил альфреску и получил вот такую вот ошибку..... когда в консоли пытаюсь задеплойдь в самой альфреске пишет.
org.alfresco.error.AlfrescoRuntimeException: 05100162 Exception in Transaction
Caused by: org.dom4j.DocumentException: Error on line 178 of document : The element type "alfresco-config" must be terminated by the matching end-tag "". Nested exception: The element type "alfresco-config" must be terminated by the matching end-tag "". at org.dom4j.io.SAXReader.read(SAXReader.java:482) at org.dom4j.io.SAXReader.read(SAXReader.java:343) at org.springframework.extensions.config.xml.XMLConfigService.parse(XMLConfigService.java:212)
Angelina аватар
У Вас неправильный XML. Судя по alfresco-config - это или share-config-custom.xml, или же web-client-config-custom.xml

Как Вы уже увидели, практически все файлы процесса - модели, описания процессов, описание интерфейсов и клиентов - это XML-ки. Соответственно, все элементы и атрибуты должны писаться правильно и закрываться в правильном месте.

Я Вам посоветую следующее: править файлы процесса в редакторах, которые имеют встроенные парсеры. К примеру, я использую jEdit  с установленным на него XML-плаггином. В нем очень легко олавливать ошибки xml-ого синтаксиса
А на что сейчас ругается как я понял что то не так с файлом web-client-config-custom


2013-06-10 18:59:04,821 ERROR [extensions.config.BaseConfigService] [localhost-startStop-1] Input stream invalid - skipped for source: classpath:alfresco/extension/web-client-config-custom.xml' org.springframework.extensions.config.ConfigException: 05100001 Failed to parse config stream at org.springframework.extensions.config.xml.XMLConfigService.parse(XMLConfigService.java:224) at org.springframework.extensions.config.BaseConfigService.appendConfig(BaseConfigService.java:268) at org.springframework.extensions.config.BaseConfigService.parse(BaseConfigService.java:298) at org.springframework.extensions.config.xml.XMLConfigService.initConfig(XMLConfigService.java:132) at org.alfresco.repo.config.xml.RepoXMLConfigService.access$001(RepoXMLConfigService.java:53) at org.alfresco.repo.config.xml.RepoXMLConfigService$1.execute(RepoXMLConfigService.java:133) at org.alfresco.repo.config.xml.RepoXMLConfigService$1.execute(RepoXMLConfigService.java:127) at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:433) at org.alfresco.repo.transaction.RetryingTransactionHelper.doInTransaction(RetryingTransactionHelper.java:323) at org.alfresco.repo.config.xml.RepoXMLConfigService.initRepoConfig(RepoXMLConfigService.java:125) at org.alfresco.repo.config.xml.RepoXMLConfigService.resetRepoConfig(RepoXMLConfigService.java:195) at org.alfresco.repo.config.xml.RepoXMLConfigService.initConfig(RepoXMLConfigService.java:109) at org.alfresco.repo.config.xml.RepoXMLConfigService$2.doWork(RepoXMLConfigService.java:241) at org.alfresco.repo.security.authentication.AuthenticationUtil.runAs(AuthenticationUtil.java:529) at org.alfresco.repo.config.xml.RepoXMLConfigService.onBootstrap(RepoXMLConfigService.java:237) at org.springframework.extensions.surf.util.AbstractLifecycleBean.onApplicationEvent(AbstractLifecycleBean.java:56) at org.alfresco.repo.management.SafeApplicationEventMulticaster.multicastEventInternal(SafeApplicationEventMulticaster.java:209) at org.alfresco.repo.management.SafeApplicationEventMulticaster.multicastEvent(SafeApplicationEventMulticaster.java:180) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:303) at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:911) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:428) at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47) at org.alfresco.web.app.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:63) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4791) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5285) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:618) at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:963) at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1600) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:722) Caused by: org.dom4j.DocumentException: Error on line 10 of document : Invalid byte 2 of 2-byte UTF-8 sequence. Nested exception: Invalid byte 2 of 2-byte UTF-8 sequence. at org.dom4j.io.SAXReader.read(SAXReader.java:482) at org.dom4j.io.SAXReader.read(SAXReader.java:343) at org.springframework.extensions.config.xml.XMLConfigService.parse(XMLConfigService.java:212) ... 38 more 2013-06-10 18:59:27,288 INFO [extensions.webscripts.TemplateProcessorRegistry] [localhost-startStop-1] Registered template processor freemarker for extension ftl 2013-06-10 18:59:27,425 INFO [extensions.webscripts.ScriptProcessorRegistry] [localhost-startStop-1] Registered script processor javascript for extension js 2013-06-10 18:59:27,426 INFO [extensions.webscripts.TemplateProcessorRegistry] [localhost-startStop-1] Registered template processor freemarker for extension ftl 2013-06-10 18:59:27,431 INFO [extensions.webscripts.ScriptProcessorRegistry] [localhost-startStop-1] Registered script processor javascript for extension js 2013-06-10 18:59:32,479 INFO [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 342 Web Scripts (+0 failed), 355 URLs 2013-06-10 18:59:32,479 INFO [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 8 Package Description Documents (+0 failed) 2013-06-10 18:59:32,479 INFO [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 0 Schema Description Documents (+0 failed) 2013-06-10 18:59:32,710 INFO [extensions.webscripts.AbstractRuntimeContainer] [localhost-startStop-1] Initialised Spring Surf Container Web Script Container (in 5270.954ms) 2013-06-10 18:59:32,718 INFO [extensions.webscripts.TemplateProcessorRegistry] [localhost-startStop-1] Registered template processor freemarker for extension ftl 2013-06-10 18:59:32,725 INFO [extensions.webscripts.ScriptProcessorRegistry] [localhost-startStop-1] Registered script processor javascript for extension js 2013-06-10 18:59:34,602 INFO [web.site.EditionInterceptor] [http-apr-8080-exec-9] Successfully retrieved license information from Alfresco. 2013-06-10 18:59:47,464 INFO [web.scripts.ImapServerStatus] [http-apr-8080-exec-6] Successfully retrieved IMAP server status from Alfresco: disabled 
 Спасибо уже установил 
Все решил эту ошибку. Сейчас в логах ошибки нету но процесс также отсутствует в списке процессов. Из за чего это может быть?
Angelina аватар
Значит, процесса нет в контексте или он не активирован.
Ангелина а можно получить ваш почтовый ящик или скайп для консультаций ? Просто наша компания заинтересована в альфреско   
Angelina аватар
Вы можете мне написать мне в личку здесь на портале. Письмо придет в мой почтовый ящик :)
 Ya pitalsya. Kogda clickaew napisat soobsheniya, vixodyt stranica ne naidena
Aviriel аватар
Я Вам крайне рекомендую зарегистрироваться на OSSPortal. Сейчас Вы либо логинитесь по OpenID, либо просто вводите имя, когда оставляете комментарий.
Зарегистрированным пользователям доступен обмен прямыми сообщениями. После регистрации в профиле других пользователей (например, Angelina) Вам будет видна вторая вкладка "Отправить сообщение".
 Я пользователь все равно не отправляется. Возможно проблема во мне
Добрый день! А каким образом нужно будет изменить описание процесса, если предусмотреть выбор нескольких исполнителей (на этапе inspection запускать что-то типа activitiParallelReview)?
Angelina аватар
Это можно сделать несколькими способами, в зависимости от того, какой сценарий Вам нужно имплементировать. К примеру, Вам нужно задачу скидывать в пул некоей группе исполнителей. Задача создается одна и попадает в пул, владелец задачи пока не определен. Каждый юзер из обозначенной группы может взять на себя задачу (и вернуть в пул, соответственно). И только тогда, когда задача взята, у нее появляется owner. В данном случае вместо humanPerformer используется следующая конструкция:
<potentialOwner>
  <resourceAssignmentExpression>
    <formalExpression>${group_name}</formalExpression>
  </resourceAssignmentExpression>
</potentialOwner>
Или же используйте атрибут activiti:candidateUsers в элементе userTask В данном случае надо помнить, что значение formalExpression - это переменная типа List. Т е если у вас есть predefined список юзеров, то указываются они так: <formalExpression>petrov, sidorov, ivanov</formalExpression> Если же Вы хотите брать список юзеров из bmp_assignes, динамически определяя список юзеров, то нужно создать из bpm_assignes список. Это можно сделать так. К примеру, у вас есть созданный Вами js scoped object converter с методом convert, который принимает в качестве параметра строку типа "ivanov, petorv, sidorov" и делает из нее List Код в джаве конвертора выглядит так:
import java.util.*;
import org.alfresco.repo.processor.BaseProcessorExtension;

public class StringConverter extends BaseProcessorExtension {
	
	public List convert(String s) {
		List list = new ArrayList(Arrays.asList(s.split(",")));
		return list;
	}	
}
регистрируете его в Spring так:
<bean id="converter" parent="baseJavaScriptExtension" class="ru.activiti.StringConverter">
        <property name="extensionName">
            <value>converter</value>
        </property>
    </bean>
На стартовом ивенте в процессе Вы делаете что-то примерно такое:
var coordinators = "";
coordinatorsCount = bpm_assignes.size();	
for (var i=0; i<coordinatorsCount; i++ ) {
  coordinators += bpm_assignes.get(i).properties.userName+",";
}

var userList = converter.convert(coordinators);
execution.setVariable('userList', userList);
И уже пул Вы определяете атрибутом activiti:candidateUsers="${userList}" в нужном userTask-е. Если же у Вас задача, выбрав несколько юзеров, создать целенаправленный список задач с определенными owner-ами, то можете использовать элемент активити multiInstanceLoopCharacteristics Пример его использования можно увидеть в parallel-review.bpmn20.xml, который лежит в alfresco/tomcat/webapps/alfresco/WEB_INF/classes/alfresco/workflow. Обратите внимание на конструкию в примере, именно она и создает список задач с определенными владельцами:
 <multiInstanceLoopCharacteristics isSequential="false">
           	   <loopDataInputRef>bpm_assignees </loopDataInputRef>
           	   <inputDataItem name="reviewAssignee" />
           	   <completionCondition>${wf_actualPercent >= wf_requiredApprovePercent} </completionCondition>
            </multiInstanceLoopCharacteristics >
Кстати, там же лежат несколько примеров, написанный на активити
Как раз пытаюсь использовать multiInstanceLoopCharacteristics, добавив в описание этапа perform следующее:
<humanPerformer>
   <resourceAssignmentExpression>
   <formalExpression>${reviewAssignee.properties.userName}</formalExpression>
   </resourceAssignmentExpression>
</humanPerformer>
           
<multiInstanceLoopCharacteristics isSequential="false">
   <loopDataInputRef>performer</loopDataInputRef>
   <inputDataItem name="reviewAssignee" />
   <completionCondition>${wf_actualPercent >= wf_requiredApprovePercent}</completionCondition>
</multiInstanceLoopCharacteristics>
на что получаю "Variable performer' is not a Collection". В какую сторону копать? В Activiti я практически полный ноль... Аспект dir:performer в модели описан полностью аналогично аспекту bpm:assignees в bpmModel.xml
Angelina аватар
Понятно. Вот как раз этом я говорила - про то, что переменные должны быть типа List<String> Вы передаете свою переменную performer, которая, судя по всему, есть переменная типа String вида "ivanov, petrov, sidorov" или еще какого-то другого типа. А это не сработает. Я выше в комментарии написала, как я решила эту проблему. У меня в модели на старте определяются bpm_assignes - все необходимые мне юзеры. Или же это моя кастомная переменная, которая есть multiple person. Что я делаю, чтобы вытащить список userName-ов из переменной? В процессе на старте я собираю в цикле строку из userName-ов, отдельнных друг от друга запятыми (выглядеть это будет как "ivanov, petrov, sidorov"). Затем я пишу свой js scoped object (java-код и часть контекста я также привела в комментарии выше) converter, чем метод принимает в виде параметра строку с userName-ами и возвращает их уже в виде переменной типа Collеction: И уже в месте <loopDataInputRef>performer</loopDataInputRef> вместо performer я указываю вот ту самую переменную.
Angelina аватар
Как писать js scoped object и использовать в js процессов, fufler хорошо написал здесь http://www.ossportal.ru/technologies/alfresco/blogs/142
Angelina аватар
Вы знаете, я постараюсь как-нибудь подробно описать этот момент в блоге отдельной темой.
 Спасибо большое вы чудо))
Angelina аватар
Пожалуйста!  Рада, что оказалась полезной :)
Здравствуйте еще раз а как сделать так чтобы bpm:assignee был уже поставлен и пользователю не нужно было его выбирать?
Angelina аватар
Это можно сделать тремя способами.
1. Вы знаете, что процесс всегда поднимается, к примеру, на Иванова. Тогда в модели на старте Вы не указываете в аспектах bpm:assignee, а в процессе в соответствующем атрибуте прямо прописываете userid Иванова:
<userTask id="perform" name="Исполнение поручения."	activiti:formKey="dir:perform" 
			activiti:assignee="ivanov" >

2. У Вас в модели остается bpm:assignee, но процесс Вы поднимаете автоматически, из-вне неким скриптом и владельца задачи Вы прописываете прямо в скрипте. Например:
var workflow = actions.create("start-workflow");
workflow.parameters.workflowName = "activiti$PerformDirective";
workflow.parameters["bpm:workflowDescription"] = "Мое описание";
workflow.parameters["bpm:assignee"] = "ivanov";
workflow.execute(document);

3. Вы добавляете в процесс процедуру старта (start event). В процедуре старта Вы создаете переменную процесса, к примеру, assignee, и инициализируете, присваивая значение "ivanov". При этом bpm:assignee также отсутствует в аспектах старта в модели:
<process id="PerformDirective" name="Исполнение внешних директив">
 
  <!-- стартовый ивент -->
  <extensionElements>
    <activiti:executionListener event="start" class="org.alfresco.repo.workflow.activiti.listener.ScriptExecutionListener">
      <activiti:field name="script">
        <activiti:string>
          execution.setVariable('assignee', 'ivanov');
        </activiti:string>
      </activiti:field>
    </activiti:executionListener>
  </extensionElements>
 
  <!-- Переход от старта к задаче ознакомления с директивой -->
  <sequenceFlow id='flow1' sourceRef='start' targetRef='inspection' />
 
  <!-- Ознакомление с директивой и передача на исполнение -->
  <userTask id="inspection" name="Ознакомиться с документом и передать на исполнение."	
  activiti:formKey="dir:inspection"  activiti:assignee="${assignee}">
...



Блинннн ваш бизнесс-процесс получается а когда пытаюсь свой сделать аналогичный вашему у меня не получается(((((я смог изменить пару вещей в форме каждого шага но я не могу пока менять маршруты. Главные изменение нужно делать в файлах описания и модели бизнесс-процесса?
Angelina аватар
Смотрите, основные шаги процесса описываются моделью. А их поведение - описанием процесса на активити. Надо исходить из этого.

Надо четко понимать, какие изменения и как Вы производите.

Вы без проблем можете производить изменения в описании процесса, как в части скриптов, так и части добавления процедур и развилок, единственное условие - это соответствие задач описанию оных в модели процесса. Т е просто убирать userTask или добавить Вы не можете, они всегда соответствуют модели. Единственно, помните, что уже поднятые процессы будут идти по старому сценарию.

Если же Вы меняете модель процесса, тот тут есть свои законы. Смотрите, есть правило: все изменения на уже установленной модели в альфреско должны происходить в порядке возрастания. Т е Вы можете в модели добавить к каждому шагу аспекты, но убирать уже существующие не можете.  Вы можете добавлять в модели типы, но убирать существующие - не можете. И т д . Вы даже не можете, к примеру, поменять свойство аспекта с mandatory=true на mandatory=false. Это тоже считается правкой с убыванием.

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

У меня такое ощущение, что Вы пытаетесь изменить процесс, который уже существует и работает на Вашей альфреске. И изменения эти не в порядке увеличения. Судя по всему, Вы пытаетесь удалить аспект bpm:assignee  в модели. Если это так, то лучше все же создать новый процесс. Еще более простой вариант, если Вы просто пока "играетесь" процессами локально - это переставить альфреску :)

Или же, если все дело в этом bpm:assignee, оставьте этот аспект, не рисуйте его в клиенте и интерфейса, но проставьте его значение через стартовую процедуру, поскольку он обязательный - это аспект. Если же дело не в аспекте, то проверьте правки модели и описания на то, о чем я говорила выше.

Кроме того, надо помнить, что процесс - это не только модель и описание. Это еще вэб-клиент и интерфейс. Т е там тоже надо вносить соответствующие правки.

Вы знаете, мне кажется, что Вы пока не совсем себе представляете работу процессов на альфреске. Знаете, я Вам посоветую хорошую книжку: "Professional Alfresco® Practical Solutions for Enterprise Content Management
Alfresco", написанное в соавторстве с David Caruana, John Newton, Michael Farman, Michael G. Uzquiano, Kevin Roast. Описание процессов там дано на JBPM, но все остальное в альфреске не изменилось. Особенно там подробно описаны создание моделей. Важно понимать. как модель связана/определяет процесс.
 Хорошо я вас примерно понял. Пока я хочу создать элементарный процесс на заявку оборудования. А где можно эту книгу найти?
Angelina аватар
Вы знаете, я ее отсюда покупала, с Амазона. Но и вики самой Альфрески тоже бывают полезными...
Angelina аватар
Вот здесь описывается, как деплоить модель через интерфейс. А вот здесь - как процесс Описание процесса также деплоиться в DataDictionary/WorkflowsDefinitions Только не забудьте слово jbmp поменять на activiti  при установке в окошке свойств

Angelina аватар
Мой совет: создайте новую модель с новым процессом. И отрабатывайте ее через интерфейс самой альфрески. Это хорошо и тем, что не нужен рестарт, а также Вы можете посмотреть в логе, в чем причина. А уж потом, когда заработает, пишите вэб клиент и интерфейс.
 Хорошо спасибо большое. Хотелось бы увидеть новые бизнесс-процессы с разными сценариями. Например дроп даун лист и т.д в формах.
Angelina аватар
Хорошо, постараюсь написать.

Кстати, поля описываются также в модели через свойства и аспекты. В них Вы можете устанавливать тип поля - будет ли это список, целое число, дата и прочее, а также будет ли поле обязательным, множественным и прочее. А на форме процесса, при загрузке в share, вид поля Вы можете описать сами. Формы, а также элементы управления в Альфреско рисуются с помощью FreeMarker-а  и JavaScript-а.  Также в самой альфреске есть некоторые готовые шаблоны эти элементов, такие, как дата, простые списки (в альфреско они представлены элементов select), ассоциации... Все это также описано в той книжке. Вообще, полезная книженция :)
Окей спасибо большое))))
 все скачал книгу но там 400 с лишним страниц....... О.О
Здравствуйте еще раз, хотелось бы узнать как можно будучи админом видеть на какой стадий находиться бизнесс-процесс? После того как я начинаю бизнесс-процесс, он выявляется в панели текущих бизнесс-процессов но когда я на него кликаю там ничего нет...  
Angelina аватар
Стадии процесса можно увидеть только у инициатора процесса пока этот процесс активен. Для этого надо зайти на рабочем столе в More (Еще)->Workflow I've Started (Запущенные мной деловые процессы). Здесь Вы увидете список процессов, поднятых юзером, и среди них и найдете свой процесс.

Также можно самому создать ссылку на данный процесс. Выглядит ссылка примерно вот так:

http:localhost:8080/share/page/workflow-details?workflowId=206006&referrer=workflows
где 206006 - уникальный номер процесса

У каждого процесса свой идентификационный номер, генерируемый самой альфреской. В скрипте внутри описания процессов  напишите:
var  procID = execution.processInstanceId;
где procID и есть тот самый идентификационный номер.
Ну я когда кликаю на свой процесс точнее ваш. Там написано сведения и ничего нет, на какой он сейчас стадий и т.д
Angelina аватар
Эм... не совсем поняла, где и как кликаете. А можете картинку приаттачить?
V dashboard clickayu eshe -> eshe -> moi business processi -> tekushie . I vizhy moi process potom clickayu na nego. I tam napisano svedeniya: i pustota
Angelina аватар
А что в логе пишет при выборе процесса для просмотра? Какая у Вас версия альфреско? Может, у вас share перекошенный?

У меня никогда такой ситуации не возникало, разве что Вы сами прописываете ссылку, в которой указываете идентификационный номер несуществующего процесса.

2013-06-03 15:09:46,702 ERROR [alfresco.web.site] [http-apr-8080-exec-3] javax.servlet.ServletException: Could not resolve view with name '_d41d8cd98f0b24e980998ecf8427e' in servlet with name 'Spring Surf Dispatcher Servlet'
Angelina аватар
Вот, что я нашла по этому поводу: issues.alfresco.com/jira/browse/ALF-16338
Судя по всему, баг определенной версии альфрески. Прямо сейчас у меня 4.0.с Там такого не происходит.

 здравствуй Ангелина незнал куда еще вам написать лично не отправляется. Можно ли создавать бизнес-процессы через Alvex?
Angelina аватар
Вы знаете, этот вопрос лучше задать на форуме ossportal в разделе Альфреско. Боюсь, я Вам не смогу помочь с этим вопросом, а ребята оперативно ответят.
Image and video hosting by TinyPic
Angelina аватар
Выше дала ссылку на талончик в джире. Это баг в определенной версии альфреско. Или поставьте 4.0.c, или же поправьте текущую версию так, как указано в талончике.
Ok spasibo Angelina :))
Добрый день, не могли бы подсказать где ошибка? В логах вот это. Как я понял что то не то в файлах интерфейса ... 12:37:15,116 WARN [org.springframework.extensions.webscripts.DeclarativeRegistry] Unable to register script classpath:alfresco/site-webscripts/org/alfresco/components/dashlets/my-tasks.get.desc.xml due to error: 05070000 Web Script document org/alfresco/components/dashlets/my-tasks.get.desc.xml is attempting to define the url '/components/dashlets/my-tasks:GET' already defined by my-tasks-dashlet/my-tasks.get.desc.xml 12:37:15,117 WARN [org.springframework.extensions.webscripts.DeclarativeRegistry] Unable to register script classpath:alfresco/site-webscripts/org/alfresco/components/footer/footer.get.desc.xml due to error: 05070001 Web Script document org/alfresco/components/footer/footer.get.desc.xml is attempting to define the url '/components/footer:GET' already defined by footer/footer.get.desc.xml 12:37:15,117 WARN [org.springframework.extensions.webscripts.DeclarativeRegistry] Unable to register script classpath:alfresco/site-webscripts/org/alfresco/components/workflow/filter/all.get.desc.xml due to error: 05070002 Web Script document org/alfresco/components/workflow/filter/all.get.desc.xml is attempting to define the url '/components/workflow/filter/all:GET' already defined by all-filter/all.get.desc.xml 12:37:15,117 WARN [org.springframework.extensions.webscripts.DeclarativeRegistry] Unable to register script classpath:alfresco/site-webscripts/org/alfresco/components/workflow/start-workflow.get.desc.xml due to error: 05070003 Web Script document org/alfresco/components/workflow/start-workflow.get.desc.xml is attempting to define the url '/components/workflow/start:GET' already defined by workflow-shortcut-dashlet/start-workflow.get.desc.xml 12:37:15,117 WARN [org.springframework.extensions.webscripts.DeclarativeRegistry] Unable to register script classpath:alfresco/site-webscripts/org/alfresco/components/workflow/task-details-header.get.desc.xml due to error: 05070004 Web Script document org/alfresco/components/workflow/task-details-header.get.desc.xml is attempting to define the url '/components/workflow/task-details-header:GET' already defined by task-details-header/alvex-task-details-header.get.desc.xml 12:37:15,117 WARN [org.springframework.extensions.webscripts.DeclarativeRegistry] Unable to register script classpath:alfresco/site-webscripts/org/alfresco/components/workflow/task-edit-header.get.desc.xml due to error: 05070005 Web Script document org/alfresco/components/workflow/task-edit-header.get.desc.xml is attempting to define the url '/components/workflow/task-edit-header:GET' already defined by task-edit-header/alvex-task-edit-header.get.desc.xml 12:37:15,117 WARN [org.springframework.extensions.webscripts.DeclarativeRegistry] Unable to register script classpath:alfresco/site-webscripts/org/alfresco/components/workflow/task-list.get.desc.xml due to error: 05070006 Web Script document org/alfresco/components/workflow/task-list.get.desc.xml is attempting to define the url '/components/workflow/task-list:GET' already defined by task-list/task-list.get.desc.xml 12:37:15,117 WARN [org.springframework.extensions.webscripts.DeclarativeRegistry] Unable to register script classpath:alfresco/site-webscripts/org/alfresco/components/workflow/workflow-details-header.get.desc.xml due to error: 05070007 Web Script document org/alfresco/components/workflow/workflow-details-header.get.desc.xml is attempting to define the url '/components/workflow/workflow-details-header:GET' already defined by workflow-details-header/alvex-workflow-details-header.get.desc.xml 12:37:15,117 WARN [org.springframework.extensions.webscripts.DeclarativeRegistry] Unable to register script classpath:alfresco/site-webscripts/org/alfresco/components/workflow/workflow-form.get.desc.xml due to error: 05070008 Web Script document org/alfresco/components/workflow/workflow-form.get.desc.xml is attempting to define the url '/components/workflow/workflow-form:GET' already defined by workflow-details-form/workflow-form.get.desc.xml 12:37:15,117 WARN [org.springframework.extensions.webscripts.DeclarativeRegistry] Unable to register script classpath:alfresco/site-webscripts/org/alfresco/components/workflow/workflow-list.get.desc.xml due to error: 05070009 Web Script document org/alfresco/components/workflow/workflow-list.get.desc.xml is attempting to define the url '/components/workflow/workflow-list:GET' already defined by workflow-list/workflow-list.get.desc.xml 12:37:15,117 WARN [org.springframework.extensions.webscripts.DeclarativeRegistry] Unable to register script classpath:alfresco/site-webscripts/org/alfresco/modules/about-share.get.desc.xml due to error: 05070010 Web Script document org/alfresco/modules/about-share.get.desc.xml is attempting to define the url '/modules/about-share:GET' already defined by about-share/about-share.get.desc.xml
Angelina аватар
Это бывает в случаях, когда корежатся стандартные дашлеты в альфреско
 Это не ошибки, всего лишь предупреждения. Появляются после установки Alvex в систему, так как Alvex перезаписывает некоторые стандартные дашлеты, расширяя их функционал. Эти предупреждения не влияют на работу системы. 
 Здравствуйте еще раз, я просто думал что это и есть причина не выевления моего процесса в списке доступных бизнес-процессов. Из за чего это может быть?
Как сделать так чтобы уведомления приходило о результате данного бизнес-процесса (Approve или reject)
Angelina аватар
Результат шага проверки исполнения - Outcome - это в нашем случае свойство.Значения этого свойства описаны в модели. В нашем случае это свойство
dir:appOutcome
значениями которого могут быть approve или reject

Чтобы послать уведомление о решении начальника, мы должны извлечь значение решения и, в зависимости от этого значения, скомпановать письмо.  Шаг проверки исполнения будет выглядеть следующим образом:

<!-- Проверка исполнения -->
		<!-- Задача для начальника -->
		<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'));
                                                        var mail = actions.create("mail");			
                                                        mail.parameters.to = адрес_того_кому_посылаете_уведомление;
							mail.parameters.subject = "Начальник вынес решение об исполнении директивы";
                                                        var text = "Добрый день.\n\n";
                                                        if (task.getVariable('dir_appOutcome')=='reject')
                                                          text += "Исполнение не утверждено";
                                                        else
                                                           text += "Исполнение утверждено";
							mail.parameters.text = text;
							mail.execute(bpm_package);
						</activiti:string>
					</activiti:field>
				</activiti:taskListener>
			</extensionElements>
		</userTask>
 


Я имел ввиду не емайл а в самой шаре в левом нижнем углу. Например исполнения утверждено или наоборот. У инициатора
Angelina аватар
Если честно, не совсем поняла вопрос. 

Все, что находится на рабочем столе - есть дашлеты. Задачи, которые поднимаются  у людей, собираются и показываются в дашлете "Мои задачи" Т е Вам нужно или же написать дашлет, отслеживающий состояние, или же генерить параллельную задачу инициатору, в которой будет описана вся информация текущая.

Также, если Вы выберите в верху рабочего стола Еще - Запущенные мной деловые процессы, Вы увидите список процессов, инициированных данным юзером. И там, нажав на линк соответствующего процесса, увидите все его состояния.
Да чтобы у инициатора в моих задачах высветилось что исполнитель утвержден или наоборот. Ну как в стандартных воркфлоу альфрески
Angelina аватар
Тогда генерите отдельную задачу для инициатора для ознакомления.

Первый способ - это написать простенький процесс, состоящий из одного таска "для ознакомления" и содержащий все необходимые поля. Тогда в скрипте процесса исполнения директивы в процедурах поднимать java script-ом поднимать эти задачи. Код скрипта бывает примерно такой:
var wfdef = workflow.getDefinitionByName("activiti$YourSimpleProcess"); if (wfdef) {
  var wfparams = new Array();
  wfparams["bpm:workflowDescription"] = "Ознакомление";
  wfparams["bpm:assignee"] = initiator.properties.userName;
  wfparams["bpm:workflowPriority"] = bpm_workflowPriority;
  wfparams["bpm:workflowDueDate"] = bpm_workflowDueDate;
  var wfpackage = workflow.createPackage();
  var wfpath = wfdef.startWorkflow(wfpackage, wfparams);
}
Второй способ для генерации параллельных задач - это использовать структуру multiInstanceLoopCharacteristics. Пример ее использования находится в самой Альфреско в ALFRESCO_HOME/tomcat/webapps/alfresco/WEB-INF/classes/alfresco/workflow/parallel-review.bpmn20.xml



Доброе время суток, хотелось бы спросить можно ли стадию исполнения поручения сделать с апрувам и речектом как в проверке исполнения ? Если есть bpm:startTask обязателен ли bpm:workflowTask ? Заранее спасибо
Angelina аватар
"можно ли стадию исполнения поручения сделать с апрувам и речектом как в проверке исполнения"

Можно. Для этого Вы добавляете соответствующие свойства в модель, а в описании процесса в нужном месте ставите развилку.

"Если есть bpm:startTask обязателен ли bpm:workflowTask ?"

На самом деле вопрос включает два подвопроса. Если Вы имеете в виду, можно ли в модели описать только один стартТаск, то ответ - да, можно. Если же вопрос касается того, можно ли в описании процесса описать только один стартТаск, то здесь ответ - нет. Поскольку в описании процессов на активити в каждом процессе, кроме начальной и конечной процедуры  необходимо описать хотя бы один userTask. Хотя и эту проблему можно решить. Если Ваш процесс обязательно должен состоять из стартовой процедуры и конечной  (т е воркфлоу в Альфреске используется, например, как форма заполнения чего-то), то можно ввести timer event и переходить со старта на таймер, ждать пару секунд, а затем завершить процесс.

 Добрый день.

Пытаюсь сделать простенький процесс на основе примера.
Возникла проблема: при описании модели для startTask не указал аспект bpm:assignee. Обнаружилось это, когда при попытке запуска процесса нет возможности указать исполнителя. Добавил в модель аспект, добавлять ведь можно, на сколько я понимаю? Однако ничего не меняется. В какую сторону копать?
Спасибо.