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

17 篇文章 4 订阅
14 篇文章 16 订阅

最近接到一任务,需求是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 allowed
Java服务启动时,如出现以下异常,则需在SAP中修改网关参数:
com.sap.conn.jco.JCoException: (113) JCO_ERROR_REGISTRATION_DENIED: CPIC-CALL: SAP_CMACCPTP3 on convId:       
LOCATION    SAP-Gateway on host LRP-ERP / sapgw00
ERROR       registration of tp JCOTEST from host JIANGZHENGJUN not allowed
TIME        Wed Apr 16 21:25:39 2014
RELEASE     720
COMPONENT   SAP-Gateway
VERSION     2
RC          720
MODULE      gwxxrd.c
LINE        3612
COUNTER     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 province
city
district
county
street
segment
tunnel
znum
        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 sever
		Properties 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;

@Service
public class SapServiceImpl implements ISapService {

	@Override
	public 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());
		}

		// 执行function
		function.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;
	}

	@Override
	public ResponseVO submitPo2Lq() {
		// TODO Auto-generated method stub
		return null;
	}

	// 在Java服务端定义远程函数(不需要在ABAP端进行函数的签名定义)
	@PostConstruct
	static 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 block
					e.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 block
				e.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 implements
			JCoServerStateChangedListener {// 服务状态改变监听器
		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 由服务器端程序自由分配

至此大功告成!


  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值