Alfresco webscripts: первые шаги

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

Для начала немного теории. Ниже приведен мой вольный перевод наиболее важных (на мой взгляд) кусков Alfresco wiki с небольшими комментариями. Ссылки на оригинал — в конце статьи.

Веб-скрипт в терминологии Alfresco —  это RESTful-сервис, который привязан к определенному URI. Веб-скрипт может обрабатывать разные типы HTTP-запросов: GET, PUT, POST, DELETE. Обычно тип запроса выбирается в зависимости от выполняемых функций (GET — выдача данных, PUT — загрузка данных и т.д.). Все скрипты можно поделить на два класса:

  • скрипты, работающие с данными (data webscripts)
  • скрипты представления (presentation webscripts)

Первый тип скриптов, как следует из названия, предназначен для работы с данными в хранилище (repository): чтение, изменение, доступ к различным JavaScript API. Такие скрипты могут быть запущены только внутри Alfresco Repository Server.

Второй тип скриптов используется для создания интерфейса: дашлеты для Share и Explorer, всякие другие штуки :) Эти скрипты в ответ обычно возвращают  HTML (возможно, с клиентским JavaScript кодом).

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

  1. Web Script Runtime (WSR) получает запрос от клиента на конкретный URI. Я долго думал, как правильно перевести WSR на русский язык, но, так и не придумав, решил оставить оригинальное название.
  2. WSR ищет веб-скрипт с соответствующим шаблоном URI (Template URI). Если такой скрипт найден, то он запускается (при необходимости осуществляется процедура аутентификации). Первым шагом исполнения такого веб-скрипта является запуск соответствующего ему js-контроллера.
  3. При помощи js-контроллера можно получить доступ к различнысм сервисам Alfresco. Если js-скрипт запущен внутри Alfresco Repository Server, то он может получить доступ к хранилищу, изменять и/или создавать документы, использовать различные сервисы и API (People API, Search API и т.д.). Если же скрипт запущен вне Alfresco Repository Server, то он может использовать вызов других скриптов для доступа к хранилищу.
  4. Данные, собранные при помощи js-контроллера, преобразыются в выходной формат при помощи шаблонов ответа (response templates) FreeMarker. Выходных форматов достаточно много, наиболее часто используемыми из них являются HTML, JSON, XML, RSS.
  5. WSR отправляет клиенту сформированный ответ.
  6. Клиент получает ответ от WSR в запрошенном формате.

На этом, я думаю, можно перейти к практике. Для описания своего веб-скрипта нам потребуется написать несколько файлов, а именно:

  • listhome.get.desc.xml — описание скрипта
  • <!--Начало описания скрипта-->
    <webscript>
    	<!--Короткое название-->
    	<shortname>List Home Webscript</shortname>
    	<!--Описание-->
    	<description>Lists user's home directory</description>
    	<!--
    		URI скрипта
    		скрипт будет доступен по адресу
    		http[s]://hostname:port/alfresco/service/ossportal/listhome
     
    		скрипт может принимать необязательный аргумент dirsonly
    		-->
    	<url>/ossportal/listhome?dirsonly={dirsonly?}</url>
    	<!--
    		Способ указания выходного формата и формат по умолчанию
     
    		Для указания выходного формата может использоваться как передача
    		отдельного параметра ?format=FMT так и расширение listhome.FMT
     
    		Выходной формат по умолчанию - JSON
    		-->
    	<format default="json">any</format>
    	<!--
    		Аутентификация
     
    		Этот скрипт будет доступен любому пользователю системы (требуются
    		логин и пароль
    		-->
    	<authentication>user</authentication>
    	<!--Включаем транзакции для доступа к хранилищу-->
    	<transaction>required</transaction>
    	<!--Тип скрипта: демонстрационный-->
    	<lifecycle>sample</lifecycle>
    </webscript>
    <!--Конец описания скрипта-->
     
  • listhome.get.js — js-контроллер
  • // получаем значение параметра dirsonly
    var dirsonly = args["dirsonly"] == 'true' ? true : false;
     
    // инициализируем массив
    list = [];
    // перебираем все элементы в домашней папке
    for each(var child in userhome.children)
    	// проверяем, нужно ли отображать этот элемент
    	if ((child.isContainer && dirsonly) || !dirsonly)
    		// добавляем новый объект в список
    		list.push(
    				{
    					"name": child.properties["cm:name"],
    					"uuid": child.properties["sys:node-uuid"],
    					"folder": child.isContainer
    				});
     
    // заполняем model для передачи данных в FreeMarker
    model.data = {"userhome": userhome.displayPath, "items" :list};
     
  • listhome.get.xml.ftl — шаблон для вывода XML
  • <?xml version="1.0" encoding="utf8"?>
    <#--Включаем экранирование символов-->
    <#escape x as x?xml>
    <#--Корневой элемент-->
    <dirslist>
    	<data>
    		<userhome>${data.userhome}</userhome>
    		<items>
    			<#--
    				Перебираем все элементы в items
    				и формируем ответ
    				-->
    			<#list data.items as item>
    			<item>
    				<name>${item.name}</name>
    				<uuid>${item.uuid}</uuid>
    				<folder>${item.folder?string}</folder>
    			</item>
    			</#list>
    		</items>
    	</data>
    </dirslist>
    </#escape>
     
  • listhome.get.json.ftl — шаблон для вывода JSON
  • <#--Включаем экранирование символов-->
    <#escape x as jsonUtils.encodeJSONString(x)>
    {
    	<#--Корневой элемент-->
    	"data":
    	{
    		<#-- Домашняя папка -->
    		"userhome": "${data.userhome}",
    		<#-- Список элементов -->
    		"items":
    		[
    			<#--
    				Перебираем все элементы в items
    				и формируем ответ
    				-->
    			<#list data.items as item>
    			{
    				"name": "${item.name}",
    				"uuid": "${item.uuid}",
    				"folder": ${item.folder?string}
    			}<#if item_has_next>,</#if>
    			</#list>
    		]
    	}
    }
    </#escape>

 Небольшое пояснение к шаблоном: ftl файлы представяют из себя неизменяемый текст, специальные директивы (тэги, начинающиеся с #), подстановки (начинаются с $). Ссылка на более подробное описание в конце статьи.

 

Теперь можно положить файлы скрипта в tomcat/shared/classes/alfresco/templates/webscripts/ и перезапустить сервер. После этого открываем в браузере наш скрипт http[s]://host:port/alfresco/service/ossportal/listhome.xml?dirsonly=true и видим результат:

<?xml version="1.0" encoding="utf8"?>
<dirslist>
	<data>
		<userhome></userhome>
		<items>
			<item>
				<name>Data Dictionary</name>
				<uuid>1fdd3e22-ad92-4a01-ad24-30eee808b874</uuid>
				<folder>true</folder>
 
			</item>
			<item>
				<name>Guest Home</name>
				<uuid>fd764456-5846-42d4-ae56-0a78d5c76d54</uuid>
				<folder>true</folder>
			</item>
			<item>
 
				<name>User Homes</name>
				<uuid>605bec60-d9ee-44b8-b5c5-8aab52fa33bc</uuid>
				<folder>true</folder>
			</item>
			<item>
				<name>Sites</name>
				<uuid>9b37df4b-cc14-4145-bd06-1ddc138eaea5</uuid>
 
				<folder>true</folder>
			</item>
			<item>
				<name>Web Projects</name>
				<uuid>34cb7801-07d3-4e66-b18a-3f07d0b79429</uuid>
				<folder>true</folder>
			</item>
 
			<item>
				<name>Web Deployed</name>
				<uuid>ad100a03-c00e-468c-aa97-035b5393a71e</uuid>
				<folder>true</folder>
			</item>
			<item>
				<name>sreewew</name>
 
				<uuid>62d7a796-e94d-4f26-a3d4-fd4d5254b34e</uuid>
				<folder>true</folder>
			</item>
			<item>
				<name>testfolder</name>
				<uuid>d7785b81-2aee-4a96-877d-ac8b720acaf8</uuid>
				<folder>true</folder>
 
			</item>
			<item>
				<name>testfolder2</name>
				<uuid>47121149-431c-4a4b-8360-ad127c27d7b2</uuid>
				<folder>true</folder>
			</item>
			<item>
 
				<name>testfolder3</name>
				<uuid>878053e2-d74d-4fad-94a8-e81f2bf2e303</uuid>
				<folder>true</folder>
			</item>
		</items>
	</data>
</dirslist>
 

 

Полезные ссылки по теме

2111
Прикрепленные файлыРазмер
listhome_webscript.zip3.26 кб