Обычно считается, что фреймворки для разработки полезны тем, что предоставляют возможность программисту пользоваться некой готовой инфраструктурой. То есть основной плюс – в том, что ДОБАВЛЯЮТСЯ ВОЗМОЖНОСТИ использовать готовое. Но мне в последнее время кажется, что главное преимущество даже не в этом, а в том, что фреймворки, как правило, помимо дополнительных возможностей также накладывают существенные ограничения на код, который будет в рамках него работать.
Пример – Spring MVC предлагает только несколько стандартных способов написать обработчик запроса. Хочешь обработать запрос – пропиши маппинг и добавь метод в контроллер. Хочешь датабиндинг – используй @ModelAttribute. Почему это хорошо ? Потому что разработчику нужно меньше шевелить мозгами, раздумывая над тем, как бы лучше запрограммировать этот кусочек. Больше времени останется на продумывание более важных вещей. Плюс к этому, все, кто знакомы со Spring MVC, будут с первого взгляда понимать то, что хотел сказать программист Вася, написавший этот код года два назад. Значит, добавление ограничений положительно влияет на процесс разработки ? Получается, так.
Действительно, имея широкий набор возможностей, тяжело научиться их правильно использовать. Причем, как правило, сначала учишься использовать правильно, набивая шишки, и попутно придумываешь правила сам. Некий кодстайл, паттерны для того, чтобы писать корректный код, не думая о деталях. Так я учился в своё время языку С++. Читая описание того, что такое header-файл, я нигде не мог найти аргументированных правил по его использованию. Сейчас такая литература появилась в изобилии, но в то время у меня еще не было интернета. И я долгое время не знал, как оформлять h-файлы и как их инклудить в cpp – что именно должно быть в h-файле, а что – в cpp, можно ли инклудить h-файл в другой h-файл; если cpp-файл использует h-файл, зависящий от другого, то нужно ли в cpp-файл включать эту зависимость итд. Поэтому сидел и морщил ум на тему, как же сделать правильно. А всё потому, что С++ предоставляет множество способов сделать это НЕправильно, а очевидности, очевидные для опытных программистов, далеко не так очевидны для новичков. Аналогичные шишки приходилось набивать и на других платформах. C#, к примеру, заставил меня призадуматься о стратегии обработки исключений и особенно о корректной реализации IDisposable в иерархии классов.
Поэтому хороший фреймворк должен не только предоставлять пачку возможностей, но и набор несложных правил о том, как, собственно, писать код. Чтобы лезть в декомпилятор/исходники/дебагер приходилось как можно реже. Codestyle & FAQ – идеальные форматы для такой информации.
Часто при использовании EJB возникает необходимость получить пропертисы объекта одним запросом, но проперти помечено как LAZY и исправлять на EAGER нежелательно. Выход в данной ситуации стандартными методами есть только один : опуститься на уровень native query. Ну или если хочется убить производительность, то разместить цикл опроса Lazy полей (это приведет к генерации циклических запросов к СУБД, и, соответственно, к деградации перформанса).Что же делать ? На помощь приходит возможность HQL указать хибернейту, что некоторые пропертисы или коллекции необходимо подгрузить сразу, не откладывая момент вызова lazy-прокси. Например,
select u from User u
inner join fetch u.company c
подгрузит присоединяемое свойство за один запрос в джойне так, как бы это было реализовано, используй мы native query.
Или
from Document fetch all properties
сделает все то же для всех свойств объекта Document.
После того, как все заработало, не поленитесь проверить в профайлере запросов, что сгенерировал хибер и какие запросы были выполнены. Возможно, что-то пошло не так, и запросы не отвечают требованиям производительности. Если это случилось – что ж, в любом случае у вас еще остаются native query 🙂
В общем, теперь можно не париться и объявлять все пропертисы по умолчанию как fetchMode = LAZY.
Подробнее синтаксис описан в документе http://docs.jboss.org/hibernate/core/3.3/reference/en/html/queryhql.html
Итак, сегодня мы займемся настройкой портов HTTP, а также настройкой HTTPS. Стандартный бандл JBoss сконфигурирован так, что HTTP привязан к порту 8080, а HTTPS – к порту 8443. Допустим, нам необходимо настроить сервер так, чтобы использовался 80 порт для HTTP и 443 для HTTPS, причем при заходе на 80 порт сервер перекидывал клиента на порт HTTPS. Для этого необходимо внести следующие изменения в конфигурационные файлы:
/server/default/conf/bindingservice.beans/META-INF/bindings-jboss-beans.xml (заменяем в трех местах – первые два определяют порты по умолчанию, третье место определяет XSLT-преобразование, которое применяется для конфигурационного файла server.xml.) У меня эти три места были приведены к следующему виду:
<bean>
<property name=”serviceName”>jboss.web:service=WebServer</property>
<property name=”port”>80</property>
<property name=”description”>JBoss Web HTTP connector socket; also drives the values for the HTTPS and AJP sockets</property>
<bean>
<property name=”serviceName”>jboss.web:service=WebServer</property>
<property name=”bindingName”>HttpsConnector</property>
<property name=”port”>443</property>
<property name=”description”>JBoss Web HTTPS connector socket</property>
</bean>
<Connector>
<xsl:for-each select=”@*”>
<xsl:choose>
<xsl:when test=”(name() = ‘port’ and . = ’80’)”>
<xsl:attribute name=”port”><xsl:value-of select=”$port” /></xsl:attribute>
</xsl:when>
<xsl:when test=”(name() = ‘port’ and . = ‘8009’)”>
<xsl:when test=”(name() = ‘redirectPort’)”>
<xsl:attribute name=”redirectPort”><xsl:value-of select=”$portHttps” /></xsl:attribute>
</xsl:when>
<xsl:when test=”(name() = ‘port’ and . = ‘443’)”>
<xsl:attribute name=”port”><xsl:value-of select=”$portHttps” /></xsl:attribute>
</xsl:when>
<xsl:otherwise>
2. /server/default/deploy/jbossweb.sar/server.xml
Здесь для наших настроек самое главное будет выглядеть так:
<!– A HTTP/1.1 Connector on port 8080 –>
<Connector protocol=”HTTP/1.1″ port=”80″ address=”${jboss.bind.address}”
connectionTimeout=”20000″ redirectPort=”443″ />
<!– A AJP 1.3 Connector on port 8009 –>
<Connector protocol=”AJP/1.3″ port=”8009″ address=”${jboss.bind.address}”
redirectPort=”443″ />
<!– SSL/TLS Connector configuration using the admin devl guide keystore–>
<Connector protocol=”HTTP/1.1″ SSLEnabled=”true”
port=”443″ address=”${jboss.bind.address}”
scheme=”https” secure=”true” clientAuth=”false”
keystoreFile=”${jboss.server.home.dir}/conf/mykeystore”
keystorePass=”qwerty” sslProtocol = “TLS” />
Здесь keystore-путь к файлу, содержащему ключи, необходимые для работы HTTPS. Если у вас такого файла нет, вы можете сгенерировать самоподписанный сертификат с использованием стандартной джавовой тулзы keytool (лежит в директории bin в JDK) следующей командой:
<blockquote>keytool –genkey –alias jboss –keypass qwerty –keyalg RSA –keystore mykeystore –validity 3650</blockquote>
Соответственно, keystorePass- пароль для этой связки ключей.
Интересно, что если сконфигурировать server.xml, но оставить bindings-jboss-beans.xml таким же, то JBoss запустится, но порты будут использованы не те. Не только у меня это вызывает недоумение, но, судя по топику http://community.jboss.org/message/540960?tstart=0, это решение (выполнение дополнительного XSLT преобразования над server.xml) было продиктовано исторически, и в данный момент уже не является чем-то необходимым. Поэтому, скорее всего, в следующих версиях JBoss AS такого дублирования не будет.
Итак, осталось только исправить на всякий случай еще один конфиг, использующий порты 8080 и 8443 – /server/default/deployers/jbossws.deployer/META-INF/jboss-beans.xml :
<!–
Set these properties to explicitly define the ports that will be used for rewriting the SOAP address.
Otherwise the ports will be identified by querying the list of installed connectors.
If multiple connectors are found the port of the first connector is used.–>
<property name=”webServiceSecurePort”>443</property>
<property name=”webServicePort”>80</property>
</bean>
Последний шаг – для каждого WAR указать в дескрипторе web.xml на необходимость использования именно защищенного HTTPS протокола. Для этого в web.xml необходимо добавить строки:
<security-constraint>
<web-resource-collection>
<web-resource-name>Protected Context</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
В первую очередь это можно проверить на встроенных админ-панельках джейбосса (ROOT.war, admin-console.war и тд).
0