SAP通过JCO调用Java程序配置开发

来源:互联网 发布:天刀数据加载失败:data 编辑:程序博客网 时间:2024/06/07 03:32

最近接到一任务,需求是SAP将采购请求发送给第三方EDI程序,我的任务是将第三方EDI接口封装好,然后供本公司SAP程序调用。之前都是JAVA通过JCO来调用SAP的RFC程序,这已经很熟悉了,没有任何问题。现在反过来调用,还是头一回,查阅了大量资料,终于搞定。现将研究成果与大家分享,避免大家走许多弯路。项目框架采用的是springmvc,spring初始化的时候加载该服务。

准备工作

安装JCo3
JCo有32位和64为之分,32位的JVM选择32位的JCO, 64位的JVM选择64位的JCO, 在windows环境,选择相应的sapjco3.dll, Unix和Linux环境选择合适的sapjco3.so,这里不多做介绍。如果服务器是window操作系统,见博客no sapjco3 in java.library.path,如果服务器是linux操作系统,具体安装方法见博客linux配置sapjco3。

ABAP访问Java服务

1、ABAP端

ABAP(作为Clint端),调用JAVA(作为服务器端)。
SAP通过JCO反向调用JAVA的RFC服务其实也是相对简单的,只是在JAVA端需要使用JCO创建一个RFC服务,然后在SAP端注册这个服务程序。
首先,JCo服务器程序需在网关中进行注册,在SM59中,定义一个连接类型为T的远程目标。



RFC目标系统:是ABAP RFC调用Java时,需指定的目标系统名。
Program ID:是JAVA程序中使用的。

Gateway Host与Gateway service值来自以下界面(Tcode:SMGW):



所有配置好且Java服务器代码跑起来后,点击“Connection Test”按钮,如不出现红色文本,则表示链接成功(注:此时需要ServerDataProvider.JCO_PROGID设置的Program ID要与SM59中设置的相同,否则测试不成功。另要注意的是:即使Java服务器设置的Program ID乱设置,Java服务端还是能启起来,但ABAP测试连接时会不成功,也就代表ABAP不能调用Java):



此时可以通过SMGW来观测连接:


如果出现如下异常:

连接异常registrationnot allowedJava服务启动时,如出现以下异常,则需在SAP中修改网关参数:com.sap.conn.jco.JCoException: (113) JCO_ERROR_REGISTRATION_DENIED: CPIC-CALL: SAP_CMACCPTP3 on convId:       LOCATION    SAP-Gateway on host LRP-ERP / sapgw00ERROR       registration of tp JCOTEST from host JIANGZHENGJUN not allowedTIME        Wed Apr 16 21:25:39 2014RELEASE     720COMPONENT   SAP-GatewayVERSION     2RC          720MODULE      gwxxrd.cLINE        3612COUNTER     275


代码如下:

*&---------------------------------------------------------------------**& Report  ZRMMLQ_REQUEST_OUT*&*&---------------------------------------------------------------------**&*&*&---------------------------------------------------------------------*REPORT  zrmmlq_request_out.TABLES: zmmlqpo_d,        zmmlqpo_h.DATA: requesth TYPE zslq_request_out OCCURS 0 WITH HEADER LINE,      requestd TYPE zslq_request_out_item OCCURS 0 WITH HEADER LINE.DATA: i_h LIKE zmmlqpo_h OCCURS 0 WITH HEADER LINE,      i_d LIKE zmmlqpo_d OCCURS 0 WITH HEADER LINE.DATA: message TYPE char100.DATA: v_p(6) TYPE c.DATA: v_q(6) TYPE c.DATA: v_string TYPE string.SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE text-001.SELECT-OPTIONS: s_ebeln FOR zmmlqpo_h-ebeln,                s_aedat FOR zmmlqpo_h-aedat.SELECTION-SCREEN END OF BLOCK b1.START-OF-SELECTION.  SELECT * FROM zmmlqpo_h INTO TABLE i_h    WHERE ebeln IN s_ebeln      AND aedat IN s_aedat      AND status = '02'.  IF sy-subrc EQ 0.    SELECT * FROM zmmlqpo_d INTO TABLE i_d      FOR ALL ENTRIES IN i_h      WHERE ebeln = i_h-ebeln.    LOOP AT i_h.      MOVE i_h-aedat TO requesth-porchasedate.      MOVE i_h-ebeln TO requesth-pono.      MOVE i_h-thirdparty TO requesth-thirdparty.*      request-others      requesth-signtype = 'B'.*      request-purchasecontact*      request-contactareatel*      request-contacttel**      CLEAR orderitem.**      CLEAR orderitem[].****      request-orderitem = orderitem[].      SELECT SINGLE provincecitydistrictcountystreetsegmenttunnelznum        FROM zmd_sqxx1        INTO (requesth-province,      requesth-city,      requesth-area,      requesth-village,      requesth-road,      requesth-section,      requesth-lane,      requesth-oddeven        )        WHERE zzmd_mdbm = requesth-shiptocust.      READ TABLE i_d WITH KEY ebeln = i_h-ebeln.      IF sy-subrc EQ 0.        MOVE i_d-werks TO requesth-shiptocust.      ENDIF.      APPEND requesth.      CLEAR requesth.    ENDLOOP.    LOOP AT i_d  .      MOVE i_d-ebeln TO requestd-pono.*        requestd-POCOMMENTS      MOVE i_d-ebelp TO requestd-polineno.      MOVE i_d-matnr TO requestd-stockcode.*requestd-UNITPRICE      MOVE i_d-menge TO v_string.      SPLIT v_string AT '.' INTO v_p v_q.      MOVE v_p TO requestd-orderqty.*requestd-DISCOUNT*requestd-PROMOTION      APPEND requestd.    ENDLOOP.    CALL FUNCTION 'ZFM_LQ_REQUEST_OUT' DESTINATION 'ZLQTEST'      IMPORTING        message  = message      TABLES        requesth = requesth        requestd = requestd.    IF message = 'SUCCESS'.      LOOP AT i_h.        i_h-status = '01'.        MODIFY i_h.      ENDLOOP.    ELSE.      LOOP AT i_h.        i_h-status = '00'.        MODIFY i_h.      ENDLOOP.    ENDIF.    MODIFY zmmlqpo_h FROM TABLE i_h.*    CALL FUNCTION 'ZFM_LQ_REQUEST_OUT' DESTINATION 'ZLQTEST'*      TABLES*        requesth = requesth*        requestd = requestd.  ENDIF.

对应的RFC结构如下:


程度运行结果如下:


2、JAVA端

采购单头代码如下:
package com.pcmall.domain.vo;import java.util.Date;import java.util.List;public class SapPo {private String PorchaseDate;private String PoNo;private String ThirdParty;private String ShipToCust;private String Province;private String City;private String Area;private String Village;private String Road;private String Section;private String Lane;private String Oddeven;private String Others;private String SignType;private String PurchaseContact;private String ContactAreaTel;private String ContactTel;private List<SapPod> pods;public String getPorchaseDate() {return PorchaseDate;}public void setPorchaseDate(String porchaseDate) {PorchaseDate = porchaseDate;}public String getPoNo() {return PoNo;}public void setPoNo(String poNo) {PoNo = poNo;}public String getThirdParty() {return ThirdParty;}public void setThirdParty(String thirdParty) {ThirdParty = thirdParty;}public String getShipToCust() {return ShipToCust;}public void setShipToCust(String shipToCust) {ShipToCust = shipToCust;}public String getProvince() {return Province;}public void setProvince(String province) {Province = province;}public String getCity() {return City;}public void setCity(String city) {City = city;}public String getArea() {return Area;}public void setArea(String area) {Area = area;}public String getVillage() {return Village;}public void setVillage(String village) {Village = village;}public String getRoad() {return Road;}public void setRoad(String road) {Road = road;}public String getSection() {return Section;}public void setSection(String section) {Section = section;}public String getLane() {return Lane;}public void setLane(String lane) {Lane = lane;}public String getOddeven() {return Oddeven;}public void setOddeven(String oddeven) {Oddeven = oddeven;}public String getOthers() {return Others;}public void setOthers(String others) {Others = others;}public String getSignType() {return SignType;}public void setSignType(String signType) {SignType = signType;}public String getPurchaseContact() {return PurchaseContact;}public void setPurchaseContact(String purchaseContact) {PurchaseContact = purchaseContact;}public String getContactAreaTel() {return ContactAreaTel;}public void setContactAreaTel(String contactAreaTel) {ContactAreaTel = contactAreaTel;}public String getContactTel() {return ContactTel;}public void setContactTel(String contactTel) {ContactTel = contactTel;}public List<SapPod> getPods() {return pods;}public void setPods(List<SapPod> pods) {this.pods = pods;}}
采购单行代码如下:
package com.pcmall.domain.vo;public class SapPod {private String PoComments;private String PoLineNo;private String StockCode;private String UnitPrice;private String OrderQty;private String Discount;private String Promotion;public String getPoComments() {return PoComments;}public void setPoComments(String poComments) {PoComments = poComments;}public String getPoLineNo() {return PoLineNo;}public void setPoLineNo(String poLineNo) {PoLineNo = poLineNo;}public String getStockCode() {return StockCode;}public void setStockCode(String stockCode) {StockCode = stockCode;}public String getUnitPrice() {return UnitPrice;}public void setUnitPrice(String unitPrice) {UnitPrice = unitPrice;}public String getOrderQty() {return OrderQty;}public void setOrderQty(String orderQty) {OrderQty = orderQty;}public String getDiscount() {return Discount;}public void setDiscount(String discount) {Discount = discount;}public String getPromotion() {return Promotion;}public void setPromotion(String promotion) {Promotion = promotion;}}
SAPJCO连接类代码如下:
package com.pcmall.common.sap;import java.io.File;import java.io.FileOutputStream;import java.io.InputStream;import java.util.Hashtable;import java.util.Properties;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Value;import com.sap.conn.jco.JCo;import com.sap.conn.jco.JCoDestination;import com.sap.conn.jco.JCoDestinationManager;import com.sap.conn.jco.ext.DestinationDataProvider;import com.sap.conn.jco.ext.ServerDataProvider;public class SapjcoConnector {private static Logger logger = LoggerFactory.getLogger(SapjcoConnector.class);static Hashtable<String, JCoDestination> destinations = new Hashtable<String, JCoDestination>();public static String SERVER_NAME = "SANPOWER_SERVER";public static String DESTINATION_NAME = "ABAP_AS_WITH_POOL";static {try {doInitialize();} catch (Exception e) {e.printStackTrace();}}/** * 初始化SAP连接 *  * @param fdPoolName * @return * @throws Exception */public static synchronized void doInitialize() throws Exception {JCo.setTrace(4, null);// 打开调试Properties connectProperties = new Properties();InputStream is = SapjcoConnector.class.getResourceAsStream("/properties/sap-config.properties");connectProperties.load(is);createDataFile(DESTINATION_NAME, "jcoDestination", connectProperties);// ******JCo severProperties servertProperties = new Properties();InputStream isServer = SapjcoConnector.class.getResourceAsStream("/properties/sap-config-server.properties");servertProperties.load(isServer);/*servertProperties.setProperty(ServerDataProvider.JCO_GWHOST,"xxx.xxx.xxx.xxx");// TCP服务sapgw是固定的,后面的00就是SAP实例系统编号,也可直接是端口号(端口号可以在// etc/server文件中找sapgw00所对应的端口号)servertProperties.setProperty(ServerDataProvider.JCO_GWSERV, "sapgw30");// 这里的程序ID来自于SM59中设置的Program ID,必须相同servertProperties.setProperty(ServerDataProvider.JCO_PROGID, "JCO_SANPOWER_LQ");servertProperties.setProperty(ServerDataProvider.JCO_REP_DEST,DESTINATION_NAME);servertProperties.setProperty(ServerDataProvider.JCO_CONNECTION_COUNT,"2");*/createDataFile(SERVER_NAME, "jcoServer", servertProperties);}/** * 创建连接文件(必须) *  * @param name * @param suffix * @param properties */private static void createDataFile(String name, String suffix,Properties properties) {File cfg = new File(name + "." + suffix);if (cfg.exists()) {cfg.deleteOnExit();}try {FileOutputStream fos = new FileOutputStream(cfg, false);properties.store(fos, "for connection");fos.close();logger.info("createDataFile: " + name + "." + suffix);} catch (Exception e) {throw new RuntimeException("Unable to create the destination file "+ cfg.getName(), e);}}/** * 获取连接池,利用JCoDestinationManager创建连接池放到表中 *  * @param fdPoolName * @return * @throws Exception */public static JCoDestination getDestination(String fdPoolName)throws Exception {JCoDestination destination = null;if (destinations.containsKey(fdPoolName)) {destination = destinations.get(fdPoolName);} else {destination = JCoDestinationManager.getDestination(fdPoolName);destinations.put(fdPoolName, destination);}return destination;}}


Service层代码如下:
package com.pcmall.service.sap.impl;import java.io.ByteArrayOutputStream;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List;import javax.annotation.PostConstruct;import org.dom4j.Document;import org.dom4j.DocumentHelper;import org.dom4j.Element;import org.dom4j.io.OutputFormat;import org.dom4j.io.XMLWriter;import org.springframework.stereotype.Service;import com.pcmall.common.sap.SapConnector;import com.pcmall.common.sap.SapjcoConnector;import com.pcmall.common.utils.XmlConverUtil;import com.pcmall.domain.vo.ResponseVO;import com.pcmall.domain.vo.SapPo;import com.pcmall.domain.vo.SapPod;import com.pcmall.domain.vo.SapPurchaseAttachDetailVO;import com.pcmall.domain.vo.SapPurchaseAttachVO;import com.pcmall.service.sap.ISapService;import com.pcmall.service.sap.impl.SapRfc.StfcConnectionHandler;import com.sap.conn.jco.JCo;import com.sap.conn.jco.JCoCustomRepository;import com.sap.conn.jco.JCoDestination;import com.sap.conn.jco.JCoDestinationManager;import com.sap.conn.jco.JCoException;import com.sap.conn.jco.JCoFunction;import com.sap.conn.jco.JCoFunctionTemplate;import com.sap.conn.jco.JCoListMetaData;import com.sap.conn.jco.JCoMetaData;import com.sap.conn.jco.JCoParameterList;import com.sap.conn.jco.JCoRecord;import com.sap.conn.jco.JCoRepository;import com.sap.conn.jco.JCoTable;import com.sap.conn.jco.server.DefaultServerHandlerFactory;import com.sap.conn.jco.server.JCoServer;import com.sap.conn.jco.server.JCoServerContext;import com.sap.conn.jco.server.JCoServerContextInfo;import com.sap.conn.jco.server.JCoServerErrorListener;import com.sap.conn.jco.server.JCoServerExceptionListener;import com.sap.conn.jco.server.JCoServerFactory;import com.sap.conn.jco.server.JCoServerFunctionHandler;import com.sap.conn.jco.server.JCoServerState;import com.sap.conn.jco.server.JCoServerStateChangedListener;@Servicepublic class SapServiceImpl implements ISapService {@Overridepublic ResponseVO submitPurchaseAttach(SapPurchaseAttachVO attach)throws Exception {ResponseVO responseVO = new ResponseVO();String sParam[] = null;JCoDestination foo = SapConnector.getDestination(SapConnector.fdPoolName);JCoRepository mRepository = foo.getRepository();JCoFunctionTemplate ft = mRepository.getFunctionTemplate("ZFMHK_ORDER");JCoFunction function = ft.getFunction();JCoParameterList input = function.getImportParameterList();// 设置输入参数// 设置输入参数JCoTable tableDataH = function.getTableParameterList().getTable("I_ZTHK0001H");tableDataH.appendRow();tableDataH.setValue("MANDT", attach.getMANDT());tableDataH.setValue("ZERPNO", attach.getZERPNO());tableDataH.setValue("ZTYPE", attach.getZTYPE());tableDataH.setValue("BUKRS_F", attach.getBUKRS_F());tableDataH.setValue("KOSTL_F", attach.getKOSTL_F());tableDataH.setValue("PRCTR_F", attach.getPRCTR_F());tableDataH.setValue("PRCTR_F", attach.getPRCTR_F());tableDataH.setValue("ZFROMNO", attach.getZFROMNO());tableDataH.setValue("BUKRS_T", attach.getBUKRS_T());tableDataH.setValue("KOSTL_T", attach.getKOSTL_T());tableDataH.setValue("PRCTR_T", attach.getPRCTR_T());tableDataH.setValue("ZTONO", attach.getZTONO());tableDataH.setValue("ZSTATUS", attach.getZSTATUS());tableDataH.setValue("EKORG", attach.getEKORG());tableDataH.setValue("LIFNR", attach.getLIFNR());tableDataH.setValue("LIFNR_TXT", attach.getLIFNR_TXT());tableDataH.setValue("ZBEIZHU", attach.getZBEIZHU());tableDataH.setValue("BUDAT", attach.getBUDAT());tableDataH.setValue("ZOUTIN", attach.getZOUTIN());tableDataH.setValue("BELNR1", attach.getBELNR1());tableDataH.setValue("BELNR2", attach.getBELNR2());tableDataH.setValue("ERDAT", attach.getERDAT());tableDataH.setValue("ZCRE_DATE", attach.getZCRE_DATE());tableDataH.setValue("ZCRE_TIME", attach.getZCRE_TIME());tableDataH.setValue("ZCRE_USER", attach.getZCRE_USER());tableDataH.setValue("ZUP_DATE", attach.getZUP_DATE());tableDataH.setValue("ZUP_TIME", attach.getZUP_TIME());tableDataH.setValue("ZUP_USER", attach.getZUP_USER());tableDataH.setValue("NETWR2", attach.getNETWR2());JCoTable tableData = function.getTableParameterList().getTable("I_ZTHK0001D");for (SapPurchaseAttachDetailVO detail : attach.getDetails()) {tableData.appendRow();tableData.setValue("MANDT", detail.getMANDT());tableData.setValue("ZERPNO", detail.getZERPNO());tableData.setValue("POSNUM", detail.getPOSNUM());tableData.setValue("MATNR", detail.getMATNR());tableData.setValue("MAKTX", detail.getMAKTX());tableData.setValue("MENGE", detail.getMENGE());tableData.setValue("NETPR", detail.getNETPR());tableData.setValue("NETWR", detail.getNETWR());// tableData.setValue("NETWR2",detail.getNETWR2());tableData.setValue("MWSBP", detail.getMWSBP());tableData.setValue("ZOUTIN", detail.getZOUTIN());}// 执行functionfunction.execute(foo);// 得到输出参数TABLE// JCoTable tableExport =// function.getTableParameterList().getTable("RETURN");String result = function.getExportParameterList().getString("RETCODE");String message = function.getExportParameterList().getString("RETMSG");if (result.equals("E")) {responseVO.setSuccess(false);responseVO.setErrorMsg(message);} else {responseVO.setSuccess(true);}return responseVO;}@Overridepublic ResponseVO submitPo2Lq() {// TODO Auto-generated method stubreturn null;}// 在Java服务端定义远程函数(不需要在ABAP端进行函数的签名定义)@PostConstructstatic void startPo2LqRfc() {/* * JCoListMetaData impList = JCo.createListMetaData("IMPORT"); * impList.add("REQUTEXT", JCoMetaData.TYPE_CHAR, 100, 50, 0, null, * null, JCoListMetaData.IMPORT_PARAMETER, null, null); * impList.lock();// 锁住,不允许再修改 */JCoListMetaData expList = JCo.createListMetaData("EXPORT");expList.add("MESSAGE", JCoMetaData.TYPE_CHAR, 100, 50, 0, null, null,JCoListMetaData.EXPORT_PARAMETER, null, null);expList.lock();JCoListMetaData tblList = JCo.createListMetaData("TABLE");tblList.add("REQUESTH", JCoMetaData.TYPE_TABLE, 1000, 500, 0, null, null,JCoListMetaData.OPTIONAL_PARAMETER, "ZSLQ_REQUEST_OUT", null);tblList.add("REQUESTD", JCoMetaData.TYPE_TABLE, 1000, 500, 0, null, null,JCoListMetaData.OPTIONAL_PARAMETER, "ZSLQ_REQUEST_OUT_ITEM", null);tblList.lock();// 注:ZSTFC_CONNECTION函数不必要在ABAP端时行定义了(只定义签名,不需要实现),因为在这里(Java)// 进行了动态的函数对象创建的创建与注册,这与上面simpleServer方法示例是不一样的JCoFunctionTemplate fT = JCo.createFunctionTemplate("ZFM_LQ_REQUEST_OUT",null, expList, null, tblList, null);JCoCustomRepository cR = JCo.createCustomRepository("MyCustomRepository");cR.addFunctionTemplateToCache(fT);JCoServer server;try {server = JCoServerFactory.getServer(SapjcoConnector.SERVER_NAME);} catch (JCoException ex) {throw new RuntimeException("Unable to create the server "+ SapjcoConnector.SERVER_NAME + " because of "+ ex.getMessage(), ex);}String repDest = server.getRepositoryDestination();if (repDest != null) {try {cR.setDestination(JCoDestinationManager.getDestination(repDest));} catch (JCoException e) {e.printStackTrace();System.out.println(">>> repository contains static function definition only");}}server.setRepository(cR);JCoServerFunctionHandler requestHandler = new StfcConnectionHandler();DefaultServerHandlerFactory.FunctionHandlerFactory factory = new DefaultServerHandlerFactory.FunctionHandlerFactory();factory.registerHandler(fT.getName(), requestHandler);server.setCallHandlerFactory(factory);server.start();}// 处理来自ABAP端的调用请求,实现注册过的虚拟函数真正功能static class StfcConnectionHandler implements JCoServerFunctionHandler {public void handleRequest(JCoServerContext serverCtx,JCoFunction function) {// 处理远程调用请求printServerInfo(serverCtx, function);JCoTable poTable = function.getTableParameterList().getTable("REQUESTH");JCoTable podTable = function.getTableParameterList().getTable("REQUESTD");List<SapPo> listPo = new ArrayList<SapPo>();for(int i=0;i<poTable.getNumRows();i++){poTable.setRow(i);SapPo po = new SapPo();SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");Date date = null;try {date = formatter.parse(poTable.getString("PORCHASEDATE"));} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();}String dateString = formatter.format(date);po.setPorchaseDate(dateString);po.setPoNo(poTable.getString("PONO"));po.setThirdParty(poTable.getString("THIRDPARTY"));po.setShipToCust(poTable.getString("SHIPTOCUST"));po.setProvince(poTable.getString("PROVINCE"));po.setCity(poTable.getString("CITY"));po.setArea(poTable.getString("AREA"));po.setVillage(poTable.getString("VILLAGE"));po.setRoad(poTable.getString("ROAD"));po.setSection(poTable.getString("SECTION"));po.setLane(poTable.getString("LANE"));po.setOddeven(poTable.getString("ODDEVEN"));po.setOthers(poTable.getString("OTHERS"));po.setSignType(poTable.getString("SIGNTYPE"));po.setPurchaseContact(poTable.getString("PURCHASECONTACT"));po.setContactAreaTel(poTable.getString("CONTACTAREATEL"));po.setContactTel(poTable.getString("CONTACTTEL"));List<SapPod> listPod = new ArrayList<SapPod>();for(int j=0;j<podTable.getNumRows();j++){podTable.setRow(j);if(podTable.getString("PONO").equals(poTable.getString("PONO"))){SapPod pod = new SapPod();pod.setPoComments(podTable.getString("POCOMMENTS"));pod.setPoLineNo(podTable.getString("POLINENO"));pod.setStockCode(podTable.getString("STOCKCODE"));pod.setUnitPrice(podTable.getString("UNITPRICE"));pod.setOrderQty(podTable.getString("ORDERQTY"));pod.setDiscount(podTable.getString("DISCOUNT"));pod.setPromotion(podTable.getString("PROMOTION"));listPod.add(pod);}}po.setPods(listPod);listPo.add(po);}try {System.out.println(listtoXml(listPo));} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}function.getExportParameterList().setValue("MESSAGE", "SUCCESS");}public void printServerInfo(JCoServerContext serverCtx,JCoFunction function) {System.out.println("----------------------------------------------------------------");System.out.println("call              : " + function.getName());// ABAP调用的是哪个函数System.out.println("ConnectionId      : "+ serverCtx.getConnectionID());System.out.println("SessionId         : "+ serverCtx.getSessionID());System.out.println("TID               : " + serverCtx.getTID());System.out.println("repository name   : "+ serverCtx.getRepository().getName());System.out.println("is in transaction : "+ serverCtx.isInTransaction());System.out.println("is stateful       : "+ serverCtx.isStatefulSession());System.out.println("----------------------------------------------------------------");System.out.println("gwhost: "+ serverCtx.getServer().getGatewayHost());System.out.println("gwserv: "+ serverCtx.getServer().getGatewayService());System.out.println("progid: "+ serverCtx.getServer().getProgramID());System.out.println("----------------------------------------------------------------");System.out.println("attributes  : ");System.out.println(serverCtx.getConnectionAttributes().toString());System.out.println("----------------------------------------------------------------");System.out.println("CPIC conversation ID: "+ serverCtx.getConnectionAttributes().getCPICConversationID());System.out.println("----------------------------------------------------------------");}}static class MyThrowableListener implements JCoServerErrorListener,JCoServerExceptionListener {// 服务异常监听器public void serverErrorOccurred(JCoServer jcoServer,String connectionId, JCoServerContextInfo serverCtx, Error error) {System.out.println(">>> Error occured on "+ jcoServer.getProgramID() + " connection " + connectionId);error.printStackTrace();}public void serverExceptionOccurred(JCoServer jcoServer,String connectionId, JCoServerContextInfo serverCtx,Exception error) {System.out.println(">>> Error occured on "+ jcoServer.getProgramID() + " connection " + connectionId);error.printStackTrace();}}static class MyStateChangedListener implementsJCoServerStateChangedListener {// 服务状态改变监听器public void serverStateChangeOccurred(JCoServer server,JCoServerState oldState, JCoServerState newState) {// Defined states are: STARTED启动, DEAD死, ALIVE活, STOPPED停止;// see JCoServerState class for details.// Details for connections managed by a server instance// are available via JCoServerMonitor.System.out.println("Server state changed from "+ oldState.toString() + " to " + newState.toString()+ " on server with program id " + server.getProgramID());}}/** *  * @param document * @return */public static String doc2String(Document document) {String s = "";try {// 使用输出流来进行转化ByteArrayOutputStream out = new ByteArrayOutputStream();// 使用UTF-8编码OutputFormat format = new OutputFormat("   ", true, "UTF-8");XMLWriter writer = new XMLWriter(out, format);writer.write(document);s = out.toString("UTF-8");} catch (Exception ex) {ex.printStackTrace();}return s;}public static String listtoXml(List<SapPo> listSapPo) throws Exception{//创建文档及设置根元素节点的方式          Element root = DocumentHelper.createElement("PurchaseOrdersRequest");          Document document = DocumentHelper.createDocument(root);                  Element baseID = root.addElement("BaseID").addText("10321");        Element purchaseOrderList = root.addElement("PurchaseOrderList");                for(SapPo po : listSapPo){        Element purchaseOrder = purchaseOrderList.addElement("PurchaseOrder");        Element porchaseDate = purchaseOrder.addElement("PorchaseDate").addText(po.getPorchaseDate());        Element poNo = purchaseOrder.addElement("PoNo").addText(po.getPoNo());        Element thirdParty = purchaseOrder.addElement("ThirdParty").addText(po.getThirdParty());        Element shipToCust = purchaseOrder.addElement("shipToCust").addText(po.getShipToCust());        Element province = purchaseOrder.addElement("Province").addText(po.getProvince());        Element city = purchaseOrder.addElement("City").addText(po.getCity());        Element area = purchaseOrder.addElement("Area").addText(po.getArea());        Element village = purchaseOrder.addElement("Village").addText(po.getVillage());        Element road = purchaseOrder.addElement("Road").addText(po.getRoad());        Element section = purchaseOrder.addElement("Section").addText(po.getSection());        Element lane = purchaseOrder.addElement("Lane").addText(po.getLane());        Element oddeven = purchaseOrder.addElement("Oddeven").addText(po.getOddeven());        Element others = purchaseOrder.addElement("Others").addText(po.getOthers());        Element signType = purchaseOrder.addElement("SignType").addText(po.getSignType());        Element purchaseContact = purchaseOrder.addElement("PurchaseContact").addText(po.getPurchaseContact());        Element contactAreaTel = purchaseOrder.addElement("contactAreaTel").addText(po.getContactAreaTel());        Element contactTel = purchaseOrder.addElement("contactTel").addText(po.getContactTel());                Element orderItemList = purchaseOrder.addElement("OrderItemList");        for(SapPod pod : po.getPods()){        Element orderItem = orderItemList.addElement("OrderItem");        Element poComments = orderItem.addElement("PoComments").addText(pod.getPoComments());        Element poLineNo = orderItem.addElement("PoLineNo").addText(pod.getPoLineNo());        Element stockCode = orderItem.addElement("StockCode").addText(pod.getStockCode());        Element unitPrice = orderItem.addElement("UnitPrice").addText(pod.getUnitPrice());        Element orderQty = orderItem.addElement("OrderQty").addText(pod.getOrderQty());        Element discount = orderItem.addElement("Discount").addText(pod.getDiscount());        Element promotion = orderItem.addElement("Promotion").addText(pod.getPromotion());        }        }                String strXml = doc2String(document);        return strXml;}}

3、ABAP端调用

ABAP端调用后,JAVA根据采购单列表进行拼接XML,生成的XML文件如下,供第三方EDI做为入参。
<?xml version="1.0" encoding="utf-8"?><PurchaseOrdersRequest>   <BaseID>10321</BaseID>    <PurchaseOrderList>     <PurchaseOrder>       <PorchaseDate>2017-04-17</PorchaseDate>        <PoNo>4500004860</PoNo>        <ThirdParty>N</ThirdParty>        <shipToCust/>        <Province/>        <City/>        <Area/>        <Village/>        <Road/>        <Section/>        <Lane/>        <Oddeven/>        <Others/>        <SignType>B</SignType>        <PurchaseContact/>        <contactAreaTel/>        <contactTel/>        <OrderItemList/>     </PurchaseOrder>      <PurchaseOrder>       <PorchaseDate>2017-05-03</PorchaseDate>        <PoNo>4500004863</PoNo>        <ThirdParty>N</ThirdParty>        <shipToCust>D000</shipToCust>        <Province/>        <City/>        <Area/>        <Village/>        <Road/>        <Section/>        <Lane/>        <Oddeven/>        <Others/>        <SignType>B</SignType>        <PurchaseContact/>        <contactAreaTel/>        <contactTel/>        <OrderItemList>         <OrderItem>           <PoComments/>            <PoLineNo>00001</PoLineNo>            <StockCode>000000000000106261</StockCode>            <UnitPrice/>            <OrderQty>10</OrderQty>            <Discount/>            <Promotion/>         </OrderItem>       </OrderItemList>     </PurchaseOrder>      <PurchaseOrder>       <PorchaseDate>2017-05-03</PorchaseDate>        <PoNo>4500004864</PoNo>        <ThirdParty>N</ThirdParty>        <shipToCust>D000</shipToCust>        <Province/>        <City/>        <Area/>        <Village/>        <Road/>        <Section/>        <Lane/>        <Oddeven/>        <Others/>        <SignType>B</SignType>        <PurchaseContact/>        <contactAreaTel/>        <contactTel/>        <OrderItemList>         <OrderItem>           <PoComments/>            <PoLineNo>00001</PoLineNo>            <StockCode>000000000000106261</StockCode>            <UnitPrice/>            <OrderQty>10</OrderQty>            <Discount/>            <Promotion/>         </OrderItem>          <OrderItem>           <PoComments/>            <PoLineNo>00002</PoLineNo>            <StockCode>000000000000106262</StockCode>            <UnitPrice/>            <OrderQty>2</OrderQty>            <Discount/>            <Promotion/>         </OrderItem>       </OrderItemList>     </PurchaseOrder>   </PurchaseOrderList> </PurchaseOrdersRequest>

4、常见问题

开发完毕之后,我就将程序发布到Linux测试服务器上,结果SAP端通过SMGW是可以连接的,但是通过SM59测试连接,死活连接不通。一直报如下错误:

后来想是不是Linux服务器问题啊,我们领导就让我在Windows服务器上再部署试一下,结果还是不行,不过它报错了,一直报"sapgw30 service unknow...",后来一想我机器上是安装了SAP客户端,目录“C:\Windows\System32\drivers\etc"下的services文件中有sapgw30服务,这样我们在services文件中加入sapgw30服务,就可以了。
同理,我们在Linux服务器上/etc/services也添加sapgw30服务,
sapgw30  3330/tcp
这下就能成功连接了。

注:
/etc/services文件包含了服务名和端口号之间的映射,很多的系统程序要使用这个文件。一般情况下,不要修改该文件的内容,因为这些设置都是Internet标准的设置。一旦修改,可能会造成系统冲突,使用户无法正常访问资源。Linux系统的端口号的范围为0–65535,不同范围有不同的意义。
0 不使用
1--1023 系统保留,只能由root用户使用
1024---4999 由客户端程序自由分配
5000---65535 由服务器端程序自由分配

至此大功告成!


1 0