1. 调用EJB的三种方法

调用EAP 6 EJB的第一种方法,使用JBoss API,如下:

  1. Properties p = new Properties();
  2. p.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
  3. p.put("remote.connections", "default");
  4. p.put("remote.connection.default.host", "localhost");
  5. p.put("remote.connection.default.port", "4447");
  6. p.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
  7. EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(p);
  8. ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc);
  9. EJBClientContext.setSelector(selector);
  10. Properties props = new Properties();
  11. props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
  12. InitialContext context = new InitialContext(props);
  13. final boolean useScopedExample = Boolean.getBoolean("UseScopedContext");
  14. final String rcal = "ejb:jboss-ejb-multi-server-app-main/ejb//" + (useScopedExample ? "MainAppSContextBean" : "MainAppBean") + "!" + MainApp.class.getName();
  15. final MainApp remote = (MainApp) context.lookup(rcal);
Properties p = new Properties();
p.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
p.put("remote.connections", "default");
p.put("remote.connection.default.host", "localhost");
p.put("remote.connection.default.port", "4447");
p.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false"); EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(p);
ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc);
EJBClientContext.setSelector(selector); Properties props = new Properties();
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
InitialContext context = new InitialContext(props); final boolean useScopedExample = Boolean.getBoolean("UseScopedContext");
final String rcal = "ejb:jboss-ejb-multi-server-app-main/ejb//" + (useScopedExample ? "MainAppSContextBean" : "MainAppBean") + "!" + MainApp.class.getName();
final MainApp remote = (MainApp) context.lookup(rcal);

这种方法在Standalone client (client is not running inside of JBoss EAP 6)能正常调用,但在EAP 6环境中会报java.lang.SecurityException: EJBCLIENT000021: EJB client context selector may not be changed。

第二种方法使用scoped context,代码如下:

  1. Properties props = new Properties();
  2. props.put("org.jboss.ejb.client.scoped.context", "true");
  3. props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
  4. //props.put(Context.OBJECT_FACTORIES, "org.jboss.ejb.client.naming.ejb.ejbURLContextFactory");
  5. props.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
  6. props.put("remote.connections", "default");
  7. props.put("remote.connection.default.port", 4447);
  8. props.put("remote.connection.default.host", host);
  9. //props.put("remote.connection.default.username", username);
  10. //props.put("remote.connection.default.password", password);
  11. props.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
  12. props.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
  13. Context context = (Context) new InitialContext(props).lookup("ejb:");
  14. try {
  15. final TimerExample bean = (TimerExample) context.lookup("TestTimer/TestTimerEJB/TimerExampleBean!org.example.jboss.timer.TimerExample");
  16. bean.doSomething();
  17. } finally {
  18. try {
  19. context.close();
  20. } catch(Exception e) { }
  21. }
Properties props = new Properties();
props.put("org.jboss.ejb.client.scoped.context", "true");
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
//props.put(Context.OBJECT_FACTORIES, "org.jboss.ejb.client.naming.ejb.ejbURLContextFactory");
props.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
props.put("remote.connections", "default");
props.put("remote.connection.default.port", 4447);
props.put("remote.connection.default.host", host);
//props.put("remote.connection.default.username", username);
//props.put("remote.connection.default.password", password);
props.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
props.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false"); Context context = (Context) new InitialContext(props).lookup("ejb:");
try {
final TimerExample bean = (TimerExample) context.lookup("TestTimer/TestTimerEJB/TimerExampleBean!org.example.jboss.timer.TimerExample");
bean.doSomething();
} finally {
try {
context.close();
} catch(Exception e) { }
}

这种方式,可以完全通过代码实现配置,但由客户端来创建和管理Connection,因此需要更多的资源,性能不高。还有一个严重的问题,当使用CMT,事物跨多个EJB时,因每次调用EJB后都关闭context(如不close,connection会一直保持),这将造成事务commit/rollback失败。这种情况下,就得使用第三种方式,也是推荐的方式:

先来看代码:

  1. Properties props = new Properties();
  2. props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
  3. final Context context = new javax.naming.InitialContext(props);
  4. final Greeter bean = (Greeter) context.lookup("ejb:myapp/myejb/GreeterBean!" + org.myapp.ejb.Greeter.class.getName());
  5. bean.doSometing();
Properties props = new Properties();
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new javax.naming.InitialContext(props);
final Greeter bean = (Greeter) context.lookup("ejb:myapp/myejb/GreeterBean!" + org.myapp.ejb.Greeter.class.getName());
bean.doSometing();

代码很简单,注意没有调用close()方法。那这是怎么找到远程主机的呢?需要增加一些配置,先在war的WEB-INF或ear的META-INF中新建一个文件jboss-ejb-client.xml,内容如下:

  1. <jboss-ejb-client xmlns="urn:jboss:ejb-client:1.2">
  2. <client-context>
  3. <ejb-receivers>
  4. <remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection-app1" connect-timeout="10000"/>
  5. <remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection-app2" connect-timeout="10000"/>
  6. </ejb-receivers>
  7. </client-context>
  8. </jboss-ejb-client>
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.2">
<client-context>
<ejb-receivers>
<remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection-app1" connect-timeout="10000"/>
<remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection-app2" connect-timeout="10000"/>
</ejb-receivers>
</client-context>
</jboss-ejb-client>

然后在standalone.xml增加如下配置,建立与远程主机的关联:

  1. <subsystem xmlns="urn:jboss:domain:remoting:1.2">
  2. <connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm"/>
  3. <outbound-connections>
  4. <remote-outbound-connection name="remote-ejb-connection-app1" outbound-socket-binding-ref="remote-ejb-app1">
  5. <properties>
  6. <property name="SASL_POLICY_NOANONYMOUS" value="false"/>
  7. <property name="SSL_ENABLED" value="false"/>
  8. </properties>
  9. </remote-outbound-connection>
  10. <remote-outbound-connection name="remote-ejb-connection-app2" outbound-socket-binding-ref="remote-ejb-app2">
  11. <properties>
  12. <property name="SASL_POLICY_NOANONYMOUS" value="false"/>
  13. <property name="SSL_ENABLED" value="false"/>
  14. </properties>
  15. </remote-outbound-connection>
  16. </outbound-connections>
  17. </subsystem>
  18. ...
  19. <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
  20. <outbound-socket-binding name="remote-ejb-app1">
  21. <remote-destination host="localhost" port="4447"/>
  22. </outbound-socket-binding>
  23. <outbound-socket-binding name="remote-ejb-app2">
  24. <remote-destination host="localhost" port="4447"/>
  25. </outbound-socket-binding>
  26. </socket-binding-group>
<subsystem xmlns="urn:jboss:domain:remoting:1.2">
<connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm"/>
<outbound-connections>
<remote-outbound-connection name="remote-ejb-connection-app1" outbound-socket-binding-ref="remote-ejb-app1">
<properties>
<property name="SASL_POLICY_NOANONYMOUS" value="false"/>
<property name="SSL_ENABLED" value="false"/>
</properties>
</remote-outbound-connection>
<remote-outbound-connection name="remote-ejb-connection-app2" outbound-socket-binding-ref="remote-ejb-app2">
<properties>
<property name="SASL_POLICY_NOANONYMOUS" value="false"/>
<property name="SSL_ENABLED" value="false"/>
</properties>
</remote-outbound-connection>
</outbound-connections>
</subsystem> ... <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
<outbound-socket-binding name="remote-ejb-app1">
<remote-destination host="localhost" port="4447"/>
</outbound-socket-binding>
<outbound-socket-binding name="remote-ejb-app2">
<remote-destination host="localhost" port="4447"/>
</outbound-socket-binding>
</socket-binding-group>

调用EJB后,来查看一下connection情况:netstat -aon | findstr "4447"(netstat -np | grep 4447)

2. Could not register a EJB receiver: java.lang.RuntimeException: Operation failed with status WAITING

EJB调用配置中包含以下三个timeout参数:

  • invocation.timeout

The timeout for the EJB handshake or method invocation request/response cycle. The value is in milliseconds. The invocation of any method throws a java.util.concurrent.TimeoutException if the execution takes longer than the timeout period. The execution completes and the server is not interrupted.

  • reconnect.tasks.timeout

The timeout for the background reconnect tasks. The value is in milliseconds. If a number of connections are down, the next client EJB invocation will use an algorithm to decide if a reconnect is necessary to find the right node.

  • remote.connection.CONNECTION_NAME.connect.timeout

The timeout period for the initial connection. After that, the reconnect task will periodically check whether the connection can be established. The value is in milliseconds.

remote.connection.CONNECTION_NAME.connect.timeout默认值为5000ms(参见代码InitialContextFactory.getInitialContext),当在timeout时间内连接不上时,就会报以上错误。

3. 关于Rollback

EJB方法抛出RuntimeException会引起rollback,那有方法指定某个Exception是否引起Rollback么?可以使用注解@ApplicationException,如下:

@ApplicationException(rollback = true)

public class MyException extends Exception {     // ... }

4. How to close scoped EJB client contexts?

Internally, when a lookup happens for a ejb: URL string, a relevant javax.naming.Context is created for that ejb: lookup.

So we first create a JNDI context and then use it to lookup an EJB.

  1. final Properties props = new Properties();
  2. // mark it for scoped EJB client context
  3. props.put("org.jboss.ejb.client.scoped.context","true");
  4. // add other properties
  5. props.put(....);
  6. ...
  7. Context jndiCtx = new InitialContext(props);
  8. Context ejbRootNamingContext = (Context) jndiCtx.lookup("ejb:");
  9. try {
  10. final MyBean bean = ejbRootNamingContext.lookup("app/module/distinct/bean!interface"); // rest of the EJB jndi lookup string
  11. bean.doSomething();
  12. } finally {
  13. try {
  14. // close the EJB naming JNDI context
  15. ejbRootNamingContext.close();
  16. } catch (Throwable t) {
  17. // log and ignore
  18. }
  19. try {
  20. // also close our other JNDI context since we are done with it too
  21. jndiCtx.close();
  22. } catch (Throwable t) {
  23. // log and ignore
  24. }
  25. }
final Properties props = new Properties();
// mark it for scoped EJB client context
props.put("org.jboss.ejb.client.scoped.context","true");
// add other properties
props.put(....);
...
Context jndiCtx = new InitialContext(props);
Context ejbRootNamingContext = (Context) jndiCtx.lookup("ejb:");
try {
final MyBean bean = ejbRootNamingContext.lookup("app/module/distinct/bean!interface"); // rest of the EJB jndi lookup string
bean.doSomething();
} finally {
try {
// close the EJB naming JNDI context
ejbRootNamingContext.close();
} catch (Throwable t) {
// log and ignore
}
try {
// also close our other JNDI context since we are done with it too
jndiCtx.close();
} catch (Throwable t) {
// log and ignore
} }

Invoking Session Beans

Scoped EJB client contexts

How to configure an EJB client in JBoss EAP 6

Jboss EAP 6 EJB调用常见问题的更多相关文章

  1. JBoss部属和EJB调用-EJB3.0入门经典学习笔记(2)

    目录 1. 在JBoss中部属  2. 在Tomcat中调用EJB  3. 在JBoss中调用EJB  1. 在JBoss中部属 1) JBoss的配置目录 路径D:\Java\jboss6\serv ...

  2. 需要安全认证的远程EJB调用示例(Jboss EAP 6.2环境)

    一,Remote EJB 服务接口定义: package yjmyzz.ejb.server.helloworld; public interface HelloWorldService { publ ...

  3. JBOSS EAP 6 系列四 EJB实现——调用(贯穿始终的模块)

    本文主要介绍在JBOSS EAP 6.2(或者JBOSS AS7)中模块是如何贯穿EJB实现的始终.延续上一博文<认识模块的使用>的话题继续聊JBOSS做为模块申明式容器的这一特性在EJB ...

  4. JBOSS EAP 6 系列一 新特性

    在项目中,采用的架构是Springmvc+spring+EJB+Jpa等架构,当然服务器是Jboss,本次Jboss我们采用的是JBossEap6.2,Jboss7的新特性与Jboss4.5的大的改变 ...

  5. 如何让jboss eap 6.2+ 的多个war应用共享 jar 包?

    weblogic有一个很贴心的功能,允许把多个war应用共同依赖的jar包,打包一个单独的war,以libary方式部署,然后各应用在weblogic.xml里声明引用该libary即可,这样可大大减 ...

  6. jboss EAP 6.2 + Message Drive Bean(MDB) 整合IBM Webshpere MQ 7.5

    上一篇我们知道了消息驱动Bean的基本用法,实际大型分布式企业应用中,往往会采用高性能的商业Queue产品,比如IBM Webshpere MQ(目前最新版本是7.5 ),下面讲解下如何在Jboss ...

  7. JBoss+Ant实现EJB无状态会话bean实例

    EJB分为session bean.entity bean.message-driven bean,session bean又分为无状态会话bean和有状态会话bean. session bean负责 ...

  8. JBOSS EAP实战(1)

    JBOSS的诞生 1998年,在硅谷SUN公司的SAP实验室,一个年轻人正坐在电脑前面思考,然后写着什么东西.不,他没有在写程序,他在写辞呈.他正在做出人生的一个重大决定:他要辞掉在SUN的这份工作, ...

  9. WebLogic Server 12c相对JBoss EAP 6的优势

    原文来自:https://blogs.oracle.com/middlewareplace/entry/why_should_you_choose_oracle 1.多数据中心部署和集群 WebLog ...

随机推荐

  1. mac 安装 python mysqlclient 遇到的问题及解决方法

    在 mac 上安装 mysqlclient 遇到了一些问题,查找资料很多人都遇到了同样的问题.通过资料和试验,成功了.这里记录一下,希望帮到遇到同样问题的人. 本人使用python3, 安装步骤如下: ...

  2. shell脚本案例分享 - 业务系统日志自定义保留或删除需求

    需求说明:  线上某些业务系统的日志不定期产生, 有的每天产生, 有的好几天才产生, 因为系统只有在用的时候才产生日志,日志文件均存放在以当天日期命名的目录下. 当日志目录越来越多时就需要处理, 由此 ...

  3. 解决:git使用git push 命令跳出remote: Permission to A denied to B的问题

    开始git上传项目,不料,在git push这一步骤发生了错误? remote: Permission to qwe2193066947/firstRepository.git denied to m ...

  4. C语言Win32 Application 的标题栏图标,任务栏图标,exe文件图标问题

    我们这里新建的首先是一个空工程,新建c文件. 因为是空工程,我们没有资源文件,要用到图标资源,首先要新建和导入图标为资源. 选择引入资源,选择要引入的ico文件 完成,重命名保存Script_icon ...

  5. 虚拟机中安装完 CentOS7minimal 版本后无法联网的问题

    问题描述 安装完系统后无法上网,然后进入到目录 /etc/sysconfig/network-script 查看.发现只有一个 ifcfg-lo. 解决办法 这种情况是没有识别到网卡. 在 VMwar ...

  6. Java的策略模式

    策略模式也是我们经常使用的模式,它的定义如下:将可变的部分从程序中抽象分离出来成为算法接口,在该部分下分别封装一系列算法实现并使它们可以相互替换. 举个例子,我们现在有三种支付方式:支付宝支付,微信支 ...

  7. Redis常用数据类型及使用场景

    Redis最为常用的数据类型 字符串(String) 字符串列表(list) 字符串集合(set) 哈希(hash) 有序的字符串集合(sorted set) String(字符串) 字符串是最基本的 ...

  8. iframe 页面刷新

    1.点击刷新 [1].html页面代码 <a href="javascript:;" title="刷新当前页" id="Refresh&quo ...

  9. agc007D - Shik and Game(dp 单调性)

    题意 题目链接 Sol 主人公的最优决策一定是经过熊->返回到某个位置->收集经过的钻石 那么可以直接设\(f[i]\)表示收集完了前\(i\)个位置的钻石的最小时间,转移的时候枚举下最后 ...

  10. webstorm技巧

    webstorm安装后的一些设置技巧: 如何更改主题(字体&配色):File -> settings -> Editor -> colors&fonts -> ...