通过 @Resource 注入的无状态远程 bean 仅提供单个实例
Stateless remote bean injected via @Resource only providing single instance
我是 运行 具有前端(JSF
、CDI
)和后端(EJB
、Hibernate
的 Web 应用程序) 应用程序的各个部分,每个部分都在单独的 WildFly 9.0.1.Final AS
上。前端通过 Remote EJB Client
通过 JNDI 名称与后端通信。
一些前端代码:
@ViewScoped
@Named("ddc")
public class DynamicDatatableController implements Serializable {
@Produces
@Resource(lookup = "ejb:bpm-back-ear/bpm-back-dynamicTable/DynamicTableBean!bc.bpm.dynamicTable.back.beans.remote.DynamicTableBeanRemote")
private DynamicTableBeanRemote dtb;
private Integer tableId;
private DynamicTable table;
@PostConstruct
public void init{
table = dtb.getTable(tableId);
}
}
以及一些后台接口代码:
@Remote
public interface DynamicTableBeanRemote {
List<DynamicTable> getTable(Integer tableId);
}
还有一些后端bean代码:
@Stateless
@LocalBean
public class DynamicTableBean implements DynamicTableBeanRemote {
final static Logger LOGGER = LoggerFactory.getLogger(DynamicTableBean.class);
@PersistenceContext(unitName = "bpmBeans")
private EntityManager em;
@Override
public List<DynamicTable> getTableList(Integer tableId) {
return em.find(DynamicTable.class, tableId);
}
}
问题是,无论我使用 JMeter 或通过刷新几个浏览器选项卡发出多少请求,在任何给定时间都只有一个 DynamicTableBean
实例处于活动状态。每个请求都由队列中的那个 bean 实例执行。如您所知,该应用程序绝对无法使用,因为它绝对是单线程 EJB 明智的。可能是什么问题?
检查您的 jboss ejb 池配置。在 jboss 中(这适用于 eap 6.4.2 并假设在 wildfly 上也是如此)您可以在 domain.xml
中配置 ejb 池大小
<subsystem xmlns="urn:jboss:domain:ejb3:1.5">
<session-bean>
<stateless>
<bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
</stateless>
</session-bean>...
<pools>
<bean-instance-pools>
<strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
</bean-instance-pools>
</pools>
您可以在 jboss-ejb3.xml 中引用此池作为:
<?xml version="1.1" encoding="UTF-8"?>
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="urn:clustering:1.0" xmlns:r="urn:resource-adapter-binding"
xmlns:p="urn:ejb-pool:1.0"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee
http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
version="3.1" impl-version="2.0">
<assembly-descriptor>
<p:pool>
<ejb-name>ejebId</ejb-name>
<p:bean-instance-pool-ref>slsb-strict-max-pool</p:bean-instance-pool-ref>
</p:pool>
</assembly-descriptor>
</jboss:ejb-jar>
无状态会话 bean 有可能能够以比请求到达速率更快的速率完成请求。
在这种情况下,您可能会看到只有一个无状态会话 bean 能够满足所有请求。您可能想在无状态会话 bean 中注入一些延迟,看看您是否仍然只看到它的一个实例。您可以通过
注入延迟
public List<DynamicTable> getTableList(Integer tableId) {
try {Thread.sleep(3000); } catch (InterruptedException ex) {}
return em.find(DynamicTable.class, tableId);
}
并且还在无状态会话 bean 默认构造函数中添加一些日志语句以检查创建了多少个实例。
顺便问一下,您是如何推断出只有一个无状态会话 bean 实例被创建的?通过任何日志或控制台等
问题出在 Intellij 14 和过时版本的 JRebel 客户端上,两者都在 Linux 工作站上 运行。所以这里要记住的一件事是始终使您的工具保持最新:)
我是 运行 具有前端(JSF
、CDI
)和后端(EJB
、Hibernate
的 Web 应用程序) 应用程序的各个部分,每个部分都在单独的 WildFly 9.0.1.Final AS
上。前端通过 Remote EJB Client
通过 JNDI 名称与后端通信。
一些前端代码:
@ViewScoped
@Named("ddc")
public class DynamicDatatableController implements Serializable {
@Produces
@Resource(lookup = "ejb:bpm-back-ear/bpm-back-dynamicTable/DynamicTableBean!bc.bpm.dynamicTable.back.beans.remote.DynamicTableBeanRemote")
private DynamicTableBeanRemote dtb;
private Integer tableId;
private DynamicTable table;
@PostConstruct
public void init{
table = dtb.getTable(tableId);
}
}
以及一些后台接口代码:
@Remote
public interface DynamicTableBeanRemote {
List<DynamicTable> getTable(Integer tableId);
}
还有一些后端bean代码:
@Stateless
@LocalBean
public class DynamicTableBean implements DynamicTableBeanRemote {
final static Logger LOGGER = LoggerFactory.getLogger(DynamicTableBean.class);
@PersistenceContext(unitName = "bpmBeans")
private EntityManager em;
@Override
public List<DynamicTable> getTableList(Integer tableId) {
return em.find(DynamicTable.class, tableId);
}
}
问题是,无论我使用 JMeter 或通过刷新几个浏览器选项卡发出多少请求,在任何给定时间都只有一个 DynamicTableBean
实例处于活动状态。每个请求都由队列中的那个 bean 实例执行。如您所知,该应用程序绝对无法使用,因为它绝对是单线程 EJB 明智的。可能是什么问题?
检查您的 jboss ejb 池配置。在 jboss 中(这适用于 eap 6.4.2 并假设在 wildfly 上也是如此)您可以在 domain.xml
中配置 ejb 池大小<subsystem xmlns="urn:jboss:domain:ejb3:1.5">
<session-bean>
<stateless>
<bean-instance-pool-ref pool-name="slsb-strict-max-pool"/>
</stateless>
</session-bean>...
<pools>
<bean-instance-pools>
<strict-max-pool name="slsb-strict-max-pool" max-pool-size="20" instance-acquisition-timeout="5" instance-acquisition-timeout-unit="MINUTES"/>
</bean-instance-pools>
</pools>
您可以在 jboss-ejb3.xml 中引用此池作为:
<?xml version="1.1" encoding="UTF-8"?>
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="urn:clustering:1.0" xmlns:r="urn:resource-adapter-binding"
xmlns:p="urn:ejb-pool:1.0"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee
http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"
version="3.1" impl-version="2.0">
<assembly-descriptor>
<p:pool>
<ejb-name>ejebId</ejb-name>
<p:bean-instance-pool-ref>slsb-strict-max-pool</p:bean-instance-pool-ref>
</p:pool>
</assembly-descriptor>
</jboss:ejb-jar>
无状态会话 bean 有可能能够以比请求到达速率更快的速率完成请求。
在这种情况下,您可能会看到只有一个无状态会话 bean 能够满足所有请求。您可能想在无状态会话 bean 中注入一些延迟,看看您是否仍然只看到它的一个实例。您可以通过
注入延迟public List<DynamicTable> getTableList(Integer tableId) {
try {Thread.sleep(3000); } catch (InterruptedException ex) {}
return em.find(DynamicTable.class, tableId);
}
并且还在无状态会话 bean 默认构造函数中添加一些日志语句以检查创建了多少个实例。
顺便问一下,您是如何推断出只有一个无状态会话 bean 实例被创建的?通过任何日志或控制台等
问题出在 Intellij 14 和过时版本的 JRebel 客户端上,两者都在 Linux 工作站上 运行。所以这里要记住的一件事是始终使您的工具保持最新:)