SAP接口編程 之 JCo3.0系列(04) : 會話管理

SAP接口編程之 NCo3.0系列(06) : 會話管理 這篇文章中根盒,對會話管理的相關(guān)知識點已經(jīng)說得很詳細(xì)了阳懂,請參考×罂現(xiàn)在用JCo3.0來實現(xiàn)音婶。

1. JCoContext

如果SAP中多個函數(shù)需要在一個session中運行,需要JCoContext來提供保證倒谷。如果在同一個線程中蛛蒙,大體模式這樣:

JCoContext.begin(sapDestination);

fm1.execute(sapDestination);
fm2.execute(sapDestination);

JCoContext.end(destination);

begin()和end()之間的函數(shù)execute之后,SAP不會釋放連接渤愁,確保同一個session之中牵祟。

第二種情況:如果不同的函數(shù)不在同一個線程中,需要由開發(fā)人員實現(xiàn)SessionReferenceProvider接口抖格,在類中提供session id诺苹。邏輯跟nco3.0也是一樣的。JCo3.0提供了一個示例代碼雹拄,但是搞的太復(fù)雜收奔,我弄了一個簡單的,方便理解滓玖。

2. SAP函數(shù)

我們要使用的函數(shù)是從標(biāo)準(zhǔn)系統(tǒng)函數(shù)INCREMENT_COUNTER
坪哄,GET_COUNTER拷貝而來的。在SAP系統(tǒng)中INCREMENT_COUNTER
势篡,GET_COUNTER在同一個function group中翩肌,共享一個變量count(計數(shù)器),每次運行INCREMENT_COUNTER
, count就會加一禁悠,GET_COUNTER函數(shù)
可以獲得這個count念祭。因為這兩個函數(shù)不能被遠(yuǎn)程調(diào)用,所以我們將這兩個函數(shù)拷貝出另外兩個函數(shù)ZINCREMENT_COUNTER和ZGET_COUNTER绷蹲。

3. 同一線程中執(zhí)行函數(shù)

首先我們把兩個函數(shù)定義在一個類RfcFunctions中:

package jco3.demo6;

import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.JCoFunction;

public class RfcFunctions
{
    public static int runGetCounter(JCoDestination dest) throws JCoException
    {
        JCoFunction counterFM = dest.getRepository().getFunction("ZGET_COUNTER");
        counterFM.execute(dest);
        int counter = (int) counterFM.getExportParameterList().getValue("GET_VALUE");
        
        return counter;     
    }
    
    public static void runIncrement(JCoDestination dest) throws JCoException
    {
        JCoFunction increment = dest.getRepository().getFunction("ZINCREMENT_COUNTER");
        increment.execute(dest);        
    }
}

然后編寫測試類進(jìn)行測試:

package jco3.demo6;

import com.sap.conn.jco.JCoContext;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;

public class TestSessionSameThread
{
    public static void main(String[] args) throws JCoException, InterruptedException
    {       
        // get JCoDestination object instance
        JCoDestination destination = JCoDestinationManager.getDestination("ECC");
        
        // make sure the two functions will be executed in the same session
        JCoContext.begin(destination);
        
        // Before increment
        System.out.println("Before execution of ZINCREMENT_COUNTER:");
        System.out.println("Counter:" + RfcFunctions.runGetCounter(destination));
        
        // Run incrementCounter five times
        for(int i = 0; i < 5; i++){
            RfcFunctions.runIncrement(destination);
            System.out.println("Add:" + (i + 1));
        }
        
        // After increment  
        System.out.println("After execution of ZINCREMENT_COUNTER:");
        System.out.println("Counter:" + RfcFunctions.runGetCounter(destination));   
        
        // release the connection 
        JCoContext.end(destination);
    }
}

代碼很直觀棒卷,就不多說了顾孽。函數(shù)執(zhí)行前祝钢,counter的值為0比规,運行函數(shù)5次之后,counter的值為5拦英。如果我們注釋掉JCoContext.begin(destination);JCoContext.end(destination);蜒什,可以對比出不同的效果。

4. 不同線程中執(zhí)行函數(shù)

如果在不同的線程中執(zhí)行不同的函數(shù)疤估,需要開發(fā)者提供session id灾常。我準(zhǔn)備將兩個函數(shù)放在不同的線程中:

  • 在JVM的主線程中調(diào)用ZGET_COUNTER,查看counter的結(jié)果铃拇。
  • 在另外一個線程中運行ZINCREMENT_COUNTER钞瀑,兩個線程通過JCoContext,保持在同一個session ID下慷荔。

4.1 實現(xiàn)JCoSessionReference接口

JCoSessionRefence實現(xiàn)類的主要作用是提供session ID:

package jco3.session;

import java.util.concurrent.atomic.AtomicInteger;
import com.sap.conn.jco.ext.JCoSessionReference;

public class JCoSessionRefenceImpl implements JCoSessionReference
{
    private AtomicInteger atomInt = new AtomicInteger(0);
    private String id = "session"+String.valueOf(atomInt.addAndGet(1));
    
    public void contextFinished()
    {       
    }

    public void contextStarted()
    {   
    }

    @Override
    public String getID()
    {
        /**
         * We need to override getID() method
         */
        
        return id;
    }
}

4.2 實現(xiàn)SessionReferenceProvider接口

SessionReferenceProvider接口的實現(xiàn)類中雕什,改寫getCurrentSessionReference()方法,獲取上面定義的JCoSessionRefence显晶,從而獲得session ID贷岸。其他方法保持不動。

package jco3.session;

import com.sap.conn.jco.ext.JCoSessionReference;
import com.sap.conn.jco.ext.SessionException;
import com.sap.conn.jco.ext.SessionReferenceProvider;

public class SessionReferencProviderImpl implements SessionReferenceProvider
{

    @Override
    public JCoSessionReference getCurrentSessionReference(String scopeType)
    {
        /**
         *  We need to override getCurrentSessionReference() method
         */
        
        JCoSessionRefenceImpl sessionRef = new JCoSessionRefenceImpl();
        return sessionRef;
    }

    @Override
    public boolean isSessionAlive(String sessionID)
    {
        return false;
    }

    public void jcoServerSessionContinued(String sessionID) throws SessionException
    {       
    }

    public void jcoServerSessionFinished(String sessionID)
    {       
    }

    public void jcoServerSessionPassivated(String sessionID) throws SessionException
    {       
    }

    public JCoSessionReference jcoServerSessionStarted() throws SessionException
    {
        return null;
    }
}

4.3 注冊 SessionReferenceProvider接口

注冊SessionReferenceProvider接口的實現(xiàn)類磷雇,這樣JCoDestination就有狀態(tài)管理功能了偿警。

package jco3.session;

import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.ext.Environment;
import com.sap.conn.jco.ext.SessionReferenceProvider;

public class DestinationProvider
{
    public static JCoDestination getDestination() throws JCoException
    {
        // create an instance of SessionReferenceProvider
        // and register in environment
        SessionReferenceProvider provider = new SessionReferencProviderImpl();
        Environment.registerSessionReferenceProvider(provider);
        
        JCoDestination destination = JCoDestinationManager.getDestination("ECC");
        
        return destination;
    }
}

4.4 在單獨線程中執(zhí)行ZINCREMENT_COUNTER

定義WorkingThread, 從Thread類繼承,在這個線程中執(zhí)行函數(shù)ZINCREMENT_COUNTER 5次唯笙。

package jco3.demo6;

import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;

public class WorkingThread extends Thread
{
    private boolean doneSignal;
    private JCoDestination destination;
    
    // constructor
    public WorkingThread(JCoDestination destination, boolean doneSignal)
    {
        this.destination = destination;
        this.doneSignal = doneSignal;
    }
    
    public boolean hasDone()
    {
        return doneSignal;
    }
    
    @Override
    public void run()
    {
        /**
         * run method of runIncrement() for five times
         */
        
        for (int i = 0; i < 5; i++){
            try {
                RfcFunctions.runIncrement(this.destination);    
                System.out.println("Run " + (i+1) + " times.");
            } catch (JCoException e) {              
                e.printStackTrace();
            }
        }
        
        this.doneSignal = true;
    }   
}

doneSignal用于標(biāo)識該線程是否結(jié)束螟蒸。線程本身結(jié)束,是run()方法運行完畢崩掘。

4.5 測試多線程函數(shù)調(diào)用

好了尿庐,最后來測試在多線程中函數(shù)調(diào)用:

package jco3.demo6;

import com.sap.conn.jco.JCoContext;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;
import jco3.session.DestinationProvider;

public class TestSAPSessionMultiThread
{   
    public static void main(String[] args) throws JCoException, InterruptedException
    {
        /**
         * Run ZINCREMENT_COUNTER & ZGET_COUNTER functions in
         * different threads in a stateful way.
         * 
         * The SAP will keep a session id which was created in
         * JCoSessionReferenceImpl class 
         * and used in SessionReferenceProviderImpl class.
         * 
         * Before using, SessionReferenceProviderImpl class should be
         * registered using Environment.registerSessionReferenceProvider() method.
         */
        
        // get JCoDestination object instance
        JCoDestination destination = DestinationProvider.getDestination();
        
        // make sure the two functions will be executed in the same session
        JCoContext.begin(destination);
        
        // Before increment
        System.out.println("Before execution of ZINCREMENT_COUNTER:");
        System.out.println("Counter:" + RfcFunctions.runGetCounter(destination));
        
        // start a new Thread in which function ZINCREMENT_COUNTER
        // will be executed for five times
        WorkingThread workingThread = new WorkingThread(destination, false);
        workingThread.start();
        
        // wait and switch thread
        Thread.sleep(1000);
        
        // After increment
        if (workingThread.hasDone() == true){
            System.out.println("After execution of ZINCREMENT_COUNTER:");
            System.out.println("Counter:" + RfcFunctions.runGetCounter(destination));   
        }
        
        // release the connection 
        JCoContext.end(destination);
    }
}

與前面同一個線程中代碼的主要區(qū)別是:
定義一個WorkingThread類的實例,然后啟動線程:

WorkingThread workingThread = new WorkingThread(destination, false);
workingThread.start();

然后通過Thread.sleep(), 將線程切換到workingThread中執(zhí)行呢堰,執(zhí)行完畢再回到主線程顯示結(jié)果抄瑟。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市枉疼,隨后出現(xiàn)的幾起案子皮假,更是在濱河造成了極大的恐慌,老刑警劉巖骂维,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件惹资,死亡現(xiàn)場離奇詭異,居然都是意外死亡航闺,警方通過查閱死者的電腦和手機(jī)褪测,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進(jìn)店門猴誊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人侮措,你說我怎么就攤上這事懈叹。” “怎么了分扎?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵澄成,是天一觀的道長。 經(jīng)常有香客問我畏吓,道長墨状,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任菲饼,我火速辦了婚禮肾砂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宏悦。我一直安慰自己镐确,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布肛根。 她就那樣靜靜地躺著辫塌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪派哲。 梳的紋絲不亂的頭發(fā)上臼氨,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機(jī)與錄音芭届,去河邊找鬼储矩。 笑死,一個胖子當(dāng)著我的面吹牛褂乍,可吹牛的內(nèi)容都是我干的持隧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼逃片,長吁一口氣:“原來是場噩夢啊……” “哼屡拨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起褥实,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤呀狼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后损离,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哥艇,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年僻澎,在試婚紗的時候發(fā)現(xiàn)自己被綠了貌踏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片十饥。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖祖乳,靈堂內(nèi)的尸體忽然破棺而出逗堵,到底是詐尸還是另有隱情,我是刑警寧澤凡资,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布砸捏,位于F島的核電站谬运,受9級特大地震影響隙赁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梆暖,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一伞访、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧轰驳,春花似錦厚掷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至勤哗,卻和暖如春抡爹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背芒划。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工冬竟, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人民逼。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓泵殴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拼苍。 傳聞我的和親對象是個殘疾皇子笑诅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 前面我們看到,SAP函數(shù)調(diào)用疮鲫,Invoke語句的代碼是這樣的: 我們不用關(guān)心與SAP系統(tǒng)的連接吆你,連接都是NCo3....
    Stone0823閱讀 1,610評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)棚点,斷路器早处,智...
    卡卡羅2017閱讀 134,626評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法瘫析,內(nèi)部類的語法砌梆,繼承相關(guān)的語法默责,異常的語法,線程的語...
    子非魚_t_閱讀 31,596評論 18 399
  • 從三月份找實習(xí)到現(xiàn)在咸包,面了一些公司桃序,掛了不少,但最終還是拿到小米烂瘫、百度媒熊、阿里、京東坟比、新浪芦鳍、CVTE、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,206評論 11 349
  • 因為可能沒什么時間更新葛账,可能解釋會比較少數(shù)組是為了放一系列的數(shù)值的一個集合柠衅,他的表現(xiàn)形式類似于 "{數(shù)組[0]=1...
    水電梁師傅閱讀 205評論 0 0