设为首页 收藏本站
查看: 1681|回复: 0

[经验分享] Apache OFBiz 学习笔记 之 服务引擎 二

[复制链接]

尚未签到

发表于 2015-8-2 14:27:15 | 显示全部楼层 |阅读模式
加载服务定义文件



ofbiz-component.xml:所有的服务定义文件在每个组件的ofbi-component.xml文件中



加载服务定义

例:framework/common/ofbiz-component.xml






   







  
服务参数




IN:输入参数,类似于java方法中的入参一样,一个ofibiz服务同样需要声明入参,声明方式为在attribute中添加属性mode="IN"

例:





  


OUT:输出参数,类似于java方法中会有返回值一样,一个ofbiz服务也需要声明输出参数,声明方式为在attribute中添加属性mode="OUT"

例:





  




INOUT:输入输出参数,为了方便起见,可以将一个参数既作为输入参数,又作为输出参数,声明方式为在attribute中添加属性mode="INOUT"

例:





  




隐含参数:如同servlet内置对象,在ofbiz服务中有少数参数已经在框架中定义了,无需声明就可以在服务中使用




name


type


mode


optional


说明


responseMessage


String


OUT


true


返回信息(success/error/fail)


errorMessage


String


OUT


true


错误信息


errorMessageList


java.util.List


OUT


true


错误信息列表


successMessage


String


OUT


true


成功信息


successMessageList


java.util.List


OUT


true


成功信息列表
userLoginorg.ofbiz.entity.GenericValueINOUTtrue登陆用户对象,用于权限验证
localejava.util.LocaleINOUTtrue国际化本地对象




可选/必选参数:服务的参数可以是可选,也可以是必须。必须输入的参数在服务调用之前会做检验,如果输入参数的名字及对象类型与声明不符,服务就不会被调用(报错)。必须的输出参数在服务调用之后会被检验,如果输出参数的名字及对象类型与声明不符,会导致服务失败(报错)。只有声明为必须的参数才被检验,同样如果你传入了一个没有意义的参数,也将导致服务调用失败。声明方式为在attribute中添加属性optional="true"/optional="false"(缺省)

例:






  




Interface服务引擎

interface服务引擎实现了在定义服务时可以共享同样的参数。interface服务是不可以被调用的,它仅作为其他服务继承而定义。每个接口服务都需要用interface服务引擎来定义

例:applications/order/servicedef/services.xml






   

Interface for Mass Order Change Services


  




继承上述的接口来实现新的服务

例:applications/order/servicedef/services.xml





   











  




然后我们分别查看java类org.ofbiz.order.order.OrderServices中的方法massPickOrders、massChangeApproved、massProcessOrders

代码片中都存在如下代码,可以获取参数接口定义的变量orderIdList






        // make the list per facility
List orderIds = UtilGenerics.checkList(context.get("orderIdList"));
  




覆盖接口,覆盖接口中的属性或新增属性

例:applications/order/servicedef/services.xml






   




  


查看代码java类org.ofbiz.order.order.OrderServices中的方法massPrintOrders






        String screenLocation = (String) context.get("screenLocation");
String printerName = (String) context.get("printerName");
// make the list per facility
List orderIds = UtilGenerics.checkList(context.get("orderIdList"));
  




实现服务

实现一个服务可以用一个或多个服务引擎来实现,这里描述下常用的实现方法

java:用java代码实习服务

首先定义java类型的服务

服务定义:applications/party/servicedef/services_view.xml






   
Gets a person entity from the cache/database



  


engine: java

location:指向带包路径的类名

invoke:静态的方法名称

代码

1、参数通过Map方式传递给java方法

2、在java事件中GenericValue类型的userLogin、Locale类型的locale作为属性加入到request中

3、第一个参数DispatchContext包含访问数据库、调用其他服务的工具

4、从java代码中如下访问便利的对象

GenericValue userLogin = (GenericValue)context.get("userLogin");

Locale locale = (Locale)context.get("locale");

Delegator delegator = dctx.getDelegator();



安全和访问控制

例:详细参考/applications/order/src/org/ofbiz/order/order/OrderLookupServices.java




public static Map findOrders(DispatchContext dctx, Map context) {
Security security = dctx.getSecurity();
// check security flag for purchase orders
boolean canViewPo = security.hasEntityPermission("ORDERMGR", "_PURCHASE_VIEW", userLogin);
if (!canViewPo) {
conditions.add(EntityCondition.makeCondition("orderTypeId", EntityOperator.NOT_EQUAL, "PURCHASE_ORDER"));
}
}
  




服务返回

服务必须返回一个map,这个map至少包含一个responseMessage

ModelService.RESPOND_SUCCESS

ModelService.RESPOND_ERROR

ModelService.RESPOND_FAIL





simple:使用minilang开发的服务详细使用方法参考后续的《minilang开发 学习笔记 》系列

脚本:applications/party/servicedef/services.xml






   


Create a Relationship between two Parties;
if partyIdFrom is not specified the partyId of the current userLogin will be used;
if roleTypeIds are not specified they will default to "_NA_".
If a partyIdFrom is passed in, it will be used if the userLogin has PARTYMGR_REL_CREATE permission.






  


engine: simple

location:实现文件的全路径

invoke:simple-method

























  


entity-auto服务

例:specialpurpose/example/servicedef/services.xml






   

Create a Example








  


RMI服务

例:applications/accounting/servicedef/services_rita.xml






   

RiTA Credit Card Pre-Authorization/Sale


  


engine:rmi

location:rita-rmi这个是是在serviceengine.xml中配置的





  


invoke:ritaCCAuth 服务名,该服务如下,也在applications/accounting/servicedef/services_rita.xml中






   

RiTA Credit Card Pre-Authorization/Sale


  


设置为可被远程调用 export=“true”



route 服务

这类类型不常用,路由服务使用路由引擎定义,当一个路由服务被调用时,不会执行调用,但是所有定义的ECA会在适当事件中运行。通过利用ECA服务选项可以路由(‘route‘)到其他服务



http服务

使用http服务是调用定义在其他系统上远程服务的一种方法。本地定义应该和远程定义一致,但是引擎应该是http,location应该是httpService事件在远程系统上运行的完全URL,方法应该是远程系统上被调用运行的服务名。远程系统必须有挂在HTTP服务上公允的httpService事件。默认情况下,commonapp web应用程序有用来接收服务请求的这样的事件。在远程系统上的服务必须将export属性设为true允许远程调用。HTTP服务本质就是同步的。



JMS服务

JMS服务和HTTP服务很相似,除了服务请求被发送到JMS topic/queue。engine属性应该设置为jms,location属性应该设置为在serviceengine.xml文件中定义的JMS服务名。方法应该是你请求要执行的远程系统上的JMS服务名。本质就是异步



服务组

服务组由多个服务组成的集合。

组的定义:包含一个拥有多个service元素的group元素。group元素包含name属性和mode属性

mode用来定义服务怎么执行

service:类似于ECA中的action元素,不同之处在于resutl-to-context属性的默认值不同。

例:applications/workeffort/servicedef/service_groups.xml
















  






调用服务

调用一个存在的服务是非常简单的,可以通过webtools的Service Engine Tools查看具体的服务信息

1、java:使用java方式调用服务

例:applications/content/src/org/ofbiz/content/search/SearchEvents.java






1    public static String indexTree(HttpServletRequest request, HttpServletResponse response) {
2  
3         Map result;
4         Map serviceInMap = FastMap.newInstance();
5         HttpSession session = request.getSession();
6         GenericValue userLogin = (GenericValue)session.getAttribute("userLogin");
7         serviceInMap.put("userLogin", userLogin);
8         LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
9         Map paramMap = UtilHttp.getParameterMap(request);
10         String siteId = (String)paramMap.get("contentId");
11         serviceInMap.put("contentId", siteId);
12         try {
13             result = dispatcher.runSync("indexTree", serviceInMap);
14         } catch (GenericServiceException e) {
15             String errorMsg = "Error calling the indexTree service." + e.toString();
16             Debug.logError(e, errorMsg, module);
17             request.setAttribute("_ERROR_MESSAGE_", errorMsg + e.toString());
18             return "error";
19         }
20         String errMsg = ServiceUtil.getErrorMessage(result);
21         if (Debug.infoOn()) Debug.logInfo("errMsg:" + errMsg, module);
22         if (Debug.infoOn()) Debug.logInfo("result:" + result, module);
23         if (UtilValidate.isEmpty(errMsg)) {
24             List badIndexList = UtilGenerics.checkList(result.get("badIndexList"));
25             if (Debug.infoOn()) Debug.logInfo("badIndexList:" + badIndexList, module);
26             String badIndexMsg = StringUtil.join(badIndexList, "\n") + badIndexList.size() + " entities not indexed";
27             Integer goodIndexCount = (Integer)result.get("goodIndexCount");
28             String goodIndexMsg = goodIndexCount + " entities indexed.";
29             if (Debug.infoOn()) Debug.logInfo("goodIndexCount:" + goodIndexCount, module);
30             ServiceUtil.setMessages(request, badIndexMsg, goodIndexMsg, null);
31             return "success";
32         } else {
33             ServiceUtil.setMessages(request, errMsg, null, null);
34             return "error";
35         }
36     }
  

调用服务






1         try {
2             result = dispatcher.runSync("indexTree", serviceInMap);
3         } catch (GenericServiceException e) {
4             String errorMsg = "Error calling the indexTree service." + e.toString();
5             Debug.logError(e, errorMsg, module);
6             request.setAttribute("_ERROR_MESSAGE_", errorMsg + e.toString());
7             return "error";
8         }
  


如上调用了indxTree服务,该服务在applications/content/servicedef/services.xml中被定义




   
Index content under publish point




  




2、smiple-method:使用simple-method方式调用服务



例:applications/accounting/script/org/ofbiz/accounting/payment/PaymentServices.xml


   















  


调用服务






        


  


该服务createPayment定义于applications/accounting/script/org/ofbiz/accounting/payment/PaymentServices.xml




   






















































  

异步方式调用




   








  

异步调用代码




     
  




服务中的事务申明

一个服务是否使用事务,是否必须是独立的事务,以及事务的超时时间设置,均可以在服务定义时声明,或者在通过服务引擎调用服务时指定(传入)

1、服务定义时申明事务

例:applications/order/servicedef/services.xml






   
Send a order confirmation


  


2、在服务调用时指定

java代码




dispatcher.runSync(servicename, context,transactionTimeOut,requireNewTransaction);
dispatcher.runAsync(servicename, context,requester,persist,transactionTimeOut,requireNewTransaction);
  




事务的管理规则

1、调用服务时传入的参数(是否为独立事务、事务的超时时间)的优先级高于服务定义时定义的参数

2、若服务在定义时声明了不使用事务(use-transaction="false"),那么无论是定义什么的独立事务和超市时间,还是调用服务的时候定义了独立事务和超市时间,都将不会生效

3、服务被申明为不使用事务,则所有的默认为每次操作位一个独立的事务



事务的提交规则

1、没有在服务内部显示操作事务的情况下,事务由服务引擎来管理,当服务返回error时,回滚事务;当服务返回failure或success时提交事务

2、服务间调用使用同一个事务时,内层服务返回failure或success,不提交事务,在最外层服务返回时方提交

3、服务间调用使用同一个事务时,任何一个服务返回error,事务均会回滚。

4、服务间调用使用独立事务时,一个事务回滚或提交不影响其他事务,但一个事务不能访问另一个事务尚未提交的数据

5、服务执行超时,回滚事务



服务超时

1、服务执行是否超时由服务引擎来控制,超时时间,在定义服务时指定,或调用服务的时候指定,若不指定,默认时间为60秒

2、这个超时时间为服务执行的总时间,包括服务内部执行的其他操作时间的总和

3、如果没有开启事务,则配置超时时间也不会生效。



EEAC、SEAC、MCA概念

EEAC:在实体上触发一个服务的调用

SEAC:当条件满足时,调用另外一个服务

MCA:启动javamail-container

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-93392-1-1.html 上篇帖子: 【2011.9.20】基于CXF Web Service:Apache CXF简单部署 . 下篇帖子: 用 Apache Tika 理解信息内容
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表