Custom Constraint
В альфреске в Company Home/XML находится position.xml. Задача у меня следующая: на основе этого XML создавать динамический список, собственный constraint для использования в процессе.
Попробовала создать свой LIST, прочитав эту тему - http://www.ecm-alfresco.ru/viewtopic.php?f=14&t=54
- Расширила класс ListOfValuesConstraint
package my.constraints; public class ListOfPositionsConstraint extends ListOfValuesConstraint implements Serializable { private static Log logger = LogFactory.getLog(BaseComponentGenerator.class); private static final long serialVersionUID=1; private FileFolderService fileFolderService; private SearchService searchService; private String POSITIONS_XML = "XML/positions.xml"; private List<String> av = new ArrayList<String>(); public void setFileFolderService(FileFolderService fileFolderService) { this.fileFolderService = fileFolderService; } public void setSearchService(SearchService searchService) { this.searchService = searchService; } private List<String> allowedLabels; public void setAllowedValues(List allowedValues) {} public void setCaseSensitive(boolean caseSensitive) {} public void initialize() { super.setCaseSensitive(true); this.loadData(); } public List getAllowedValues() { this.loadData(); return super.getAllowedValues(); } public List<String> getAllowedLabels() { return this.allowedLabels; } public void setAllowedLabels(List<String> allowedLabels) { this.allowedLabels=allowedLabels; } public List<SelectItem> getSelectItemList() { List<SelectItem> result = new ArrayList<SelectItem>(this.getAllowedValues().size()); for(int i=0;i<this.getAllowedValues().size();i++) { result.add(new SelectItem((Object)this.getAllowedValues().get(i),this.allowedLabels.get(i))); } return result; } protected NodeRef getNodeRef(NodeRef parent, String path) { ... } public List parseXML(NodeRef xml) { ... } protected void loadData() { StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore"); ResultSet rs = searchService.query(storeRef, SearchService.LANGUAGE_XPATH, "/app:company_home"); NodeRef companyHomeRef = null; List<String> av = new ArrayList<String>(); List<String> al=new ArrayList<String>(); try { if (rs.length() == 0) logger.error("Cann't find Company Home"); else companyHomeRef = rs.getNodeRef(0); } finally { rs.close(); } if (companyHomeRef!=null) { NodeRef pNode = getNodeRef(companyHomeRef, POSITIONS_XML); if (pNode!=null) { av = parseXML(pNode); al = av; } else logger.error("Unable to locate "+POSITIONS_XML+" path"); } super.setAllowedValues(av); this.setAllowedLabels(al); } }
- создала service-context.xml и поместила его в tomcat/shared/classes/alfresco/extension/:
<?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="ListOfPositionsConstraint" class="my.constraints.ListOfPositionsConstraint" > <property name="searchService"> <ref bean="searchService" /> </property> <property name="fileFolderService"> <ref bean="fileFolderService"/> </property> </bean> </beans>
- Добавила в модель следующее:
... <constraints> <constraint name="fappgu10:positionsLabel" type="myr.constraints.ListOfPositionsConstraint"> <parameter name="allowedValues"> <list> </list> </parameter> <parameter name="caseSensitive"> <value>true</value> </parameter> </constraint> </constraints> ... <type name="fappgu10:performRequest"> <parent>bpm:workflowTask</parent> <properties> <property name="fappgu10:positions"> <type>d:text</type> <constraints> <constraint ref="fappgu10:positionsLabel" /> </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> <mandatory-aspects> <aspect>fappgu10:mail</aspect> <aspect>fappgu10:mailText</aspect> <aspect>fappgu10:sendByEmail</aspect> <aspect>fappgu10:sendByMail</aspect> <aspect>fappgu10:phone</aspect> <aspect>fappgu10:fname</aspect> <aspect>fappgu10:lname</aspect> <aspect>fappgu10:pname</aspect> <aspect>fappgu10:address</aspect> </mandatory-aspects> </type> ...
Альфреска падает при рестарте с сообщением о неудачной попытке задеплоить модель.
Что я делаю не так?
UPD: Заработало. Новый код:
package my.constraints; public class ListOfPositionsConstraint extends ListOfValuesConstraint implements Serializable { org.alfresco.repo.jscript.ScriptLogger logger = new org.alfresco.repo.jscript.ScriptLogger(); private static final long serialVersionUID=1; private String POSITIONS_XML = "XSL/positions.xml"; private List<String> av = new ArrayList<String>(); private static ServiceRegistry registry; private static Repository repository; public ServiceRegistry getServiceRegistry() { return registry; } public void setServiceRegistry(ServiceRegistry registry) { ListOfPositionsConstraint.registry = registry; } public void setRepository(Repository repository) { ListOfPositionsConstraint.repository = repository; } public Repository getRepository() { return repository; } private List<String> allowedLabels; public void setAllowedValues(List allowedValues) {} public void setCaseSensitive(boolean caseSensitive) {} public void initialize() { super.setCaseSensitive(true); this.loadData(); } public List getAllowedValues() { this.loadData(); return super.getAllowedValues(); } public List<String> getAllowedLabels() { return this.allowedLabels; } public void setAllowedLabels(List<String> allowedLabels) { this.allowedLabels=allowedLabels; } public List<SelectItem> getSelectItemList() { List<SelectItem> result = new ArrayList<SelectItem>(this.getAllowedValues().size()); for(int i=0;i<this.getAllowedValues().size();i++) { result.add(new SelectItem((Object)this.getAllowedValues().get(i),this.allowedLabels.get(i))); } return result; } protected NodeRef getNodeRef(NodeRef parent, String path) { ... } public List parseXML(NodeRef xml) { ... } protected void loadData() { NodeRef companyHomeRef = null; try { companyHomeRef = getRepository().getCompanyHome(); } catch(Exception ex){ logger.error(ex.toString()); } List<String> av = new ArrayList<String>(); List<String> al=new ArrayList<String>(); if (companyHomeRef!=null) { NodeRef pNode = getNodeRef(companyHomeRef, POSITIONS_XML); if (pNode!=null) { av = parseXML(pNode); al = av; } else logger.error("Unable to locate "+POSITIONS_XML+" path"); } super.setAllowedValues(av); this.setAllowedLabels(al); } }
service-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="ListOfPositionsConstraint" class="my.constraints.ListOfPositionsConstraint" > <property name="serviceRegistry"> <ref bean="ServiceRegistry" /> </property> <property name="repository"> <ref bean="repositoryHelper" /> </property> </bean> </beans>
В модели изменений не было.
Комментарии
08/07/2012 - 09:29
А можно увидеть то самое сообщение?
09/07/2012 - 10:37
Ошибка упирается в
Добавила в метод loadData форсированное заполнение списков значений и меток:
Та же ошибка...
09/07/2012 - 11:24
Поняла, где падает. Падает уже на
Убрала из метода loadData все, кроме форсированной инициализации списков. Так работает. Остается понять, почему падает на этих строках.
09/07/2012 - 12:16
Поняла, что нулевым получается ResultSet. Попробовала по-другому запросить company home:
searchService.query(storeRef, SearchService.LANGUAGE_LUCENE, "PATH:\""+"/app:company_home"+"/*\"")
и опять получается нул.
Может, что-то надо включить в альфреске?
09/07/2012 - 13:28
Вообщем, проблемма в том, что я не могу никак вытащить компани хоум. NullPointerExceptoin
Инъектировала в bean ServiceRegistry и repositoryHelper, попыталась вытащить через companyHomeRef = this.repository.getCompanyHome(). То же самое - пусто. Попробую через CMIS, но как-то странно... почему я не могу вытащить альфрескиными апи.
09/07/2012 - 15:33
Странно, должно бы работать. У меня с ходу нет идей, что может быть не так.
09/07/2012 - 16:00
Проблему наконец решила. Пошла путем товарища Джина Бармаша. С одной поправкой: не использовала searchService, поскольку его использование привело к ошибку с правами доступа (замечу, что все делается из-под админа). Сейчас напишу апдейт к посту, вдруг кому полезно будет.
09/07/2012 - 18:46
Предлагаю открыть тикет на JIRA, потому что всё выглядит как-то странно.
10/07/2012 - 11:13
Смотрите, ошибка с нулом исправилась после того, как я изменила сеттеры сервисных параметров. Но при использовании searchService возникла ошибка ProviderNotFoundException (я ее назвала ошибкой доступа) А на это дело я нашла следующий этот талончик. Он вроде у них закрыт за невозможностью воспроизвести... Может быть, все же я что-то не то делаю...
10/07/2012 - 15:00
На сеттеры я внимания не обратил :) Я обычно использую такое описание бина
и такие сеттеры
После этого можно использовать
10/07/2012 - 15:26
Вот с такими сеттерами и бинами у меня нулы и получались в собственном списке. Хотя, к примеру, в модулях истории процессов я также, как и у Вас, использую сеттеры :)
Вообщем, странная история...
10/07/2012 - 15:48
Что-то я торможу. Оно ведь и не должно работать :) В модели указан класс, инстанс которого используется как constraint. При таком подходе не происходит dependency injection, соответственно, получаем null'ы.
03/09/2013 - 11:50
14/09/2013 - 15:38
В документации альфреско есть готовые примеры. Вот здесь, например, описано, как делать вэб скрипты, используя джаву.
18/11/2014 - 13:31
http://forums.alfresco.com/forum/developer-discussions/repository-servic...
Здесь есть объяснение пустого SerchService
https://forums.alfresco.com/forum/developer-discussions/alfresco-api/dyn...
"Sine you implements a dynamic list of constraints like this ,then some one can change your dynamic list of constraints by adding/modifying/deleting node. Adding nodes will not be a problem, but deleting nodes will leave nodes with this property value in an invalid state.
I think the reason why it gets locked indefinetly in the point of the query is because during alfresco startup the search component is busy doing some initialization work ( for example checks consistence between the metadata, indexes and content) and not ready to provide search searvice.
You can try to define your bean like this
Or you can just deploy your custom model into Company Home/Dictionary/Models in Alfresco repository instead of deploying content model XML file in classpath"
20/11/2014 - 21:07
Впрочем, как показала практика, пользоваться data list-ом гораздо быстрее, чем писать собственный констраинт