博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Jboss EAP 6 EJB调用常见问题
阅读量:4591 次
发布时间:2019-06-09

本文共 10520 字,大约阅读时间需要 35 分钟。

1. 调用EJB的三种方法

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

Java代码  
  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.   
  8. EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(p);  
  9. ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc);  
  10. EJBClientContext.setSelector(selector);  
  11.   
  12. Properties props = new Properties();  
  13. props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");  
  14. InitialContext context = new InitialContext(props);  
  15.   
  16. final boolean useScopedExample = Boolean.getBoolean("UseScopedContext");  
  17. final String rcal = "ejb:jboss-ejb-multi-server-app-main/ejb//" + (useScopedExample ? "MainAppSContextBean" : "MainAppBean") + "!" + MainApp.class.getName();  
  18. 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
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,代码如下:

Java代码  
  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.   
  14. Context context = (Context) new InitialContext(props).lookup("ejb:");  
  15. try {  
  16.    final TimerExample bean = (TimerExample) context.lookup("TestTimer/TestTimerEJB/TimerExampleBean!org.example.jboss.timer.TimerExample");  
  17.    bean.doSomething();  
  18. finally {  
  19.    try {   
  20.        context.close();  
  21.    } catch(Exception e) { }  
  22. }   
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失败。这种情况下,就得使用第三种方式,也是推荐的方式:

先来看代码:

Java代码  
  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,内容如下:

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>  

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

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. ...  
  20.   
  21. <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">  
  22.     <outbound-socket-binding name="remote-ejb-app1">  
  23.         <remote-destination host="localhost" port="4447"/>  
  24.     </outbound-socket-binding>  
  25.     <outbound-socket-binding name="remote-ejb-app2">  
  26.         <remote-destination host="localhost" port="4447"/>  
  27.     </outbound-socket-binding>  
  28. </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.

Java代码  
  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.    
  26. }  
final Properties props = new Properties();// mark it for scoped EJB client contextprops.put("org.jboss.ejb.client.scoped.context","true");// add other propertiesprops.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    } }

 

转载于:https://www.cnblogs.com/firstdream/p/9796234.html

你可能感兴趣的文章
Vue 数组 字典 template v-for 的使用
查看>>
蓝牙模块选择经验谈
查看>>
java中==和equals
查看>>
CCActionPageTurn3D
查看>>
python random
查看>>
esp32-智能语音-cli(调试交互命令)
查看>>
netty与MQ使用心得
查看>>
关于dl dt dd 文字过长换行在移动端显示对齐的探讨总结
查看>>
组合设计模式
查看>>
第十五部分_Struts2.1拦截器深度剖析、异常处理
查看>>
Python匿名函数详解
查看>>
python面向对象(六)之元类
查看>>
quartz.net插件类库封装(含源码)
查看>>
package.json中 npm依赖包版本前的符号的意义
查看>>
Cygwin下获取Android源代码
查看>>
C 自删除技术---批处理方式
查看>>
maven学习(下)利用Profile构建不同环境的部署包
查看>>
win8自带输入法如何切换全角、半角操作流程
查看>>
TensorFlow windows 安装(base anaconda)
查看>>
Percona XtraDB Cluster集群
查看>>