ITPUB论坛-中国最专业的IT技术社区

 
 注册
热搜:
查看: 1231|回复: 1

[原创] C# 搭建NCO RFC SERVER SAP调用外部函数 增JCO代码

[复制链接]
认证徽章
论坛徽章:
4
优秀写手
日期:2013-12-18 09:29:132014年新春福章
日期:2014-02-18 16:42:02马上有房
日期:2014-02-18 16:42:02沸羊羊
日期:2015-04-28 23:44:36
跳转到指定楼层
1#
发表于 2017-8-11 18:07 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hyd85716 于 2017-8-12 20:16 编辑

和往常一样,代码放上面,拿走不谢:
C# 项目源码: SAPNCOSERVER.rar (1.04 MB, 下载次数: 12)
说明:
    NCO介绍:/thread-1919608-1-1.html
    RFC_SERVER是使用NCO搭建的RFC SERVER 是SAP连接外围系统的方式之一.
    类似于调用webservice的方式,只不过对于ABAPER来说更友好,更顺畅.
整体运行方式如下:
SAP创建RFC  ==> RFC SERVER继承并重写RFC内部逻辑 ==> SAP可以通过SM59配置的连接调用RFC SERVER的逻辑


一.安装NCO 3.0 (我使用的32位)
/thread-1919608-1-1.html 下载 安装.
安装过程,下一步到最后.
二.创建项目
创建过程:
  1.新建WINFORM项目

  2.更改项目为.NET 4.0



  3.更改后,出现app.config文件

三.APP.config (我的项目是4.0)
要点说明:
  1.PROGRAM_ID 必须大写
  2.不要漏掉.NET 4.0 的配置结点
  1. <startup>
  2. <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  3. </startup>
  4. <startup useLegacyV2RuntimeActivationPolicy="true">
  5. <supportedRuntime version="v4.0"/>
  6. </startup>
  7. </configuration>
复制代码
3.服务端配置结点说明:
    NAME 配置字符串唯一标识;
    GWHOST 服务器HOST名称,需要在HOSTS文件做响应配置
    GWSERV 服务端口:SAPGW+系统标识号(SYSNR)
    PROGRAM_ID:在SM59上要填写,是服务的名称,此处必须大写
    REPOSITORY_DESTINATION:对应客户端登录信息的NAME


完整代码项目会已附件形式上传,不在这里贴文件)
  1. <?xml version="1.0"?>
  2. <configuration>
  3.   <configSections>
  4.     <sectionGroup name="SAP.Middleware.Connector">
  5.       <sectionGroup name="ClientSettings">
  6.         <section name="DestinationConfiguration" type="SAP.Middleware.Connector.RfcDestinationConfiguration,sapnco"/>
  7.       </sectionGroup>
  8.       <sectionGroup name="ServerSettings">
  9.         <section name="ServerConfiguration" type="SAP.Middleware.Connector.RfcServerConfiguration, sapnco"/>
  10.       </sectionGroup>
  11.     </sectionGroup>
  12.   </configSections>
  13.   <SAP.Middleware.Connector>
  14.     <ClientSettings>
  15.       <DestinationConfiguration>
  16.         <destinations>
  17.           <add NAME="125" USER="huyadong" PASSWD="231432" CLIENT="125" SYSNR="00" ASHOST="172.16.11.41" LANG="EN"   MAX_POOL_SIZE="5" ></add>
  18.           <add NAME="105" USER="huyd" PASSWD="123121" CLIENT="105" SYSNR="01" ASHOST="192.168.11.33" LANG="EN"   MAX_POOL_SIZE="5"></add>
  19.           <!--SAPROUTER="/H/221.234.25.27/W/DEV/H/"  GROUP="PUBLIC"-->
  20.         </destinations>
  21.       </DestinationConfiguration>
  22.     </ClientSettings>

  23.     <ServerSettings>
  24.       <ServerConfiguration>
  25.         <servers>
  26.           <add NAME="NCO_Server1" GWHOST="saptest.xinyf.com" GWSERV="sapgw01" PROGRAM_ID="NCOHYD" REPOSITORY_DESTINATION="105" REG_COUNT="1"/>
  27.           <add NAME="NCO_Server2" GWHOST="jteccdev.hisense.com" GWSERV="sapgw00" PROGRAM_ID="NCOHYD" REPOSITORY_DESTINATION="125" REG_COUNT="1"/>
  28.         </servers>
  29.       </ServerConfiguration>
  30.     </ServerSettings>
  31.   </SAP.Middleware.Connector>
  32.   <startup>
  33.     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  34.   </startup>
  35.   <startup useLegacyV2RuntimeActivationPolicy="true">
  36.     <supportedRuntime version="v4.0"/>
  37.   </startup>
  38. </configuration>

复制代码
四.引用:sapnco.dll sapnco_utils.dll
  默认路径:C:\Program Files (x86)\SAP\SAP_DotNetConnector3\



五.添加代码
SapncoClient.cs
SapncoServer.cs
SapncoTidHandler.cs
SAPServerHandler.cs
添加举例:
  1.添加类文件

  2.指定类名称

  3.覆盖代码

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using SAP.Middleware.Connector;

  6. public class SapncoClient
  7. {
  8.     private RfcDestination _rfcDestination = null;

  9.     /// <summary>
  10.     /// Register Client
  11.     /// </summary>
  12.     public void RegisterRfcDestination()
  13.     {
  14.         try
  15.         {
  16.             if (_rfcDestination == null)
  17.                 _rfcDestination = RfcDestinationManager.GetDestination("105"); //获取 config配置中DEV节点参数,并注册RfcClient
  18.         }
  19.         catch (Exception ex)
  20.         {
  21.             throw ex;
  22.         }
  23.     }
  24. }
复制代码
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using SAP.Middleware.Connector;

  6. public class SapncoServer
  7. {
  8.     private RfcServer _rfcServer = null;

  9.     public void RegisterRfcServer()
  10.     {
  11.         try
  12.         {
  13.             Type[] handlers = new Type[1] { typeof(SAPServerHandler) };
  14.             if (_rfcServer == null)
  15.             {
  16.                 _rfcServer = RfcServerManager.GetServer("NCO_Server1", handlers); //获取 config配置中NCO_Server节点参数,并注册RfcServer
  17.             }
  18.             _rfcServer.RfcServerError += OnRfcServerError;
  19.             _rfcServer.RfcServerApplicationError += OnRfcServerError;
  20.             _rfcServer.TransactionIDHandler = new SapncoTidHandler();
  21.             //SAPServerHandler.IDocEndReceiveCompleteEvent += new SAPServerHandler.IDocReceiveEventHandler(SAPServerHandler_IDocEndReceiveCompleteEvent);
  22.             SAPServerHandler.IDocEndReceiveCompleteEvent += new SAPServerHandler.IDocReceiveEventHandler(SAPServerHandler_IDocEndReceiveCompleteEvent);
  23.             if (_rfcServer.Monitor.State != RfcServerState.Running)
  24.             {
  25.                 _rfcServer.Start();
  26.             }
  27.             //_rfcServer.Shutdown(true);
  28.         }
  29.         catch (Exception ex)
  30.         {
  31.             throw ex;
  32.         }
  33.     }

  34.     public void StopServer()
  35.     {
  36.         try
  37.         {
  38.             if (_rfcServer.Monitor.State == RfcServerState.Running)
  39.             {
  40.                 _rfcServer.Shutdown(true);
  41.             }
  42.         }
  43.         catch (Exception ex)
  44.         {
  45.             throw ex;
  46.         }
  47.     }
  48.      
  49.     //函数调用执行完成
  50.     private void SAPServerHandler_IDocEndReceiveCompleteEvent(Dictionary<string, List<string>> diclist)
  51.     {
  52.         //处理 diclist
  53.         //根据IDOC各个字段长度,从SDATA字符串中截取对应的字段值
  54.     }

  55.     private static void OnRfcServerError(Object server, RfcServerErrorEventArgs errorEventData)
  56.     {
  57.         string exMsg = String.Empty;
  58.         RfcServer rfcServer = server as RfcServer;
  59.         RfcServerApplicationException appEx = errorEventData.Error as RfcServerApplicationException;
  60.         if (appEx != null)
  61.             exMsg += string.Format("RfcServerApplicationError occured in RFC server {0} :", rfcServer.Name);
  62.         else
  63.             exMsg += string.Format("RfcServerError occured in RFC server {0} :", rfcServer.Name);
  64.         if (errorEventData.ServerContextInfo != null)
  65.         {
  66.             exMsg += string.Format("RFC Caller System ID: {0} ", errorEventData.ServerContextInfo.SystemAttributes.SystemID);
  67.             exMsg += string.Format("RFC function Name: {0} ", errorEventData.ServerContextInfo.FunctionName);
  68.         }
  69.         exMsg += string.Format("Error type: {0}", errorEventData.Error.GetType().Name);
  70.         exMsg += string.Format("Error message: {0}", errorEventData.Error.Message);
  71.         if (appEx != null)
  72.         {
  73.             exMsg += string.Format("Inner exception type: {0}", appEx.InnerException.GetType().Name);
  74.             exMsg += string.Format("Inner exception message: {0}", appEx.InnerException.Message);
  75.         }
  76.         Exception ex = new Exception(exMsg);
  77.         throw ex;
  78.     }
  79. }
复制代码
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using SAP.Middleware.Connector;

  6. public class SapncoTidHandler : ITransactionIDHandler
  7. {
  8.     //ONLY for tests. Use a database to store the TID state!
  9.     static List<string> tids = new List<string>();

  10.     //If DB is down, throw an exception at this point. .Net Connector will then abort
  11.     //the tRFC and the R/3 backend will try again later.
  12.     public bool CheckTransactionID(RfcServerContextInfo serverContext, RfcTID tid)
  13.     {
  14.         //TextBox.Text += ("Check transaction ID " + tid);
  15.         lock (tids)
  16.         {
  17.             if (tids.Contains(tid.TID))
  18.                 return false;
  19.             else
  20.             {
  21.                 tids.Add(tid.TID);
  22.                 return true;
  23.             }
  24.         }
  25.         // "true" means that NCo will now execute the transaction, "false" means
  26.         // that we have already executed this transaction previously, so NCo will
  27.         // skip the function execution step and will immediately return an OK code to R/3.
  28.     }

  29.     // clean up the resources
  30.     public void ConfirmTransactionID(RfcServerContextInfo serverContext, RfcTID tid)
  31.     {
  32.         //TextBox.Text += ("Confirm transaction ID " + tid);
  33.         try
  34.         {
  35.             //clean up the resources
  36.             //partner won't react on an exception at this point
  37.         }
  38.         finally
  39.         {
  40.             lock (tids)
  41.             {
  42.                 tids.Remove(tid.TID);
  43.             }
  44.         }
  45.     }

  46.     // react on commit e.g. commit on the database
  47.     // if necessary throw an exception, if the commit was not possible
  48.     public void Commit(RfcServerContextInfo serverContext, RfcTID tid)
  49.     {
  50.         //TextBox.Text += ("Commit transaction ID " + tid);
  51.         lock (tids)
  52.         {
  53.             if (!tids.Contains(tid.TID))
  54.                 throw new Exception("tid " + tid.TID + " doesn't exist, hence it cannot be committed");

  55.         }
  56.     }

  57.     // react on rollback e.g. rollback on the database
  58.     public void Rollback(RfcServerContextInfo serverContext, RfcTID tid)
  59.     {
  60.         //TextBox.Text += ("Rollback transaction ID " + tid);
  61.         /* Make sure the TID is removed from the list, otherwise CheckTransactionID will
  62.          * return false the next time the backend retries this failed transaction, and then
  63.          * it will never be executed...
  64.          */
  65.         tids.Remove(tid.TID);
  66.     }
  67. }
复制代码
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using SAP.Middleware.Connector;

  6. public class SAPServerHandler
  7. {
  8.     public delegate void IDocReceiveEventHandler(Dictionary<string, List<string>> diclist);
  9.     public static event IDocReceiveEventHandler IDocEndReceiveCompleteEvent;
  10.     //public static event IDocReceiveEventHandler IDocBeginReceiveCompleteEvent;

  11.     /// <summary>
  12.     /// Call back handler method,invoked by RFC Server.
  13.     /// </summary>
  14.     /// <param name="context">RfcServerContext</param>
  15.     /// <param name="function">Rfc Function passed by Rfc Server manager</param>
  16.     [RfcServerFunction(Name = "IDOC_INBOUND_ASYNCHRONOUS", Default = false)]
  17.     public static void IDOC_INBOUND_ASYNCHRONOUS(RfcServerContext context, IRfcFunction function)
  18.     {
  19.         Dictionary<string, List<string>> diclist = new Dictionary<string, List<string>>();
  20.         string docnum = String.Empty;

  21.         IRfcTable RfcTb = function.GetTable("IDOC_CONTROL_REC_40"); //获取 EDI_DC40 结构
  22.         foreach (IRfcStructure rfcControlRecord in RfcTb)
  23.         {
  24.             docnum = rfcControlRecord.GetValue("DOCNUM").ToString(); //从 EDI_DC40 结构中获取 DOCNUM 字段值
  25.         }


  26.         IRfcTable RfcDtTable = function.GetTable("IDOC_DATA_REC_40"); //获取 EDI_DD40 结构
  27.         List<string> list = new List<string>();
  28.         foreach (IRfcStructure rfcDataRecord in RfcDtTable)
  29.         {
  30.             string sdataStr = rfcDataRecord.GetValue("SDATA").ToString(); //获取IDOC_DATA_REC_40 结构中SDATA字段值(IDOC值)
  31.             list.Add(sdataStr);
  32.         }
  33.         diclist.Add(docnum, list);
  34.         if (IDocEndReceiveCompleteEvent != null)
  35.             IDocEndReceiveCompleteEvent(diclist);
  36.     }

  37.     [RfcServerFunction(Name = "STFC_CONNECTION", Default = false)]
  38.     public static void StfcConnection(RfcServerContext context, IRfcFunction function)
  39.     {
  40.         function.SetValue("ECHOTEXT", "HYD ECHOTEXT");
  41.         function.SetValue("RESPTEXT", "HYD RESPTEXT");
  42.     }


  43.     [RfcServerFunction(Name = "ZHYD_NCOTEST", Default = false)]
  44.     public static void ZHYD_NCOTEST(RfcServerContext context, IRfcFunction function)
  45.     {
  46.         string matnr = function.GetValue("MATNR").ToString();
  47.         function.SetValue("OMATNR", "HYD" + matnr);

  48.     }


  49.     #region 含IDOC 的RfcTable结构
  50.     //function.GetTable(0)   
  51.     //{TABLE  [STRUCTURE EDI_DC40 { FIELD TABNAM=EDI_DC40 FIELD MANDT=777 FIELD DOCNUM=0000000009241610 FIELD DOCREL=700 FIELD STATUS=30 FIELD DIRECT=1 FIELD OUTMOD=2 FIELD EXPRSS= FIELD TEST= FIELD IDOCTYP=ZTZECODE_IDOC FIELD CIMTYP= FIELD MESTYP=ZECODE_MSG FIELD MESCOD= FIELD MESFCT= FIELD STD= FIELD STDVRS= FIELD STDMES= FIELD SNDPOR=SAPASB FIELD SNDPRT=LS FIELD SNDPFC= FIELD SNDPRN=AZASB01777 FIELD SNDSAD= FIELD SNDLAD= FIELD RCVPOR=A000000017 FIELD RCVPRT=LS FIELD RCVPFC= FIELD RCVPRN=CN_ECODING FIELD RCVSAD= FIELD RCVLAD= FIELD CREDAT=2013-06-18 FIELD CRETIM=10:35:40 FIELD REFINT= FIELD REFGRP= FIELD REFMES= FIELD ARCKEY= FIELD SERIAL=20130618103540 }]}    SAP.Middleware.Connector.IRfcTable {SAP.Middleware.Connector.RfcTable}
  52.     //function.GetTable(1)   
  53.     //{TABLE  [STRUCTURE EDI_DD40 { FIELD SEGNAM=ZTZECODE000 FIELD MANDT=777 FIELD DOCNUM=0000000009241610 FIELD SEGNUM=000001 FIELD PSGNUM=000000 FIELD HLEVEL=02 FIELD SDATA=0003575897008500006600000010251                   CNIT00006 9000001001                              10010     2              1 }]}
  54.     //SAP.Middleware.Connector.IRfcTable {SAP.Middleware.Connector.RfcTable}
  55.     #endregion

  56. }
复制代码

六.启动服务
要点说明:
  1.登陆信息一定要正确
  1. <add NAME="105" USER="huyd" PASSWD="123121" CLIENT="105" SYSNR="01" ASHOST="192.168.11.33" LANG="EN" MAX_POOL_SIZE="5"></add>
  2. <add NAME="NCO_Server1" GWHOST="saptest.xinyf.com" GWSERV="sapgw01" PROGRAM_ID="NCOHYD" REPOSITORY_DESTINATION="105" REG_COUNT="1"/>
复制代码
2.REPOSITORY_DESTINATION 要与上面的NAME相同
  3.PROGRAM_ID="NCOHYD" 的内容必须大写
操作步骤:
  1.窗口加个按钮,在按钮事件中加入如下代码
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;

  9. namespace WindowsFormsApplication2
  10. {
  11.     public partial class Form1 : Form
  12.     {
  13.         public Form1()
  14.         {
  15.             InitializeComponent();
  16.         }

  17.         private void button1_Click(object sender, EventArgs e)
  18.         {
  19.              SapncoClient client = new SapncoClient();
  20.             SapncoServer server = new SapncoServer();
  21.             client.RegisterRfcDestination();
  22.             server.RegisterRfcServer();
复制代码
  2.启动项目,点击按钮,如果登陆信息输入无问题,则按钮将变为"启动二字"

七.配置SM59
  1.配置C:\Windows\System32\drivers\etc\hosts 文件
    192.168.11.33 saptest.xinxx.com saptest
  2.登陆SAP 输入事务代码SM59.光标定位在TCP/IP上点击创建

  3.输入名称 描述 程序ID ,注:程序ID 为APP.config里面配置的值,必须大写

  4.输入网关信息 服务器名称和端口(sapgw01  sapgw+系统标识)

  5.保存
  6.这里点测试,如果是新系统的话,一般不会成功,应为需要对网管进行注册.
    老系统有人搞过的话,会在网关配置
  1. P TP=*
复制代码
   这种全通过的配置
八.SMGW 注册网关
  1.输入事务代码smgw

  2.R3 ,ECC,S4 版本不一样... R3的我没找到配置的地方

  3.切换到Reginfo 页签

  4.创建新的记录

  5.选中我们配置的SM59,点击保存

  6.继续保存

  7.保存后生成的记录不可用,还需要继续修改为:
  1. P TP=NCOHYD HOST=* CANCEL=* ACCESS=*
复制代码

  8.测试SM59



到此,我们可以随便玩了


九.创建一个空的RFC函数


7.项目中继承,并重载

  1.     [RfcServerFunction(Name = "STFC_CONNECTION", Default = false)]
  2.     public static void StfcConnection(RfcServerContext context, IRfcFunction function)
  3.     {
  4.         function.SetValue("ECHOTEXT", "HYD ECHOTEXT");
  5.         function.SetValue("RESPTEXT", "HYD RESPTEXT");
  6.     }
复制代码
这里就可以随意发挥了
比如,写表.
比如,创建外围系统单据.
比如,备份数据库等你想干的

十.测试
  1.输入目标系统(SM59 创建的名称) 及传入参数 点击执行

  2.等待执行结果


  3.ABAP调用代码
  1. FUNCTION zhyd_ncotest.
  2. *"----------------------------------------------------------------------
  3. *"*"本地接口:
  4. *"  IMPORTING
  5. *"     VALUE(MATNR) TYPE  MATNR OPTIONAL
  6. *"  EXPORTING
  7. *"     VALUE(OMATNR) TYPE  MATNR
  8. *"  TABLES
  9. *"      TMARA STRUCTURE  MARA
  10. *"----------------------------------------------------------------------
  11.   CALL FUNCTION 'ZHYD_NCOTEST' DESTINATION 'A'
  12.       EXPORTING
  13.             matnr  = matnr
复制代码


JCO的代码
  1. package com.savor.sms.cmn.service.jcoServer;

  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import java.util.Date;
  5. import java.util.HashMap;
  6. import java.util.Hashtable;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.Properties;

  10. import org.springframework.stereotype.Service;

  11. import com.sap.conn.jco.JCoException;
  12. import com.sap.conn.jco.JCoFunction;
  13. import com.sap.conn.jco.JCoParameterList;
  14. import com.sap.conn.jco.JCoStructure;
  15. import com.sap.conn.jco.ext.DestinationDataProvider;
  16. import com.sap.conn.jco.ext.ServerDataProvider;
  17. import com.sap.conn.jco.server.JCoServer;
  18. import com.sap.conn.jco.server.JCoServerContext;
  19. import com.sap.conn.jco.server.JCoServerContextInfo;
  20. import com.sap.conn.jco.server.JCoServerErrorListener;
  21. import com.sap.conn.jco.server.JCoServerExceptionListener;
  22. import com.sap.conn.jco.server.JCoServerFactory;
  23. import com.sap.conn.jco.server.JCoServerFunctionHandler;
  24. import com.sap.conn.jco.server.JCoServerFunctionHandlerFactory;
  25. import com.sap.conn.jco.server.JCoServerState;
  26. import com.sap.conn.jco.server.JCoServerStateChangedListener;
  27. import com.sap.conn.jco.server.JCoServerTIDHandler;
  28. import com.savor.core.util.SpringBeanUtil;
  29. import com.savor.sms.cmn.model.gen.tranNotice.TranNotice;
  30. import com.savor.sms.cmn.model.jcoServer.DbBackLog;
  31. import com.savor.sms.cmn.sap.RfcOutputInfo;
  32. import com.savor.sms.cmn.service.tranNotice.TranNoticeService;
  33. import com.savor.sms.cmn.util.SapUtil;

  34. @Service
  35. public class RfcJcoServerService {
  36.        
  37.         //private static Logger log = LoggerFactory.getLogger(RfcJcoServerService.class);
  38.        
  39.         static String SERVER_NAME1 = "SERVER";
  40.         static String DESTINATION_NAME1 = "ABAP_AS_WITHOUT_POOL";
  41.         static String DESTINATION_NAME2 = "ABAP_AS_WITH_POOL";
  42.         static MyTIDHandler myTIDHandler = null;
  43.         static {
  44.                 Properties connectProperties = new Properties();
  45.                 connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST,"192.168.11.32");
  46.                 connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "01");
  47.                 connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "105");
  48.                 connectProperties.setProperty(DestinationDataProvider.JCO_USER, "LIUS");
  49.                 connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD,"6511121");
  50.                 connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ZH");
  51.                 createDataFile(DESTINATION_NAME1, "jcoDestination", connectProperties);
  52.                 connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3");
  53.                 connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT,"10");
  54.                 createDataFile(DESTINATION_NAME2, "jcoDestination", connectProperties);
  55.                 Properties servertProperties = new Properties();
  56.                 servertProperties.setProperty(ServerDataProvider.JCO_GWHOST,"192.168.11.32");
  57.                 servertProperties.setProperty(ServerDataProvider.JCO_GWSERV, "3301");//sapgw01或者端口号,有的地方sapgw01不好使,换成端口试试
  58.                 servertProperties.setProperty(ServerDataProvider.JCO_PROGID, "JCO_SMS");//必须大写
  59.                 servertProperties.setProperty(ServerDataProvider.JCO_REP_DEST,"ABAP_AS_WITH_POOL");
  60.                 servertProperties.setProperty(ServerDataProvider.JCO_CONNECTION_COUNT,"2");
  61.                 createDataFile(SERVER_NAME1, "jcoServer", servertProperties);
  62.         }

  63.         static void createDataFile(String name, String suffix, Properties properties) {
  64.                 File cfg = new File(name + "." + suffix);
  65.                 if (!cfg.exists()) {
  66.                         try {
  67.                                 FileOutputStream fos = new FileOutputStream(cfg, false);
  68.                                 properties.store(fos, "for tests only !");
  69.                                 fos.close();
  70.                         } catch (Exception e) {
  71.                                 throw new RuntimeException(
  72.                                                 "Unable to create the destination file "
  73.                                                                 + cfg.getName(), e);
  74.                         }
  75.                 }else{
  76.                         cfg.delete();
  77.                         try {
  78.                                 FileOutputStream fos = new FileOutputStream(cfg, false);
  79.                                 properties.store(fos, "for tests only !");
  80.                                 fos.close();
  81.                         } catch (Exception e) {
  82.                                 throw new RuntimeException(
  83.                                                 "Unable to create the destination file "
  84.                                                                 + cfg.getName(), e);
  85.                         }
  86.                 }
  87.         }

  88. /*        static void step1SimpleServer() {
  89.                 JCoServer server;
  90.                 try {
  91.                         server = JCoServerFactory.getServer(SERVER_NAME1);
  92.                 } catch (JCoException ex) {
  93.                         throw new RuntimeException("Unable to create the server "
  94.                                         + SERVER_NAME1 + ", because of " + ex.getMessage(), ex);
  95.                 }
  96.                 JCoServerFunctionHandler stfcConnectionHandler = new StfcConnectionHandler();
  97.                 DefaultServerHandlerFactory.FunctionHandlerFactory factory = new DefaultServerHandlerFactory.FunctionHandlerFactory();
  98.                 factory.registerHandler("ZSTFC_MATERIAL_LIST", stfcConnectionHandler);
  99.                 server.setCallHandlerFactory(factory);
  100.                 server.start();
  101.                 System.out.println("The program can be stoped using <ctrl>+<c>");
  102.         }*/

  103.         /*        static void step3SimpleTRfcServer() {
  104.         JCoServer server;
  105.         try {
  106.                 server = JCoServerFactory.getServer(SERVER_NAME1);
  107.         } catch (JCoException ex) {
  108.                 throw new RuntimeException("Unable to create the server "
  109.                                 + SERVER_NAME1 + ", because of " + ex.getMessage(), ex);
  110.         }
  111.         JCoServerFunctionHandler stfcConnectionHandler = new StfcConnectionHandler();
  112.         DefaultServerHandlerFactory.FunctionHandlerFactory factory = new DefaultServerHandlerFactory.FunctionHandlerFactory();
  113.         factory.registerHandler("ZSTFC_MATERIAL_LIST", stfcConnectionHandler);
  114.         server.setCallHandlerFactory(factory);
  115.         // additionally to step 1
  116.         myTIDHandler = new MyTIDHandler();
  117.         server.setTIDHandler(myTIDHandler);
  118.         server.start();
  119.         System.out.println("The program can be stoped using <ctrl>+<c>");
  120. }*/
  121.        
  122.         static class MyThrowableListener implements JCoServerErrorListener,
  123.                         JCoServerExceptionListener {
  124.                 public void serverErrorOccurred(JCoServer jcoServer,
  125.                                 String connectionId, JCoServerContextInfo serverCtx, Error error) {
  126.                         System.out.println(">>> Error occured on "
  127.                                         + jcoServer.getProgramID() + " connection " + connectionId);
  128.                         error.printStackTrace();
  129.                 }

  130.                 public void serverExceptionOccurred(JCoServer jcoServer,
  131.                                 String connectionId, JCoServerContextInfo serverCtx,
  132.                                 Exception error) {
  133.                         System.out.println(">>> Error occured on "
  134.                                         + jcoServer.getProgramID() + " connection " + connectionId);
  135.                         error.printStackTrace();
  136.                 }
  137.         }

  138.         static class MyStateChangedListener implements
  139.                         JCoServerStateChangedListener {
  140.                 public void serverStateChangeOccurred(JCoServer server,
  141.                                 JCoServerState oldState, JCoServerState newState) {
  142.                         // Defined states are: STARTED, DEAD, ALIVE, STOPPED;
  143.                         // see JCoServerState class for details.
  144.                         // Details for connections managed by a server instance
  145.                         // are available via JCoServerMonitor
  146.                         System.out.println("Server state changed from "
  147.                                         + oldState.toString() + " to " + newState.toString()
  148.                                         + " on server with program id " + server.getProgramID());
  149.                 }
  150.         }

  151.         static class MyTIDHandler implements JCoServerTIDHandler {
  152.                 Map<String, TIDState> availableTIDs = new Hashtable<String, TIDState>();

  153.                 public boolean checkTID(JCoServerContext serverCtx, String tid) {
  154.                         // This example uses a Hashtable to store status information. But
  155.                         // usually
  156.                         // you would use a database. If the DB is down, throw a
  157.                         // RuntimeException at
  158.                         // this point. JCo will then abort the tRFC and the R/3 backend will
  159.                         // try
  160.                         // again later.
  161.                         System.out.println("TID Handler: checkTID for " + tid);
  162.                         TIDState state = availableTIDs.get(tid);
  163.                         if (state == null) {
  164.                                 availableTIDs.put(tid, TIDState.CREATED);
  165.                                 return true;
  166.                         }
  167.                         if (state == TIDState.CREATED || state == TIDState.ROLLED_BACK)
  168.                                 return true;
  169.                         return false;
  170.                         // ��true�� means that JCo will now execute the transaction, ��false��
  171.                         // means
  172.                         // that we have already executed this transaction previously, so JCo
  173.                         // will
  174.                         // skip the handleRequest() step and will immediately return an OK
  175.                         // code to R/3.
  176.                 }

  177.                 public void commit(JCoServerContext serverCtx, String tid) {
  178.                         System.out.println("TID Handler: commit for " + tid);
  179.                         // react on commit e.g. commit on the database
  180.                         // if necessary throw a RuntimeException, if the commit was not
  181.                         // possible
  182.                         availableTIDs.put(tid, TIDState.COMMITTED);
  183.                 }

  184.                 public void rollback(JCoServerContext serverCtx, String tid) {
  185.                         System.out.println("TID Handler: rollback for " + tid);
  186.                         availableTIDs.put(tid, TIDState.ROLLED_BACK);
  187.                         // react on rollback e.g. rollback on the database
  188.                 }

  189.                 public void confirmTID(JCoServerContext serverCtx, String tid) {
  190.                         System.out.println("TID Handler: confirmTID for " + tid);
  191.                         try {
  192.                                 // clean up the resources
  193.                         }
  194.                         // catch(Throwable t) {} //partner wont react on an exception at
  195.                         // this point
  196.                         finally {
  197.                                 availableTIDs.remove(tid);
  198.                         }
  199.                 }

  200.                 public void execute(JCoServerContext serverCtx) {
  201.                         String tid = serverCtx.getTID();
  202.                         if (tid != null) {
  203.                                 System.out.println("TID Handler: execute for " + tid);
  204.                                 availableTIDs.put(tid, TIDState.EXECUTED);
  205.                         }
  206.                 }

  207.                 private enum TIDState {
  208.                         CREATED, EXECUTED, COMMITTED, ROLLED_BACK, CONFIRMED;
  209.                 }
  210.         }
  211.        
  212.         //地磅过磅移库,交货单创建,交货过账SAP回传
  213.         static class DbDnHandler extends StatefulFunctionModule {
  214.                
  215.                
  216.                 public void handleRequest(JCoServerContext serverCtx,JCoFunction function) {
  217.                         System.out.println(new Date()+"*****************SAP回传地磅信息 start*******************");
  218.                         //地磅号
  219.                         String dbNo = function.getImportParameterList().getString("IM_DBNO");
  220.                         //销售订单号
  221.                         String salesOrderNo = function.getImportParameterList().getString("IM_VBELV");
  222.                        
  223.                         //接口信息 结构
  224.                         JCoStructure message = function.getImportParameterList().getStructure("IM_RETURN");
  225.                         //SAP状态
  226.                         String status = (String) message.getValue("RTYPE");
  227.                         //SAP返回信息 S成功F失败
  228.                         String msg = (String) message.getValue("RTMSG");
  229.                         //物料凭证编号
  230.                         String materialsNo = (String) message.getValue("MBLNR");
  231.                         //物料凭证年度
  232.                         //String materialsYear = (String) message.getValue("MJAHR");
  233.                         //SAP交货单号
  234.                         String sapDnCode = (String) message.getValue("VBELN");
  235.                        
  236.                         //封装SMS中需要的数据
  237.                         TranNotice tranNotice = new TranNotice();
  238.                         tranNotice.setSapCode(salesOrderNo);
  239.                         tranNotice.setDbNo(dbNo);
  240.                         tranNotice.setSapDnCode(sapDnCode);
  241.                         tranNotice.setSapDnMsg(msg);
  242.                         tranNotice.setSapDnStatus(status);
  243.                         tranNotice.setMaterialsNo(materialsNo);
  244.                        
  245.                         JCoParameterList tableOut = function.getTableParameterList();
  246.                         RfcOutputInfo output = new RfcOutputInfo();
  247.                         Map<Class<?>, List<?>> resultMap = new HashMap<Class<?>, List<?>>();
  248.                         resultMap.put(DbBackLog.class, null);
  249.                         output.setBeans(resultMap);
  250.                        
  251.                         try {
  252.                                 SapUtil.setBeans(tableOut,resultMap,false);
  253.                         } catch (Exception e) {
  254.                                 e.printStackTrace();
  255.                         }
  256.                        
  257.                         @SuppressWarnings("unchecked")
  258.                         List<DbBackLog> logList = (List<DbBackLog>) output.getBeans().get(DbBackLog.class);
  259.                        
  260.                         //处理具体业务逻辑
  261.                         TranNoticeService tranNoticeService = (TranNoticeService) SpringBeanUtil.getBean(TranNoticeService.class);
  262.                         tranNoticeService.updateDbBack(tranNotice, logList);
  263.                        
  264.                         // In sample 3 (tRFC Server) we also set the status to executed:
  265.                         if (myTIDHandler != null)
  266.                                 myTIDHandler.execute(serverCtx);
  267.                          System.out.println(new Date()+"*****************SAP回传地磅信息 end*******************");
  268.                 }
  269.         }
  270.        
  271.         static class StfcConnectionHandler2 extends StatefulFunctionModule {
  272.                 public void handleRequest(JCoServerContext serverCtx,JCoFunction function) {
  273.                         System.out.println(new Date()+"*****************ZTEST002 start*******************");
  274.                         String str1 = function.getImportParameterList().getString("MATNR");
  275.                         String str2 = function.getImportParameterList().getString("MENGE");
  276.                        
  277.                         System.out.println(str1+"--"+str2);
  278.                        
  279.                         //function.getExportParameterList().setValue("TEXT", "Success");

  280.                         // In sample 3 (tRFC Server) we also set the status to executed:
  281.                         if (myTIDHandler != null)
  282.                                 myTIDHandler.execute(serverCtx);
  283.                         System.out.println(new Date()+"*****************ZTEST002 start*******************");
  284.                 }
  285.         }
  286.        
  287.         static abstract class StatefulFunctionModule implements JCoServerFunctionHandler {
  288.                 Hashtable<String, Object> sessionData;

  289.                 public void setSessionData(Hashtable<String, Object> sessionData) {
  290.                         this.sessionData = sessionData;
  291.                 }
  292.         }
  293.        
  294.         static class MyFunctionHandlerFactory implements JCoServerFunctionHandlerFactory {
  295.                 // 会话上下文,其实就是每一个ABAP端都有这样一个全局对象,同一ABAP客户端共享着同一个这个的会话上下文对象
  296.                 class SessionContext {
  297.                         // 用于存储(缓存)会话中的数据
  298.                         Hashtable<String, Object> cachedSessionData = new Hashtable<String, Object>();
  299.                         // 其他会话数据......
  300.                 }

  301.                 // 每个任务单元LUW都有自己的会话上下文,Key为任务会话ID(比如同时多个ABAP客户端调用当前同一Java服务端时,
  302.                 // 会产会多个任务会话,而且每次调用时,同一ABAP客户端所传递过来的会话ID是同一个)
  303.                 private Map<String, SessionContext> statefulSessions = new Hashtable<String, SessionContext>();
  304.                
  305.                 //地磅过磅移库,交货单创建,交货过账SAP回传
  306.                 JCoServerFunctionHandler dbDnHandler = new DbDnHandler();
  307.                 //测试
  308.                 JCoServerFunctionHandler stfcConnectionHandler2 = new StfcConnectionHandler2();

  309.                 public JCoServerFunctionHandler getCallHandler(JCoServerContext serverCtx, String functionName) {
  310.                         JCoServerFunctionHandler handler = null;
  311.                         if ("ZSDI_TH_TYPE".equals(functionName)) {//地磅过磅移库,交货单创建,交货过账SAP回传
  312.                                 handler = dbDnHandler;
  313.                         }else if("ZTEST002".equals(functionName)){
  314.                                 handler = stfcConnectionHandler2;
  315.                         }
  316.                         if (handler instanceof StatefulFunctionModule) {
  317.                                 SessionContext cachedSession;
  318.                                 // 如果是某任务LUW中第一次调用时,则serverCtx服务上下文为非状态,需设置为状态调用
  319.                                 if (!serverCtx.isStatefulSession()) {
  320.                                         // 设置为状态调用,这样在有状态调用的情况下,上下文中会携带会话ID
  321.                                         serverCtx.setStateful(true);
  322.                                         cachedSession = new SessionContext();// 新建会话
  323.                                         // 将会话存储在映射表中,以便某个任务里每次远程调用都可以拿到同一会话
  324.                                         statefulSessions.put(serverCtx.getSessionID(), cachedSession);
  325.                                 } else {// 非第一次调用
  326.                                         cachedSession = statefulSessions.get(serverCtx.getSessionID());
  327.                                         if (cachedSession == null)
  328.                                                 throw new RuntimeException("Unable to find the session context for session id " + serverCtx.getSessionID());
  329.                                 }
  330.                                 // 为远程函数处理器设置会话
  331.                                 ((StatefulFunctionModule) handler).setSessionData(cachedSession.cachedSessionData);
  332.                                 return handler;
  333.                         }
  334.                         // null leads to a system failure on the ABAP side
  335.                         return null;
  336.                 }
  337.                
  338.                 //SAP关闭程序允许在程序触发这个方法
  339.                 public void sessionClosed(JCoServerContext serverCtx, String message, boolean error) {
  340.                         System.out.println(
  341.                                         "Session " + serverCtx.getSessionID() + " was closed " + (error ? message : "by SAP system"));
  342.                         statefulSessions.remove(serverCtx.getSessionID());
  343.                 }
  344.         }
  345.        
  346.         static void step2SimpleServer() {
  347.                 JCoServer server;
  348.                 try {
  349.                         server = JCoServerFactory.getServer(SERVER_NAME1);
  350.                 } catch (JCoException ex) {
  351.                         throw new RuntimeException("Unable to create the server "
  352.                                         + SERVER_NAME1 + ", because of " + ex.getMessage(), ex);
  353.                 }
  354.                 /*JCoServerFunctionHandler stfcConnectionHandler = new StfcConnectionHandler();
  355.                 JCoServerFunctionHandler stfcConnectionHandler2 = new StfcConnectionHandler2();
  356.                 DefaultServerHandlerFactory.FunctionHandlerFactory factory = new DefaultServerHandlerFactory.FunctionHandlerFactory();
  357.                 factory.registerHandler("ZTEST003", stfcConnectionHandler);
  358.                 factory.registerHandler("ZTEST002", stfcConnectionHandler2);*/
  359.                
  360.                 MyFunctionHandlerFactory factory = new MyFunctionHandlerFactory();
  361.                
  362.                 server.setCallHandlerFactory(factory);
  363.                 // additionally to step 1
  364.                 MyThrowableListener eListener = new MyThrowableListener();
  365.                 server.addServerErrorListener(eListener);
  366.                 server.addServerExceptionListener(eListener);
  367.                 MyStateChangedListener slistener = new MyStateChangedListener();
  368.                 server.addServerStateChangedListener(slistener);
  369.                 server.start();
  370.                 System.out.println("The program can be stoped using <ctrl>+<c>");
  371.         }
  372.    
  373.         //创建listener,在启动时初始化此方法
  374.         public void startServer(){
  375.                 step2SimpleServer();
  376.         }
  377. }
复制代码


28.png (39.01 KB, 下载次数: 3)

28.png

27.png (17.96 KB, 下载次数: 3)

27.png
认证徽章
论坛徽章:
0
2#
发表于 2017-11-7 21:03 | 只看该作者
剛好有相關的技術,參考一下樓主的寫法

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档 |
  | | |
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 网站律师 隐私政策 知识产权声明
 北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表