Refs #1633 CUBA documentation (views)

This commit is contained in:
Konstantin Krivopustov 2012-11-23 15:53:30 +00:00
parent 5e57586e14
commit 62faad76b0
5 changed files with 618 additions and 353 deletions

View File

@ -112,45 +112,6 @@
<title>Описание скриптов сборки</title>
<para>TODO</para>
</section>
<section>
<title>Описание конфигурационных файлов</title>
<variablelist>
<varlistentry id="datatypes.xml">
<term>datatypes.xml</term>
<listitem>
<para>TODO</para>
</listitem>
</varlistentry>
<varlistentry>
<term id="persistence.xml">persistence.xml</term>
<listitem>
<para>TODO</para>
</listitem>
</varlistentry>
<varlistentry id="metadata.xml">
<term>metadata.xml</term>
<listitem>
<para>TODO</para>
</listitem>
</varlistentry>
<varlistentry id="text_context_xml">
<term>context.xml</term>
<listitem>
<para>В данном конфигурационном файле задается <link linkend="dbms_types_section">тип используемой СУБД</link>, а также использование <classname>PersistenceManager</classname>.</para>
<para>Пример файла <filename>context.xml</filename> для приложения Магазин:</para>
<programlisting language="xml"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="source/context.xml" encoding="UTF-8" parse="text"/></programlisting>
</listitem>
</varlistentry>
<varlistentry id="text_web_xml_core">
<term>web.xml</term>
<listitem>
<para>Файл <filename>web.xml</filename> модуля <structname>core</structname> приложения Магазин:</para>
<programlisting language="xml"><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="source/web.xml" encoding="UTF-8" parse="text"/></programlisting>
</listitem>
</varlistentry>
</variablelist>
<para>TODO</para>
</section>
<section>
<title>Создание проекта</title>
<para>TODO</para>

View File

@ -43,21 +43,13 @@
</imageobject>
</mediaobject>
</figure>
<para>CUBA-приложение всегда состоит как минимум из двух частей:</para>
<itemizedlist>
<listitem>
<para>Веб-приложения среднего слоя (<structname>Middleware</structname>)</para>
</listitem>
<listitem>
<para>Веб-приложения веб-клиента (<structname>Web Client</structname>)</para>
</listitem>
</itemizedlist>
<para>Опционально приложение может содержать десктопный клиент и один или несколько порталов.</para>
<para>Обязательным уровнем любого приложения является средний слой - <structname>Middleware</structname>. Для реализации пользовательского интерфейса как правило используется один или несколько клиентских уровней, например <structname>Web Client</structname> и <structname>Web Portal</structname>. </para>
<para>Вышеперечисленные уровни являются стандартными, однако в комплексном приложении для разделения функциональности можно без труда создать произвольное количество как клиентских уровней, так и уровней среднего слоя.</para>
<para>Все клиенты взаимодействуют со средним слоем одинаковым образом посредством протокола <application>HTTP</application>, что позволяет размещать средний слой произвольным образом, в том числе за сетевым экраном. Следует отметить, что при развертывании в простейшем случае среднего слоя и веб-клиента на одном сервере между ними организуется локальное взаимодействие в обход сетевого стека для снижения накладных расходов.</para>
</section>
<section id="app_modules_section">
<title>Модули приложения</title>
<para>Модуль наименьшая структурная единица CUBA-приложения. Представляет собой один модуль проекта приложения и соответствующий ему JAR файл.</para>
<para>Модуль наименьшая структурная единица CUBA-приложения. Представляет собой один модуль проекта приложения и соответствующий ему JAR файл с исполняемым кодом.</para>
<para>Стандартные модули: <itemizedlist>
<listitem>
<para><structname>global</structname> включает в себя классы сущностей, интерфейсы сервисов и другие общие для всех уровней классы. Используется на всех <link linkend="app_tiers_section">уровнях приложения</link>.</para>
@ -210,7 +202,7 @@
<para>сущность</para>
</listitem>
</itemizedlist></para>
<figure>
<figure id="entity_base_classes">
<title>Базовые классы сущностей</title>
<mediaobject>
<imageobject>
@ -402,7 +394,7 @@
<para>Пример:<programlisting>@PrimaryKeyJoinColumn(name = &quot;CARD_ID&quot;, referencedColumnName = &quot;ID&quot;)</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry id="namePattern">
<term>
<interfacename>@NamePattern</interfacename>
</term>
@ -1058,177 +1050,180 @@ public class MyBean implements AppContext.Listener {
<para>позволяет создавать универсальные механизмы работы с данными</para>
</listitem>
</itemizedlist>
<figure>
<title>Интерфейсы фреймворка метаданных</title>
<mediaobject>
<imageobject>
<imagedata contentwidth="80%" align="center" fileref="img/MetadataFramework.png"/>
</imageobject>
</mediaobject>
</figure>
<para>Рассмотрим основные интерфейсы метаданных.</para>
<variablelist>
<varlistentry>
<term>
<interfacename>Session</interfacename>
</term>
<listitem>
<para>Точка входа в фреймворк метаданных. Позволяет получать экземпляры <interfacename>MetaClass</interfacename> по имени и по соответствующему классу Java. Обратите внимание на различие методов <code>getClass()</code> и <code>getClassNN()</code> - первые могут возвращать <code>null</code>, вторые нет (NonNull).</para>
<para>Объект <interfacename>Session</interfacename> может быть получен через интерфейс инфраструктуры <interfacename>
<link linkend="Metadata">Metadata</link>
</interfacename>.</para>
<para>Пример:<programlisting>@Inject
<section>
<title>Интерфейсы метаданных</title>
<para>Рассмотрим основные интерфейсы метаданных.</para>
<figure>
<title>Интерфейсы фреймворка метаданных</title>
<mediaobject>
<imageobject>
<imagedata contentwidth="80%" align="center" fileref="img/MetadataFramework.png"/>
</imageobject>
</mediaobject>
</figure>
<variablelist>
<varlistentry>
<term>
<interfacename>Session</interfacename>
</term>
<listitem>
<para>Точка входа в фреймворк метаданных. Позволяет получать экземпляры <interfacename>MetaClass</interfacename> по имени и по соответствующему классу Java. Обратите внимание на различие методов <code>getClass()</code> и <code>getClassNN()</code> - первые могут возвращать <code>null</code>, вторые нет (NonNull).</para>
<para>Объект <interfacename>Session</interfacename> может быть получен через интерфейс инфраструктуры <interfacename>
<link linkend="Metadata">Metadata</link>
</interfacename>.</para>
<para>Пример:<programlisting>@Inject
protected Metadata metadata;
...
Session session = metadata.getSession();
MetaClass metaClass1 = session.getClassNN(&quot;sec$User&quot;);
MetaClass metaClass2 = session.getClassNN(User.class);
assert metaClass1 == metaClass2;</programlisting></para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<interfacename>MetaModel</interfacename>
</term>
<listitem>
<para>Редко используемый интерфейс, служит для группировки мета-классов. </para>
<para>Группировка осуществляется по первым трем частям имени пакета Java класса сущности. Например, мета-класс сущности <classname>com.abc.sales.entity.Customer</classname> принадлежит мета-модели с именем <code>com.abc.sales</code></para>
</listitem>
</varlistentry>
<varlistentry id="MetaClass">
<term>
<interfacename>MetaClass</interfacename>
</term>
<listitem>
<para>Интерфейс метаданных класса сущности. <classname>MetaClass</classname> всегда ассоциирован с классом Java, которого он представляет.</para>
<para>Основные методы:</para>
<itemizedlist>
<listitem>
<para><code>getName()</code> имя сущности, по соглашению первой частью имени до знака <code>$</code> является код пространства имен, например, <classname>sales$Customer</classname></para>
</listitem>
<listitem>
<para><code>getProperties()</code> список мета-свойств (<interfacename>MetaProperty</interfacename>)</para>
</listitem>
<listitem>
<para><code>getProperty()</code>, <code>getPropertyNN()</code> - получение мета-свойства по имени. Первый метод в случае отсутствия атрибута с указанным именем возвращает <code>null</code>, второй выбрасывает исключение.</para>
<para>Пример:<programlisting>MetaClass userClass = session.getClassNN(User.class);
</listitem>
</varlistentry>
<varlistentry>
<term>
<interfacename>MetaModel</interfacename>
</term>
<listitem>
<para>Редко используемый интерфейс, служит для группировки мета-классов. </para>
<para>Группировка осуществляется по первым трем частям имени пакета Java класса сущности. Например, мета-класс сущности <classname>com.abc.sales.entity.Customer</classname> принадлежит мета-модели с именем <code>com.abc.sales</code></para>
</listitem>
</varlistentry>
<varlistentry id="MetaClass">
<term>
<interfacename>MetaClass</interfacename>
</term>
<listitem>
<para>Интерфейс метаданных класса сущности. <classname>MetaClass</classname> всегда ассоциирован с классом Java, которого он представляет.</para>
<para>Основные методы:</para>
<itemizedlist>
<listitem>
<para><code>getName()</code> имя сущности, по соглашению первой частью имени до знака <code>$</code> является код пространства имен, например, <classname>sales$Customer</classname></para>
</listitem>
<listitem>
<para><code>getProperties()</code> список мета-свойств (<interfacename>MetaProperty</interfacename>)</para>
</listitem>
<listitem>
<para><code>getProperty()</code>, <code>getPropertyNN()</code> - получение мета-свойства по имени. Первый метод в случае отсутствия атрибута с указанным именем возвращает <code>null</code>, второй выбрасывает исключение.</para>
<para>Пример:<programlisting>MetaClass userClass = session.getClassNN(User.class);
MetaProperty groupProperty = userClass.getPropertyNN(&quot;group&quot;);</programlisting></para>
</listitem>
<listitem>
<para><code>getPropertyPath()</code> - позволяет перемещаться по ссылкам. Данный метод принимает строковый параметр - путь из имен атрибутов, разделенных точкой. Возвращаемый объект <classname>MetaPropertyPath</classname> позволяет обратиться к искомому (последнему в пути) атрибуту вызовом <code>getMetaProperty()</code>. </para>
<para>Пример:<programlisting>MetaClass userClass = session.getClassNN(User.class);
</listitem>
<listitem>
<para><code>getPropertyPath()</code> - позволяет перемещаться по ссылкам. Данный метод принимает строковый параметр - путь из имен атрибутов, разделенных точкой. Возвращаемый объект <classname>MetaPropertyPath</classname> позволяет обратиться к искомому (последнему в пути) атрибуту вызовом <code>getMetaProperty()</code>. </para>
<para>Пример:<programlisting>MetaClass userClass = session.getClassNN(User.class);
MetaProperty groupNameProp = userClass.getPropertyPath(&quot;group.name&quot;).getMetaProperty();
assert groupNameProp.getDomain().getName().equals(&quot;sec$Group&quot;);</programlisting></para>
</listitem>
<listitem>
<para><code>getJavaClass()</code> класс сущности, которому соответствует данный <classname>MetaClass</classname></para>
</listitem>
<listitem>
<para><code>getAnnotations()</code> коллекция <link linkend="meta_annotations_section">мета-аннотаций</link> </para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
<varlistentry>
<term>
<interfacename>MetaProperty</interfacename>
</term>
<listitem>
<para>Интерфейс метаданных атрибута сущности. </para>
<para>Основные методы:</para>
<itemizedlist>
<listitem>
<para><code>getName()</code> имя свойства, соответствует имени атрибута сущности</para>
</listitem>
<listitem>
<para><code>getDomain()</code> мета-класс, которому принадлежит данное свойство</para>
</listitem>
<listitem id="MetaProperty.getType">
<para><code>getType() </code> тип свойства:<itemizedlist>
<listitem>
<para>простой тип: <code>DATATYPE</code></para>
</listitem>
<listitem>
<para>перечисление: <code>ENUM</code></para>
</listitem>
<listitem>
<para>ссылочный тип двух видов:</para>
<itemizedlist>
<listitem>
<para><code>ASSOCIATION</code> простая ссылка на другую сущность. Например, отношение заказа и покупателя ассоциация.</para>
</listitem>
<listitem>
<para><code>COMPOSITION</code> ссылка на сущность, которая не имеет самостоятельного значения без владеющей сущности. <code>COMPOSITION</code> можно считать &quot;более тесным&quot; отношением, чем <code>ASSOCIATION</code>. Например, отношение заказа и пункта этого заказа <code>COMPOSITION</code>, т.к. пункт не может существовать без заказа, которому он принадлежит.</para>
</listitem>
</itemizedlist>
<para>Вид ссылочного атрибута <code>ASSOCIATION</code> или <code>COMPOSITION</code> влияет на режим редактирования сущности: в первом случае сохранение связанной сущности в базу данных происходит независимо, а во втором связанная сущность сохраняется в БД только вместе с владеющей сущностью.</para>
</listitem>
</itemizedlist></para>
</listitem>
<listitem>
<para><code>getRange()</code> интерфейс <interfacename>Range</interfacename>, детально описывающий тип данного атрибута</para>
</listitem>
<listitem>
<para><code>isMandatory()</code> признак обязательности атрибута. Используется, например, визуальными компонентами для сигнализации пользователю о необходимости ввода значения.</para>
</listitem>
<listitem>
<para><code>isReadOnly()</code> признак неизменности атрибута</para>
</listitem>
<listitem>
<para><code>getInverse()</code> для ссылочного атрибута возвращает мета-свойство с обратной стороны ассоциации, если таковое имеется</para>
</listitem>
<listitem>
<para><code>getAnnotatedElement()</code> поле (<classname>java.lang.reflect.Field</classname>) или метод (<classname>java.lang.reflect.Method</classname>), соответствующие данному атрибуту сущности</para>
</listitem>
<listitem>
<para><code>getJavaType()</code> класс Java данного атрибута сущности. Это либо тип поля класса, либо тип возвращаемого значения метода.</para>
</listitem>
<listitem>
<para><code>getDeclaringClass()</code> класс Java, содержащий данный атрибут</para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
<varlistentry>
<term>
<interfacename>Range</interfacename>
</term>
<listitem>
<para>Интерфейс, детально описывающий тип атрибута сущности.</para>
<para>Основные методы:</para>
<itemizedlist>
<listitem>
<para><code>isDatatype()</code> возвращает <code>true</code> для атрибута простого <link linkend="MetaProperty.getType">типа</link></para>
</listitem>
<listitem>
<para><code>asDatatype()</code> - возвращает <link linkend="Datatype_section">
<interfacename>Datatype</interfacename>
</link> для атрибута простого <link linkend="MetaProperty.getType">типа</link></para>
</listitem>
<listitem>
<para><code>isEnum()</code> возвращает <code>true</code> для атрибута <link linkend="MetaProperty.getType">типа</link> перечисления</para>
</listitem>
<listitem>
<para><code>asEnumeration()</code> - возвращает <link linkend="Datatype_section">
<interfacename>Enumeration</interfacename>
</link> для атрибута <link linkend="MetaProperty.getType">типа</link> перечисления</para>
</listitem>
<listitem>
<para><code>isClass()</code> возвращает <code>true</code> для ссылочного атрибута <link linkend="MetaProperty.getType"> типа</link> <code>ASSOCIATION</code> или <code>COMPOSITION</code></para>
</listitem>
<listitem>
<para><code>asClass()</code> - возвращает <link linkend="MetaClass">мета-класс</link> ассоциированной сущности для ссылочного атрибута</para>
</listitem>
<listitem>
<para><code>isOrdered()</code> возвращает <code>true</code> если атрибут представляет собой упорядоченную коллекцию (например <interfacename>List</interfacename>)</para>
</listitem>
<listitem>
<para><code>getCardinality()</code> вид отношения для ссылочного атрибута: <code>ONE_TO_ONE</code>, <code>MANY_TO_ONE</code>, <code>ONE_TO_MANY</code>, <code>MANY_TO_MANY</code></para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
</variablelist>
</listitem>
<listitem>
<para><code>getJavaClass()</code> класс сущности, которому соответствует данный <classname>MetaClass</classname></para>
</listitem>
<listitem>
<para><code>getAnnotations()</code> коллекция <link linkend="meta_annotations_section">мета-аннотаций</link> </para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
<varlistentry>
<term>
<interfacename>MetaProperty</interfacename>
</term>
<listitem>
<para>Интерфейс метаданных атрибута сущности. </para>
<para>Основные методы:</para>
<itemizedlist>
<listitem>
<para><code>getName()</code> имя свойства, соответствует имени атрибута сущности</para>
</listitem>
<listitem>
<para><code>getDomain()</code> мета-класс, которому принадлежит данное свойство</para>
</listitem>
<listitem id="MetaProperty.getType">
<para><code>getType() </code> тип свойства:<itemizedlist>
<listitem>
<para>простой тип: <code>DATATYPE</code></para>
</listitem>
<listitem>
<para>перечисление: <code>ENUM</code></para>
</listitem>
<listitem>
<para>ссылочный тип двух видов:</para>
<itemizedlist>
<listitem>
<para><code>ASSOCIATION</code> простая ссылка на другую сущность. Например, отношение заказа и покупателя ассоциация.</para>
</listitem>
<listitem>
<para><code>COMPOSITION</code> ссылка на сущность, которая не имеет самостоятельного значения без владеющей сущности. <code>COMPOSITION</code> можно считать &quot;более тесным&quot; отношением, чем <code>ASSOCIATION</code>. Например, отношение заказа и пункта этого заказа <code>COMPOSITION</code>, т.к. пункт не может существовать без заказа, которому он принадлежит.</para>
</listitem>
</itemizedlist>
<para>Вид ссылочного атрибута <code>ASSOCIATION</code> или <code>COMPOSITION</code> влияет на режим редактирования сущности: в первом случае сохранение связанной сущности в базу данных происходит независимо, а во втором связанная сущность сохраняется в БД только вместе с владеющей сущностью.</para>
</listitem>
</itemizedlist></para>
</listitem>
<listitem>
<para><code>getRange()</code> интерфейс <interfacename>Range</interfacename>, детально описывающий тип данного атрибута</para>
</listitem>
<listitem>
<para><code>isMandatory()</code> признак обязательности атрибута. Используется, например, визуальными компонентами для сигнализации пользователю о необходимости ввода значения.</para>
</listitem>
<listitem>
<para><code>isReadOnly()</code> признак неизменности атрибута</para>
</listitem>
<listitem>
<para><code>getInverse()</code> для ссылочного атрибута возвращает мета-свойство с обратной стороны ассоциации, если таковое имеется</para>
</listitem>
<listitem>
<para><code>getAnnotatedElement()</code> поле (<classname>java.lang.reflect.Field</classname>) или метод (<classname>java.lang.reflect.Method</classname>), соответствующие данному атрибуту сущности</para>
</listitem>
<listitem>
<para><code>getJavaType()</code> класс Java данного атрибута сущности. Это либо тип поля класса, либо тип возвращаемого значения метода.</para>
</listitem>
<listitem>
<para><code>getDeclaringClass()</code> класс Java, содержащий данный атрибут</para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
<varlistentry>
<term>
<interfacename>Range</interfacename>
</term>
<listitem>
<para>Интерфейс, детально описывающий тип атрибута сущности.</para>
<para>Основные методы:</para>
<itemizedlist>
<listitem>
<para><code>isDatatype()</code> возвращает <code>true</code> для атрибута простого <link linkend="MetaProperty.getType">типа</link></para>
</listitem>
<listitem>
<para><code>asDatatype()</code> - возвращает <link linkend="Datatype_section">
<interfacename>Datatype</interfacename>
</link> для атрибута простого <link linkend="MetaProperty.getType">типа</link></para>
</listitem>
<listitem>
<para><code>isEnum()</code> возвращает <code>true</code> для атрибута <link linkend="MetaProperty.getType">типа</link> перечисления</para>
</listitem>
<listitem>
<para><code>asEnumeration()</code> - возвращает <link linkend="Datatype_section">
<interfacename>Enumeration</interfacename>
</link> для атрибута <link linkend="MetaProperty.getType">типа</link> перечисления</para>
</listitem>
<listitem>
<para><code>isClass()</code> возвращает <code>true</code> для ссылочного атрибута <link linkend="MetaProperty.getType"> типа</link> <code>ASSOCIATION</code> или <code>COMPOSITION</code></para>
</listitem>
<listitem>
<para><code>asClass()</code> - возвращает <link linkend="MetaClass">мета-класс</link> ассоциированной сущности для ссылочного атрибута</para>
</listitem>
<listitem>
<para><code>isOrdered()</code> возвращает <code>true</code> если атрибут представляет собой упорядоченную коллекцию (например <interfacename>List</interfacename>)</para>
</listitem>
<listitem>
<para><code>getCardinality()</code> вид отношения для ссылочного атрибута: <code>ONE_TO_ONE</code>, <code>MANY_TO_ONE</code>, <code>ONE_TO_MANY</code>, <code>MANY_TO_MANY</code></para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
</variablelist>
</section>
<section>
<title>Формирование метаданных</title>
<para>Основной источник формирования структуры метаданных - <link linkend="entity_annotations_section">аннотированные</link> классы сущностей. </para>
@ -1405,26 +1400,143 @@ String formattedValue = format.format(value);</programlisting></para>
</section>
<section id="views_section">
<title>Представления</title>
<para>Механизм представлений обеспечивает извлечение из БД и передачу клиенту графов сущностей, ограниченных в глубину и/или по атрибутам.</para>
<para>Представление всегда должно быть задано при запросе данных у <glossterm linkend="middleware_glossentry">middleware</glossterm>. Получив выборку данных по представлению, клиентский код может быть уверен, что все запрошенные атрибуты и связанные сущности получены, и их можно использовать без опаски получить <errorname role="italic">NullPointerException</errorname> или исключение типа <errorname role="italic">LazyInitializationException</errorname>. Представление решает и обратную задачу ненужные атрибуты не извлекаются из БД, что снижает нагрузку в случае &quot;широких&quot; сущностей (содержащих большое число атрибутов).</para>
<para>Для каждой сущности по умолчанию доступны два типа представления с именами <filename>_local</filename> и <filename>_minimal</filename></para>
<itemizedlist>
<listitem>
<para><filename>_local</filename> определяет все локальные атрибуты сущности (т.е. все, кроме ссылок на другие сущности);</para>
</listitem>
<listitem>
<para><filename>_minimal</filename> определяет атрибуты, входящие в <varname>InstanceName</varname>. Если <varname>InstanceName</varname> не задано, данное представление определяет только системные атрибуты (<varname>id</varname>, <varname>createTs</varname> и пр.).</para>
</listitem>
</itemizedlist>
<para>Представления нужно определять в файле <filename>ext-views.xml</filename> модуля <structname>core</structname>.</para>
<warning>
<title>Внимание</title>
<para>Имя представления должно быть уникально в пределах сущности. При этом рекомендуется давать более &quot;описательные&quot; имена. Например, не &quot;browse&quot;, а &quot;nameOfEntityBrowse&quot;. Это упрощает поиск XML-описателей представлений по имени. </para>
</warning>
<para>Пример представления для сущности <classname>User</classname>, которое должно выбирать все простые поля и ссылку на группу:</para>
<programlisting>&lt;view entity=&quot;sec$User&quot; name=&quot;user.browse&quot; extends=&quot;_local&quot;&gt;
&lt;property name=&quot;group&quot; view=&quot;_local&quot;/&gt;
&lt;/view&gt;</programlisting>
<section>
<title>Общие сведения</title>
<para>При извлечении сущностей из базы данных обычно встает вопрос - как обеспечить загрузку связанных сущностей на нужную глубину? </para>
<para>Например, для браузера Заказов нужно отобразить дату и сумму заказа совместно с названием Покупателя, т.е. загрузить связанный экземпляр Покупателя. А для экрана редактирования Заказа необходимо загрузить еще и коллекцию Пунктов заказа, причем каждый Пункт заказа должен содержать связанный экземпляр Товара для отображения его наименования. </para>
<para><glossterm linkend="lazy_loading">Загрузка по требованию</glossterm> в большинстве случаев не может помочь, так как обработка данных как правило происходит не в транзакции, в которой загружаются сущности, а, например, на клиентском <link linkend="app_tiers_section">уровне</link> в пользовательском интерфейсе. В то же время задание <glossterm linkend="eager_fetching">энергичной загрузки</glossterm> в <link linkend="entity_annotations_section">аннотациях сущностей</link> недопустимо, так как приводит к постоянному извлечению всего графа связанных сущностей, который может быть очень большим.</para>
<para>Другой похожей проблемой является ограничение набора <glossterm linkend="local_attribute">локальных</glossterm> атрибутов сущностей загружаемого графа: например, некоторая сущность имеет 50 атрибутов, в том числе BLOB, а в экране отображается только 10 атрибутов. Зачем загружать из БД, затем сериализовать и передавать клиенту 40 атрибутов, которые ему в данный момент не нужны?</para>
<para>Механизм <firstterm>представлений</firstterm> (views) решает эти проблемы, обеспечивая извлечение из базы данных и передачу клиенту графов сущностей, ограниченных в глубину и по атрибутам. <firstterm>Представление</firstterm> является описателем графа объектов, который требуется в некотором экране UI или другом процессе обработки данных.</para>
<para>Обработка представлений производится следующим образом:<itemizedlist>
<listitem>
<para>все связи в модели данных объявляются с признаком <glossterm linkend="lazy_loading">загрузки по требованию</glossterm> (<code>fetch = FetchType.LAZY</code>, см. <xref linkend="entity_annotations_section"/>)</para>
</listitem>
<listitem>
<para>в процессе загрузки данных через <link linkend="DataService_section">DataService</link> клиентский код помимо <glossterm linkend="jpql_glossentry">JPQL</glossterm> запроса указывает нужное представление</para>
</listitem>
<listitem>
<para>на основе представления формируется так называемый <firstterm>Fetch Plan</firstterm> - особенность лежащего в основе <link linkend="orm_section">слоя ORM</link> фреймворка <application>Apache OpenJPA</application>. Fetch Plan влияет на формирование SQL запроса к базе данных: как на список возвращаемых полей, так и на соединения с другими таблицами, содержащими связанные сущности.</para>
</listitem>
<listitem>
<para>ссылки, не включенные в Fetch Plan (иногда это полезно для упрощения основного SQL запроса), загружаются отдельными SQL запросами, для чего механизм обработки представлений просто обращается к соответствующим методам чтения атрибутов</para>
</listitem>
<listitem>
<para>в результате на момент завершения <link linkend="transactions_section">транзакции</link>, загружающей данные, в памяти <structname>Middleware</structname> содержится граф объектов, заданный JPQL запросом и представлением.</para>
</listitem>
</itemizedlist></para>
<figure>
<title>Классы представления</title>
<mediaobject>
<imageobject>
<imagedata fileref="img/View.png" align="center"/>
</imageobject>
</mediaobject>
</figure>
<para>Представление определяется экземпляром класса <classname>View</classname>, в котором:<itemizedlist>
<listitem>
<para><code>entityClass</code> - класс сущности, для которого определено представление. Другими словами, &quot;корень&quot; дерева загружаемых сущностей.</para>
</listitem>
<listitem>
<para><code>name</code> - имя представления. Должно быть либо <code>null</code>, либо уникальным в пределах данной сущности.</para>
</listitem>
<listitem>
<para><code>properties</code> - коллекция экземпляров класса ViewProperty, соответствующих загружаемым атрибутам сущности.</para>
</listitem>
<listitem>
<para><code>includeSystemProperties</code> - признак включения системных атрибутов (входящих в состав <link linkend="entity_base_classes">базовых интерфейсов</link> персистентных сущностей <interfacename>BaseEntity</interfacename> и <interfacename>Updatable</interfacename>). Системные атрибуты не перечисляются в <code>properties</code> явно, а учитываются механизмом обработки представлений в зависимости от того, какие интерфейсы реализует данная сущность.</para>
</listitem>
</itemizedlist></para>
<para>Класс <classname>ViewProperty</classname> имеет следующие свойства:<itemizedlist>
<listitem>
<para><code>name</code> - имя атрибута сущности</para>
</listitem>
<listitem>
<para><code>view</code> - для ссылочных атрибутов задает представление, с которым необходимо загружать связанную сущность</para>
</listitem>
<listitem>
<para><code>lazy</code> - для ссылочных атрибутов признак того, что данный атрибут нужно не включать в Fetch Plan, а загружать отдельным SQL запросом, инициированным обращением к атрибуту. Следует иметь в виду, что атрибут в любом случае будет загружен на момент окончания транзакции, данный признак влияет только на способ загрузки. </para>
</listitem>
</itemizedlist></para>
<warning>
<para>Независимо от набора атрибутов, определенного в представлении, всегда загружаются следующие атрибуты:<itemizedlist>
<listitem>
<para><code>id</code> - идентификатор сущности</para>
</listitem>
<listitem>
<para><code>version</code> - для оптимистично блокируемых сущностей, реализующих <interfacename>Versioned</interfacename></para>
</listitem>
<listitem>
<para><code>deleteTs</code>, <code>deletedBy</code> - для сущностей, реализующих <interfacename>
<link linkend="soft_delete_section">SoftDelete</link>
</interfacename></para>
</listitem>
</itemizedlist></para>
</warning>
</section>
<section>
<title>Создание представлений</title>
<para>Представление может быть создано двумя путями:<itemizedlist>
<listitem>
<para><emphasis role="bold">программно</emphasis> - созданием экземпляра <classname>View</classname>, например:<programlisting>View view = new View(Order.class)
.addProperty(&quot;date&quot;)
.addProperty(&quot;amount&quot;)
.addProperty(&quot;customer&quot;, new View(Customer.class)
.addProperty(&quot;name&quot;)
);</programlisting></para>
<para>Как правило, таким способом создаются представления, используемые только в каком-то одном месте бизнес-логики.</para>
<warning>
<para>Механизм обработки представлений кэширует создаваемые для <emphasis>именованных</emphasis> представлений объекты Fetch Plan. Это означает, что если Вы <emphasis>программно</emphasis> создадите два представления для одной сущности с одинаковыми именами, но с разным набором атрибутов, то выборка со вторым представлением окажется неверной.</para>
<para>Поэтому никогда не задавайте имен для &quot;одноразовых&quot; представлений, создаваемых программно.</para>
</warning>
</listitem>
<listitem>
<para><emphasis role="bold">декларативно</emphasis> - путем создания описателя на XML и его развертывания в репозитории представлений <classname>ViewRepository</classname>. При развертывании на основе XML-описателя создаются и кэшируются экземпляры <classname>View</classname>. В дальнейшем в любом месте кода приложения требуемое представление можно получить вызовом репозитория с указанием класса сущности и имени представления.</para>
</listitem>
</itemizedlist></para>
<para>Рассмотрим подробнее декларативный способ создания и работы с представлениями.</para>
<para>Ссылка на <classname>ViewRepository</classname> может быть получена через интерфейс инфраструктуры <interfacename>
<link linkend="Metadata">Metadata</link>
</interfacename>. Для получения экземпляра <classname>View</classname>, содержащегося в репозитории, используются методы <code>getView()</code>. Для развертывания XML-описателей представлений в репозитории используются методы <code>deployViews()</code>.</para>
<para>В репозитории для каждой сущности по умолчанию доступны два представления с именами <filename>_local</filename> и <filename>_minimal</filename>:<itemizedlist>
<listitem>
<para><filename>_local</filename> включает в себя все <glossterm linkend="local_attribute">локальные</glossterm> атрибуты сущности</para>
</listitem>
<listitem>
<para><filename>_minimal</filename> включает в себя атрибуты, входящие в имя экземпляра сущности, и задаваемые аннотацией <interfacename>
<link linkend="namePattern">@NamePattern</link>
</interfacename>. Если аннотация <interfacename>@NamePattern</interfacename> для сущности не указана, данное представление не включает никаких атрибутов.</para>
</listitem>
</itemizedlist></para>
<para>Подробная структура XML-описателей изложена в <xref linkend="views.xml"/></para>
<para>Пример описателя представления для сущности Заказ, которое должно обеспечить загрузку всех локальных атрибутов, ассоциированного Покупателя и коллекции Пунктов заказа:<programlisting>&lt;view class=&quot;com.haulmont.sales.entity.Order&quot;
name=&quot;orderWithCustomer&quot;
extends=&quot;_local&quot;&gt;
&lt;property name=&quot;customer&quot; view=&quot;_minimal&quot;/&gt;
&lt;property name=&quot;items&quot; view=&quot;itemsInOrder&quot;/&gt;
&lt;/view&gt;</programlisting></para>
<para>Рекомендуемый способ группировки и развертывания описателей представлений:<itemizedlist>
<listitem>
<para>В <link linkend="app_modules_section">модуле</link> <structname>core</structname> в корне <filename>src</filename> создать файл <filename>{имя_проекта}-views.xml</filename> и поместить в него все описатели представлений, которые должны быть доступны глобально, т.е. на всех <link linkend="app_tiers_section">уровнях приложения</link>.</para>
</listitem>
<listitem>
<para>Зарегистрировать данный файл в свойстве <property>
<link linkend="cuba.viewsConfig">cuba.viewsConfig</link>
</property> уровня <structname>Middleware</structname>, т.е. в файле <filename>{имя_проекта}-app.properties</filename> модуля <structname>core</structname>. Это обеспечит автоматическое развертывание представлений на старте приложения в репозитории <structname>Middleware</structname> (см. метод <code>MetadataImpl.initViews()</code>). Развернутые представления будут доступны и для <structname>Middleware</structname>, и для клиентских уровней приложения, которые получат соответствующие экземпляры <classname>View</classname> при подключении к среднему слою.</para>
</listitem>
<listitem>
<para>Если существуют представления, которые необходимы только какому-то одному клиентскому уровню приложения, то можно определить их в аналогичном файле этого уровня, например <filename>{имя_проекта}-web-views.xml</filename>, и зарегистрировать в свойстве <property>
<link linkend="cuba.viewsConfig">cuba.viewsConfig</link>
</property> этого уровня, т.е. в файле <filename>{имя_проекта}-web-app.properties</filename>. Тогда клиентский уровень сначала загрузит все имеющиеся представления с <structname>Middleware</structname>, а затем развернет свои собственные (см. <code>MetadataClientImpl.initViews()</code>).</para>
<para>Возможна также ситуация, когда некоторому клиентскому уровню не нужны глобальные представления, зарегистрированные на среднем слое, или нужны редко. В этом случае имеет смысл объявить на этом клиентском уровне свойство <link linkend="cuba.lazyLoadServerViews">
<property>cuba.lazyLoadServerViews</property>
</link>, тогда глобальные представления будут загружаться на клиентский уровень не все сразу, а по необходимости.</para>
</listitem>
</itemizedlist></para>
<para>Если на момент развертывания некоторого представления в репозитории уже есть представление для этого же класса сущности и с таким же именем, то новое будет проигнорировано. Для того, чтобы представление заменило имеющееся в репозитории и гарантированно было развернуто, в XML-описателе должен быть явно указан атрибут <literal>overwrite = &quot;true&quot;</literal>. В частности, развертывание представлений клиентского уровня производится после загрузки представлений со среднего слоя, поэтому некоторое клиентское представление может оказаться &quot;замаскированным&quot; одноименным представлением <structname>Middleware</structname>.</para>
<tip>
<para>Рекомендуется давать представлениям &quot;описательные&quot; имена. Например, не &quot;browse&quot;, а &quot;customerBrowse&quot;. Это упрощает поиск XML-описателей представлений по имени в процессе разработки приложения.</para>
</tip>
</section>
</section>
<section id="infrastructure_interfaces_section">
<title>Интерфейсы инфраструктуры</title>
@ -1445,6 +1557,10 @@ String formattedValue = format.format(value);</programlisting></para>
<title>Metadata</title>
<para>Обеспечивает доступ к сессии <link linkend="metadata_framework_section">метаданных</link> и ViewRepository.</para>
</section>
<section id="resources">
<title>Resources</title>
<para>TODO</para>
</section>
<section id="scripting_section">
<title>Scripting</title>
<para><interfacename>Scripting</interfacename> глобальный интерфейс инфраструктуры, решающий следующие задачи:</para>

View File

@ -56,6 +56,17 @@
</glossdef>
</glossentry>
</glossdiv>
<glossdiv>
<title>З</title>
<glossentry id="lazy_loading">
<glossterm>
<emphasis role="bold">Загрузка по требованию</emphasis>
</glossterm>
<glossdef>
<para>Режим загрузки данных, при котором связанные сущности загружаются не одновременно с основной сущностью, а отложенно, при обращении к соответствующему атрибуту. Загрузка по требованию возможна только в рамках транзакции, в которой была загружена основная сущность.</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv>
<title>И</title>
<glossentry id="datasource_glossentry">
@ -89,6 +100,17 @@
</glossdef>
</glossentry>
</glossdiv>
<glossdiv>
<title>Л</title>
<glossentry id="local_attribute">
<glossterm>
<emphasis role="bold">Локальный атрибут</emphasis>
</glossterm>
<glossdef>
<para>Атрибут сущности, не являющийся ссылкой или коллекцией ссылок на другую сущность. Значения всех локальных атрибутов сущности как правило хранятся в одной таблице (исключение составляют некоторые стратегии наследования сущностей). </para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv>
<title>П</title>
<glossentry id="message_pack_glossentry">
@ -100,7 +122,7 @@
<para>См. <xref xrefstyle="" linkend="localization_section"/></para>
</glossdef>
</glossentry>
<glossentry id="message_pack_glossentry_1">
<glossentry id="persistence_context">
<glossterm>
<emphasis role="bold">Персистентный контекст</emphasis>
</glossterm>
@ -150,6 +172,17 @@
</glossdef>
</glossentry>
</glossdiv>
<glossdiv>
<title>Э</title>
<glossentry id="eager_fetching">
<glossterm>
<emphasis role="bold">Энергичная загрузка</emphasis>
</glossterm>
<glossdef>
<para>Загрузка данных подклассов и связанных объектов одновременно с основной запрашиваемой сущностью.</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv>
<title>A</title>
<glossentry id="app_tiers_glossentry">
@ -180,13 +213,11 @@
</glossdiv>
<glossdiv>
<title>E</title>
<glossentry id="eager_fetching_glossentry">
<glossentry id="">
<glossterm>
<emphasis role="bold">Eager Fetching</emphasis>
</glossterm>
<glossdef>
<para>Энергичная загрузка загрузка данных подклассов и связанных объектов одновременно с основной запрашиваемой сущностью.</para>
</glossdef>
<glosssee otherterm="eager_fetching"/>
</glossentry>
<glossentry id="EntityManager_glossentry">
<glossterm>
@ -210,6 +241,13 @@
</glossdef>
</glossentry>
</glossdiv>
<glossdiv>
<title>L</title>
<glossentry>
<glossterm>Lazy loading</glossterm>
<glosssee otherterm="lazy_loading"/>
</glossentry>
</glossdiv>
<glossdiv>
<title>J</title>
<glossentry id="javaee_web_profile_glossentry">

View File

@ -108,9 +108,268 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="chapter_development.xml" encoding="UTF-8"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="chapter_deployment.xml" encoding="UTF-8"/>
<appendix>
<title>Часто задаваемые вопросы</title>
<para>TODO</para>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="qanda.xml" encoding="UTF-8"/>
<title>Описание конфигурационных файлов</title>
<section id="datatypes.xml">
<title>datatypes.xml</title>
<para>TODO</para>
</section>
<section id="persistence.xml">
<title>persistence.xml</title>
<para>TODO</para>
</section>
<section id="metadata.xml">
<title>metadata.xml</title>
<para>TODO</para>
</section>
<section id="views.xml">
<title>views.xml</title>
<para>Файлы данного типа используются для описания представлений, см. <xref linkend="views_section"/></para>
<para>Схема XML доступна по адресу <ulink url="http://schemas.haulmont.com/cuba/4.0/view.xsd">http://schemas.haulmont.com/cuba/4.0/view.xsd</ulink></para>
<itemizedlist>
<listitem>
<para><sgmltag>views</sgmltag> - корневой элемент</para>
<para>Элементы <sgmltag>views</sgmltag>:<itemizedlist>
<listitem>
<para><sgmltag>view</sgmltag> - описатель <classname>View</classname></para>
<para>Атрибуты <sgmltag>view</sgmltag>:<itemizedlist>
<listitem>
<para><sgmltag>class</sgmltag> - класс сущности</para>
</listitem>
<listitem>
<para><sgmltag>name</sgmltag> - имя представления, должно быть уникальным в пределах сущности</para>
</listitem>
<listitem>
<para><sgmltag>systemProperties</sgmltag> - признак включения системных атрибутов сущности (входящих в состав <link linkend="entity_base_classes">базовых интерфейсов</link> персистентных сущностей <interfacename>BaseEntity</interfacename> и <interfacename>Updatable</interfacename>). Необязательный атрибут, по умолчанию <literal>false</literal>.</para>
</listitem>
<listitem>
<para><sgmltag>overwrite</sgmltag> - признак того, что данный описатель должен переопределить представление с таким же классом и именем, уже развернутое в репозитории. Необязательный атрибут, по умолчанию <literal>false</literal>.</para>
</listitem>
<listitem>
<para><sgmltag>extends</sgmltag> - указывает имя представления той же сущности, от которого нужно унаследовать атрибуты. Порядок следования описателей в файле при этом не важен. Например, при указании <literal>extends=&quot;_local&quot;</literal> в текущее представление будут включены все <link linkend="local_attribute">локальные атрибуты</link> сущности. Необязательный атрибут.</para>
</listitem>
</itemizedlist></para>
<para>Элементы <sgmltag>view</sgmltag>:<itemizedlist>
<listitem>
<para><sgmltag>property</sgmltag> - описатель <classname>ViewProperty</classname></para>
<para>Атрибуты <sgmltag>property</sgmltag>:<itemizedlist>
<listitem>
<para><sgmltag>name</sgmltag> - имя атрибута сущности</para>
</listitem>
<listitem>
<para><sgmltag>view</sgmltag> - для ссылочного атрибута указывает имя представления, с которым должна загружаться ассоциированная сущность. Порядок следования описателей в файле при этом не важен.</para>
</listitem>
<listitem>
<para><sgmltag>lazy</sgmltag> - для ссылочных атрибутов признак того, что данный атрибут нужно не включать в Fetch Plan, а загружать отдельным SQL запросом, инициированным обращением к атрибуту. Необязательный атрибут, по умолчанию <literal>false</literal>.</para>
<para>Рекомендуется использовать <sgmltag>lazy</sgmltag> для атрибутов-коллекций, если таких атрибутов больше одного для данного графа представлениий. Т.е. устанавливайте <literal>lazy = &quot;true&quot;</literal> для всех коллекций, кроме одной.</para>
</listitem>
</itemizedlist></para>
<para>Элементы <sgmltag>property</sgmltag>:<itemizedlist>
<listitem>
<para><sgmltag>property</sgmltag> - описатель атрибута связанной сущности. Таким способом можно определить неименованное представление для связанной сущности прямо внутри текущего описателя (inline). </para>
</listitem>
</itemizedlist></para>
</listitem>
</itemizedlist></para>
</listitem>
<listitem>
<para><sgmltag>include</sgmltag> - включение другого файла типа views.xml</para>
<para>Атрибуты <sgmltag>include</sgmltag>:<itemizedlist>
<listitem>
<para><sgmltag>file</sgmltag> - путь к файлу по правилам интерфейса <interfacename>
<link linkend="resources">Resources</link>
</interfacename></para>
</listitem>
</itemizedlist></para>
</listitem>
</itemizedlist></para>
</listitem>
</itemizedlist>
<para>Пример:<programlisting>&lt;views xmlns=&quot;http://schemas.haulmont.com/cuba/4.0/view.xsd&quot;&gt;
&lt;view class=&quot;com.haulmont.sales.entity.Order&quot;
name=&quot;orderWithCustomer&quot;
extends=&quot;_local&quot;&gt;
&lt;property name=&quot;customer&quot; view=&quot;_minimal&quot;/&gt;
&lt;/view&gt;
&lt;view class=&quot;com.haulmont.sales.entity.Item&quot;
name=&quot;itemsInOrder&quot;&gt;
&lt;property name=&quot;quantity&quot;/&gt;
&lt;property name=&quot;product&quot; view=&quot;_minimal&quot;/&gt;
&lt;/view&gt;
&lt;view class=&quot;com.haulmont.sales.entity.Order&quot;
name=&quot;orderWithCustomerDefinedInline&quot;
extends=&quot;_local&quot;&gt;
&lt;property name=&quot;customer&quot;&gt;
&lt;property name=&quot;name&quot;/&gt;
&lt;property name=&quot;email&quot;/&gt;
&lt;/property&gt;
&lt;/view&gt;
&lt;/views&gt;</programlisting></para>
<para>См. также свойство приложения <property>
<link linkend="cuba.viewsConfig">cuba.viewsConfig</link>
</property></para>
</section>
<section id="web.xml">
<title>web.xml</title>
<para>TODO</para>
</section>
<section id="context.xml">
<title>context.xml</title>
<para>TODO</para>
</section>
</appendix>
<appendix id="appendix_security_properties">
<title>Описание свойств приложения</title>
<variablelist>
<varlistentry id="cuba.viewsConfig">
<term>cuba.viewsConfig</term>
<listitem>
<para>Конфигурационный параметр, задающий набор файлов <link linkend="views.xml">views.xml</link>, автоматически развертываемых на старте приложения. См. <xref linkend="views_section"/></para>
<para><link linkend="app_tiers_section">Уровень</link>: все</para>
<para>Пример:<programlisting>cuba.viewsConfig=cuba-views.xml reports-views.xml sales-views.xml</programlisting></para>
</listitem>
</varlistentry>
<varlistentry id="cuba.lazyLoadServerViews">
<term>cuba.lazyLoadServerViews</term>
<listitem>
<para>Указывает, что глобальные представления c <structname>Middleware</structname> нужно загружать на клиентский уровень не все сразу, а по необходимости. См. <xref linkend="views_section"/></para>
<para>Значение по умолчанию: <code>false</code></para>
<para>Интерфейс: <classname>ClientConfig</classname></para>
<para><link linkend="app_tiers_section">Уровень</link>: клиентский - <structname>Web Client</structname>, <structname>Web Portal</structname>, <structname>Desktop Client</structname></para>
</listitem>
</varlistentry>
<varlistentry>
<term>cuba.availableLocales</term>
<listitem>
<para id="property_available_locales">Список поддерживаемых языков интерфейса. Формат свойства: <code>&lt;Название языка&gt;|&lt;Языковой код&gt;</code>. Значения разных языков между собой разделяются точкой с запятой. Пример: <programlisting>cuba.availableLocales=French|fr;English|en</programlisting></para>
<para><code>&lt;Название языка&gt;</code> это название, которое будет отображаться в списках доступных языков. Например, в окне входа в систему, в экране редактирования пользователя. <code>&lt;Языковой код</code>&gt; это суффикс для формирования <glossterm linkend="message_pack_glossentry">файлов локализации</glossterm>. Например, <filename>messages_fr.properties.</filename></para>
<para>Следует иметь в виду, что язык, который указан первым в списке языков свойства <parameter>cuba.availableLocales</parameter>, будет отображаться первым в списке доступных языков в том случае, если среди языков данного свойства не будет найден текущий язык системы. В противном случае первым будет отображаться язык системы. </para>
<para>Если для языка, указанного в свойстве, отсутствует файл для его локализации, то по умолчанию берется локализация из файла без суффикса <filename>messages.properties</filename>.</para>
<para>Значение по умолчанию: <literal>cuba.availableLocales=English|en;Russian|ru</literal></para>
<para>Интерфейс: <classname>GlobalConfig</classname></para>
<para><link linkend="app_tiers_section">Уровень</link>: все</para>
</listitem>
</varlistentry>
<varlistentry>
<term>cuba.web.localeSelectVisible</term>
<listitem id="parameter_locale_visible">
<para>Включает или отключает возможность пользователя выбирать язык
интерфейса при входе в систему. </para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.web.localeSelectVisible=true</parameter></para>
<para>Интерфейс: <classname>GlobalConfig</classname></para>
<para>Уровень: свойство принадлежит всем <glossterm linkend="app_tiers_glossentry">уровням</glossterm>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>cuba.trustedClientPassword</term>
<listitem>
<para>Пароль, используемый методом <methodname>LoginService.loginTrusted()</methodname>. Доверенный клиент может зайти в систему, не вводя пользовательский пароль. Это свойство используется при интеграции с <application>Active Directory</application>.</para>
<para>Интерфейсы: <interfacename> ServerConfig</interfacename>, <interfacename>WebConfig</interfacename></para>
<para><link linkend="app_tiers_section">Уровень</link>: <structname>Middleware</structname>, <structname>Web Client</structname>, <structname>Web Portal</structname></para>
</listitem>
</varlistentry>
<varlistentry>
<term>cuba.userSessionExpirationTimeoutSec</term>
<listitem id="property_sessionExpirTime">
<para>Задает таймаут неактивности сессии пользователя
в секундах.</para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.userSessionExpirationTimeoutSec=1800</parameter></para>
<para>Интерфейс: <classname>ServerConfig</classname></para>
<para>Уровень: <glossterm linkend="text_middleware_id">Middleware</glossterm>.</para>
<tip>
<para>В большинстве случаев рекомендуется выставлять параметры <parameter>cuba.userSessionExpirationTimeoutSec</parameter> и <link linkend="property_httpExpirTime">cuba.httpSessionExpirationTimeoutSec</link> в одинаковое значение.</para>
</tip>
</listitem>
</varlistentry>
<varlistentry>
<term>cuba.httpSessionExpirationTimeoutSec</term>
<listitem id="property_httpExpirTime">
<para>Задает таймаут бездействия HTTP-сессии
в секундах.</para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.httpSessionExpirationTimeoutSec=1800</parameter></para>
<para>Интерфейс: <classname>WebConfig</classname></para>
<para>Уровень: <glossterm linkend="text_webclient_id">Web Client</glossterm>.</para>
<tip>
<para>В большинстве случаев рекомендуется выставлять параметры <link linkend="property_sessionExpirTime">cuba.userSessionExpirationTimeoutSec</link> и <parameter>cuba.httpSessionExpirationTimeoutSec</parameter> в одинаковое значение.</para>
</tip>
</listitem>
</varlistentry>
<varlistentry>
<term>cuba.passwordPolicyEnabled</term>
<listitem id="property_passwPolicyEnabled">
<para>Определяет, нужно ли применять политику проверки пароля. Если свойство имеет значение <code>true</code>, то все новые пароли будут проверены в соответствии со свойством cuba.passwordPolicyRegExp.</para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.passwordPolicyEnabled=false</parameter></para>
<para>Интерфейс: <classname>ClientConfig</classname></para>
<para>Уровни: <glossterm linkend="text_webclient_id">Web Client</glossterm>, <glossterm linkend="text_portal_id">Web Portal</glossterm>, <glossterm linkend="text_desktop_id">Desktop Client</glossterm>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>cuba.passwordPolicyRegExp</term>
<listitem id="property_passwPolicyRegExp">
<para>В данном свойстве задается регулярное выражение, которое используется в политике проверки пароля.</para>
<para>Значение по умолчанию:</para>
<para><prompt>cuba.passwordPolicyRegExp=((?=.*\\d)(?=.*\\p{javaLowerCase}) (?=.*\\p{javaUpperCase}).{6,20})</prompt></para>
<para>Это означает, что в пароль должен содержать от 6 до 20 символов, в нем можно использоваться цифры, символы и буквы латинского алфавита. При этом обязательно в пароле должна быть хотя бы одна цифра, одна буква в нижнем регистре и одна буква в верхнем регистре. Более подробная информация о синтаксисе регулярных выражений можно найти на сайтах: <ulink url="http://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D0%B5_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F">http://ru.wikipedia.org/wiki/Регулярные_выражения</ulink> и <ulink url="http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html">http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html</ulink></para>
<para>Интерфейс: <classname>ClientConfig</classname></para>
<para>Уровни: <glossterm linkend="text_webclient_id">Web Client</glossterm>, <glossterm linkend="text_portal_id">Web Portal</glossterm>, <glossterm linkend="text_desktop_id">Desktop Client</glossterm>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>cuba.web.loginDialogDefaultUser</term>
<listitem>
<para>Задает имя пользователя по умолчанию. Оно будет автоматически указываться в экране входа в систему. Если в качестве значения свойства указать
&lt;disabled&gt;, то при входе в систему пользователь сам будет вводить имя.</para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.web.loginDialogDefaultUser=admin</parameter></para>
<para>Интерфейс: <classname>WebConfig</classname></para>
<para>Уровень: <glossterm linkend="text_webclient_id">Web Client</glossterm>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>cuba.web.loginDialogDefaultPassword</term>
<listitem>
<para>Задает имя пользователя по умолчанию. Оно будет автоматически указываться в экране входа в систему. Если в качестве значения свойства указать
&lt;disabled&gt;, то при входе в систему пользователь сам будет вводить пароль.</para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.web.loginDialogDefaultPassword=admin</parameter></para>
<para>Интерфейс: <classname>WebConfig</classname></para>
<para>Уровень: <glossterm linkend="text_webclient_id">Web Client</glossterm>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>cuba.user.fullNamePattern</term>
<listitem id="property_fullNamePattern">
<para>Задает шаблон формирования полного имени пользователя. </para>
<para>Значение по умолчанию</para>
<para><parameter>cuba.user.fullNamePattern={LL| }{F|. }{M|.}</parameter></para>
<para>Таким образом, можно сформировать полное имя по шаблону из имени, отчества и фамилии пользователя. В шаблоне используются следующие правила:</para>
<itemizedlist>
<listitem>
<para>Фигурными скобками {} разделяются части шаблона между собой</para>
</listitem>
<listitem>
<para>Правила формирования шаблона внутри фигурных скобок: один из следующих символов и далее, без пробела, символ |.</para>
<para><code>LL</code> означает фамилию пользователя, написанную в полном варианте (Иванов)</para>
<para><code>L</code> означает фамилию пользователя, написанную в кратком варианте (И)</para>
<para><code>FF</code> означает имя пользователя, написанного в полном варианте (Петр)</para>
<para><code>F</code> означает фамилию пользователя, написанную в кратком варианте (П)</para>
<para><code>MM</code> означает отчество пользователя, написанное в полном варианте (Сергеевич)</para>
<para><code>M</code> означает отчество пользователя, написанное в кратком варианте (С)</para>
</listitem>
<listitem>
<para>После символа | могут идти любые символы, в том числе, и пробел.</para>
</listitem>
</itemizedlist>
</listitem>
</varlistentry>
</variablelist>
</appendix>
<appendix>
<title>Схема базы данных</title>
@ -123,114 +382,5 @@
</mediaobject>
</figure>
</appendix>
<appendix id="appendix_security_properties">
<title>Описание конфигурационных свойств</title>
<itemizedlist>
<listitem>
<para id="property_available_locales"><parameter>cuba.availableLocales</parameter>. Список поддерживаемых языков интерфейса. Формат свойства: <code>&lt;Название языка&gt;|&lt;Языковой код&gt;</code>. Значения разных языков между собой разделяются точкой с запятой. Пример: <programlisting>cuba.availableLocales=French|fr;English|en</programlisting></para>
<para><code>&lt;Название языка&gt;</code> это название, которое будет отображаться в списках доступных языков. Например, в окне входа в систему, в экране редактирования пользователя. <code>&lt;Языковой код</code>&gt; это суффикс для формирования <glossterm linkend="message_pack_glossentry">файлов локализации</glossterm>. Например, <filename>messages_fr.properties.</filename></para>
<para>Следует иметь в виду, что язык, который указан первым в списке языков свойства <parameter>cuba.availableLocales</parameter>, будет отображаться первым в списке доступных языков в том случае, если среди языков данного свойства не будет найден текущий язык системы. В противном случае первым будет отображаться язык системы. </para>
<para>Если для языка, указанного в свойстве, отсутствует файл для его локализации, то по умолчанию берется локализация из файла без суффикса <filename>messages.properties</filename>.</para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.availableLocales=English|en;Russian|ru</parameter></para>
<para>Интерфейс: <classname>GlobalConfig</classname></para>
<para>Уровень: свойство принадлежит всем <glossterm linkend="app_tiers_glossentry">уровням</glossterm>.</para>
</listitem>
<listitem id="parameter_locale_visible">
<para><parameter>cuba.web.localeSelectVisible</parameter>. Включает или отключает возможность пользователя выбирать язык
интерфейса при входе в систему. </para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.web.localeSelectVisible=true</parameter></para>
<para>Интерфейс: <classname>GlobalConfig</classname></para>
<para>Уровень: свойство принадлежит всем <glossterm linkend="app_tiers_glossentry">уровням</glossterm>.</para>
</listitem>
<listitem>
<para><parameter>cuba.trustedClientPassword</parameter>. Пароль, используемый методом <methodname>LoginService.loginTrusted()</methodname>. Доверенный клиент может зайти в систему, не вводя пользовательский пароль. Это свойство используется при интеграции с <application>Active Directory</application>.</para>
<para>Интерфейсы: <classname>GlobalConfig</classname>, <classname>ServerConfig</classname></para>
<para>Уровень: свойство принадлежит всем <glossterm linkend="app_tiers_glossentry">уровням</glossterm>.</para>
</listitem>
<listitem id="property_sessionExpirTime">
<para><parameter>cuba.userSessionExpirationTimeoutSec</parameter> задает таймаут неактивности сессии пользователя
в секундах.</para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.userSessionExpirationTimeoutSec=1800</parameter></para>
<para>Интерфейс: <classname>ServerConfig</classname></para>
<para>Уровень: <glossterm linkend="text_middleware_id">Middleware</glossterm>.</para>
<caution>
<title>Совет</title>
<para>В большинстве случаев рекомендуется выставлять параметры <parameter>cuba.userSessionExpirationTimeoutSec</parameter> и <link linkend="property_httpExpirTime">cuba.httpSessionExpirationTimeoutSec</link> в одинаковое значение.</para>
</caution>
</listitem>
<listitem id="property_httpExpirTime">
<para><parameter>cuba.httpSessionExpirationTimeoutSec</parameter> задает таймаут бездействия HTTP-сессии
в секундах.</para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.httpSessionExpirationTimeoutSec=1800</parameter></para>
<para>Интерфейс: <classname>WebConfig</classname></para>
<para>Уровень: <glossterm linkend="text_webclient_id">Web Client</glossterm>.</para>
<caution>
<title>Совет</title>
<para>В большинстве случаев рекомендуется выставлять параметры <link linkend="property_sessionExpirTime">cuba.userSessionExpirationTimeoutSec</link> и <parameter>cuba.httpSessionExpirationTimeoutSec</parameter> в одинаковое значение.</para>
</caution>
</listitem>
<listitem id="property_passwPolicyEnabled">
<para><parameter>cuba.passwordPolicyEnabled</parameter> определяет, нужно ли применять политику проверки пароля. Если свойство имеет значение <code>true</code>, то все новые пароли будут проверены в соответствии со свойством cuba.passwordPolicyRegExp.</para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.passwordPolicyEnabled=false</parameter></para>
<para>Интерфейс: <classname>ClientConfig</classname></para>
<para>Уровни: <glossterm linkend="text_webclient_id">Web Client</glossterm>, <glossterm linkend="text_portal_id">Web Portal</glossterm>, <glossterm linkend="text_desktop_id">Desktop Client</glossterm>.</para>
</listitem>
<listitem id="property_passwPolicyRegExp">
<para><parameter>cuba.passwordPolicyRegExp</parameter>. В данном свойстве задается регулярное выражение, которое используется в политике проверки пароля.</para>
<para>Значение по умолчанию:</para>
<para><prompt>cuba.passwordPolicyRegExp=((?=.*\\d)(?=.*\\p{javaLowerCase}) (?=.*\\p{javaUpperCase}).{6,20})</prompt></para>
<para>Это означает, что в пароль должен содержать от 6 до 20 символов, в нем можно использоваться цифры, символы и буквы латинского алфавита. При этом обязательно в пароле должна быть хотя бы одна цифра, одна буква в нижнем регистре и одна буква в верхнем регистре. Более подробная информация о синтаксисе регулярных выражений можно найти на сайтах: <ulink url="http://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%B3%D1%83%D0%BB%D1%8F%D1%80%D0%BD%D1%8B%D0%B5_%D0%B2%D1%8B%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F">http://ru.wikipedia.org/wiki/Регулярные_выражения</ulink> и <ulink url="http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html">http://docs.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html</ulink></para>
<para>Интерфейс: <classname>ClientConfig</classname></para>
<para>Уровни: <glossterm linkend="text_webclient_id">Web Client</glossterm>, <glossterm linkend="text_portal_id">Web Portal</glossterm>, <glossterm linkend="text_desktop_id">Desktop Client</glossterm>.</para>
</listitem>
<listitem>
<para><parameter>cuba.web.loginDialogDefaultUser</parameter> задает имя пользователя по умолчанию. Оно будет автоматически указываться в экране входа в систему. Если в качестве значения свойства указать
&lt;disabled&gt;, то при входе в систему пользователь сам будет вводить имя.</para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.web.loginDialogDefaultUser=admin</parameter></para>
<para>Интерфейс: <classname>WebConfig</classname></para>
<para>Уровень: <glossterm linkend="text_webclient_id">Web Client</glossterm>.</para>
</listitem>
<listitem>
<para><parameter>cuba.web.loginDialogDefaultPassword</parameter> задает имя пользователя по умолчанию. Оно будет автоматически указываться в экране входа в систему. Если в качестве значения свойства указать
&lt;disabled&gt;, то при входе в систему пользователь сам будет вводить пароль.</para>
<para>Значение по умолчанию:</para>
<para><parameter>cuba.web.loginDialogDefaultPassword=admin</parameter></para>
<para>Интерфейс: <classname>WebConfig</classname></para>
<para>Уровень: <glossterm linkend="text_webclient_id">Web Client</glossterm>.</para>
</listitem>
<listitem id="property_fullNamePattern">
<para><parameter>cuba.user.fullNamePattern</parameter> задает шаблон формирования полного имени пользователя. </para>
<para>Значение по умолчанию</para>
<para><parameter>cuba.user.fullNamePattern={LL| }{F|. }{M|.}</parameter></para>
<para>Таким образом, можно сформировать полное имя по шаблону из имени, отчества и фамилии пользователя. В шаблоне используются следующие правила:</para>
<itemizedlist>
<listitem>
<para>Фигурными скобками {} разделяются части шаблона между собой</para>
</listitem>
<listitem>
<para>Правила формирования шаблона внутри фигурных скобок: один из следующих символов и далее, без пробела, символ |.</para>
<para><code>LL</code> означает фамилию пользователя, написанную в полном варианте (Иванов)</para>
<para><code>L</code> означает фамилию пользователя, написанную в кратком варианте (И)</para>
<para><code>FF</code> означает имя пользователя, написанного в полном варианте (Петр)</para>
<para><code>F</code> означает фамилию пользователя, написанную в кратком варианте (П)</para>
<para><code>MM</code> означает отчество пользователя, написанное в полном варианте (Сергеевич)</para>
<para><code>M</code> означает отчество пользователя, написанное в кратком варианте (С)</para>
</listitem>
<listitem>
<para>После символа | могут идти любые символы, в том числе, и пробел.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
</appendix>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="glossary.xml" encoding="UTF-8"/>
<index type="А" lang="ru">
<para>TODO</para>
</index>
</book>

View File

@ -363,8 +363,8 @@ pre {
}
.tip {
background: #FAF7F5;
border: solid #e2d2c9 1px;
background: #ecf2ff;
border: solid #4c72bf 1px;
}
.tip .title {
color: #80614D;