<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9096196924950961475</id><updated>2024-10-12T15:51:42.652-07:00</updated><category term="jbpm"/><category term="wicket"/><category term="solution"/><category term="java"/><category term="installation"/><category term="jboss"/><category term="process management engine"/><category term="spring"/><category term="web-framework"/><category term="workflow engine"/><category term="JasperReports"/><category term="UTF-8"/><category term="WebMoney"/><category term="ajax"/><category term="apache"/><category term="commons-configuration"/><category term="ejb3"/><category term="fonts"/><category term="jpa"/><category term="jpdl"/><category term="performance"/><category term="spring ३"/><category term="tapestry"/><category term="validators"/><title type='text'>Java development</title><subtitle type='html'>&quot;На тысячу обрывающих листья с дерева зла находится лишь один, рубящий его под корень.&quot; Генри Дэвид Торо.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>18</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-4751609160238885504</id><published>2012-08-21T01:40:00.000-07:00</published><updated>2012-08-29T05:04:21.652-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="fonts"/><category scheme="http://www.blogger.com/atom/ns#" term="JasperReports"/><category scheme="http://www.blogger.com/atom/ns#" term="solution"/><category scheme="http://www.blogger.com/atom/ns#" term="UTF-8"/><title type='text'>Использование шрифтов в JasperReports</title><content type='html'>Не так давно одной из моих задач было создать модуль отчетности, позволяющий разным клиентским приложениям использовать его  для генерации и отдачи сгенерированного контента. 
При реализации этой задачи я активно работал с библиотекой JasperReports 4.5.1. Одна из первоочередных задач при работе с кирилическими документами - подключение шрифтов. В стандартном варианте подключения JasperRepots не имеет поддержки UTF-8 шрифтов. В нашем случае были необходимы шрифты Arial и Helvetica. Ни того ни другого нет по умолчанию. Дальше я опишу два подхода. Первый был выбран на скорую руку и я впоследствии решил от него отказаться. Второй подход - то как надо было делать сразу и он верный. 
&lt;p&gt;
&lt;b&gt;Решение 1. - Неправильное(мое оценочное суждение).&lt;/b&gt; 
&lt;ul&gt;
&lt;li&gt; Скачать файлы ttf, из интернета, либо, если у вас windows, то их можно найти в директории &lt;b&gt;{WIN_INSTALLATION_DIR}\Fonts\&lt;/b&gt; 
&lt;li&gt; Положить эти файлы в директорию проекта, чтобы они были доступны в &lt;b&gt;classpath&lt;/b&gt;. Например сюда &lt;b&gt;{project_dir}\src\main\resources\Arial.ttf&lt;/b&gt; 
&lt;li&gt; Явно указать название файла в отчете.
&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[   
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;jasperReport xmlns=&quot;http://jasperreports.sourceforge.net/jasperreports&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xsi:schemaLocation=&quot;http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd&quot; name=&quot;BasicReport&quot; pageWidth=&quot;595&quot; pageHeight=&quot;842&quot; whenNoDataType=&quot;AllSectionsNoDetail&quot; columnWidth=&quot;555&quot; leftMargin=&quot;20&quot; rightMargin=&quot;20&quot; topMargin=&quot;20&quot; bottomMargin=&quot;20&quot;&gt;
 &lt;property name=&quot;ireport.zoom&quot; value=&quot;1.3310000000000004&quot;/&gt;
 &lt;property name=&quot;ireport.x&quot; value=&quot;0&quot;/&gt;
 &lt;property name=&quot;ireport.y&quot; value=&quot;0&quot;/&gt;
 &lt;style name=&quot;Default&quot; isDefault=&quot;true&quot; fontName=&quot;Helvetica&quot; fontSize=&quot;10&quot; 
 isBold=&quot;false&quot; isItalic=&quot;false&quot; isUnderline=&quot;false&quot; isStrikeThrough=&quot;false&quot; 
 pdfFontName=&quot;Helvetica.ttf&quot; pdfEncoding=&quot;Cp1251&quot; isPdfEmbedded=&quot;true&quot;/&gt;

&lt;!-- template code here--&gt;



&lt;/jasperReport&gt;
]]&gt;&lt;/script&gt;
&lt;/ul&gt; 

Такой подход привел сразу к проблемам, выяснилось, что выделение жирным не работает, потому что указанный шрифт не содержит жирного варианта. Была выбрана заплатка в таком виде - явно указывать шрифт для элемента. Поскольку сроки поджимали так и было сделано: 
&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[   
&lt;textField isStretchWithOverflow=&quot;true&quot;&gt;
    &lt;reportElement x=&quot;341&quot; y=&quot;353&quot; width=&quot;214&quot; height=&quot;16&quot;/&gt;
    &lt;textElement textAlignment=&quot;Left&quot; markup=&quot;none&quot;&gt;
     &lt;font size=&quot;10&quot; isBold=&quot;true&quot; isUnderline=&quot;false&quot; pdfFontName=&quot;Helvetica Bold.ttf&quot;/&gt;
    &lt;/textElement&gt;
    &lt;textFieldExpression class=&quot;java.lang.String&quot;&gt;&lt;![CDATA[$F{fio}]]&gt;&lt;/textFieldExpression&gt;
   &lt;/textField&gt;
&lt;/script&gt;

Конечно, это жутко неудобно не только потому, что так можно делать только для элемента, а внутри элемента разделение на жирный и нежирный шрифт работать не будет, но и как следствие мы лишаемся гибкости в комбинировании элементов и их расположении. Ну и плюс к тому нужно постоянно прописывать явно имя шрифта. Почитав внимательнее документацию по JasperReports был выбран и использован верный способ работы со шрифтами. 

&lt;p&gt;
&lt;b&gt;Решение 2 - Правильное(рекомендованное документацией и сообществом JasperReports)&lt;/b&gt;
&lt;p&gt;
Для этого решения используется расширение стандартных шрифтов JasperReports через конфигурационные файлы. Шаги следующие: 
&lt;ul&gt;
&lt;li&gt; Скачать/скопировать необходимые шрифты в папку &lt;b&gt;{project_dir}\src\main\resources\fonts&lt;/b&gt;
&lt;li&gt; Создать файл jasperreports_extension.properties в директории &lt;b&gt;{project_dir}\src\main\resources\&lt;/b&gt;. Файл приведен ниже:
&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: text;&quot;&gt;&lt;![CDATA[   
net.sf.jasperreports.extension.registry.factory.fonts=net.sf.jasperreports.engine.fonts.SimpleFontExtensionsRegistryFactory
net.sf.jasperreports.extension.simple.font.families.myfamily=fonts/specialfonts.xml
]]&gt;&lt;/script&gt;

&lt;li&gt; Создать файл specialfonts.xml в директории &lt;b&gt;{project_dir}\src\main\resources\fonts &lt;/b&gt;
Файл содержит описание того откуда JasperRepots будет брать файлы шрифтов и какой файл какому(жирному, курсиву и т.д.) стилю соответствует. Ниже пример моего файла: 
&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[   
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;fontFamilies&gt;

    &lt;fontFamily name=&quot;Helvetica&quot;&gt;
        &lt;normal&gt;&lt;![CDATA[fonts/Helvetica.ttf]]&gt;&lt;/normal&gt;
        &lt;bold&gt;&lt;![CDATA[fonts/Helvetica Bold.ttf]]&gt;&lt;/bold&gt;
        &lt;pdfEmbedded&gt;&lt;![CDATA[true]]&gt;&lt;/pdfEmbedded&gt;
    &lt;/fontFamily&gt;

    &lt;fontFamily name=&quot;Arial&quot;&gt;
        &lt;normal&gt;&lt;![CDATA[fonts/arial.ttf]]&gt;&lt;/normal&gt;
        &lt;bold&gt;&lt;![CDATA[fonts/arialbd.ttf]]&gt;&lt;/bold&gt;
        &lt;italic&gt;&lt;![CDATA[fonts/ariali.ttf]]&gt;&lt;/italic&gt;
        &lt;boldItalic&gt;&lt;![CDATA[fonts/arialbi.ttf]]&gt;&lt;/boldItalic&gt;
        &lt;pdfEmbedded&gt;&lt;![CDATA[true]]&gt;&lt;/pdfEmbedded&gt;
    &lt;/fontFamily&gt;


&lt;/fontFamilies&gt;

&lt;/script&gt;

&lt;li&gt; Указать какой шрифт будет использоваться в шаблоне отчета.
&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[   
&lt;style name=&quot;Default&quot; isDefault=&quot;true&quot; fontName=&quot;Helvetica&quot; fontSize=&quot;10&quot; isBold=&quot;false&quot; 
 isItalic=&quot;false&quot; isUnderline=&quot;false&quot; isStrikeThrough=&quot;false&quot; pdfEncoding=&quot;Cp1251&quot;     isPdfEmbedded=&quot;true&quot;/&gt;

]]&gt;
&lt;/script&gt;
&lt;/ul&gt;
&lt;p&gt;
Плюс этого подхода в том, что в шаблоне указывается просто имя шрифта, весь маппинг и настройки находятся за пределами шаблона. Дополнительно мы получаем гибкость в использовании жирных курсивов и прочих вариантов текста внутри одного шрифта. 
















</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/4751609160238885504/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2012/08/jasperreports.html#comment-form' title='Комментарии: 4'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/4751609160238885504'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/4751609160238885504'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2012/08/jasperreports.html' title='Использование шрифтов в JasperReports'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-2460372109006827271</id><published>2012-08-20T07:05:00.002-07:00</published><updated>2012-08-21T01:46:55.954-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ejb3"/><category scheme="http://www.blogger.com/atom/ns#" term="jboss"/><category scheme="http://www.blogger.com/atom/ns#" term="jpa"/><title type='text'>JBOSS 7 and several persistence units.</title><content type='html'>В течение этого года один из проектов, в котором я участвую, пишется с использованием технологий JEE, EJB3, JPA. Проект интеграционный и зачастую возникает задача использования нескольких баз в рамках одного модуля. Решается это просто: используется несколько persistence-unit в рамках одного persistence.xml. Например вот так: 
&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[   
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;persistence version=&quot;1.0&quot; xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot;
             xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
             xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd&quot;&gt;
    &lt;persistence-unit name=&quot;CoreReportJPA&quot; transaction-type=&quot;JTA&quot;&gt;
        &lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
        &lt;jta-data-source&gt;java:app/env/datasource/processDS&lt;/jta-data-source&gt;
        &lt;mapping-file&gt;META-INF/report-orm.xml&lt;/mapping-file&gt;
        &lt;class&gt;com.blogger.anpetrov.jpa.ReportCategory&lt;/class&gt;
        &lt;class&gt;com.blogger.anpetrov.jpa.ReportTemplate&lt;/class&gt;

        &lt;class&gt;com.blogger.anpetrov.process.jpa.StartPrivelegy&lt;/class&gt;
        &lt;class&gt;com.blogger.anpetrov.process.jpa.ProcessCategory&lt;/class&gt;
        &lt;properties&gt;
            &lt;property name=&quot;jboss.as.jpa.providerModule&quot; value=&quot;org.hibernate:3&quot;/&gt;
            &lt;property name=&quot;javax.persistence.lock.timeout&quot; value=&quot;50&quot;/&gt;
            &lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.Oracle10gDialect&quot;/&gt;
            &lt;property name=&quot;hibernate.show_sql&quot; value=&quot;false&quot;/&gt;
            &lt;property name=&quot;hibernate.transaction.manager_lookup_class&quot;
                      value=&quot;org.hibernate.transaction.JBossTransactionManagerLookup&quot;/&gt;

            &lt;property name=&quot;jboss.entity.manager.factory.jndi.name&quot; value=&quot;java:/CoreReportJPAFactory&quot;/&gt;
            &lt;property name=&quot;jboss.entity.manager.jndi.name&quot; value=&quot;java:/CoreReportJPA&quot;/&gt;
        &lt;/properties&gt;
    &lt;/persistence-unit&gt;

    &lt;persistence-unit name=&quot;CoreReportAnotherSchemaJPA&quot; transaction-type=&quot;JTA&quot;&gt;
        &lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
        &lt;jta-data-source&gt;java:jboss/datasources/another-schema&lt;/jta-data-source&gt;
        &lt;mapping-file&gt;META-INF/report-another-schema.xml&lt;/mapping-file&gt;

        &lt;class&gt;com.blogger.anpetrov.jpa.Division&lt;/class&gt;
        &lt;class&gt;com.blogger.anpetrov.jpa.DicDivision&lt;/class&gt;
        &lt;properties&gt;
            &lt;property name=&quot;jboss.as.jpa.providerModule&quot; value=&quot;org.hibernate:3&quot;/&gt;
            &lt;property name=&quot;javax.persistence.lock.timeout&quot; value=&quot;50&quot;/&gt;
            &lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.Oracle10gDialect&quot;/&gt;
            &lt;property name=&quot;hibernate.show_sql&quot; value=&quot;false&quot;/&gt;
            &lt;property name=&quot;hibernate.transaction.manager_lookup_class&quot;
                      value=&quot;org.hibernate.transaction.JBossTransactionManagerLookup&quot;/&gt;

            &lt;property name=&quot;jboss.entity.manager.factory.jndi.name&quot; value=&quot;java:/CoreReportAnotherSchemaJPAFactory&quot;/&gt;
            &lt;property name=&quot;jboss.entity.manager.jndi.name&quot; value=&quot;java:/CoreReportAnotherSchemaJPA&quot;/&gt;
        &lt;/properties&gt;
    &lt;/persistence-unit&gt;
&lt;/persistence&gt;

]]&gt;&lt;/script&gt;

Все бы ничего вот только проблема заключается в том, что при таком подходе при запуске JBOSS жалуется на ошибку инициализации CoreReportAnotherSchemaJPA контекста, он пытается в нем найти связку для класса ReportCategory, который вроде бы даже не определен в этом persistence-unit. Оказывается проблема заключается в следующем. При определении персистеных классов во всех модулях нашего проекта используется аннотация Entity. Ниже пример такого класса: 
&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;![CDATA[   
@Entity
@Table(name = &quot;BP_REPORT_CATEGORY&quot;, schema = &quot;BASE&quot;)
public class ReportCategory implements Serializable {
//other code

}

]]&gt;&lt;/script&gt;

При старте приложения, сервер приложений не обращает внимание на то, что явно указаны классы в persistence-unit он сканирует на предмет наличия аннотации Entity доступный в classpath классы. Отсюда возникает эта коллизия. 
Решение оказалось довольно простым в спецификации есть тег exclude-unlisted-classes по умолчанию он имеет значение false, поэтому и добавляются не нужные мне классы и происходит коллизия с тем что указано. Включив этот флажок получаем именно то что нам нужно - включаться будут только те классы что указаны руками. Конечно, в обычном приложении без интеграционных замарочек с legacy кодом в разных базах такой проблемы не возникнет. Но кому-то все же этот прием может понадобится. Ниже приведен пример работающего кода с означенным тегом:


&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[   
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;persistence version=&quot;1.0&quot; xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot;
             xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
             xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd&quot;&gt;
    &lt;persistence-unit name=&quot;CoreReportJPA&quot; transaction-type=&quot;JTA&quot;&gt;
        &lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
        &lt;jta-data-source&gt;java:app/env/datasource/processDS&lt;/jta-data-source&gt;
        &lt;mapping-file&gt;META-INF/report-orm.xml&lt;/mapping-file&gt;
        &lt;class&gt;com.blogger.anpetrov.jpa.ReportCategory&lt;/class&gt;
        &lt;class&gt;com.blogger.anpetrov.jpa.ReportTemplate&lt;/class&gt;

        &lt;class&gt;com.blogger.anpetrov.process.jpa.StartPrivelegy&lt;/class&gt;
        &lt;class&gt;com.blogger.anpetrov.process.jpa.ProcessCategory&lt;/class&gt;

        &lt;exclude-unlisted-classes&gt;true&lt;/exclude-unlisted-classes&gt;
        &lt;properties&gt;
            &lt;property name=&quot;jboss.as.jpa.providerModule&quot; value=&quot;org.hibernate:3&quot;/&gt;
            &lt;property name=&quot;javax.persistence.lock.timeout&quot; value=&quot;50&quot;/&gt;
            &lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.Oracle10gDialect&quot;/&gt;
            &lt;property name=&quot;hibernate.show_sql&quot; value=&quot;false&quot;/&gt;
            &lt;property name=&quot;hibernate.transaction.manager_lookup_class&quot;
                      value=&quot;org.hibernate.transaction.JBossTransactionManagerLookup&quot;/&gt;

            &lt;property name=&quot;jboss.entity.manager.factory.jndi.name&quot; value=&quot;java:/CoreReportJPAFactory&quot;/&gt;
            &lt;property name=&quot;jboss.entity.manager.jndi.name&quot; value=&quot;java:/CoreReportJPA&quot;/&gt;
        &lt;/properties&gt;
    &lt;/persistence-unit&gt;

    &lt;persistence-unit name=&quot;CoreReportAnotherSchemaJPA&quot; transaction-type=&quot;JTA&quot;&gt;
        &lt;provider&gt;org.hibernate.ejb.HibernatePersistence&lt;/provider&gt;
        &lt;jta-data-source&gt;java:jboss/datasources/another-schema&lt;/jta-data-source&gt;
        &lt;mapping-file&gt;META-INF/report-another-schema.xml&lt;/mapping-file&gt;

        &lt;class&gt;com.blogger.anpetrov.jpa.Division&lt;/class&gt;
        &lt;class&gt;com.blogger.anpetrov.jpa.DicDivision&lt;/class&gt;

        &lt;exclude-unlisted-classes&gt;true&lt;/exclude-unlisted-classes&gt;
        &lt;properties&gt;
            &lt;property name=&quot;jboss.as.jpa.providerModule&quot; value=&quot;org.hibernate:3&quot;/&gt;
            &lt;property name=&quot;javax.persistence.lock.timeout&quot; value=&quot;50&quot;/&gt;
            &lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.Oracle10gDialect&quot;/&gt;
            &lt;property name=&quot;hibernate.show_sql&quot; value=&quot;false&quot;/&gt;
            &lt;property name=&quot;hibernate.transaction.manager_lookup_class&quot;
                      value=&quot;org.hibernate.transaction.JBossTransactionManagerLookup&quot;/&gt;

            &lt;property name=&quot;jboss.entity.manager.factory.jndi.name&quot; value=&quot;java:/CoreReportAnotherSchemaJPAFactory&quot;/&gt;
            &lt;property name=&quot;jboss.entity.manager.jndi.name&quot; value=&quot;java:/CoreReportAnotherSchemaJPA&quot;/&gt;
        &lt;/properties&gt;
    &lt;/persistence-unit&gt;
&lt;/persistence&gt;

]]&gt;&lt;/script&gt;














</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/2460372109006827271/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2012/08/jboss-7-and-several-persistence-units.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/2460372109006827271'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/2460372109006827271'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2012/08/jboss-7-and-several-persistence-units.html' title='JBOSS 7 and several persistence units.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-1158103880651680974</id><published>2011-01-26T13:07:00.000-08:00</published><updated>2011-01-26T14:06:04.009-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="solution"/><category scheme="http://www.blogger.com/atom/ns#" term="spring ३"/><title type='text'>Использование placeholders из одного properties файла для конфигурации другого.</title><content type='html'>&lt;p&gt;Иногда появляются нетривиальные задачи конфигурирования приложения для определенных нужд. Один из примеров: есть приложение, которое должно работать в разных environment&#39;ах: development, test, production. В зависимости от environment&#39;а используются разные файлы конфигурации/настройки. Другой пример - одно и тоже приложение может запускаться в нескольких экземплярах в одном application-сервере, при этом по разному сконфигурировано, с помощью разных файлов настроек.&lt;br /&gt;Во втором случае одно из достаточно неплохих решений я опишу ниже. Файлы конфигурации - это обычные property-файлы с парами ключ значение. При этом конфигуарция всех модулей находится в одном месте, путь к которому я указываю через переменную окружения CONF_HOME. Эта переменная указывает на корень конфигурации. А в нем уже идут директории module1, module2, ..., moduleN, module1-diffconfig, modulek-n-configuration. Внутри каждой папки есть файлы типа conf.properties.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;В spring чтобы использовать значения из файлов настройки в виде ${server.property1} нужно объявить в context.xml следующую конструкцию:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[   &lt;bean id=&quot;serverProperties&quot; class=&quot;org.springframework.beans.factory.config.PropertiesFactoryBean&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;locations&quot;&gt;&lt;br /&gt;            &lt;list&gt;&lt;br /&gt;                &lt;value&gt;file:${CONF_HOME}/module1/conf.properties&lt;/value&gt;&lt;br /&gt;            &lt;/list&gt;&lt;br /&gt;        &lt;/property&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;propertyConfigurer&quot; class=&quot;org.springframework.beans.factory.config.PropertyPlaceholderConfigurer&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;properties&quot; ref=&quot;serverProperties&quot;&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Но ведь мне нужно иметь возможность без перекомпиляции модуля запустить несколько его экземпляров с разными файлами настройки.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Решение следующее: в каталоге CONF_HOME для каждого экземпляра модуля заводится отдельная папка, а в ней находятся файлы настройки с одинаковыми именами,но, понятно, с разными значениями одних и тех же параметров:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: text;&quot;&gt;&lt;![CDATA[ &lt;br /&gt;CONF_HOME       &lt;br /&gt;     module1           &lt;br /&gt;         conf.properties       &lt;br /&gt;     module2       &lt;br /&gt;     module1-specific-conf           &lt;br /&gt;         conf.properties&lt;br /&gt;         ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Понятно, что основной вопрос - как нам изменить строчку в context.xml&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;value&gt;file:${CONF_HOME}/module1/conf.properties&lt;/value&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;чтобы вместо module1 подставлялось значение для конкретного экземляпра модуля. Решений может быть несколько, один из простых вариантов - сделать дополнительный файл настроек module.properties в котором будет одно поле nodeName=module-specific-conf. Можно сделать таким образом, чтобы это значение подменялось при мавенской сборке. Поскольку это не тема данной статьи, то варианты решения я оставлю на усмотрение любознательного читателя.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Итак я сделал дополнительный файл настроек, который собирается в war-ник и его значение используется при поиске специфичных для приложения настроек.&lt;br /&gt;Казалось бы теперь все очень просто и нам должна помочь вот такая конструкция:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[   &lt;bean id=&quot;moduleNameProperties&quot; class=&quot;org.springframework.beans.factory.config.PropertiesFactoryBean&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;locations&quot;&gt;&lt;br /&gt;            &lt;list&gt;&lt;br /&gt;                &lt;value&gt;classpath:org/anpetrov/test/conf.properties&lt;/value&gt;&lt;br /&gt;            &lt;/list&gt;&lt;br /&gt;        &lt;/property&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;serverProperties&quot; class=&quot;org.springframework.beans.factory.config.PropertiesFactoryBean&quot; on=&quot;moduleNameProperties&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;locations&quot;&gt;&lt;br /&gt;            &lt;list&gt;&lt;br /&gt;                &lt;value&gt;file:${CONF_HOME}/${nodeName}/conf.properties&lt;/value&gt;&lt;br /&gt;            &lt;/list&gt;&lt;br /&gt;        &lt;/property&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;propertyConfigurer&quot; class=&quot;org.springframework.beans.factory.config.PropertyPlaceholderConfigurer&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;properties&quot; ref=&quot;serverProperties&quot;&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Но ни тут-то было. Spring при инициализации бина, не может распознать nodeName. Оказывается это связано с некой спецификой при загрузке property-файлов и работы PropertyPlaceholderConfigurer-ов. На форуме Spring&#39;а есть несколько тем и даже запросы в джире на изменения, но все мимо. На помощь приходит SpEL - Spring Expression Language, появившийся в Spring 3. С его помощью проблема решается просто и элегантно. Вот так:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[   &lt;bean id=&quot;moduleNameProperties&quot; class=&quot;org.springframework.beans.factory.config.PropertiesFactoryBean&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;locations&quot;&gt;&lt;br /&gt;            &lt;list&gt;&lt;br /&gt;                &lt;value&gt;classpath:org/anpetrov/test/conf.properties&lt;/value&gt;&lt;br /&gt;            &lt;/list&gt;&lt;br /&gt;        &lt;/property&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;serverProperties&quot; class=&quot;org.springframework.beans.factory.config.PropertiesFactoryBean&quot; on=&quot;moduleNameProperties&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;locations&quot;&gt;&lt;br /&gt;            &lt;list&gt;&lt;br /&gt;                &lt;value&gt;file:${CONF_HOME}/#{moduleNameProperties.nodeName}/conf.properties&lt;/value&gt;&lt;br /&gt;            &lt;/list&gt;&lt;br /&gt;        &lt;/property&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;propertyConfigurer&quot; class=&quot;org.springframework.beans.factory.config.PropertyPlaceholderConfigurer&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;properties&quot; ref=&quot;serverProperties&quot;&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Объяснения требует лишь одно выражение:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[ #{connectorNameProperties.nodeName} ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Здесь решетка означает, что дальше идет SpEL, а дальнейшее - это доступ к бину и его свойству. Вот все просто получилось, благодаря третьему Spring. &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/1158103880651680974/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2011/01/placeholders-properties.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/1158103880651680974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/1158103880651680974'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2011/01/placeholders-properties.html' title='Использование placeholders из одного properties файла для конфигурации другого.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-5525557247261247298</id><published>2010-04-21T10:56:00.000-07:00</published><updated>2010-04-21T11:00:52.746-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ajax"/><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="wicket"/><title type='text'>Wicket  работа с Ajax</title><content type='html'>&lt;p&gt;Рассмотрим как работает Wicket с Ajax. Для демонстрации рассмотрим следующий пример: при нажатии на гиперссылку, меняется содержимое другой области страницы.&lt;br /&gt;Шаблон страницы:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;&lt;br /&gt;        &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;&lt;br /&gt;&lt;html xmlns:wicket=&quot;http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd&quot;&gt;&lt;br /&gt;&lt;body&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;            &lt;a href=&quot;#&quot; wicket:id=&quot;amountLink&quot;&gt;&lt;br /&gt;                &lt;span wicket:id=&quot;description&quot;&gt;100 рублей&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;            &lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;После проведения операции с Вас будет списано &lt;span wicket:id=&quot;totalAmount&quot;&gt;108&lt;/span&gt; рублей&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;Класс страницы:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;import org.apache.wicket.markup.html.WebPage;&lt;br /&gt;import org.apache.wicket.markup.html.basic.Label;&lt;br /&gt;import org.apache.wicket.markup.html.link.Link;&lt;br /&gt;import org.apache.wicket.PageParameters;&lt;br /&gt;import org.apache.wicket.model.PropertyModel;&lt;br /&gt;import org.apache.wicket.ajax.markup.html.AjaxFallbackLink;&lt;br /&gt;import org.apache.wicket.ajax.AjaxRequestTarget;&lt;br /&gt;&lt;br /&gt;import java.math.BigDecimal;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class Example extends WebPage {&lt;br /&gt;    private String totalAmount;&lt;br /&gt;    private Integer amountInt;&lt;br /&gt;&lt;br /&gt;    public Example(PageParameters aParameters) {&lt;br /&gt;        super(aParameters);&lt;br /&gt;        final Label totalAmountLabel = new Label(&quot;totalAmount&quot;, new PropertyModel(this, &quot;totalAmount&quot;));&lt;br /&gt;        totalAmountLabel.setOutputMarkupId(true);&lt;br /&gt;        add(totalAmountLabel);&lt;br /&gt;        Link link = new AjaxFallbackLink(&quot;amountLink&quot;, new PropertyModel(this, &quot;value&quot;)) {&lt;br /&gt;            @Override&lt;br /&gt;            public void onClick(AjaxRequestTarget target) {&lt;br /&gt;                if (target != null) {&lt;br /&gt;                    Integer value = (Integer) getModelObject();&lt;br /&gt;                    totalAmount = extractTotalAmount(value);&lt;br /&gt;                    amountInt = value;&lt;br /&gt;                    target.addComponent(totalAmountLabel);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;        link.add(new Label(&quot;description&quot;, &quot;пополнить&quot;));&lt;br /&gt;        add(link);&lt;br /&gt;        amountInt = 0;&lt;br /&gt;        totalAmount = extractTotalAmount(amountInt);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public String getTotalAmount() {&lt;br /&gt;        return totalAmount;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setTotalAmount(String totalAmount) {&lt;br /&gt;        this.totalAmount = totalAmount;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private Integer getValue() {&lt;br /&gt;        return 5;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    private String extractTotalAmount(Integer value) {&lt;br /&gt;        BigDecimal bigDecimal = BigDecimal.valueOf(value).multiply(BigDecimal.valueOf(1.008));&lt;br /&gt;        return String.format(&quot;%.2f&quot;, bigDecimal);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Из кода видно, что при клике на гиперссылке, происходит ajax вызов метода onClick класса гиперссылки. Внутри этого метода обновляется значение поля totalAmountLabel. Чтобы обновление действительно произошло нужно вызвать target.addComponent(). Конечно, таким образом можно обновлять и поля формы, в зависимости от изменений других полей.</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/5525557247261247298/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2010/04/wicket-ajax.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/5525557247261247298'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/5525557247261247298'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2010/04/wicket-ajax.html' title='Wicket  работа с Ajax'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-3735047361100759154</id><published>2010-04-19T03:10:00.000-07:00</published><updated>2010-04-19T03:16:45.819-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="wicket"/><title type='text'>Wicket кастомизация html при рендеринге компонентов.</title><content type='html'>&lt;p&gt;&lt;br /&gt;Зачастую при написании приложений на основе компонентных фреймворков, стандартный шаблон компонента требуется подправить. Например, поменять стиль, динамически вставить дополнительный элемент html разметки. В этой статье я разберу как это можно сделать в &lt;a href=&quot;http://wicket.apache.org/&quot;&gt;Wicket&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;В базовом классе Component есть два метода для динамического добавления/изменения содержимого компонента:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;protected void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag)&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;Этот метод позволяет изменять содержимое компонента, то есть добавлять новые теги или заменять их.&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;protected void onComponentTag(final ComponentTag tag)&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;С помощью данного метода можно заменять, добавлять атрибуты в тег компонента.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Рассмотрим случай, когда по какой-то причине мне нужно добавить атрибут class со специфичным значением в компонент AjaxFallbackLink.&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;a class=&quot;nonselected&quot; wicket:id=&quot;someLink&quot;&gt;some link&lt;/a&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;Link link = new AjaxFallbackLink(&quot;someLink&quot;, new PropertyModel(item, &quot;value&quot;)) {&lt;br /&gt;     @Override&lt;br /&gt;                    protected void onComponentTag(ComponentTag componentTag) {&lt;br /&gt;                        super.onComponentTag(componentTag);&lt;br /&gt;                        if (someCondition) {&lt;br /&gt;                            componentTag.put(&quot;class&quot;, &quot;selected&quot;);&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;Код довольно прост. В заивсимости от какого-то условия я добавляю (или меняю уже существующее значение) атрибута class у тега гиперссылки. Аналогичным образом можно удалить этот же атрибут. Для этого можно использовать следующий метод:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt; componentTag.remove(&quot;class&quot;);&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Теперь рассмотрим случай, когда ссылки добавляются динамически. Из предыдущей &lt;a href=&quot;http://anpetrov.blogspot.com/2010/04/wicket_15.html&quot;&gt;статьи&lt;/a&gt; известно что для этого используется вспомогательный компонент RepeatingView. Проблема в том, что компонент-ссылка содержится в WebMarkupContainer, а последний в RepeatingView. И сразу непонятно где именно нужно переопределять метод onComponentTag, чтобы добраться до самой ссылки. Опытным путем я пришел к тому, что переопределять его нужно так же в самой ссылке. Не знаю почему, но для меня это было неочевидно. Я перепробовал варианты с переопределением этого метода как для RepeatingView, так и для WebMarkupContainer. В итоге пришел к самой ссылке. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Рассмотрим пример с изменением содержимого тега компонента. &lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;a class=&quot;nonselected&quot; wicket:id=&quot;someLink&quot;&gt;some link&lt;/a&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;Link link = new AjaxFallbackLink(&quot;someLink&quot;, new PropertyModel(item, &quot;value&quot;)) {&lt;br /&gt;      @Override&lt;br /&gt;                    protected void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag) {&lt;br /&gt;                        if (!someCond) {&lt;br /&gt;                            super.onComponentTagBody(markupStream, openTag);&lt;br /&gt;                            return;&lt;br /&gt;                        }&lt;br /&gt;                        final AppendingStringBuffer buffer = new AppendingStringBuffer();&lt;br /&gt;                        buffer.append(&quot;&lt;ul&gt;&lt;li&gt;first&lt;li&gt;second&lt;li&gt;third&lt;/ul&gt;&quot;);&lt;br /&gt;                        buffer.append(&quot;\n&quot;);&lt;br /&gt;                        replaceComponentTagBody(markupStream, openTag, buffer);&lt;br /&gt;                    }&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;Сначала проверяю условие, если оно не выполняется, то тело тега остается без изменения. Если же условие выполняется, то формирую строку,  на которую хочу заменить содержимое компонента, а потом вызываю метод заменяющий тело тега компонента. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Как видно из примеров &lt;a href=&quot;http://wicket.apache.org/&quot;&gt;Wicket&lt;/a&gt; дает довольно обширные возможности для манипуляций с контентом компонентов. И делать это довольно просто. Правда основной минус всех этих манипуляций состоит в том, что для каждого компонента, содержимое которого мы хотим поменять, нужно создавать анонимный подкласс, переопределяющий тот или иной метод. От этого код становится трудночитаемым и плохо сопровождаемым. Вообще я считаю  &quot;многословность&quot; основной проблемой этого фреймворка. &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/3735047361100759154/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2010/04/wicket-html.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/3735047361100759154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/3735047361100759154'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2010/04/wicket-html.html' title='Wicket кастомизация html при рендеринге компонентов.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-2709586237606321453</id><published>2010-04-15T22:14:00.000-07:00</published><updated>2010-04-15T22:37:33.138-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="wicket"/><title type='text'>Wicket Работа с динамическими списками элементов</title><content type='html'>&lt;p&gt;Теперь, когда я рассказал про общую &lt;a href=&quot;http://anpetrov.blogspot.com/2010/03/wicket.html&quot;&gt;концепцию&lt;/a&gt;, &lt;a href=&quot;http://anpetrov.blogspot.com/2010/04/wicket_14.html&quot;&gt;установку&lt;/a&gt; и &lt;a href=&quot;http://anpetrov.blogspot.com/2010/04/wicket.html&quot;&gt;валидацию&lt;/a&gt; в &lt;a href=&quot;http://wicket.apache.org/&quot;&gt;Wicket&lt;/a&gt;, перейдем к работе с его компонентами.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Задача. Необходимо отображать данные, количество которых меняется, то есть неизвестно заранее сколько их будет. Это может быть таблица товаров, перечень допустимых действий над объектом или что-то еще. Все это объединяет тот факт, что мы не знаем в момент написания шаблона, сколько табличных или списочных элементов нам понадобится.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Для этих целей используется компонент RepeatingView, он не отображается сам при отрисовке страницы. Его основное назначение - быть контейнером для динамических данных. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Сразу перейдем к примеру и его объяснению. Я буду отображать на странице некие статические данные (понятно, что здесь может быть вызов сервиса, предоставляющего данные из базы). Шаблон страницы (Example.html) выглядит так:&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;br /&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;&lt;br /&gt;        &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;&lt;br /&gt;&lt;html xmlns:wicket=&quot;http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd&quot;&gt;&lt;br /&gt;&lt;body&gt;&lt;br /&gt;&lt;br /&gt; &lt;span wicket:id=&quot;interestLinksList&quot;&gt;&lt;br /&gt;            &lt;a wicket:id=&quot;interestLink&quot;&gt;&lt;br /&gt;                &lt;span wicket:id=&quot;linkDescription&quot;&gt;Interest link description&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;            &lt;/a&gt;&lt;br /&gt;        &lt;/span&gt;&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Шаблон довольно простой. Стоит заметить, что для всех элементов, содержащихся в interestLinksList будут повторяться только внутренние элементы. То есть span повторяться не будет.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;Рассмотрим класс страницы. &lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;import org.apache.wicket.PageParameters;&lt;br /&gt;import org.apache.wicket.markup.html.WebMarkupContainer;&lt;br /&gt;import org.apache.wicket.markup.html.WebPage;&lt;br /&gt;import org.apache.wicket.markup.html.basic.Label;&lt;br /&gt;import org.apache.wicket.markup.html.link.BookmarkablePageLink;&lt;br /&gt;import org.apache.wicket.markup.html.link.Link;&lt;br /&gt;import org.apache.wicket.markup.repeater.RepeatingView;&lt;br /&gt;&lt;br /&gt;import java.io.Serializable;&lt;br /&gt;import java.util.Arrays;&lt;br /&gt;import java.util.List;&lt;br /&gt;&lt;br /&gt;public class Example extends WebPage {&lt;br /&gt;    private static final List&lt;ListItem&gt; LINKS = Arrays.asList(new ListItem(Example.class, &quot;Новости&quot;), new ListItem(Example.class, &quot;поиск&quot;));&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public Example(PageParameters aParameters) {&lt;br /&gt;        super(aParameters);&lt;br /&gt;        RepeatingView interestLinksList = new RepeatingView(&quot;interestLinksList&quot;);&lt;br /&gt;        add(interestLinksList);&lt;br /&gt;        for (final ListItem item : LINKS) {&lt;br /&gt;            WebMarkupContainer parent = new WebMarkupContainer(interestLinksList.newChildId());&lt;br /&gt;            interestLinksList.add(parent);&lt;br /&gt;            Link link = new BookmarkablePageLink(&quot;interestLink&quot;, item.getPage());&lt;br /&gt;            link.add(new Label(&quot;linkDescription&quot;, item.getDescription()));&lt;br /&gt;            parent.add(link);&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * элемент создающийся для GUI слоя.  &lt;br /&gt;     */&lt;br /&gt;    private static class ListItem implements Serializable {&lt;br /&gt;        private Class page;&lt;br /&gt;        private String description;&lt;br /&gt;&lt;br /&gt;        private ListItem(Class page, String description) {&lt;br /&gt;            this.page = page;&lt;br /&gt;            this.description = description;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public Class getPage() {&lt;br /&gt;            return page;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void setPage(Class page) {&lt;br /&gt;            this.page = page;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public String getDescription() {&lt;br /&gt;            return description;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public void setDescription(String description) {&lt;br /&gt;            this.description = description;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        @Override&lt;br /&gt;        public boolean equals(Object o) {&lt;br /&gt;            if (this == o) return true;&lt;br /&gt;            if (o == null || getClass() != o.getClass()) return false;&lt;br /&gt;&lt;br /&gt;            ListItem listItemQ = (ListItem) o;&lt;br /&gt;&lt;br /&gt;            if (!description.equals(listItemQ.description)) return false;&lt;br /&gt;            if (!page.equals(listItemQ.page)) return false;&lt;br /&gt;&lt;br /&gt;            return true;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        @Override&lt;br /&gt;        public int hashCode() {&lt;br /&gt;            int result = page.hashCode();&lt;br /&gt;            result = 31 * result + description.hashCode();&lt;br /&gt;            return result;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        @Override&lt;br /&gt;        public String toString() {&lt;br /&gt;            return description;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;Теперь разберем этот код более подробно. Класс ListItem вспомогательный. Он создан лишь для удобства работы со списками. Статическая константа LIST необходима тоже лишь для демонстрации, поскольку в обычном приложении будет использоваться поставщик данных из сервис слоя. Более интересно наличие промежуточного компонента WebMarkupContainer. Этот компонент необходим для того, чтобы &lt;a href=&quot;http://wicket.apache.org/&quot;&gt;Wicket&lt;/a&gt; мог отличить различные элементы динамического списка. Для этого разработчик создает этот промежуточный компонент и устанавливает ему id с помощью вызова &lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;interestLinksList.newChildId()&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;Замечу, что в &lt;a href=&quot;http://tapestry.apache.org/tapestry5.1/&quot;&gt;Tapestry 5&lt;/a&gt;, этот процесс автоматизирован и скрыт от глаз разработчика, что, по моему мнению, является правильным шагом. Здесь же нужно это делать самому. Таким образом после выполнения программы мы получим страницу, содержащую html  примерно такого вида:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;&lt;br /&gt;        &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;&lt;br /&gt;&lt;html xmlns:wicket=&quot;http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd&quot;&gt;&lt;br /&gt;&lt;body&gt;&lt;br /&gt;&lt;br /&gt; &lt;span&gt; &lt;br /&gt;            &lt;a href=&quot;#&quot;&gt;&lt;br /&gt;                &lt;span&gt;Новости&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;            &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;            &lt;a href=&quot;#&quot;&gt;&lt;br /&gt;                &lt;span&gt;Поиск&lt;/span&gt;&lt;br/&gt;&lt;br /&gt;            &lt;/a&gt; &lt;br /&gt;        &lt;/span&gt;&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;Уникальные id я опустил. Главное, что нет никаких вспомогательных тегов и повторяющийся контент содержится внутри основного тега контейнера. RepeatingView точно также можно использовать и с повторяющимися элементами формы. Я покажу это в статьях, посвященных различной работе с формами.</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/2709586237606321453/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2010/04/wicket_15.html#comment-form' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/2709586237606321453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/2709586237606321453'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2010/04/wicket_15.html' title='Wicket Работа с динамическими списками элементов'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-4500030270463390449</id><published>2010-04-14T02:10:00.000-07:00</published><updated>2010-04-14T02:34:55.504-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="installation"/><category scheme="http://www.blogger.com/atom/ns#" term="spring"/><category scheme="http://www.blogger.com/atom/ns#" term="wicket"/><title type='text'>Wicket - первое приложение.</title><content type='html'>&lt;p&gt;Собственно с этой статьи и надо было начинать рассказ про &lt;a href=&quot;http://wicket.apache.org/&quot;&gt;Wicket&lt;/a&gt;, но лучше поздно чем никогда. Итак, я предполагаю использование maven. Cтруктура каталогов соответствующая.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;1. Добавляем в pom.xml зависимость:&lt;/span&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;    &lt;!-- start--&gt;&lt;br /&gt;        &lt;dependency&gt;&lt;br /&gt;            &lt;groupId&gt;org.apache.wicket&lt;/groupId&gt;&lt;br /&gt;            &lt;artifactId&gt;wicket&lt;/artifactId&gt;&lt;br /&gt;            &lt;version&gt;${wicket.version}&lt;/version&gt;&lt;br /&gt;        &lt;/dependency&gt;&lt;br /&gt;        &lt;dependency&gt;&lt;br /&gt;            &lt;groupId&gt;org.wicketstuff&lt;/groupId&gt;&lt;br /&gt;            &lt;artifactId&gt;wicketstuff-annotation&lt;/artifactId&gt;&lt;br /&gt;            &lt;version&gt;${wicketstuff-annotation.version}&lt;/version&gt;&lt;br /&gt;            &lt;!-- exclude spring framework that wicket pulls in --&gt;&lt;br /&gt;            &lt;exclusions&gt;&lt;br /&gt;                &lt;exclusion&gt;&lt;br /&gt;                    &lt;groupId&gt;org.springframework&lt;/groupId&gt;&lt;br /&gt;                    &lt;artifactId&gt;spring-core&lt;/artifactId&gt;&lt;br /&gt;                &lt;/exclusion&gt;&lt;br /&gt;            &lt;/exclusions&gt;&lt;br /&gt;        &lt;/dependency&gt;&lt;br /&gt;&lt;br /&gt; &lt;!--  WICKET-SPRING DEPENDENCIES --&gt;&lt;br /&gt; &lt;dependency&gt;&lt;br /&gt;            &lt;groupId&gt;org.apache.wicket&lt;/groupId&gt;&lt;br /&gt;            &lt;artifactId&gt;wicket-spring&lt;/artifactId&gt;&lt;br /&gt;            &lt;version&gt;${wicket-spring.version}&lt;/version&gt;&lt;br /&gt;            &lt;!-- exclude spring framework that wicket pulls in --&gt;&lt;br /&gt;            &lt;exclusions&gt;&lt;br /&gt;                &lt;exclusion&gt;&lt;br /&gt;                    &lt;groupId&gt;org.springframework&lt;/groupId&gt;&lt;br /&gt;                    &lt;artifactId&gt;spring&lt;/artifactId&gt;&lt;br /&gt;                &lt;/exclusion&gt;&lt;br /&gt;            &lt;/exclusions&gt;&lt;br /&gt;        &lt;/dependency&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        &lt;properties&gt;&lt;br /&gt;            &lt;wicket.version&gt;1.4.6&lt;/wicket.version&gt;&lt;br /&gt;            &lt;wicketstuff-annotation.version&gt;1.1&lt;/wicketstuff-annotation.version&gt;&lt;br /&gt;            &lt;wicket-spring.version&gt;1.4.6&lt;/wicket-spring.version&gt;&lt;br /&gt;        &lt;/properties&gt;&lt;br /&gt;   &lt;!-- end  --&gt;&lt;br /&gt;]]&gt;   &lt;/script&gt;&lt;br /&gt;Сюда же можно добавить поддержку wicket-security, но об этом я расскажу в статьях, посвященных интеграции с этой подсистемой. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;2. Создаем страницу Index. &lt;/span&gt;&lt;br /&gt;Общее описание коцепций я приводил &lt;a href=&quot;http://anpetrov.blogspot.com/2010/03/wicket.html&quot;&gt;здесь&lt;/a&gt;. Ниже шаблон и класс страницы, а так же properties файл.&lt;br /&gt;Шаблон&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;&lt;br /&gt;        &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;&lt;br /&gt;&lt;html xmlns:wicket=&quot;http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd&quot;&gt;&lt;br /&gt;&lt;body&gt;&lt;br /&gt;&lt;span wicket:id=&quot;pageGreeting&quot;&gt;[Page Greeting]&lt;/title&gt;&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;Класс страницы.&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;public class Index extends WebPage {&lt;br /&gt;&lt;br /&gt;    public Index(final PageParameters aParameters) {&lt;br /&gt;        add(new Label(&quot;pageTitle&quot;, new StringBuilder(getLocalizer().getString(&quot;pageGreeting&quot;, this))));&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;properties файл.&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: text;&quot;&gt;&lt;br /&gt;pageGreeting=Страница приветствия Wicket&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;3. Создаем класс WicketApplication.&lt;/span&gt; &lt;br /&gt;Это класс расширяет WebApplication, в котором находятся методы, управляющие различными свойствами &lt;a href=&quot;http://wicket.apache.org/&quot;&gt;Wicket&lt;/a&gt; приложения. Я в нем хочу переопределить то какую страницу &lt;a href=&quot;http://wicket.apache.org/&quot;&gt;Wicket&lt;/a&gt; будет отдавать как &quot;домашнюю&quot;.&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;public class WicketApplication extends WebApplication {&lt;br /&gt;    public static WicketApplication get() {&lt;br /&gt;        return (WicketApplication) Application.get();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public WicketApplication() {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public Class&lt;WicketIndex&gt; getHomePage() {&lt;br /&gt;        return Index.class;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;Класс WebApplication содержит много интересных методов. Я буду разбирать их в следующих статьях на тему &lt;a href=&quot;http://wicket.apache.org/&quot;&gt;Wicket&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;4. Добавить WicketApplication в spring контекст.&lt;/span&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;bean id=&quot;wicketApplication&quot; class=&quot;com.blogspot.anpetrov.wicket.WicketApplication&quot;/&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;5. Изменить web.xml.&lt;/span&gt;&lt;br /&gt;Он должен иметь следующий вид:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;&lt;web-app xmlns=&quot;http://java.sun.com/xml/ns/javaee&quot;&lt;br /&gt;         xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;br /&gt;         xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/javaee&lt;br /&gt;    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd&quot;&lt;br /&gt;         version=&quot;2.5&quot;&gt;&lt;br /&gt;    &lt;display-name&gt;wicket Application&lt;/display-name&gt;&lt;br /&gt;&lt;br /&gt;    &lt;context-param&gt;&lt;br /&gt;        &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;&lt;br /&gt;        &lt;param-value&gt;/WEB-INF/config/applicationContext.xml&lt;/param-value&gt;&lt;br /&gt;    &lt;/context-param&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;    &lt;filter&gt;&lt;br /&gt;        &lt;filter-name&gt;wicket&lt;/filter-name&gt;&lt;br /&gt;        &lt;filter-class&gt;org.apache.wicket.protocol.http.WicketFilter&lt;/filter-class&gt;&lt;br /&gt;        &lt;init-param&gt;&lt;br /&gt;            &lt;param-name&gt;applicationFactoryClassName&lt;/param-name&gt;&lt;br /&gt;            &lt;param-value&gt;org.apache.wicket.spring.SpringWebApplicationFactory&lt;/param-value&gt;&lt;br /&gt;        &lt;/init-param&gt;&lt;br /&gt;        &lt;init-param&gt;&lt;br /&gt;            &lt;param-name&gt;configuration&lt;/param-name&gt;&lt;br /&gt;            &lt;param-value&gt;deployment&lt;/param-value&gt;&lt;br /&gt;        &lt;/init-param&gt;&lt;br /&gt;    &lt;/filter&gt;&lt;br /&gt;&lt;br /&gt;    &lt;filter-mapping&gt;&lt;br /&gt;        &lt;filter-name&gt;wicket&lt;/filter-name&gt;&lt;br /&gt;        &lt;url-pattern&gt;/*&lt;/url-pattern&gt;&lt;br /&gt;    &lt;/filter-mapping&gt;&lt;br /&gt;&lt;/web-app&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;Здесь требуется пояснение. Первая строка необходима, чтобы загрузить в контекст бин wicketApplication. SpringWebApplicationFactory - это реализация интерфейса IWebApplicationFactory, позволяющая получать WebApplication объект из контекста Spring. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Теперь после запуска приложения, мы всегда будем попадать на стартовую страницу.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/4500030270463390449/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2010/04/wicket_14.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/4500030270463390449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/4500030270463390449'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2010/04/wicket_14.html' title='Wicket - первое приложение.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-4887064580351869050</id><published>2010-04-12T01:46:00.000-07:00</published><updated>2010-04-12T02:43:28.585-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="solution"/><category scheme="http://www.blogger.com/atom/ns#" term="validators"/><category scheme="http://www.blogger.com/atom/ns#" term="web-framework"/><category scheme="http://www.blogger.com/atom/ns#" term="wicket"/><title type='text'>Wicket - Специфика работы с валидаторами полей и ошибками</title><content type='html'>&lt;p&gt;Задача. Обеспечить проверку данных, вводимых в форму, а так же информирование об ошибках ввода. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Информирование об ошибках.&lt;/span&gt; &lt;br /&gt;Чтобы ошибки отображались в форме, нужно добавить FeedBackPanel как в  шаблон, так и в класс страницы. &lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;private class ExampleForm extends Form&lt;ExampleForm&gt; {&lt;br /&gt; private String accountNumber;&lt;br /&gt; &lt;br /&gt; private ExampleForm(String id) {&lt;br /&gt;            super(id);&lt;br /&gt;            setModel(new CompoundPropertyModel&lt;PutMoneyForm&gt;(this));&lt;br /&gt;            add(new FeedbackPanel(&quot;feedback&quot;));&lt;br /&gt; &lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;&lt;br /&gt;        &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;&lt;br /&gt;&lt;html xmlns:wicket=&quot;http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd&quot;&gt;&lt;br /&gt;&lt;body&gt;&lt;br /&gt;&lt;wicket:extend&gt;&lt;br /&gt;&lt;br /&gt; &lt;form wicket:id=&quot;putMoney&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;div wicket:id=&quot;feedback&quot;&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;br /&gt;                &lt;tr&gt;&lt;br /&gt;                        &lt;td&gt;&lt;br /&gt;                            &lt;wicket:message key=&quot;accountNumber&quot;&gt;account number&lt;/wicket:message&gt;&lt;br /&gt;                            &lt;input type=&quot;text&quot; wicket:id=&quot;accountNumber&quot; class=&#39;text&#39;/&gt;&lt;br /&gt;                            &lt;br /&gt;   &lt;/td&gt;&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;&lt;/form&gt;&lt;br /&gt;&lt;/wicket:extend&gt;&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;]]&gt;   &lt;/script&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Обязательные поля&lt;/span&gt;&lt;br /&gt;Если поле является обязательным, то можно выделить его с помощью &quot;красной звездочки&quot;, но выделение это выглядит не очень красиво.Для этого используется FormComponentFeedbackBorder. Ниже пример использования&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;span wicket:id=&#39;border&#39;&gt;&lt;input type=&quot;text&quot; wicket:id=&quot;accountNumber&quot; class=&#39;text&#39;/&gt;&lt;/span&gt;&lt;br /&gt;]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;private class ExampleForm extends Form&lt;ExampleForm&gt; {&lt;br /&gt; private String accountNumber;&lt;br /&gt; &lt;br /&gt; private ExampleForm(String id) {&lt;br /&gt;            super(id);&lt;br /&gt;            setModel(new CompoundPropertyModel&lt;PutMoneyForm&gt;(this));&lt;br /&gt;            add(new FeedbackPanel(&quot;feedback&quot;));&lt;br /&gt;&lt;br /&gt;    add(new FormComponentFeedbackBorder(&quot;border&quot;).add(new TextField&lt;String&gt;(&quot;accountNumber&quot;).setRequired(true)));&lt;br /&gt; &lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;Можно вместо звездочки сделать свою разметку.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Валидаторы.&lt;/span&gt;&lt;br /&gt;Базовые валидаторы &lt;a href=&quot;http://wicket.apache.org/&quot;&gt;Wicket&lt;/a&gt; достаточно скудные. Мне в конкретной задаче понадобился валидатор, который проверяет, что поле содержит ровно 12 цифр. Оказалось, что для этого нужно писать собственный валидатор. Ниже я привожу сам валидатор, класс страницы.&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;private class NumberSizeValidator extends AbstractValidator {&lt;br /&gt;        private int size;&lt;br /&gt;        private String fieldName;&lt;br /&gt;&lt;br /&gt;        private NumberSizeValidator(int size, String fieldName) {&lt;br /&gt;            if (size &lt;= 0)&lt;br /&gt;                throw new IllegalArgumentException(&quot;size can&#39;t be less than 1&quot;);&lt;br /&gt;            this.size = size;&lt;br /&gt;            this.fieldName = fieldName;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        @Override&lt;br /&gt;        protected void onValidate(IValidatable iValidatable) {&lt;br /&gt;            String value = (String) iValidatable.getValue();&lt;br /&gt;            try {&lt;br /&gt;                Long.valueOf(value);&lt;br /&gt;            } catch (NumberFormatException e) {&lt;br /&gt;                error(iValidatable);&lt;br /&gt;                return;&lt;br /&gt;            }&lt;br /&gt;            if (value.length() != size) {&lt;br /&gt;                error(iValidatable);&lt;br /&gt;                return;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        @Override&lt;br /&gt;        protected String resourceKey() {&lt;br /&gt;            return &quot;NumberSizeValidator&quot;;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        @Override&lt;br /&gt;        protected Map&lt;String, Object&gt; variablesMap(IValidatable iValidatable) {&lt;br /&gt;            Map map = super.variablesMap(iValidatable);&lt;br /&gt;            map.put(&quot;size&quot;, size);&lt;br /&gt;            map.put(&quot;fieldName&quot;, fieldName);&lt;br /&gt;            return map;&lt;br /&gt;        }&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;Остановимся чуть подробнее на этом классе. Конструктор принимает имя поля, на которое навешивается валидатор и размер этого поля. Метод непосредственно осуществляющий проверку не представляет особого  интереса, в нем вызывается метод error, записывающий ошибку в feedbackpanel данной формы. Тут нужно заметить, что если Вы забыли добавить компонент FeedBackPanel в форму, то ошибку Вы не увидите, хотя валидатор отработает и не допустит некорректного ввода в форму. Метод resourceKey возвращает префикс, с которого начинается локализованное сообщение об ошибке, хранящееся в properties - файле страницы. &lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: text;&quot;&gt;&lt;br /&gt;NumberSizeValidator=Поле ${fieldName} должно содержать ${size} цифр&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;Ну и последний метод предоставлет значения для замены placeholder&#39;ов в сообщении об ошибке. Теперь остается подключить валидатор к полю:&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;private class ExampleForm extends Form&lt;ExampleForm&gt; {&lt;br /&gt; private String accountNumber;&lt;br /&gt; &lt;br /&gt; private ExampleForm(String id) {&lt;br /&gt;            super(id);&lt;br /&gt;            setModel(new CompoundPropertyModel&lt;PutMoneyForm&gt;(this));&lt;br /&gt;            add(new FeedbackPanel(&quot;feedback&quot;));&lt;br /&gt;&lt;br /&gt;    add(new TextField&lt;String&gt;(&quot;accountNumber&quot;).setRequired(true).add(new NumberSizeValidator(12, &quot;Номер счета&quot;)));&lt;br /&gt; &lt;br /&gt; }&lt;br /&gt; }&lt;br /&gt;&lt;/script&gt; &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Те кто имеют опыт работы с &lt;a href=&quot;http://tapestry.apache.org/&quot;&gt;Tapestry&lt;/a&gt; оценят насколько &lt;a href=&quot;http://wicket.apache.org/&quot;&gt;Wicket&lt;/a&gt; отстает в развити от данной технологии. Для &lt;a href=&quot;http://tapestry.apache.org/&quot;&gt;Tapestry&lt;/a&gt; такие валидаторы писать просто нет нужды, все уже сделано за нас.Сравнение этих технологий я проведу позднее. А пока про валидаторы все. &lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/4887064580351869050/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2010/04/wicket.html#comment-form' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/4887064580351869050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/4887064580351869050'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2010/04/wicket.html' title='Wicket - Специфика работы с валидаторами полей и ошибками'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-2724584198587861094</id><published>2010-04-09T03:16:00.000-07:00</published><updated>2010-04-09T03:36:03.830-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="jbpm"/><category scheme="http://www.blogger.com/atom/ns#" term="performance"/><category scheme="http://www.blogger.com/atom/ns#" term="process management engine"/><category scheme="http://www.blogger.com/atom/ns#" term="workflow engine"/><title type='text'>JPBM - часть 6 - производительность.</title><content type='html'>&lt;p&gt;После пяти статей про &lt;a href=&quot;http://www.jboss.org/jbpm/&quot;&gt;JBPM&lt;/a&gt; самое время написать про основную фобию разработчиков перед такого рода движками - &lt;span style=&quot;font-weight:bold;&quot;&gt;ПРОИЗВОДИТЕЛЬНОСТЬ&lt;/span&gt;. Именно это магическое слово я слышу каждый раз когда речь заходит о workflow или process management продуктах. Одной статьей развеять эту убежденность не получится, но я все же попробую начать. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Я провел несколько тестов. В чем они заключались? На входе имеем сервлет, обрабатывающий запросы следующим образом: на основе входных параметров(v1, v2, v3), создается объект  и передается в экземпляр процесса, который после этого запускается. Использовался типовой процесс бизнес-приложения(25 нодов, в среднем 10 переходов). Сервер приложений jboss-5.0.1.GA . Для тестирования использовался &lt;a href=&quot;http://jakarta.apache.org/jmeter/&quot;&gt;Jmeter&lt;/a&gt;. Тест состоит из трех ThreadGroup, каждая из которых содержит 100 пользователей, посылающих запросы в систему.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Тестирование отклика системы.&lt;/span&gt;&lt;br /&gt;Проверялось сколько запросов система готова обработать за единицу времени. Рассматривались два случая: асинхронное и синхронное исполнение процесса со стороны JBPM. В первом случае сервлет заканчивал обработку запроса запуском процесса, после чего последний выполнялся в отдельной нитке. Во втором варианте сервлет ожидает окончания исполнения процесса и только после этого заканчивает обработку входящего запроса.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Синхронное исполнение&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE7q_we6980d1QX8ld7tBHK1SDLYO0B2TNHdV3khl_7a4rQVA17Xjgm6lsg6gKWK7_9_FxaHAPYb6PuR1FfAyZZgj7c1BcUCnsez1Owm087Q6pVVoei2K0-Wp9H-sskTvS6MZoGjjhQxk/s1600/synch.JPG&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 98px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE7q_we6980d1QX8ld7tBHK1SDLYO0B2TNHdV3khl_7a4rQVA17Xjgm6lsg6gKWK7_9_FxaHAPYb6PuR1FfAyZZgj7c1BcUCnsez1Owm087Q6pVVoei2K0-Wp9H-sskTvS6MZoGjjhQxk/s320/synch.JPG&quot; border=&quot;0&quot; alt=&quot;&quot;id=&quot;BLOGGER_PHOTO_ID_5458081102255614098&quot; /&gt;&lt;/a&gt;&lt;br /&gt;Из таблицы видим, что в этом случае обрабатывается 10.1 запроса в секунду. Максимальное время исполнения процесса 3 секунды, минимальное 10мс. 90% запросов исполняются за время &lt; 1с.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Асинхронное исполнение&lt;/span&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0jAFNbKCNxh_JvvQfIKDRSjW7zSbhw5dFihWvpkj9tXHPqsaCYq1_R_izuJY5goJIk4slRz5qUZOmc9HAwfrHngW24kXzqcprEeOJnjRVTJMYBIPUdbAfLO6PdIu3ZOXFNJlt-J6l61Q/s1600/asynch.JPG&quot;&gt;&lt;img style=&quot;display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 62px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0jAFNbKCNxh_JvvQfIKDRSjW7zSbhw5dFihWvpkj9tXHPqsaCYq1_R_izuJY5goJIk4slRz5qUZOmc9HAwfrHngW24kXzqcprEeOJnjRVTJMYBIPUdbAfLO6PdIu3ZOXFNJlt-J6l61Q/s320/asynch.JPG&quot; border=&quot;0&quot; alt=&quot;&quot;id=&quot;BLOGGER_PHOTO_ID_5458082075275307298&quot; /&gt;&lt;/a&gt;&lt;br /&gt;Видим, что разница в 9.5 раз по скорости, имеем 95.2 запросов в секунду. Максимальное время исполнения процесса в данном случае - 30 секунд. Минимальное -&lt;br /&gt;100мс. 80% запросов исполняются за время &lt; 1 c.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Выводы каждый может сделать самостоятельно. В дальнейшем я приведу тестирование производительсности на реальных данных, после чего можно будет сравнить насколько изменятся показатели.&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/2724584198587861094/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2010/04/jbpm.html#comment-form' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/2724584198587861094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/2724584198587861094'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2010/04/jbpm.html' title='JPBM - часть 6 - производительность.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiE7q_we6980d1QX8ld7tBHK1SDLYO0B2TNHdV3khl_7a4rQVA17Xjgm6lsg6gKWK7_9_FxaHAPYb6PuR1FfAyZZgj7c1BcUCnsez1Owm087Q6pVVoei2K0-Wp9H-sskTvS6MZoGjjhQxk/s72-c/synch.JPG" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-2587076999686578886</id><published>2010-04-09T01:29:00.000-07:00</published><updated>2010-04-09T02:33:58.635-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java"/><category scheme="http://www.blogger.com/atom/ns#" term="solution"/><category scheme="http://www.blogger.com/atom/ns#" term="WebMoney"/><title type='text'>XML - интерфейсы WebMoney и Java</title><content type='html'>&lt;p&gt;У &lt;a href=&quot;http://webmoney.ru&quot;&gt;WebMoney&lt;/a&gt; есть X-интерфейсы. Они предназанчены для того, чтобы программным способом взаимодействовать с этой платежной системой. Выставлять счета, получать различную статистику.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;При этом порядок работы разный и заивсит от того как вы проходили регистрацию в платежной системе. Если через Light, то у вас p12 ключ и некоторые параметры (ваш wmid и подпись через Signer) передавать не надо. Если регистрация проходила через Keeper Classic, то у вас kwm ключ, и вам необходимо указывать ваш wmid и подписывать сообщения через Signer. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Для работы через эти интерфейсы есть хорошая библиотека &lt;a href=&quot;http://code.google.com/p/webmoneyjava/&quot;&gt;WebmoneyJava&lt;/a&gt; Я работал через нее. Кошелек был зарегистрирован через Keeper Light. Но тут мне понадобилось перевести приложение на другой акканут, который был зарегистрирован через Keeper Classic. Вот тогда и началаись проблемы. Чтобы работать c ключами classic, необходимо:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Сохранить ключ из кипера в файл.&lt;br /&gt;&lt;li&gt;С помощью KeyExtractor преобразовать этот ключ в Base64&lt;br /&gt;&lt;li&gt;Положить получившийся файл в то место где его будет видеть сервис. Указать путь к нему в самом сервисе.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Трудности начинаются со второго пункта. Я тщетно пытался найти на сайте WebMoney ссылку на приложение KeyExtractor. После долгих поисков, я все же ее нашел. KeyExctractor можно скачать &lt;a href=&quot;http://code.google.com/p/wmsigner-net/downloads/list&quot;&gt;здесь&lt;/a&gt;. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Дальше меня поджидала еще одна проблема: выяснилось, что изменился формат хранения classic ключей. Сейчас KeyExtractor преобразует их в xml Base64.  Таким образом библиотека webmoneyjava не работала с новым представлением classic ключей. Я нашел обновленную версию соответствующей &lt;a href=&quot;https://wmsigner-dotnet.svn.sourceforge.net/svnroot/wmsigner-dotnet/trunk/&quot;&gt;библиотеки&lt;/a&gt;, написанной на C#. После чего поправил код webmoneyjava. Исправления затронули :&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;SignerImpl&lt;br /&gt;&lt;li&gt;wmsignerjx.Signer&lt;br /&gt;&lt;li&gt;wmsignerjx.Montgomery&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Ниже я привожу код изменненых классов. &lt;br /&gt;&lt;/p&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;public final class Montgomery {&lt;br /&gt;    private static final int BITS = 32;&lt;br /&gt;    private static final long BIT_MASK = 0x80000000L;&lt;br /&gt;    private static final long LONG_MASK = 0xFFFFFFFFL;&lt;br /&gt;    private static final int BYTES_IN_UINT = 4;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public static final int Inverse(int value) {&lt;br /&gt;        int temp = (((value + 2) &amp; 4) &lt;&lt; 1) + value;&lt;br /&gt;&lt;br /&gt;        temp *= 2 - value * temp;&lt;br /&gt;        temp *= 2 - value * temp;&lt;br /&gt;        temp *= 2 - value * temp;&lt;br /&gt;&lt;br /&gt;        return -temp;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // [1] 14.36 Algorithm Montgomery multiplication&lt;br /&gt;    // INPUT: integers&lt;br /&gt;    //      m = (m[n-1] ... m[1] m[0]){b},&lt;br /&gt;    //      x = (x[n-1] ... x[1] x[0]){b},&lt;br /&gt;    //      y = (y[n-1] ... y[1] y[0]){b}&lt;br /&gt;    //           with 0 &lt;= x, y &lt; m,&lt;br /&gt;    //           R = b^n with gcd(m, b) = 1,&lt;br /&gt;    //           and mQ = -m^1 mod b.&lt;br /&gt;    // OUTPUT: x * y * R^-1 mod m.&lt;br /&gt;    public static final int[] MontgomeryMultiplication(int[] x, int[] y, int[] m, int mQ) {&lt;br /&gt;        int n = Algebra.Significance(m);&lt;br /&gt;&lt;br /&gt;        // 1. A = 0. (Notation: A = (a[n] a[n-1] ... a[1] a[0]){b})&lt;br /&gt;        int[] a = new int[n + 1];&lt;br /&gt;&lt;br /&gt;        // 2. For i from 0 to (n - 1) do the following:&lt;br /&gt;        for (int i = 0; i &lt; n; i++) {&lt;br /&gt;            // 2.1 u_i = (a[0] + x[i] * y[0]) * mQ mod b.&lt;br /&gt;            long u = ((a[0] + (((x[i] &amp; LONG_MASK) * (y[0] &amp; LONG_MASK)) &amp; LONG_MASK)) * mQ) &amp; LONG_MASK;&lt;br /&gt;&lt;br /&gt;            // 2.2 A = (A + x[i] * y + u_i * m) / b.&lt;br /&gt;            long xy = (x[i] &amp; LONG_MASK) * (y[0] &amp; LONG_MASK);&lt;br /&gt;            long um = u * (m[0] &amp; LONG_MASK);&lt;br /&gt;&lt;br /&gt;            long temp = (a[0] &amp; LONG_MASK) + (xy &amp; LONG_MASK) + (um &amp; LONG_MASK);&lt;br /&gt;            long carry = (xy &gt;&gt;&gt; BITS) + (um &gt;&gt;&gt; BITS) + (temp &gt;&gt;&gt; BITS);&lt;br /&gt;&lt;br /&gt;            for (int pos = 1; pos &lt; n; pos++) {&lt;br /&gt;                xy = (x[i] &amp; LONG_MASK) * (y[pos] &amp; LONG_MASK);&lt;br /&gt;                um = u * (m[pos] &amp; LONG_MASK);&lt;br /&gt;&lt;br /&gt;                temp = (a[pos] &amp; LONG_MASK) + (xy &amp; LONG_MASK) + (um &amp; LONG_MASK) + (carry &amp; LONG_MASK);&lt;br /&gt;                carry = (carry &gt;&gt;&gt; 32) + (xy &gt;&gt;&gt; BITS) + (um &gt;&gt;&gt; BITS) + (temp &gt;&gt;&gt; BITS);&lt;br /&gt;&lt;br /&gt;                a[pos - 1] = (int) temp;&lt;br /&gt;&lt;br /&gt;                int bp = 0;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            carry += (a[n] &amp; LONG_MASK);&lt;br /&gt;&lt;br /&gt;            a[n - 1] = (int) carry;&lt;br /&gt;            a[n] = (int) (carry &gt;&gt;&gt; BITS);&lt;br /&gt;&lt;br /&gt;            int bp1 = 0;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // 3. If A &gt;= m then A = A - m&lt;br /&gt;        if (Algebra.Compare(a, m) &gt;= 0) {&lt;br /&gt;            Algebra.RefObject&lt;int[]&gt; refObject = new Algebra.RefObject(a);&lt;br /&gt;            Algebra.Sub(new Algebra.RefObject(a), m);&lt;br /&gt;            a = refObject.Argument;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // 4. Return (A).&lt;br /&gt;        return a;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * for new 3.1 version&lt;br /&gt;     * @param xValue&lt;br /&gt;     * @param e&lt;br /&gt;     * @param m&lt;br /&gt;     * @return&lt;br /&gt;     */&lt;br /&gt;    public static final int[] MontgomeryExponentiationUInt16(int[] xValue, byte[] e, byte[] m) {&lt;br /&gt;        int[] uE = new int[(e.length + BYTES_IN_UINT - 1) / BYTES_IN_UINT];&lt;br /&gt;        int[] uM = new int[(m.length + BYTES_IN_UINT - 1) / BYTES_IN_UINT];&lt;br /&gt;&lt;br /&gt;        Buffer.BlockCopy(e, 0, uE, 0, e.length);&lt;br /&gt;        Buffer.BlockCopy(m, 0, uM, 0, m.length);&lt;br /&gt;&lt;br /&gt;        return MontgomeryExponentiationUInt16(xValue, uE, uM);&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * for new 3.1 version&lt;br /&gt;     * @param xValue&lt;br /&gt;     * @param e&lt;br /&gt;     * @param m&lt;br /&gt;     * @return&lt;br /&gt;     */&lt;br /&gt;    public static final int[] MontgomeryExponentiationUInt16(int[] xValue, int[] e, int[] m) {&lt;br /&gt;        int[] int32Result = MontgomeryExponentiation(xValue, e, m);&lt;br /&gt;        int[] int16Result = new int[int32Result.length * 2];&lt;br /&gt;        Buffer.BlockCopy(int32Result, 0, int16Result, 0, int32Result.length * 4);&lt;br /&gt;        Algebra.RefObject&lt;int[]&gt; refObject = new Algebra.RefObject(int16Result);&lt;br /&gt;        Algebra.Normalize(refObject);&lt;br /&gt;        int16Result = refObject.Argument;&lt;br /&gt;        return int16Result;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    // [1] 14.94 Algorithm Montgomery exponentiation&lt;br /&gt;    // INPUT:&lt;br /&gt;    //      m = (m[l-1] ... m[0]){b},&lt;br /&gt;    //      R = b^l,&lt;br /&gt;    //      mQ = -m^1 mod b,&lt;br /&gt;    //      e = (e[t] ... e[0]){2}&lt;br /&gt;    //           with e[t] = 1,&lt;br /&gt;    //           and an integer x, 1 &lt;= x &lt; m.&lt;br /&gt;    // OUTPUT: x^e mod m.&lt;br /&gt;    public static final int[] MontgomeryExponentiation(int[] xValue, int[] e, int[] m) {&lt;br /&gt;        int[] x = new int[xValue.length];&lt;br /&gt;&lt;br /&gt;        for (int pos = 0; pos &lt; xValue.length; pos++)&lt;br /&gt;            x[pos] = xValue[pos];&lt;br /&gt;&lt;br /&gt;        Algebra.RefObject&lt;int[]&gt; refObject1 = new Algebra.RefObject(x);&lt;br /&gt;        Algebra.Resize(refObject1, m.length);&lt;br /&gt;        x = refObject1.Argument;&lt;br /&gt;&lt;br /&gt;        // mQ = -m^1 mod b&lt;br /&gt;        int mQ = Inverse(m[0]);&lt;br /&gt;&lt;br /&gt;        // 1. temp = Mont(x, R^2 mod m), A = R mod m.&lt;br /&gt;        int[] r2 = new int[m.length * 2 + 1];&lt;br /&gt;        r2[r2.length - 1] = 1;&lt;br /&gt;&lt;br /&gt;        Algebra.RefObject&lt;int[]&gt; refObject2 = new Algebra.RefObject(r2);&lt;br /&gt;        Algebra.Remainder(refObject2, m);&lt;br /&gt;        r2 = refObject2.Argument;&lt;br /&gt;&lt;br /&gt;        int[] temp = MontgomeryMultiplication(x, r2, m, mQ);&lt;br /&gt;&lt;br /&gt;        int[] a = new int[m.length + 1];&lt;br /&gt;        a[a.length - 1] = 1;&lt;br /&gt;&lt;br /&gt;        Algebra.RefObject&lt;int[]&gt; refObject3 = new Algebra.RefObject(a);&lt;br /&gt;        Algebra.Remainder(refObject3, m);&lt;br /&gt;        a = refObject3.Argument;&lt;br /&gt;&lt;br /&gt;        int expLen = Algebra.Significance(e); &lt;br /&gt;        int expBits = expLen * BITS;  &lt;br /&gt;        int expPos = expLen - 1; &lt;br /&gt;        long bitMask = BIT_MASK; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        while (0 == (e[expPos] &amp; bitMask)) {&lt;br /&gt;            bitMask &gt;&gt;&gt;= 1;&lt;br /&gt;            expBits--;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // 2. For i from t down to 0 do the following:&lt;br /&gt;        while (expBits != 0) {&lt;br /&gt;            // 2.1 A = Mont(A, A).&lt;br /&gt;            a = MontgomeryMultiplication(a, a, m, mQ);&lt;br /&gt;&lt;br /&gt;            // 2.2 If e[i] = 1 then A = Mont(A, temp).&lt;br /&gt;            if (0 != (e[expPos] &amp; bitMask)) // &lt;br /&gt;                a = MontgomeryMultiplication(a, temp, m, mQ);&lt;br /&gt;&lt;br /&gt;            expBits--;&lt;br /&gt;            bitMask &gt;&gt;&gt;= 1;&lt;br /&gt;&lt;br /&gt;            if (0 == bitMask) {&lt;br /&gt;                bitMask = BIT_MASK;&lt;br /&gt;                expPos--;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // 3. A Mont(A, 1).&lt;br /&gt;        int[] one = new int[m.length];&lt;br /&gt;        one[0] = 1;&lt;br /&gt;&lt;br /&gt;        a = MontgomeryMultiplication(a, one, m, mQ);&lt;br /&gt;&lt;br /&gt;        Algebra.RefObject&lt;int[]&gt; refObject4 = new Algebra.RefObject(a);&lt;br /&gt;        Algebra.Normalize(refObject4);&lt;br /&gt;        a = refObject4.Argument;&lt;br /&gt;&lt;br /&gt;        // 4. Return (A).&lt;br /&gt;        return a;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;public class Signer {&lt;br /&gt;    private static final int USHORT_BYTES = 2;&lt;br /&gt;    private static final int VALUE_BYTES = 56;&lt;br /&gt;    private static final int HASH_LEN = 16;&lt;br /&gt;    private static final int INT_BYTES = 4;&lt;br /&gt;&lt;br /&gt;    //3.1 fix&lt;br /&gt;    private static final int VERSION_MINOR = 1;&lt;br /&gt;    private static final int VERSION_MAJOR = 3;&lt;br /&gt;    private static final byte[] HEADER = new byte[]{VERSION_MINOR, VERSION_MAJOR, (byte) &#39;X&#39;, (byte) &#39;F&#39;, 1, 0};&lt;br /&gt;    private static final int SIGNIFICANCE = 0x38;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    private int[] _exponent;&lt;br /&gt;    private int[] _modulus;&lt;br /&gt;    private final MD4 _md4 = new MD4();&lt;br /&gt;&lt;br /&gt;    private byte[] _d;&lt;br /&gt;    private byte[] _newModulus;&lt;br /&gt;&lt;br /&gt;    public Signer(int[] exponent, int[] modulus) {&lt;br /&gt;        _exponent = exponent;&lt;br /&gt;        _modulus = modulus;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Signer(byte[] d, byte[] modulus) {&lt;br /&gt;        _d = d;&lt;br /&gt;        _newModulus = modulus;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String Sign(String value) {&lt;br /&gt;        byte[] bytes;&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;            bytes = value.getBytes(&quot;windows-1251&quot;);&lt;br /&gt;        }&lt;br /&gt;        catch (java.io.UnsupportedEncodingException e) {&lt;br /&gt;            throw new Error(e.getMessage());&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        int[] sign = Sign(bytes);&lt;br /&gt;&lt;br /&gt;        byte[] bSign = Buffer.GetBytes(sign);&lt;br /&gt;&lt;br /&gt;        StringBuffer stringBuffer = new StringBuffer(128);&lt;br /&gt;&lt;br /&gt;        for (int pos = 0; pos &lt;= 32; pos++) {&lt;br /&gt;            if (bSign.length &gt; pos * 2 + 1) {&lt;br /&gt;                int number = bSign[pos * 2 + 1] &amp; 0xFF;&lt;br /&gt;&lt;br /&gt;                if (number &lt; 0x10)&lt;br /&gt;                    stringBuffer.append(&quot;0&quot;);&lt;br /&gt;&lt;br /&gt;                stringBuffer.append(Integer.toString(number, 16));&lt;br /&gt;            } else&lt;br /&gt;                stringBuffer.append(&quot;00&quot;);&lt;br /&gt;&lt;br /&gt;            if (bSign.length &gt; pos * 2) {&lt;br /&gt;                int number = bSign[pos * 2] &amp; 0xFF;&lt;br /&gt;&lt;br /&gt;                if (number &lt; 0x10)&lt;br /&gt;                    stringBuffer.append(&quot;0&quot;);&lt;br /&gt;&lt;br /&gt;                stringBuffer.append(Integer.toString(number, 16));&lt;br /&gt;            } else&lt;br /&gt;                stringBuffer.append(&quot;00&quot;);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        return stringBuffer.toString();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public int[] Sign(byte[] value) {&lt;br /&gt;        if (null == value)&lt;br /&gt;            return null;&lt;br /&gt;&lt;br /&gt;        int[] signHash;&lt;br /&gt;&lt;br /&gt;        _md4.Initialize();&lt;br /&gt;        signHash = _md4.GetInt32Hash(value, 0, value.length);&lt;br /&gt;&lt;br /&gt;        byte[] rndBuffer = new byte[_newModulus.length - USHORT_BYTES - HASH_LEN - HEADER.length];&lt;br /&gt;&lt;br /&gt;        &lt;br /&gt;&lt;br /&gt;        int[] hashExtended = new int[VALUE_BYTES / INT_BYTES];&lt;br /&gt;        int[] blob = new int[(_newModulus.length + INT_BYTES - 1) / INT_BYTES];&lt;br /&gt;&lt;br /&gt;        Buffer.BlockCopy(new int[]{SIGNIFICANCE}, 0, blob, 0, USHORT_BYTES);&lt;br /&gt;        Buffer.BlockCopy(signHash, 0, blob, USHORT_BYTES, HASH_LEN);&lt;br /&gt;        //Buffer.BlockCopy(new byte[] { VALUE_BYTES, 0 }, 0, hashExtended, 0, USHORT_BYTES);&lt;br /&gt;        Buffer.BlockCopy(rndBuffer, 0, blob, USHORT_BYTES + HASH_LEN, rndBuffer.length);&lt;br /&gt;        Buffer.BlockCopy(HEADER, 0, blob, USHORT_BYTES + HASH_LEN + rndBuffer.length, HEADER.length);&lt;br /&gt;&lt;br /&gt;        //int[] result = Montgomery.MontgomeryExponentiation(blob, _exponent, _modulus);&lt;br /&gt;&lt;br /&gt;        int[] result = Montgomery.MontgomeryExponentiationUInt16(blob, _d, _newModulus);&lt;br /&gt;        return result;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;public class SignerImpl implements Signer {&lt;br /&gt;&lt;br /&gt;    private String keyPath;&lt;br /&gt;    private wmsignerjx.Signer signer;&lt;br /&gt;&lt;br /&gt;    private X2OHelper x2oHelper = new X2OHelper();&lt;br /&gt;    SAXReader saxReader = new SAXReader();&lt;br /&gt;&lt;br /&gt;    public SignerImpl() {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getKeyPath() {&lt;br /&gt;        return keyPath;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setKeyPath(String keyPath) {&lt;br /&gt;        this.keyPath = keyPath;&lt;br /&gt;        try {&lt;br /&gt;            //loadKey(keyPath);&lt;br /&gt;            loadXMLKey(keyPath);&lt;br /&gt;        } catch (WebMoneyException e) {&lt;br /&gt;            throw new Error(e);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void loadKey(String classicKeyPath) throws WebMoneyException {&lt;br /&gt;&lt;br /&gt;        try {&lt;br /&gt;&lt;br /&gt;            BufferedReader fr = new BufferedReader(new FileReader(classicKeyPath));&lt;br /&gt;&lt;br /&gt;            String sz = fr.readLine();&lt;br /&gt;&lt;br /&gt;            String[] aKeys = sz.split(&quot;:&quot;);&lt;br /&gt;&lt;br /&gt;            BASE64Decoder d = new BASE64Decoder();&lt;br /&gt;            byte[] bExponent = d.decodeBuffer(aKeys[0]);&lt;br /&gt;            byte[] bModulus = d.decodeBuffer(aKeys[1]);&lt;br /&gt;            // System.out.println(&quot;[&quot;+bExponent.length+&quot;]&quot;+Arrays.toString(bExponent)+&quot; # [&quot;+bModulus.length+&quot;] &quot;+Arrays.toString(bModulus));&lt;br /&gt;&lt;br /&gt;            int[] nExponent = new int[(bExponent.length + 4 - 1) / 4];&lt;br /&gt;            int[] nModulus = new int[(bModulus.length + 4 - 1) / 4];&lt;br /&gt;&lt;br /&gt;            Buffer.BlockCopy(bExponent, 0, nExponent, 0, bExponent.length);&lt;br /&gt;            Buffer.BlockCopy(bModulus, 0, nModulus, 0, bModulus.length);&lt;br /&gt;            //System.out.println(Arrays.toString(nExponent)+&quot; # &quot;+Arrays.toString(nModulus));&lt;br /&gt;&lt;br /&gt;            signer = new wmsignerjx.Signer(nExponent, nModulus);&lt;br /&gt;&lt;br /&gt;        } catch (IOException e) {&lt;br /&gt;            new AuthorizationException(e);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private void loadXMLKey(String classicKeyPath) throws WebMoneyException {&lt;br /&gt;        try {&lt;br /&gt;            BufferedReader fr = new BufferedReader(new FileReader(classicKeyPath));&lt;br /&gt;            BASE64Decoder base64Decoder = new BASE64Decoder();&lt;br /&gt;            Document docResponse = saxReader.read(fr, &quot;utf-8&quot;);&lt;br /&gt;            Element modulusElement = docResponse.getRootElement().element(&quot;Modulus&quot;);&lt;br /&gt;            Element dElement = docResponse.getRootElement().element(&quot;D&quot;);&lt;br /&gt;            String modulusStr = x2oHelper.asString(modulusElement, &quot;&quot;);&lt;br /&gt;            String dStr = x2oHelper.asString(dElement, &quot;&quot;);&lt;br /&gt;            byte[] bModulus = base64Decoder.decodeBuffer(modulusStr);&lt;br /&gt;            byte[] d = base64Decoder.decodeBuffer(dStr);&lt;br /&gt;&lt;br /&gt;            signer = new wmsignerjx.Signer(d, bModulus);&lt;br /&gt;        } catch (IOException e) {&lt;br /&gt;            new AuthorizationException(e);&lt;br /&gt;        } catch (DocumentException e) {&lt;br /&gt;            new AuthorizationException(e);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String sign(String srcString) throws WebMoneyException {&lt;br /&gt;        return signer.Sign(srcString);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Теперь можно смело использовать соответствующий сервис для работы с Classic ключами.&lt;br /&gt;&lt;/p&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;        Signer signer = new SignerImpl();&lt;br /&gt;        signer.setKeyPath(utils.getKeystorePath());&lt;br /&gt;        ClassicWebMoneyService webMoneyService = new ClassicWebMoneyService();&lt;br /&gt;        webMoneyService.setTrustStorePath(utils.getTrustStorePath());&lt;br /&gt;        webMoneyService.setTrustStorePassword(utils.getTrustStorePassword());&lt;br /&gt;        webMoneyService.setSigner(signer);&lt;br /&gt;&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/2587076999686578886/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2010/04/xml-webmoney-java.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/2587076999686578886'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/2587076999686578886'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2010/04/xml-webmoney-java.html' title='XML - интерфейсы WebMoney и Java'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-1726125706042070586</id><published>2010-04-02T05:39:00.000-07:00</published><updated>2010-04-02T06:25:12.408-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="jbpm"/><category scheme="http://www.blogger.com/atom/ns#" term="spring"/><title type='text'>JBPM - Часть 5 - Интеграция со Spring.</title><content type='html'>Если использовать стандартный механизм взаимодействия с JBPM, то дотсуп к основным объектам фреймворка получается не очень удобным способом. В моем приложении активно используется &lt;a href=&quot;http://www.springsource.org/&quot;&gt;Spring&lt;/a&gt;, поэтому я решил получать доступ к JBPM через него. Посмотрим как же этого добиться. &lt;br /&gt;&lt;br /&gt;Мне необходимо работать со следующими операциями: &lt;br /&gt; - Деплоить процесс или несколько процессов&lt;br /&gt; - Запускать процессы&lt;br /&gt; - Возобновлять процессы, находящиеся в ожидании. &lt;br /&gt;&lt;br /&gt;Для этих целей я ввел два интерфейса: DeployService, ProcessService. Их код представлен ниже. &lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;public interface DeployService {&lt;br /&gt;&lt;br /&gt;    void deploy(String processDefinition);&lt;br /&gt;&lt;br /&gt;    void deploy(String[] processDefinitions);&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;public interface ProcessService {&lt;br /&gt;    boolean isProcessDeployed(String key);&lt;br /&gt;&lt;br /&gt;    String startProcess(String key, Map&lt;String, ?&gt; variables);&lt;br /&gt;&lt;br /&gt;    String startProcess(String key, Map&lt;String, ?&gt; variables, String userDefKey);&lt;br /&gt;&lt;br /&gt;    void signal(Execution execution);&lt;br /&gt;&lt;br /&gt;    ProcessInstance signalExecutionById(String executionId, String signalName);&lt;br /&gt;&lt;br /&gt;    ProcessInstance signalExecutionById(String executionId, String signalName, Map&lt;String, ?&gt; parameters);&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;В реализации DeployService используется реализация &lt;a href=&quot;http://www.jpbm.org&quot;&gt;JBPM&lt;/a&gt; интерфейса RepositoryService. А в ProcessService добавляется использование ExecutionService. Ниже приводится реализация этих интерфейсов.&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;public class DeployServiceImpl implements DeployService {&lt;br /&gt;    @Autowired&lt;br /&gt;    private RepositoryService repositoryService;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public void deploy(String processDefinition) {&lt;br /&gt;        NewDeployment deployment = repositoryService.createDeployment();&lt;br /&gt;        deployment.addResourceFromClasspath(processDefinition);&lt;br /&gt;        deployment.deploy();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void deploy(String[] processDefinitions) {&lt;br /&gt;        NewDeployment deployment = repositoryService.createDeployment();&lt;br /&gt;        for (String processDefinition : processDefinitions) {&lt;br /&gt;            deployment.addResourceFromClasspath(processDefinition);&lt;br /&gt;        }&lt;br /&gt;        deployment.deploy();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;import org.jbpm.api.Execution;&lt;br /&gt;import org.jbpm.api.ExecutionService;&lt;br /&gt;import org.jbpm.api.ProcessInstance;&lt;br /&gt;import org.jbpm.api.RepositoryService;&lt;br /&gt;import org.springframework.beans.factory.annotation.Autowired;&lt;br /&gt;&lt;br /&gt;import java.util.Map;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class ProcessServiceImpl implements ProcessService {&lt;br /&gt;    @Autowired&lt;br /&gt;    private RepositoryService repositoryService;&lt;br /&gt;    @Autowired&lt;br /&gt;    private ExecutionService executionService;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public boolean isProcessDeployed(String key) {&lt;br /&gt;        return repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).list().size() &gt; 0;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String startProcess(String key, Map&lt;String, ?&gt; variables) {&lt;br /&gt;        ProcessInstance instance = executionService.startProcessInstanceByKey(key, variables);&lt;br /&gt;        return &quot;&quot;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String startProcess(String key, Map&lt;String, ?&gt; variables, String userDefKey) {&lt;br /&gt;        ProcessInstance instance = executionService.startProcessInstanceByKey(key, variables, userDefKey);   &lt;br /&gt;        return instance.getId();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void signal(Execution execution) {&lt;br /&gt;        if (execution.getState().equals(Execution.STATE_INACTIVE_SCOPE)) {&lt;br /&gt;            System.out.println(&quot;INACTIVE SCOPE&quot;);&lt;br /&gt;&lt;br /&gt;            execution = execution.getExecutions().iterator().next();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        executionService.signalExecutionById(execution.getId(), &quot;transition&quot;);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ProcessInstance signalExecutionById(String executionId, String signalName) {&lt;br /&gt;        return executionService.signalExecutionById(executionId, signalName);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public ProcessInstance signalExecutionById(String executionId, String signalName, Map&lt;String, ?&gt; parameters) {&lt;br /&gt;        return executionService.signalExecutionById(executionId, signalName, parameters);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public void setRepositoryService(RepositoryService repositoryService) {&lt;br /&gt;        this.repositoryService = repositoryService;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setExecutionService(ExecutionService executionService) {&lt;br /&gt;        this.executionService = executionService;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Можно заметить, что в реализациях я использую стандартную аннотацию Autowired, что означает наличие соответствующих бинов в контексте приложения. Чтобы они там появились необходимо добавить в контекст следующие строчки&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;    &lt;bean id=&quot;jbpmConfiguration&quot; class=&quot;org.jbpm.pvm.internal.cfg.SpringConfiguration&quot;&gt;&lt;br /&gt;        &lt;constructor-arg value=&quot;com/blogspot/anpetrov/jbpm/contexts/jbpm.cfg.xml&quot;/&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;processEngine&quot; factory-bean=&quot;jbpmConfiguration&quot; factory-method=&quot;buildProcessEngine&quot;/&gt;&lt;br /&gt;    &lt;bean id=&quot;repositoryService&quot; factory-bean=&quot;processEngine&quot; factory-method=&quot;getRepositoryService&quot;/&gt;&lt;br /&gt;    &lt;bean id=&quot;executionService&quot; factory-bean=&quot;processEngine&quot; factory-method=&quot;getExecutionService&quot;/&gt;&lt;br /&gt;]]&gt;   &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Первая строчка инициализирует конфигурацию jbpm параметрами, взятыми из файла конфигурации. Вторая стока создает основной бин, из которого уже получаются два последующих бина.&lt;br /&gt;Ну и последнее, что необходимо сделать, это создать бины для моих сервисов:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;bean class=&quot;com.blogspot.anpetrov.jbpm.services.impl.DeployServiceImpl&quot;/&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;bean id=&quot;simpleProcessService&quot; class=&quot;com.blogspot.anpetrov.jbpm.services.impl.ProcessServiceImpl&quot;/&gt;&lt;br /&gt;]]&gt;   &lt;/script&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;Вот и все. Теперь я могу спокойно деплоить процессы с помощью &lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;deployService.deploy(&quot;com/blogspot/anpetrov/jbpm/processes/some-process.jpdl.xml&quot;);&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;и запускать например так&lt;br /&gt; &lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;processService.startProcess(&quot;SomeProcess&quot;, variables);&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Вот такая достаточно простая интеграция получилась.</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/1726125706042070586/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2010/04/jbpm-5-spring.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/1726125706042070586'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/1726125706042070586'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2010/04/jbpm-5-spring.html' title='JBPM - Часть 5 - Интеграция со Spring.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-3893772675644234321</id><published>2010-03-31T10:58:00.000-07:00</published><updated>2010-03-31T11:32:25.684-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="tapestry"/><category scheme="http://www.blogger.com/atom/ns#" term="web-framework"/><category scheme="http://www.blogger.com/atom/ns#" term="wicket"/><title type='text'>Wicket первое знакомство</title><content type='html'>Среди множества web-framework-ов мне встретился &lt;a href=&quot;http://wicket.apache.org/&quot;&gt; Wicket&lt;/a&gt;. Более детальное описание данного фреймворка, а также цикл статей, сравнивающих его с &lt;a href=&quot;http://tapestry.apache.org/&quot;&gt;Tapestry&lt;/a&gt; впереди. В этой заметке я сделаю краткий обзор технологии.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight:bold;&quot;&gt;Общая концепция wicket&lt;/span&gt;&lt;br /&gt;Общая концепция схожа с Tapestry: страница формируется из шаблона страницы (MyPage.html), класса страницы (MyPage.java) и файла свойств (MyPage.properties). Шаблон страницы содержит обыкновенную html-разметку, в которую встраиваются wicket - компоненты. Достигается это добавлением специфичного атрибута wicket-id в обычные html теги. Класс страницы должен содержать все компоненты, указанные в шаблоне. Создаются они аналогично Swing приложению. Каждый должен быть явно создан и добавлен в страницу, в противном случае при попытке создания страницы в runtime wicket не найдет соответствия между шаблоном и классом страницы. Наконец, файл свойств необходим для локалилзации сообщений, выводимых на странице. &lt;br /&gt;&lt;br /&gt;Пример обычной страницы приведен ниже:&lt;br /&gt;Шаблон&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&lt;br /&gt;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;&lt;br /&gt;        &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;&lt;br /&gt;&lt;html xmlns:wicket=&quot;http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd&quot;&gt;&lt;br /&gt;&lt;body&gt;&lt;br /&gt;&lt;br /&gt;&lt;!--menu_steps--&gt;&lt;br /&gt;    &lt;table class=&#39;step_tbl&#39; id=&#39;menu&#39;&gt;&lt;br /&gt;        &lt;tr&gt;&lt;br /&gt;            &lt;td class=&#39;active&#39;&gt;&lt;br /&gt;                &lt;div&gt;&lt;br /&gt;                    &lt;wicket:message key=&quot;paymentMethod&quot;&gt;payment method&lt;/wicket:message&gt;&lt;br /&gt;                &lt;/div&gt;&lt;br /&gt;            &lt;/td&gt;&lt;br /&gt;            &lt;td&gt;&lt;br /&gt;                &lt;div&gt;&lt;br /&gt;                    &lt;wicket:message key=&quot;choosingAmount&quot;&gt;choosing amount&lt;/wicket:message&gt;&lt;br /&gt;                &lt;/div&gt;&lt;br /&gt;            &lt;/td&gt;&lt;br /&gt;            &lt;td&gt;&lt;br /&gt;                &lt;div&gt;&lt;br /&gt;                    &lt;wicket:message key=&quot;paymentInformation&quot;&gt;payment information&lt;/wicket:message&gt;&lt;br /&gt;                &lt;/div&gt;&lt;br /&gt;            &lt;/td&gt;&lt;br /&gt;        &lt;/tr&gt;&lt;br /&gt;    &lt;/table&gt;&lt;br /&gt;    &lt;!--/menu_steps--&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;span wicket:id=&quot;totalSum&quot;/&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div id=&quot;footer&quot;&gt;&lt;br /&gt;    &lt;div class=&#39;inner&#39;&gt;&lt;br /&gt;        &lt;div class=&#39;update&#39;&gt;&lt;br /&gt;            Последнее обновление: &lt;br /&gt;        &lt;/div&gt;&lt;br /&gt;        &lt;div class=&#39;legal_info&#39;&gt;&lt;br /&gt;            &lt;a href=&quot;#&quot;&gt;Соглашение&lt;/a&gt;&lt;br /&gt;        &lt;/div&gt;&lt;br /&gt;        &lt;div class=&#39;contacts&#39;&gt;&lt;br /&gt;            Телефон для связи: +7 921 000 00 00&lt;br/&gt;&lt;br /&gt;            E-mail для связи: &lt;a href=&quot;mailto:support@blabla.ru&quot;&gt;support@blabla.ru&lt;/a&gt;&lt;br /&gt;        &lt;/div&gt;&lt;br /&gt;        &lt;div class=&#39;copyright&#39;&gt;© 2000–2010 SomeFirm&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;    &lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/body&gt;&lt;br /&gt;&lt;/html&gt;&lt;br /&gt;]]&gt;   &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Класс страницы:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;public class Base extends WebPage {&lt;br /&gt;&lt;br /&gt;    public Base(final PageParameters aParameters) {&lt;br /&gt;        add(new Label(&quot;totalSum&quot;, &quot;12&quot;);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Файл свойств&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: text;&quot;&gt;&lt;br /&gt;paymentMethod=Выбор метода платежа&lt;br /&gt;choosingAmount=Выбор суммы&lt;br /&gt;paymentInformation=Информация о платеже&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Как видно все довольно просто. Конечно, основные сложности возникают при создании и обработке форм, ajax - вызовов и прочих интересных вещей. В дальнейших статьях я буду более подробно освещать эти аспекты фреймворка</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/3893772675644234321/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2010/03/wicket.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/3893772675644234321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/3893772675644234321'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2010/03/wicket.html' title='Wicket первое знакомство'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-5311184474418349433</id><published>2010-03-21T06:30:00.000-07:00</published><updated>2010-03-21T07:01:52.719-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="apache"/><category scheme="http://www.blogger.com/atom/ns#" term="commons-configuration"/><category scheme="http://www.blogger.com/atom/ns#" term="solution"/><title type='text'>Обновление файла конфигурации без перезагрузки сервера.</title><content type='html'>Суть задачи: некоторая часть наполнения системы является редко изменяемой и не требует своего хранения в базе данных. Пример: раздел справки на сайте. Он может храниться в файле(текстовом, файле - свойств или xml), а система зачитывает его при старте. Если файл обновляется, то система должна обновить его.  Тут и возникает вопрос как реализовать функциональность таким образом, чтобы не нужно было останавливать сервер приложений. &lt;br /&gt;&lt;br /&gt;Для этих целей подходит удобная библиотека &lt;a href=&quot;http://commons.apache.org/configuration/&quot;&gt;commons-configuration&lt;/a&gt; от apache. В ней есть различные интерфейсы позволяющие работать как с файлами свойств (*.properties), так и с xml файлами. Предположим, что мы храним справочную информацию в файле help.xml. Ниже приводится код, позволяющий подгружать актуальный файл при каждом обращении к нему. &lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;FileConfiguration helpConfiguration = new XMLConfiguration(&quot;help.xml&quot;);&lt;br /&gt;helpConfiguration.setReloadingStrategy(new FileChangedReloadingStrategy());&lt;br /&gt;digester.parse(helpConfiguration.getFile());&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Теперь каждый раз когда будет происходить обращение к файлу, будет проверяться время его последнего изменения и данные будут всегда актуальны. &lt;br /&gt;&lt;br /&gt;Но это не все. Нужно чтобы этот код вызывался периодически, чтобы обновлять in-memory модель данных, которая строится на основе этого файла. Для достижения этой цели я использую job, spring и qwartz. &lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;&lt;bean id=&quot;helpLoader&quot; class=&quot;com.blogspot.anpetrov.utils.HelpLoader&quot; init-method=&quot;init&quot;/&gt;&lt;br /&gt;&lt;br /&gt;    &lt;!-- Job for NewsLoader status --&gt;&lt;br /&gt;    &lt;bean id=&quot;helpLoaderJobDetail&quot; class=&quot;org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;targetObject&quot; ref=&quot;helpLoader&quot;/&gt;&lt;br /&gt;        &lt;property name=&quot;targetMethod&quot; value=&quot;loadHelp&quot;/&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean id=&quot;helpLoaderTrigger&quot; class=&quot;org.springframework.scheduling.quartz.SimpleTriggerBean&quot;&gt;&lt;br /&gt;        &lt;!-- see the example of method invoking job above --&gt;&lt;br /&gt;        &lt;property name=&quot;jobDetail&quot; ref=&quot;helpLoaderJobDetail&quot;/&gt;&lt;br /&gt;        &lt;!-- 15 seconds --&gt;&lt;br /&gt;        &lt;property name=&quot;startDelay&quot; value=&quot;15000&quot;/&gt;&lt;br /&gt;        &lt;!-- repeat every 5 minutes --&gt;&lt;br /&gt;        &lt;property name=&quot;repeatInterval&quot; value=&quot;50000&quot;/&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &lt;bean class=&quot;org.springframework.scheduling.quartz.SchedulerFactoryBean&quot;&gt;&lt;br /&gt;        &lt;property name=&quot;triggers&quot;&gt;&lt;br /&gt;            &lt;list&gt;&lt;br /&gt;                &lt;ref bean=&quot;helpLoaderTrigger&quot;/&gt;&lt;br /&gt;            &lt;/list&gt;&lt;br /&gt;        &lt;/property&gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;    &lt;!-- End job --&gt;&lt;br /&gt;]]&gt;   &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;HelpLoader - класс, реализующий метод loadHelp. Остальной код - обвязка этого класса, позволяющая вызывать метод loadHelp каждые 50 секунд.</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/5311184474418349433/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2010/03/blog-post.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/5311184474418349433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/5311184474418349433'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2010/03/blog-post.html' title='Обновление файла конфигурации без перезагрузки сервера.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-5770467845791387222</id><published>2009-08-18T05:29:00.000-07:00</published><updated>2010-03-16T03:52:01.161-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="jbpm"/><category scheme="http://www.blogger.com/atom/ns#" term="jpdl"/><title type='text'>JBPM - часть 4 - язык описания процессов JPDL.</title><content type='html'>&lt;meta equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;&lt;meta name=&quot;ProgId&quot; content=&quot;Word.Document&quot;&gt;&lt;meta name=&quot;Generator&quot; content=&quot;Microsoft Word 12&quot;&gt;&lt;meta name=&quot;Originator&quot; content=&quot;Microsoft Word 12&quot;&gt;&lt;link rel=&quot;File-List&quot; href=&quot;file:///C:%5CDOCUME%7E1%5Capetrov%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml&quot;&gt;&lt;link rel=&quot;themeData&quot; href=&quot;file:///C:%5CDOCUME%7E1%5Capetrov%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx&quot;&gt;&lt;link rel=&quot;colorSchemeMapping&quot; href=&quot;file:///C:%5CDOCUME%7E1%5Capetrov%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml&quot;&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:worddocument&gt;   &lt;w:view&gt;Normal&lt;/w:View&gt;   &lt;w:zoom&gt;0&lt;/w:Zoom&gt;   &lt;w:trackmoves/&gt;   &lt;w:trackformatting/&gt;   &lt;w:punctuationkerning/&gt;   &lt;w:validateagainstschemas/&gt;   &lt;w:saveifxmlinvalid&gt;false&lt;/w:SaveIfXMLInvalid&gt;   &lt;w:ignoremixedcontent&gt;false&lt;/w:IgnoreMixedContent&gt;   &lt;w:alwaysshowplaceholdertext&gt;false&lt;/w:AlwaysShowPlaceholderText&gt;   &lt;w:donotpromoteqf/&gt;   &lt;w:lidthemeother&gt;RU&lt;/w:LidThemeOther&gt;   &lt;w:lidthemeasian&gt;X-NONE&lt;/w:LidThemeAsian&gt;   &lt;w:lidthemecomplexscript&gt;X-NONE&lt;/w:LidThemeComplexScript&gt;   &lt;w:compatibility&gt;    &lt;w:breakwrappedtables/&gt;    &lt;w:snaptogridincell/&gt;    &lt;w:wraptextwithpunct/&gt;    &lt;w:useasianbreakrules/&gt;    &lt;w:dontgrowautofit/&gt;    &lt;w:splitpgbreakandparamark/&gt;    &lt;w:dontvertaligncellwithsp/&gt;    &lt;w:dontbreakconstrainedforcedtables/&gt;    &lt;w:dontvertalignintxbx/&gt;    &lt;w:word11kerningpairs/&gt;    &lt;w:cachedcolbalance/&gt;   &lt;/w:Compatibility&gt;   &lt;m:mathpr&gt;    &lt;m:mathfont val=&quot;Cambria Math&quot;&gt;    &lt;m:brkbin val=&quot;before&quot;&gt;    &lt;m:brkbinsub val=&quot;--&quot;&gt;    &lt;m:smallfrac val=&quot;off&quot;&gt;    &lt;m:dispdef/&gt;    &lt;m:lmargin val=&quot;0&quot;&gt;    &lt;m:rmargin val=&quot;0&quot;&gt;    &lt;m:defjc val=&quot;centerGroup&quot;&gt;    &lt;m:wrapindent val=&quot;1440&quot;&gt;    &lt;m:intlim val=&quot;subSup&quot;&gt;    &lt;m:narylim val=&quot;undOvr&quot;&gt;   &lt;/m:mathPr&gt;&lt;/w:WordDocument&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;!--[if gte mso 9]&gt;&lt;xml&gt;  &lt;w:latentstyles deflockedstate=&quot;false&quot; defunhidewhenused=&quot;true&quot; defsemihidden=&quot;true&quot; defqformat=&quot;false&quot; defpriority=&quot;99&quot; latentstylecount=&quot;267&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;0&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Normal&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;9&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;heading 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;9&quot; qformat=&quot;true&quot; name=&quot;heading 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;9&quot; qformat=&quot;true&quot; name=&quot;heading 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;9&quot; qformat=&quot;true&quot; name=&quot;heading 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;9&quot; qformat=&quot;true&quot; name=&quot;heading 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;9&quot; qformat=&quot;true&quot; name=&quot;heading 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;9&quot; qformat=&quot;true&quot; name=&quot;heading 7&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;9&quot; qformat=&quot;true&quot; name=&quot;heading 8&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;9&quot; qformat=&quot;true&quot; name=&quot;heading 9&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;39&quot; name=&quot;toc 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;39&quot; name=&quot;toc 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;39&quot; name=&quot;toc 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;39&quot; name=&quot;toc 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;39&quot; name=&quot;toc 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;39&quot; name=&quot;toc 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;39&quot; name=&quot;toc 7&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;39&quot; name=&quot;toc 8&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;39&quot; name=&quot;toc 9&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;35&quot; qformat=&quot;true&quot; name=&quot;caption&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;10&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Title&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;1&quot; name=&quot;Default Paragraph Font&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;11&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Subtitle&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;22&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Strong&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;20&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Emphasis&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;59&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Table Grid&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Placeholder Text&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;1&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;No Spacing&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;60&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Shading&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;61&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light List&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;62&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Grid&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;63&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;64&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;65&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;66&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;67&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;68&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;69&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;70&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Dark List&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;71&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Shading&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;72&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful List&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;73&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Grid&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;60&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Shading Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;61&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light List Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;62&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Grid Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;63&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 1 Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;64&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 2 Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;65&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 1 Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Revision&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;34&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;List Paragraph&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;29&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Quote&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;30&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Intense Quote&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;66&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 2 Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;67&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 1 Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;68&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 2 Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;69&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 3 Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;70&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Dark List Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;71&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Shading Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;72&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful List Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;73&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Grid Accent 1&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;60&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Shading Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;61&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light List Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;62&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Grid Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;63&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 1 Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;64&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 2 Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;65&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 1 Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;66&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 2 Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;67&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 1 Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;68&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 2 Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;69&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 3 Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;70&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Dark List Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;71&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Shading Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;72&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful List Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;73&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Grid Accent 2&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;60&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Shading Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;61&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light List Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;62&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Grid Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;63&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 1 Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;64&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 2 Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;65&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 1 Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;66&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 2 Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;67&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 1 Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;68&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 2 Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;69&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 3 Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;70&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Dark List Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;71&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Shading Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;72&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful List Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;73&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Grid Accent 3&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;60&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Shading Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;61&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light List Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;62&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Grid Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;63&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 1 Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;64&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 2 Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;65&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 1 Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;66&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 2 Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;67&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 1 Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;68&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 2 Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;69&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 3 Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;70&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Dark List Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;71&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Shading Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;72&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful List Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;73&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Grid Accent 4&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;60&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Shading Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;61&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light List Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;62&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Grid Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;63&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 1 Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;64&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 2 Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;65&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 1 Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;66&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 2 Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;67&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 1 Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;68&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 2 Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;69&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 3 Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;70&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Dark List Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;71&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Shading Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;72&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful List Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;73&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Grid Accent 5&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;60&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Shading Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;61&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light List Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;62&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Light Grid Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;63&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 1 Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;64&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Shading 2 Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;65&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 1 Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;66&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium List 2 Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;67&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 1 Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;68&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 2 Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;69&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Medium Grid 3 Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;70&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Dark List Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;71&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Shading Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;72&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful List Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;73&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; name=&quot;Colorful Grid Accent 6&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;19&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Subtle Emphasis&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;21&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Intense Emphasis&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;31&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Subtle Reference&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;32&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Intense Reference&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;33&quot; semihidden=&quot;false&quot; unhidewhenused=&quot;false&quot; qformat=&quot;true&quot; name=&quot;Book Title&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;37&quot; name=&quot;Bibliography&quot;&gt;   &lt;w:lsdexception locked=&quot;false&quot; priority=&quot;39&quot; qformat=&quot;true&quot; name=&quot;TOC Heading&quot;&gt;  &lt;/w:LatentStyles&gt; &lt;/xml&gt;&lt;![endif]--&gt;&lt;style&gt; &lt;!--  /* Font Definitions */  @font-face 	{font-family:&quot;Cambria Math&quot;; 	panose-1:2 4 5 3 5 4 6 3 2 4; 	mso-font-charset:1; 	mso-generic-font-family:roman; 	mso-font-format:other; 	mso-font-pitch:variable; 	mso-font-signature:0 0 0 0 0 0;} @font-face 	{font-family:Calibri; 	panose-1:2 15 5 2 2 2 4 3 2 4; 	mso-font-charset:204; 	mso-generic-font-family:swiss; 	mso-font-pitch:variable; 	mso-font-signature:-1610611985 1073750139 0 0 159 0;}  /* Style Definitions */  p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-unhide:no; 	mso-style-qformat:yes; 	mso-style-parent:&quot;&quot;; 	margin:0cm; 	margin-bottom:.0001pt; 	line-height:115%; 	mso-pagination:widow-orphan; 	font-size:11.0pt; 	font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;; 	mso-ascii-font-family:Calibri; 	mso-ascii-theme-font:minor-latin; 	mso-fareast-font-family:Calibri; 	mso-fareast-theme-font:minor-latin; 	mso-hansi-font-family:Calibri; 	mso-hansi-theme-font:minor-latin; 	mso-bidi-font-family:&quot;Times New Roman&quot;; 	mso-bidi-theme-font:minor-bidi; 	mso-fareast-language:EN-US;} a:link, span.MsoHyperlink 	{mso-style-priority:99; 	color:blue; 	mso-themecolor:hyperlink; 	text-decoration:underline; 	text-underline:single;} a:visited, span.MsoHyperlinkFollowed 	{mso-style-noshow:yes; 	mso-style-priority:99; 	color:purple; 	mso-themecolor:followedhyperlink; 	text-decoration:underline; 	text-underline:single;} .MsoChpDefault 	{mso-style-type:export-only; 	mso-default-props:yes; 	mso-ascii-font-family:Calibri; 	mso-ascii-theme-font:minor-latin; 	mso-fareast-font-family:Calibri; 	mso-fareast-theme-font:minor-latin; 	mso-hansi-font-family:Calibri; 	mso-hansi-theme-font:minor-latin; 	mso-bidi-font-family:&quot;Times New Roman&quot;; 	mso-bidi-theme-font:minor-bidi; 	mso-fareast-language:EN-US;} .MsoPapDefault 	{mso-style-type:export-only; 	line-height:115%;} @page Section1 	{size:612.0pt 792.0pt; 	margin:2.0cm 42.5pt 2.0cm 3.0cm; 	mso-header-margin:36.0pt; 	mso-footer-margin:36.0pt; 	mso-paper-source:0;} div.Section1 	{page:Section1;} --&gt; &lt;/style&gt;&lt;!--[if gte mso 10]&gt; &lt;style&gt;  /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:&quot;Обычная таблица&quot;; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-priority:99; 	mso-style-qformat:yes; 	mso-style-parent:&quot;&quot;; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	line-height:115%; 	mso-pagination:widow-orphan; 	font-size:11.0pt; 	font-family:&quot;Calibri&quot;,&quot;sans-serif&quot;; 	mso-ascii-font-family:Calibri; 	mso-ascii-theme-font:minor-latin; 	mso-fareast-font-family:&quot;Times New Roman&quot;; 	mso-fareast-theme-font:minor-fareast; 	mso-hansi-font-family:Calibri; 	mso-hansi-theme-font:minor-latin;} &lt;/style&gt; &lt;![endif]--&gt;    &lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;span style=&quot;&quot; lang=&quot;EN-US&quot;&gt;jPDL&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;– язык исполнения процессов с великолепными возможностями моделирования, прозрачной интеграцией с &lt;span style=&quot;&quot; lang=&quot;EN-US&quot;&gt;Java&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;и великолепными&lt;span style=&quot;&quot;&gt;  &lt;/span&gt;возможностями управления заданиями. Цитата с сайта &lt;a href=&quot;http://jboss.org/jbossjbpm/jpdl/&quot;&gt;JPDL &lt;/a&gt;&lt;a href=&quot;http://jboss.org/jbossjbpm/jpdl/&quot;&gt;&lt;/a&gt;. &lt;/span&gt;&lt;/p&gt;  &lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;Посмотрим чуть более подробно&lt;span style=&quot;&quot;&gt;  &lt;/span&gt;какие возможности предоставляет язык. Описание процесса представляет собой &lt;span style=&quot;&quot; lang=&quot;EN-US&quot;&gt;xml&lt;/span&gt;&lt;span lang=&quot;EN-US&quot;&gt; &lt;/span&gt;файл. Теги и их назначение сейчас и будет разобрано.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;font-weight: bold;&quot; class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;Действия, отвечающие за управление потоком исполнения процесса.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;1 &amp;lt;&lt;span style=&quot;font-weight: bold;&quot;&gt;process&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-size:100%;&quot;&gt; - начальный тег описания процесса.&lt;br /&gt;&lt;br /&gt;2 &lt;span style=&quot;font-weight: bold;&quot;&gt;Действия, управляющие потоком исполнения&lt;/span&gt;:&lt;br /&gt;2.1&lt;span style=&quot;font-weight: bold;&quot;&gt; &lt;/span&gt;&amp;lt;&lt;span style=&quot;font-weight: bold;&quot;&gt;start&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt; &lt;/span&gt;Указывает точку входа процесса. Она должна быть только одна и только один переход может указываться внутри нее.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;    2.2 &amp;lt;&lt;span style=&quot;font-weight: bold;&quot;&gt;state&lt;/span&gt;&amp;gt; Действие, означающее ожидание вызова внешнего тригера, который будет предоставлен через JBPM API. Данное действие не содержит никаких атрибутов или внутренних элементов. Есть две разновидности этого типа: последовательность (state sequence) и выбор (state choice). Отличие в том, что в первом случае указывается лишь один transition внутри state, а во втором их может быть несколько. В зависимости от того, что вернет внешний тригер будет выбрана та или иная ветка исполнения.&lt;br /&gt;&lt;br /&gt;Примеры обоих вариантов:&lt;br /&gt;    1)&lt;span style=&quot;font-weight: bold;&quot;&gt; sequence of states&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;          &lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;        &lt;process name=&quot;StateSequence&quot; xmlns=&quot;http://jbpm.org/4.0/jpdl&quot;&gt;&lt;br /&gt;            &lt;start&gt;&lt;br /&gt;                &lt;transition to=&quot;a&quot;/&gt;&lt;br /&gt;            &lt;/start&gt;&lt;br /&gt;            &lt;state name=&quot;a&quot;&gt;&lt;br /&gt;                &lt;transition to=&quot;b&quot;/&gt;&lt;br /&gt;            &lt;/state&gt;&lt;br /&gt;            &lt;state name=&quot;b&quot;&gt;&lt;br /&gt;                &lt;transition to=&quot;c&quot;/&gt;&lt;br /&gt;            &lt;/state&gt;&lt;br /&gt;            &lt;state name=&quot;c&quot;/&gt;&lt;br /&gt;        &lt;/process&gt;	&lt;br /&gt;]]&gt;   &lt;/script&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;Execution executionInA = processInstance.findActiveExecutionIn(&quot;a&quot;);&lt;br /&gt;assertNotNull(executionInA);&lt;br /&gt;processInstance = executionService.signalExecutionById(executionInA.getId());&lt;br /&gt;Execution executionInB = processInstance.findActiveExecutionIn(&quot;b&quot;);assertNotNull(executionInB);&lt;br /&gt;processInstance = executionService.signalExecutionById(executionInB.getId());&lt;br /&gt;Execution executionInC = processInstance.findActiveExecutionIn(&quot;c&quot;);&lt;br /&gt;assertNotNull(executionInC);&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;signalExecutionById(executionInA.getId())&lt;/span&gt; - это как раз метод инициирующий вызов внешнего тригера.&lt;br /&gt;&lt;br /&gt;    2) &lt;span style=&quot;font-weight: bold;&quot;&gt;state choice&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;    &lt;process name=&quot;StateChoice&quot; xmlns=&quot;http://jbpm.org/4.0/jpdl&quot;&gt;&lt;br /&gt;        &lt;start&gt;&lt;br /&gt;            &lt;transition to=&quot;wait for response&quot;/&gt;&lt;br /&gt;        &lt;/start&gt;&lt;br /&gt;        &lt;state name=&quot;wait for response&quot;&gt;&lt;br /&gt;            &lt;transition name=&quot;accept&quot; to=&quot;submit document&quot;/&gt;&lt;br /&gt;            &lt;transition name=&quot;reject&quot; to=&quot;try again&quot;/&gt;&lt;br /&gt;        &lt;/state&gt;&lt;br /&gt;        &lt;state name=&quot;submit document&quot;/&gt;&lt;br /&gt;        &lt;state name=&quot;try again&quot;/&gt;&lt;br /&gt;    &lt;/process&gt;&lt;br /&gt;    ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;String executionId = processInstance.findActiveExecutionIn(&quot;wait for response&quot;).getId();&lt;br /&gt;processInstance = executionService.signalExecutionById(executionId, &quot;accept&quot;);&lt;br /&gt;assertTrue(processInstance.isActive(&quot;submit document&quot;));&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;Здесь указывается по какой ветке будет переход (строчка &quot;accept&quot;).            &lt;br /&gt;&lt;br /&gt;2.3 &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;decision&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    Имеет несколько исходящих переходов. Когда достигается данное действие, то автоматически вычисляется какой из переходов будет выбран для дальнейшего исполнения процесса.&lt;br /&gt;            Возможны три варианта использования этого действия:&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;       2.3.1 &lt;span style=&quot;font-weight: bold;&quot;&gt;Decision conditions.&lt;/span&gt;&lt;br /&gt;    В этом случае внутри каждого перехода указывается condition (условие). Выбирается тот переход для которого либо выполнено условие, указанное в нем, либо переход без условий.&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;        &lt;process name=&quot;DecisionConditions&quot;&gt;&lt;br /&gt;            &lt;start&gt;&lt;br /&gt;                &lt;transition to=&quot;evaluate document&quot;/&gt;&lt;br /&gt;            &lt;/start&gt;&lt;br /&gt;            &lt;decision name=&quot;evaluate document&quot;&gt;&lt;br /&gt;                &lt;transition to=&quot;submit document&quot;&gt;&lt;br /&gt;                    &lt;condition expr=&quot;#{content==&quot;good&quot;}&quot; /&gt;&lt;br /&gt;                &lt;/transition&gt;&lt;br /&gt;                &lt;transition to=&quot;try again&quot;&gt;&lt;br /&gt;                    &lt;condition expr=&quot;#{content==&quot;not so good&quot;}&quot; /&gt;&lt;br /&gt;                &lt;/transition&gt;&lt;br /&gt;                &lt;transition to=&quot;give up&quot;/&gt;&lt;br /&gt;            &lt;/decision&gt;&lt;br /&gt;            &lt;state name=&quot;submit document&quot;/&gt;&lt;br /&gt;            &lt;state name=&quot;try again&quot;/&gt;&lt;br /&gt;            &lt;state name=&quot;give up&quot;/&gt;&lt;br /&gt;        &lt;/process&gt;&lt;br /&gt;        ]]&gt;&lt;/script&gt;&lt;br /&gt;    &lt;span style=&quot;font-style: italic;&quot;&gt;content &lt;/span&gt;- параметр, передающийся в процесс при его запуске.   &lt;br /&gt;&lt;br /&gt;    2.3.2&lt;span style=&quot;font-weight: bold;&quot;&gt; Decision expression&lt;/span&gt;&lt;br /&gt;    Аналогично предыдущему, но выражение вычисляется на уровне decision, результат вычисления - строка, сравнивается с возможными переходами.&lt;br /&gt;&lt;br /&gt;    &lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;        &lt;process name=&quot;DecisionExpression&quot; xmlns=&quot;http://jbpm.org/4.0/jpdl&quot;&gt;&lt;br /&gt;            &lt;start&gt;&lt;br /&gt;                &lt;transition to=&quot;evaluate document&quot;/&gt;&lt;br /&gt;            &lt;/start&gt;&lt;br /&gt;            &lt;decision name=&quot;evaluate document&quot; expr=&quot;#{content}&quot;&gt;&lt;br /&gt;                &lt;transition name=&quot;good&quot; to=&quot;submit document&quot;/&gt;&lt;br /&gt;                &lt;transition name=&quot;bad&quot; to=&quot;try again&quot;/&gt;&lt;br /&gt;                &lt;transition name=&quot;ugly&quot; to=&quot;give up&quot;/&gt;&lt;br /&gt;            &lt;/decision&gt;&lt;br /&gt;            &lt;state name=&quot;submit document&quot;/&gt;&lt;br /&gt;            &lt;state name=&quot;try again&quot;/&gt;&lt;br /&gt;            &lt;state name=&quot;give up&quot;/&gt;&lt;br /&gt;        &lt;/process&gt;&lt;br /&gt;     ]]&gt;&lt;/script&gt;&lt;br /&gt;    2.3.3&lt;span style=&quot;font-weight: bold;&quot;&gt; Decision handler&lt;/span&gt;&lt;br /&gt;    Это Java класс, который реализует интерфейс DecisionHandler, где программно можно определить в какую сторону пойдет дальнейшее выполнение процесса.&lt;br /&gt;        &lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;        &lt;decision name=&quot;evaluate document&quot;&gt;&lt;br /&gt;            &lt;handler class=&quot;org.jbpm.examples.decision.handler.ContentEvaluation&quot;/&gt;&lt;br /&gt;            &lt;transition name=&quot;good&quot; to=&quot;submit document&quot;/&gt;&lt;br /&gt;            &lt;transition name=&quot;bad&quot; to=&quot;try again&quot;/&gt;&lt;br /&gt;            &lt;transition name=&quot;ugly&quot; to=&quot;give up&quot;/&gt;&lt;br /&gt;        &lt;/decision&gt;&lt;br /&gt;    ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2.4 &lt;span style=&quot;font-weight: bold;&quot;&gt;concurrency&lt;/span&gt;&lt;br /&gt;С помощью элементов fork и  join можно добиться параллельного выполнения действий.  В join могут заходить несколько переходов, что и дает параллельность.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2.5 &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;end&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;Окончание исполнения. В общем случае при окончании ProcessInstance принудительно заканчиваются все параллельно выполняющиеся действия. Но можно указать, что окончиться должно только то &quot;исполнение&quot; execution, которое достигло конца, а остальные должны продолжиться. Для этого есть атрибут ends у тега end.&lt;br /&gt;&lt;br /&gt;    &lt;span style=&quot;font-style: italic;&quot;&gt;ends{processinstance|execution} &lt;/span&gt;&lt;br /&gt;Так же возможны множественные end в конце процесса. Еще можно с помощью атрибута state типизировать окончания.&lt;br /&gt;    &lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;        &lt;process name=&quot;EndMultiple&quot; xmlns=&quot;http://;jbpm.org/4/jpdl&quot;&gt;&lt;br /&gt;          &lt;start&gt;&lt;br /&gt;            &lt;transition to=&quot;get return code&quot; /&gt;&lt;br /&gt;          &lt;/start&gt;&lt;br /&gt;          &lt;state name=&quot;get return code&quot;&gt;&lt;br /&gt;            &lt;transition name=&quot;200&quot; to=&quot;ok&quot;/&gt;&lt;br /&gt;            &lt;transition name=&quot;400&quot; to=&quot;bad request&quot;/&gt;&lt;br /&gt;            &lt;transition name=&quot;500&quot; to=&quot;internal server error&quot;/&gt;&lt;br /&gt;          &lt;/state&gt;&lt;br /&gt;          &lt;end name=&quot;ok&quot;/&gt;&lt;br /&gt;          &lt;end name=&quot;bad request&quot;/&gt;&lt;br /&gt;          &lt;end name=&quot;internal server error&quot;/&gt;&lt;br /&gt;        &lt;/process&gt;&lt;br /&gt;        ]]&gt;&lt;/script&gt;&lt;br /&gt;2.6 &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;task&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;Создание задач для пользователей.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;2.7 &lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;sub-process&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;JBPM позволяет определять общие процессы в отдельных файлах и запускать их из других процессов с помощью данного тега. В подпроцесс можно передавать параметры через механизм переменных.&lt;br /&gt;&lt;br /&gt;    &lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;        &lt;sub-process name=&quot;review&quot;  sub-process-key=&quot;SubProcessReview&quot;&gt;&lt;br /&gt;            &lt;parameter-in var=&quot;document&quot; subvar=&quot;document&quot;/&gt;&lt;br /&gt;            &lt;parameter-out var=&quot;reviewResult&quot; subvar=&quot;result&quot;/&gt;&lt;br /&gt;            &lt;transition to=&quot;wait&quot;/&gt;&lt;br /&gt;        &lt;/sub-process&gt;&lt;br /&gt;        ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;2.8&lt;span style=&quot;font-weight: bold;&quot;&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;сustom&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;Позволяет использовать пользовательский код. Классы, реализующие ExternalActivityBehaviour.&lt;br /&gt;&lt;br /&gt;       &lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: xml;&quot;&gt;&lt;![CDATA[&lt;br /&gt;        &lt;process name=&quot;Custom&quot; xmlns=&quot;http://jbpm.org/4.0/jpdl&quot;&gt;&lt;br /&gt;            &lt;start&gt;&lt;br /&gt;                &lt;transition to=&quot;print dots&quot;/&gt;&lt;br /&gt;            &lt;/start&gt;&lt;br /&gt;            &lt;custom name=&quot;print dots&quot;   class=&quot;org.jbpm.examples.custom.PrintDots&quot;&gt;&lt;br /&gt;                &lt;transition to=&quot;end&quot;/&gt;&lt;br /&gt;            &lt;/custom&gt;&lt;br /&gt;            &lt;end name=&quot;end&quot;/&gt;&lt;br /&gt;        &lt;/process&gt;&lt;br /&gt;        ]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Я рассмотрел действия, отвечающие за управление потоком исполнения процесса. Так же есть ряд &quot;автоматических&quot; действий:&lt;span style=&quot;font-weight: bold;&quot;&gt; java, script, hql, sql, mail&lt;/span&gt;.&lt;br /&gt;Их я не буду рассматривать в этой статье, чтобы не перегружать ее. Вернусь к ним позднее. На этом краткий обзор языка jPDL закончен. В следующей статье разберу как интегрировать &lt;a href=&quot;http://www.jbpm.org/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JBPM &lt;/span&gt;&lt;/a&gt;со &lt;a href=&quot;http://springsource.org/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring&lt;/span&gt;&lt;/a&gt; и &lt;a href=&quot;http://hibernate.org/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Hibernate&lt;/span&gt;&lt;/a&gt;.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;p.s. Примеры xml описаний взяты из официальной документации движка.&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;span style=&quot;font-size:11;&quot;&gt;&lt;b style=&quot;&quot;&gt;&lt;br /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;b style=&quot;&quot;&gt;  &lt;/b&gt;&lt;/span&gt;&lt;p class=&quot;MsoNormal&quot;&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;o:p&gt;&lt;b style=&quot;&quot;&gt; &lt;/b&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;b style=&quot;&quot;&gt;  &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size:100%;&quot;&gt;&lt;b style=&quot;&quot;&gt;  &lt;/b&gt;&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/5770467845791387222/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2009/08/jbpm-4-jpdl.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/5770467845791387222'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/5770467845791387222'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2009/08/jbpm-4-jpdl.html' title='JBPM - часть 4 - язык описания процессов JPDL.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-3331543595690439362</id><published>2009-08-18T04:59:00.000-07:00</published><updated>2010-04-02T05:15:03.735-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="jbpm"/><title type='text'>JBPM - часть 3 - Краткое описание запуска процессов в JBPM.</title><content type='html'>В двух предыдущих частях я дал общее описание &lt;a href=&quot;http://www.jbpm.org/&quot;&gt;JBPM&lt;/a&gt;, а так же как его развернуть под &lt;a href=&quot;http://jboss.org/&quot;&gt;JBOSS&lt;/a&gt;.&lt;br /&gt;Сейчас подробнее остановлюсь на том как деплоить и запускать процессы.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Общее представление о деплое и запуске процессов.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Важны три момента:&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;1. Доступ к JBPM идет через сервисы.&lt;/span&gt; Заявляется, что это одно из основных отличий от предыдущей версии движка.&lt;br /&gt;Доступ к сервисам из приложения можно получить используя &lt;span style=&quot;font-style: italic;&quot;&gt;ProcessEngine&lt;/span&gt;, который ThreadSafe и его можно использовать через все приложение. Создается следующим образом:&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;&lt;br /&gt;ProcessEngine processEngine = new Configuration().buildProcessEngine();&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;2. Deploy процессов в jbpm. &lt;/span&gt;&lt;br /&gt;Это процесс сохранения описания процесса в БД, которую использует JBPM. Для этого используется &lt;span style=&quot;font-style: italic;&quot;&gt;RepositoryService&lt;/span&gt;, получаемый через &lt;span style=&quot;font-style: italic;&quot;&gt;ProcessEngine&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;RepositoryService repositoryService = processEngine.getRepositoryService();&lt;br /&gt;String deploymentDbid = repositoryService.createDeployment().&lt;br /&gt;addResourceFromClasspath(&quot;process-description.jpdl.xml&quot;).deploy();&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;3. Запуск нового экземпляра процесса.&lt;/span&gt;&lt;br /&gt;Экземпляр процесса (Process Instance) -это отдельный поток исполнения описания процесса, для конкретных данных.&lt;br /&gt;Запускается он через вызов метода сервиса &lt;span style=&quot;font-style: italic;&quot;&gt;ExecutionService&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;ExecutionService executionService = processEngine.getExecutionService();&lt;br /&gt;ProcessInstance processInstance = executionService.startProcessInstanceByKey(&quot;DecisionExpression&quot;, variables);&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;тут есть несколько способов запуска:&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;a) последняя версия процесса&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;executionService.startProcessInstanceByKey(&quot;ICL&quot;);&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;b) Специфичная версия процесса&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;executionService.startProcessInstanceById(&quot;ICL-1&quot;);&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;с) С пользовательским ключом&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;     При старте процесса можно указать ключ, уникальный для этого описания      процесса.  Потом к запущенному экземпляру процесса можно будет получить доступ через этот ключ &lt;span style=&quot;font-style: italic;&quot;&gt;{process-key}.{execution-id}&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;ProcessInstance processInstance =   executionService.startProcessInstanceByKey(&quot;ICL&quot;, &quot;CL92837&quot;)&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;    В качестве такого ключа удобно использовать id объекта, участвующего в процессе. В таком случае можно легко узнать состояние процесса в любой момент его исполнения.</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/3331543595690439362/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2009/08/bpm-3-jbpm.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/3331543595690439362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/3331543595690439362'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2009/08/bpm-3-jbpm.html' title='JBPM - часть 3 - Краткое описание запуска процессов в JBPM.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-5028392633056890301</id><published>2009-08-14T05:57:00.000-07:00</published><updated>2010-04-02T05:33:10.610-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="installation"/><category scheme="http://www.blogger.com/atom/ns#" term="jboss"/><category scheme="http://www.blogger.com/atom/ns#" term="jbpm"/><title type='text'>JBPM - часть 2 - установка и настройка.</title><content type='html'>Рассмотрим как установить и настроить для работы &lt;a href=&quot;http://www.jbpm.org/&quot;&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;JBPM&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;Я предполагаю, что читателю известны такие понятия как сборка, сервер приложений, сервлет-контейнер и т.п.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Что понадобится для запуска.&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;        &lt;span style=&quot;font-weight: bold;&quot;&gt;Ant&lt;/span&gt; (да-да, не naven, что меня тоже очень удивило)&lt;/li&gt;&lt;li&gt;        &lt;span style=&quot;font-weight: bold;&quot;&gt;JBoss&lt;/span&gt;. JBPM может быть развернут и под Tomcat, но по умолчанию идет простая интеграция с JBoss. Для развертывания под Tomcat нужно чуть больше действий руками. (Для любопытных, в моих следующих статьях jbpm будет развернут как раз под Tomcat 6.)&lt;/li&gt;&lt;li&gt;        &lt;span style=&quot;font-weight: bold;&quot;&gt;СУБД.&lt;/span&gt; Я предпочел PostgreSQL. Можно воспользоваться и HSQLDB с которой поставляется JBPM.&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;        Драйвер&lt;/span&gt; для выбранной СУБД&lt;/li&gt;&lt;li&gt;        &lt;span style=&quot;font-weight: bold;&quot;&gt;дистриубтив JBPM&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Теперь, когда у нас есть все необходимое, мы можем приступить к развертыванию дистрибутива и настройке всего необходимого для запуска.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;1. Распаковать дистрибутив в выбранную директорию.&lt;/span&gt; После развертывания дистрибутива, мы увидим следующую структуру каталогов:&lt;br /&gt;&lt;br /&gt;&lt;a onblur=&quot;try {parent.deselectBloggerImageGracefully();} catch(e) {}&quot; href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOGd2ZuEPhQsdwcXQqh1uYIlbZ-PbHkSwqmdv-YFSHolVojb3IDMbBF2wSgOGuMxKUvtOrmEw5vmBMmMIARB26FR6uaHV_mOqkd7N1L62jezGo33Woh232WgK8S26HSm6SHvbQ6-_NI_c/s1600-h/jbpm-folder-structure.JPG&quot;&gt;&lt;img style=&quot;margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 160px;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOGd2ZuEPhQsdwcXQqh1uYIlbZ-PbHkSwqmdv-YFSHolVojb3IDMbBF2wSgOGuMxKUvtOrmEw5vmBMmMIARB26FR6uaHV_mOqkd7N1L62jezGo33Woh232WgK8S26HSm6SHvbQ6-_NI_c/s320/jbpm-folder-structure.JPG&quot; alt=&quot;&quot; id=&quot;BLOGGER_PHOTO_ID_5369806683335513282&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Если предположить, что мы просто хотим запустить тестовый пример, то этого достаточно. Но мы хотим создать среду для дальнейшей разработки нашего собственного&lt;br /&gt;проекта. Поэтому наши дальнейшие действия будут отличаться от мануала к тестовым примерам.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;2. Установить JBOSS. &lt;/span&gt;Просто распаковать архив в выбранную директорию.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;3. Установить ant.&lt;/span&gt; (если у вас его еще нет.)&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;4. Установить соответствующую СУБД&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;5. Создать в СУБД пользователя jbpm&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;6. Под пользователем jbpm создать базу jbpmdb&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;7. Создать таблицы в базе.&lt;/span&gt; Инициировать их тестовыми данными, чтобы можно было в последующем зайти в консоль. Для этого нужно испольнить две команды&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: text;&quot;&gt;&lt;br /&gt;[jbpm home dir]/db&gt; ant -Ddatabase=postgresql create.jbpm.schema&lt;br /&gt;[jbpm home dir]/db&gt; ant -Ddatabase=postgresql load.example.identities&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;8. Положить jdbc драйвер для СУБД в &lt;/span&gt;&lt;jbpm style=&quot;font-weight: bold;&quot; installation=&quot;&quot; dir=&quot;&quot;&gt;&lt;/jbpm&gt;&lt;/jbpm&gt;&lt;/jbpm&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;jbpm&gt;&lt;/jbpm&gt;&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;[jbpm home dir]&lt;/span&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;/&lt;/span&gt;&lt;jbpm installation=&quot;&quot; dir=&quot;&quot;&gt;&lt;jbpm installation=&quot;&quot; dir=&quot;&quot;&gt;&lt;jbpm installation=&quot;&quot; dir=&quot;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;lib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;9. Создать в директории &lt;/span&gt;&lt;/jbpm&gt;&lt;/jbpm&gt;&lt;/jbpm&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;&lt;jbpm&gt;&lt;/jbpm&gt;&lt;/span&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;[jbpm home dir]&lt;/span&gt;&lt;span style=&quot;font-style: italic;&quot;&gt;/&lt;/span&gt;&lt;jbpm installation=&quot;&quot; dir=&quot;&quot;&gt;&lt;jbpm installation=&quot;&quot; dir=&quot;&quot;&gt;&lt;jbpm installation=&quot;&quot; dir=&quot;&quot;&gt;&lt;jbpm installation=&quot;&quot; dir=&quot;&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;jboss файл build.properties&lt;/span&gt;&lt;br /&gt;Этот шаг требует пояснения. Дело в том, что некоторые умолчания, используемые при сборке, нас не устраивают. По умолчанию считается что jboss установлен в директорию &lt;jbpm installation=&quot;&quot; dir=&quot;&quot;&gt;[jbpm home dir]/jboss-5.0.0.GA, что версия сервера 5.0.0.GA и СУБД HSQLDB. Создавая такой файл, мы переопределяем эти свойства сборки:&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: text;&quot;&gt;&lt;br /&gt;database=postgresql&lt;br /&gt;jboss.version=5.0.1.GA&lt;br /&gt;jboss.parent.dir=C:/bin/java/appservers&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;10. Инсталировать JBPM в JBOSS.&lt;/span&gt;&lt;br /&gt;Для этого нужно исполнить команду&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: text;&quot;&gt;&lt;br /&gt;[jbpm home dir]/jboss&gt; ant -Ddatabase=mysql install.jbpm.into.jboss&lt;br /&gt;&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;11. Запустить JBOSS.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;После выполнения  вышеописанных действий, под JBOSS будет запущено приложение JBPM, которое будет доступно через jndi. В нашем приложении мы сможем использовать JBPM именно через доступ по jndi. Имеется в виду, что получение объекта ProcessEngine (входная точка для работы c JBPM), будет осуществляться через следующую конструкцию:&lt;br /&gt;&lt;br /&gt;&lt;script type=&quot;syntaxhighlighter&quot; class=&quot;brush: java;&quot;&gt;ProcessEngine engine = new InitialContext().lookup(&quot;java:/ProcessEngine&quot;);&lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Стоит отметить, что вместо файла &lt;span style=&quot;font-style: italic;&quot;&gt;build.properties&lt;/span&gt; все параметры можно указывать в командной строке, но мне это кажется неудобным, поэтому был выбран иной способ.&lt;br /&gt;&lt;br /&gt;Вот собственно и вся установка JBPM.&lt;br /&gt;&lt;/jbpm&gt;&lt;/jbpm&gt;&lt;/jbpm&gt;&lt;/jbpm&gt;&lt;/jbpm&gt;&lt;/jbpm&gt;</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/5028392633056890301/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2009/08/jbpm-2.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/5028392633056890301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/5028392633056890301'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2009/08/jbpm-2.html' title='JBPM - часть 2 - установка и настройка.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOGd2ZuEPhQsdwcXQqh1uYIlbZ-PbHkSwqmdv-YFSHolVojb3IDMbBF2wSgOGuMxKUvtOrmEw5vmBMmMIARB26FR6uaHV_mOqkd7N1L62jezGo33Woh232WgK8S26HSm6SHvbQ6-_NI_c/s72-c/jbpm-folder-structure.JPG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-4166626607143490580</id><published>2009-08-14T01:55:00.000-07:00</published><updated>2010-04-02T05:38:01.070-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="jbpm"/><category scheme="http://www.blogger.com/atom/ns#" term="process management engine"/><category scheme="http://www.blogger.com/atom/ns#" term="workflow engine"/><title type='text'>JBPM - часть 1 - process management engine от JBOSS.</title><content type='html'>Аббревиатуру &lt;a href=&quot;http://labs.jboss.com/jbossjbpm/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JBPM&lt;/span&gt;&lt;/a&gt; видели и слышали многие. До реальной работы с этой технологией у меня руки не доходили.&lt;br /&gt;Но вот недавно вышла четвертая версия продукта и мне посчастливилось ее использовать.&lt;br /&gt;Я начинаю цикл статей о &lt;a href=&quot;http://labs.jboss.com/jbossjbpm/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JBPM 4&lt;/span&gt;&lt;/a&gt;. В этой я дам краткий обзор технологии.&lt;br /&gt;В следующих материалах будут освещены вопросы создания приложения с использованием &lt;a href=&quot;http://labs.jboss.com/jbossjbpm/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JBPM4&lt;/span&gt;&lt;/a&gt;, возможностей языка описания процессов &lt;a href=&quot;http://jboss.org/jbossjbpm/jpdl/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JPDL&lt;/span&gt;&lt;/a&gt;, взаимодействия с &lt;a href=&quot;http://labs.jboss.com/jbossjbpm/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JBPM&lt;/span&gt; &lt;/a&gt;через &lt;a href=&quot;http://www.springsource.org/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Spring&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://labs.jboss.com/jbossjbpm/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JBPM&lt;/span&gt; &lt;/a&gt;- по своей сути является платформой, обеспечивающей исполнение процессов, описанных с использованием языков описания процессов.&lt;br /&gt;Языков три: &lt;a href=&quot;http://jboss.org/jbossjbpm/jpdl/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;jPDL&lt;/span&gt;&lt;/a&gt;, &lt;a href=&quot;http://www.oasis-open.org/committees/wsbpel/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;BPEL&lt;/span&gt;&lt;/a&gt; и &lt;span style=&quot;font-weight: bold;&quot;&gt;Pageflow&lt;/span&gt;.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://jboss.org/jbossjbpm/jpdl/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;jPDL&lt;/span&gt; &lt;/a&gt;- это собственная разработка &lt;a href=&quot;http://jboss.org/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JBOSS&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.oasis-open.org/committees/wsbpel/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;BPEL&lt;/span&gt; &lt;/a&gt;- это стандарт описания процессов. &lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;Pageflow&lt;/span&gt; понятно из названия, что это за процессы. Примером для последнего типа процессов может служить Tapestry. &lt;/li&gt;&lt;/ul&gt;На &lt;a href=&quot;http://www.oasis-open.org/committees/wsbpel/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;BPEL&lt;/span&gt;&lt;/a&gt; я останавливаться не буду, поскольку не использовал его.&lt;br /&gt;&lt;a href=&quot;http://labs.jboss.com/jbossjbpm/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JBPM&lt;/span&gt; &lt;/a&gt;позовляет автоматизировать исполнение процесса, представленного в виде xml описания(&lt;a href=&quot;http://jboss.org/jbossjbpm/jpdl/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;jPDL&lt;/span&gt;&lt;/a&gt;). Основные преимущества:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;   Гарантируется сохранение состояния процесса в его промежуточной точке.&lt;/li&gt;&lt;li&gt;Возможность асинхронного исполнения процессов.&lt;/li&gt;&lt;li&gt;   Версионность описания процесса&lt;/li&gt;&lt;li&gt;   Возможность использование листенеров на входе, выходе из узлов процесса и в других случаях.&lt;/li&gt;&lt;li&gt;   Заведение в системе пользователей, назначение им заданий и уже готовый gui отображающий их  для каждого пользователя.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Поддержка рассылки email сообщений о назначении пользователям заданий.&lt;/li&gt;&lt;li&gt;   Интерфейс администратора, позволяющий отслеживать состояния запущенных процессов и тех, что уже исполнились.&lt;/li&gt;&lt;li&gt;   Возможность использования скриптового языка &lt;a href=&quot;http://java.sun.com/javaee/5/docs/tutorial/doc/bnahq.html&quot;&gt; &lt;span style=&quot;font-weight: bold;&quot;&gt;jUEL&lt;/span&gt;&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;   Запуск как отдельным приложением, так и внутри вашего приложения.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Как видно плюсов у технологии достаточно много, поробуем их разобрать более подробно в последующих статьях. А что же насчет минусов?&lt;br /&gt;Основное опасение разработчиков при использовании таких технологий как &lt;a href=&quot;http://labs.jboss.com/jbossjbpm/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JBPM&lt;/span&gt;&lt;/a&gt;, &lt;a href=&quot;http://www.opensymphony.com/osworkflow/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;OSWorkflow&lt;/span&gt; &lt;/a&gt;и т.п. состоит в том, что они считаются медленными.&lt;br /&gt;Моя дальнейшая работа с &lt;a href=&quot;http://labs.jboss.com/jbossjbpm/&quot;&gt;&lt;span style=&quot;font-weight: bold;&quot;&gt;JBPM&lt;/span&gt; &lt;/a&gt;позволила мне усомниться в этом. Результаты тестов, будут приведены в следующих статьях.</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/4166626607143490580/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2009/08/jbpm-process-management-engine-jboss.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/4166626607143490580'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/4166626607143490580'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2009/08/jbpm-process-management-engine-jboss.html' title='JBPM - часть 1 - process management engine от JBOSS.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9096196924950961475.post-790296863985448153</id><published>2009-08-14T00:56:00.000-07:00</published><updated>2009-08-14T00:57:52.111-07:00</updated><title type='text'>Начнем.</title><content type='html'>Всем привет. В этом блоге я буду писать о различных технологиях, используемых в веб-разработке. Так же не буду избегать&lt;br /&gt;текстов, связанных с общими вопросами программирования на языке Java, работы с БД, создания инфраструктуры разработки и прочих околоразработческих тем.&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://anpetrov.blogspot.com/feeds/790296863985448153/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://anpetrov.blogspot.com/2009/08/blog-post_14.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/790296863985448153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9096196924950961475/posts/default/790296863985448153'/><link rel='alternate' type='text/html' href='http://anpetrov.blogspot.com/2009/08/blog-post_14.html' title='Начнем.'/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>