7.9.2 服务器端程序
因为本小节采用BPEL流程管理服务,所有与流程相关的模块都已经被BPEL取代,只剩下2个基本的服务模块。一个是HouseLoanAgency.java,另一个是Bank.java。
例程7-13显示了HouseLoanAgency.java的代码,其主要功能就在于通过请求消息得到客户姓名“name”后,通过“name”查询得到用户的房屋数量,并创建相应的返回消息;如果系统中没有该客户姓名,则返回一个错误信息,此错误信息将会被BPEL运行环境截获,并被返回给服务请求者。其中主要用到了XML技术对消息交换(Message Exchange)的请求消息进行解析。用户的房屋数量信息存在一个数组里面,实际项目中用户房屋数量信息应该存在数据库中。
例程7-13 HouseLoanAgency.java
package houseloanbroker; …省略import public class HouseLoanAgency extends ComponentSupport implements MessageExchangeListener {
//创建HouseLoanAgency服务 public HouseLoanAgency() { setService(new Qname("urn:sample:soa:houseloanagency", "HouseLoanAgencyService")); setEndpoint("houseLoanAgency"); }
//创建客户房屋数量信息 private static String[][] loanStatusList = { {"Zhang San","0"}, {"Li Si","1"}, {"Wang Wu","2"}, {"Zhao Liu","3"} };
//onMessageExchange不停地监听请求消息 Public void onMessageExchange(MessageExchange exchange) throws MessagingException { //接收到消息交换(请求—响应类型) InOut inOut = (InOut) exchange;
//如果消息交换的状态为“done”,则返回 if (inOut.getStatus() == ExchangeStatus.DONE) { return; //如果消息交换的状态为“error”,也返回 } else if (inOut.getStatus() == ExchangeStatus.ERROR) { return; } try { //将消息交换的输入信息转换为XML的document对象 Document doc = (Document) new SourceTransformer().toDOMNode(inOut.getInMessage());
//得到节点为“name”的节点值 String name = textValueOfXPath(doc, "//*[local-name()='name']");
String operation = null; if (inOut.getOperation() != null) { operation = inOut.getOperation().getLocalPart(); } else { operation = doc.getDocumentElement().getLocalName(); } String output; //如果请求消息中的操作为“getHouseNumber”,那么创建返回带有 //客户房屋数量的返回消息“output” If ("getHouseNumber".equals(operation)) { output = "<getHouseNumberResponse xmlns=\"urn:sample:soa:houseloanagency\"><housenumber>" + getHouseNumber(name) + "</housenumber> </getHouseNumberResponse>"; }else { throw new UnsupportedOperationException(operation); } //如果查询的房屋数量为-1,表示系统中没有该客户, //那么返回没有该客户的错误信息 If(getHouseNumber(name) == -1) { Fault fault = inOut.createFault(); fault.setContent(new StringSource("<InvalidNAME xmlns=\"urn:sample:soa:houseloanagency\"> <name>" +name + "</name></InvalidNAME>")); fail(inOut, fault); } else { //将正常的返回消息“output”返回给服务请求者 NormalizedMessage answer = inOut.createMessage(); answer.setContent(new StringSource(output)); answer(inOut, answer); }
} catch (Exception e) { throw new MessagingException(e); } }
//通过姓名“name”得到房屋数量 private int getHouseNumber(String name) { int houseNumber = -1; for (int I=0; I<loanStatusList.length; I++){ String[] item = loanStatusList[I]; String itemName = item[0]; int itemNum = Integer.parseInt(item[1]); if (name.equalsIgnoreCase(itemName)) { houseNumber = itemNum; break; } } return houseNumber; }
//通过xpath得到节点值 protected String textValueOfXPath(Node node, String xpath) throws TransformerException { CachedXPathAPI cachedXPathAPI = new CachedXPathAPI(); NodeIterator iterator = cachedXPathAPI.selectNodeIterator(node, xpath); Node root = iterator.nextNode(); if (root instanceof Element) { Element element = (Element) root; if (element == null) { return ""; } String text = DOMUtil.getElementText(element); return text; } else if (root != null) { return root.getNodeValue(); } else { return null; } } }
|
例程7-14显示了Bank服务的代码,它将返回贷款利率和首付比率的服务请求。比较关键之处是Bank.java继承了ServiceMix的ComponentSupport类,并实现了ServiceMix的MessageExchangeListener接口。通过onMessageExchange方法不停地监听来自NMR的消息,并将带有贷款利率和首付比率的响应消息返回给服务请求者,贷款利率和首付比率是在servicemix.xml文件中配置的。这里和7.8节的不同之处是7.8节是将贷款利率和首付比例置于消息的属性中送出,这里是直接创建带有贷款利率和首付比率的消息。
例程7-14 Bank.java
package loanbroker; import javax.jbi.messaging.ExchangeStatus; import javax.jbi.messaging.InOut; import javax.jbi.messaging.MessageExchange; import javax.jbi.messaging.MessagingException; import javax.jbi.messaging.NormalizedMessage; import javax.xml.namespace.Qname; import org.apache.servicemix.MessageExchangeListener; import org.apache.servicemix.components.util.ComponentSupport; import org.apache.servicemix.jbi.jaxp.StringSource;
public class Bank extends ComponentSupport implements MessageExchangeListener {
private double rate; private double firstPaidRatio;
//创建Bank服务 public Bank(int number) { setService(new Qname("urn:logicblaze:soa:bank", "Bank" + number)); setEndpoint("bank"); }
//监听请求消息,并将带有贷款利率和首付比率的响应消息返回给服务请求者,贷款利率 //和首付比率是在servicemix.xml文件中配置的 Public void onMessageExchange(MessageExchange exchange) throws MessagingException { InOut inOut = (InOut) exchange; if (inOut.getStatus() == ExchangeStatus.DONE) { return; } else if (inOut.getStatus() == ExchangeStatus.ERROR) { return; } System.err.println(getService().getLocalPart() + " requested"); try { String output = "<getLoanQuoteResponse xmlns=\"urn:logicblaze:soa:bank\"><rate>" + getRate() + "</rate><firstpaidratio>" + getFirstPaidRatio() + "</firstpaidratio> </getLoanQuoteResponse>"; NormalizedMessage answer = inOut.createMessage(); answer.setContent(new StringSource(output)); answer(inOut, answer); } catch (Exception e) { throw new MessagingException(e); } }
public double getFirstPaidRatio() { return firstPaidRatio; }
public void setFirstPaidRatio(double firstPaidRatio) { this.firstPaidRatio = firstPaidRatio; }
public double getRate() { return rate; }
public void setRate(double rate) { this.rate = rate; } }
|
【责任编辑:
夏书 TEL:(010)68476606】