четверг, 23 сентября 2010 г.
EJB configured to bypass security. Please verify if this is intended
Если в логах сообщение типа "EJB configured to bypass security. Please verify if this is intended", можно смело на него забить. Спецификация не требует для MDB-бинов объявлять явно домен безопасности (security-domain)
понедельник, 14 июня 2010 г.
JAX-WS пример клиента с Basic-аутентификацией
Если получите такую ошибку при запуске, добавьте библиотеку jax-ws (скачать можно тут)
Provider com.sun.xml.ws.spi.ProviderImpl not found
Provider com.sun.xml.ws.spi.ProviderImpl not found
понедельник, 26 апреля 2010 г.
Настройки в EAR-приложениях под JBoss
Любое приложение, сложнее чем HelloWorld, требует некоторых настроек для своей работы. В приложениях, что мне приходится делать под JBoss, я использовал следующий механизм.
Существует стандартный MBean-сервис, который позволяет разместить в JNDI некоторые объекты. Реализация этого сервиса - org.jboss.naming.JNDIBindingServiceMgr. Разместив некоторые объекты в JNDI, их потом очень легко достать в EJB-бинах. Собственно, этим и воспользуемся.
Сначала нужно определить сервис JNDIBindingServiceMgr. В папке META-INF ear-архива (или папки) необходимо создать файл, оканчивающийся на -service.xml. Например, jndisettings-service.xml. Внутри этого файла определяем сервис JNDIBindingServiceMgr, как на примере ниже:
В этом XML-е нет ничего сложного. Первое "com.blogspot.j2ee-rus:name=Settings" - это имя MBean-а, соответствующего сервису. Имя может быть произвольным, но общая рекомендация - оно должно отражать суть). Второе - в файле прописаны 2 параметра настроек, которые после запуска сервиса будут доступны через JNDI. JNDI-пути также могут быть достаточно произвольными, я придерживаюсь обычно структуры пути "модуль/логический компонент/название параметра". В данном примере я использую 2 пути - "j2ee-rus/settings/hello-world-word" и "j2ee-rus/settings/goodbuy-world-word".
Отлично, теперь, если запустить EAR, то JBoss-сервис org.jboss.naming.JNDIBindingServiceMgr также установится как MBean и будет доступен по адресу com.blogspot.j2ee-rus:name=Settings (это можно посмотреть через JConsole).
Далее, чтобы получить значения из JNDI в EJB-бинах, нужно определить внутри бина контекст:
А чтобы достать некоторый объект из JNDI, используем следующую конструкцию:
Вот, собственно, и все! Еще одно замечение - когда EAR вместе с сервисом настроек установлен под JBoss, после изменение файла с настройками (jndisettings-service.xml) происходит автоматический redeploy всего EAR-приложения! В большинстве случаев - это как раз и требуется.
Существует стандартный MBean-сервис, который позволяет разместить в JNDI некоторые объекты. Реализация этого сервиса - org.jboss.naming.JNDIBindingServiceMgr. Разместив некоторые объекты в JNDI, их потом очень легко достать в EJB-бинах. Собственно, этим и воспользуемся.
Сначала нужно определить сервис JNDIBindingServiceMgr. В папке META-INF ear-архива (или папки) необходимо создать файл, оканчивающийся на -service.xml. Например, jndisettings-service.xml. Внутри этого файла определяем сервис JNDIBindingServiceMgr, как на примере ниже:
<?xml version="1.0" encoding="windows-1251"?>
<server>
<mbean code="org.jboss.naming.JNDIBindingServiceMgr"
name="com.blogspot.j2ee-rus:name=Settings">
<attribute name="BindingsConfig" serialDataType="jbxb">
<jndi:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">
<jndi:binding name="j2ee-rus/settings/hello-world-word">
<jndi:value>Hello World</jndi:value>
</jndi:binding>
<jndi:binding name="j2ee-rus/settings/goodbuy-world-word">
<jndi:value>Goodbuy World</jndi:value>
</jndi:binding>
</jndi:bindings>
</attribute>
</mbean>
</server>
В этом XML-е нет ничего сложного. Первое "com.blogspot.j2ee-rus:name=Settings" - это имя MBean-а, соответствующего сервису. Имя может быть произвольным, но общая рекомендация - оно должно отражать суть). Второе - в файле прописаны 2 параметра настроек, которые после запуска сервиса будут доступны через JNDI. JNDI-пути также могут быть достаточно произвольными, я придерживаюсь обычно структуры пути "модуль/логический компонент/название параметра". В данном примере я использую 2 пути - "j2ee-rus/settings/hello-world-word" и "j2ee-rus/settings/goodbuy-world-word".
Отлично, теперь, если запустить EAR, то JBoss-сервис org.jboss.naming.JNDIBindingServiceMgr также установится как MBean и будет доступен по адресу com.blogspot.j2ee-rus:name=Settings (это можно посмотреть через JConsole).
Далее, чтобы получить значения из JNDI в EJB-бинах, нужно определить внутри бина контекст:
@Resource
private EJBContext context;
А чтобы достать некоторый объект из JNDI, используем следующую конструкцию:
String helloWorld = (String) context.lookup("j2ee-rus/settings/hello-world-word");
String goodbuyWordl = (String) context.lookup("j2ee-rus/settings/hello-world-word");
Вот, собственно, и все! Еще одно замечение - когда EAR вместе с сервисом настроек установлен под JBoss, после изменение файла с настройками (jndisettings-service.xml) происходит автоматический redeploy всего EAR-приложения! В большинстве случаев - это как раз и требуется.
понедельник, 1 марта 2010 г.
HqlSqlWalker throws NullPointerException with explicit joins and component mapping
HqlSqlWalker throws NullPointerException with explicit joins and component mapping - такой exception словил при попытке выполнить HSQL-запрос с явным join, например:
Конечно, можно использовать неявный join, т.е. запрос может выглядеть так:
String query = "select playerStatus form PlayerStatus playerStatus WHERE playerStatus.player.name = :playerName";
Но в таком виде у меня не заработало - параметр "playerStatus.player.playerName" некорректно распознавался. Поиск в Google дал результат: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1895
Т.е. такой синтаксис не поддерживается (хотя в доке есть описание: http://docs.jboss.org/hibernate/stable/core/reference/en/html/queryhql.html). Странно, конечно. В результате я использовал обычный select с условием where, т.е.:
String query = "select playerStatus form PlayerStatus playerStatus JOIN playerStatus.player AS player WHERE player.playerName = :playerName";
Конечно, можно использовать неявный join, т.е. запрос может выглядеть так:
String query = "select playerStatus form PlayerStatus playerStatus WHERE playerStatus.player.name = :playerName";
Но в таком виде у меня не заработало - параметр "playerStatus.player.playerName" некорректно распознавался. Поиск в Google дал результат: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1895
Т.е. такой синтаксис не поддерживается (хотя в доке есть описание: http://docs.jboss.org/hibernate/stable/core/reference/en/html/queryhql.html). Странно, конечно. В результате я использовал обычный select с условием where, т.е.:
String query = "select playerStatus, player form PlayerStatus playerStatus, Player player WHERE playerStatus.playerID = :player.id and player.name = :playerName";
воскресенье, 28 февраля 2010 г.
Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
Неприятный WARN при вызове методов в EJB-бина (в частности, stateless-бинах) лечится 2мя способами:
1) Плохой - настроить Log4J в Jboss-е так, чтобы WARN в лог не падал. Пример:
2) Хороший вариант - убрать то, что больше не нужно, из файла server/default/deploy/ejb3-interceptors-aop.xml, а именно:
а - Закомментировать:
б - Закомментировать:
1) Плохой - настроить Log4J в Jboss-е так, чтобы WARN в лог не падал. Пример:
<category name="org.jboss.ejb3.interceptors">
<priority value="ERROR" />
</category>
2) Хороший вариант - убрать то, что больше не нужно, из файла server/default/deploy/ejb3-interceptors-aop.xml, а именно:
а - Закомментировать:
<!-- <aspect name="InterceptorsFactory" factory="org.jboss.ejb3.interceptors.aop.InterceptorsFactory" scope="PER_INSTANCE"/> -->
б - Закомментировать:
<bind pointcut="construction(@org.jboss.ejb3.interceptors.ManagedObject->new(..))">
<!-- interceptor-ref name="LoggingInterceptor"/> -->
<!-- TODO: we don't need invocation context here -->
<!-- TODO: we do until we've seperated the post constructs -->
<advice name="setup" aspect="InvocationContextInterceptor"/>
<!--<advice name="invoke" aspect="InterceptorsFactory"/>-->
</bind>
вторник, 16 февраля 2010 г.
Cannot simultaneously fetch multiple bags
А вот это исключение просто как гром среди ясного неба было:
Cannot simultaneously fetch multiple bags
Причина - в одной сущности не может быть более одной коллекции (Collection), заполняемой сразу (FechType.EAGER). Коллекция называется bag. Вот таблица о том, как правильно мапить коллекции, списки и т.п. http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html
Решение проблемы "по-английски" описано тут: http://community.jboss.org/message/361474#4045327
Cannot simultaneously fetch multiple bags
Причина - в одной сущности не может быть более одной коллекции (Collection), заполняемой сразу (FechType.EAGER). Коллекция называется bag. Вот таблица о том, как правильно мапить коллекции, списки и т.п. http://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html
Решение проблемы "по-английски" описано тут: http://community.jboss.org/message/361474#4045327
Repeated column in mapping for entity
Словил такую вещь: Repeated column in mapping for entity
Классы такие:
Лечится очень просто - убираем nullable = false для коллекции, и все будет ОК.
Еще пример: http://www.laliluna.de/256.html
Классы такие:
@Entity
@Table(name = "TOPICS")
public class Topic {
...
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "TO_ID", referencedColumnName = "TO_ID", nullable = false)
@OrderBy
private Collection<accelerator> accelerators;
...}
@Entity
@Table(name = "ACCELERATORS")
public class Accelerator {
...
@ManyToOne
@JoinColumn(name = "TO_ID")
private Topic topic;
}
Лечится очень просто - убираем nullable = false для коллекции, и все будет ОК.
Еще пример: http://www.laliluna.de/256.html
пятница, 12 февраля 2010 г.
Could not enlist in transaction on entering meta-aware object
Словил это исключение. Решение было быстрым и простым. Самописный ResourceAdapter, который я использовал, не поддерживал работу с транзакциями. LocalSettingsFactory инжектировался корректно, но при попытке выполнить метод getContextName() у EJB-бина выскакивало это исключение.
Причина в том, что по умолчанию используется управление транзакциями на уровне контейнера (CMT), а аттрибут транзакции - REQUIRES_NEW. Получается, что getContextName вызывался в рамках транзакции новой транзакции, но при это объект factory.getConnection() не поддерживал транзакции. Решение на данный момент было простым - добавил аннотацию @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) для метода, чтобы изменить аттрибут транзакции.
Насколько я понял, подобные проблемы могут быть и с DataSource-ами, которые используются некорректно (например, сконфигурованы для локальных транзакций, а используются в рамках XA-транзакций).
Причина в том, что по умолчанию используется управление транзакциями на уровне контейнера (CMT), а аттрибут транзакции - REQUIRES_NEW. Получается, что getContextName вызывался в рамках транзакции новой транзакции, но при это объект factory.getConnection() не поддерживал транзакции. Решение на данный момент было простым - добавил аннотацию @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) для метода, чтобы изменить аттрибут транзакции.
@Stateless
public class TestingEJB implements Testing {
@Resource(name = "LocalSettingsFactory", mappedName = "java:LocalSettingsFactory")
private LocalSettingsFactory factory;
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public String getContextName() {
try {
return factory.getConnection().getContextName();
} catch (NamingException e) {
return e.getMessage();
}
}
}
Насколько я понял, подобные проблемы могут быть и с DataSource-ами, которые используются некорректно (например, сконфигурованы для локальных транзакций, а используются в рамках XA-транзакций).
Подписаться на:
Сообщения (Atom)