-
03 이클립스에서 Jco3 테스트ABAP/JCO3 2017. 8. 18. 13:39
이클립스에서 Jco3 테스트
이클립스에서 개발환경을 구성한 다음 다운받은 예제 프로그램을 실행해 보겠습니다.
1. 이클립스에서 신규 자바 프로젝트를 생성합니다.
이클립스 메뉴 : File -> New -> Java Project
프로젝트 명 : jco3(임의로 지정함)’
2. 프로젝트에 다운로드 받은 드라이버를 저장할 폴더를 생성합니다.
폴더명 : lib(임으로 지정함0
3. 다운받은 앞축파일을 풀어서 sapjco3.dll, sapjco3.jar 파일을 프로젝트의 lib폴더에, examples폴더에 있는 자바파일을 모두 프로젝트의 src폴더에 복사합니다.
4. 프로젝트 jco3에서 마우스 오른쪽 버튼을 클릭하여 Properties를 클릭합니다.
5. Java Build Path메뉴의 Libraries 탭화면으로 이동하여 Add JARs… 버튼을 클릭하여 lib폴더에 있는 sapjco3.jar파일을 추가합니다.
6. OK버튼을 누르면 소스폴더의 자바파일 오류표시가 사라집니다.
7. 소스 폴더의 StepByStepClient.java파일을 열어서
static String ABAP_MS = "ABAP_MS_WITHOUT_POOL"; 다음 내용을 추가합니다.static
{
Properties connectProperties = new Properties();
connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, "10.10.10.10");
connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "00");
connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "330");
connectProperties.setProperty(DestinationDataProvider.JCO_USER, "testuser");
connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "password!!");
connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ko");
createDestinationDataFile(ABAP_AS, connectProperties);
connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3");
connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10");
createDestinationDataFile(ABAP_AS_POOLED, connectProperties);
Properties msConnectProperties = new Properties();
msConnectProperties.setProperty(DestinationDataProvider.JCO_MSHOST, "mserver.co.kr");
msConnectProperties.setProperty(DestinationDataProvider.JCO_R3NAME, "AEP");
msConnectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "100");
msConnectProperties.setProperty(DestinationDataProvider.JCO_USER,"testuser");
msConnectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "password!!");
msConnectProperties.setProperty(DestinationDataProvider.JCO_GROUP, "PRD");
msConnectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ko");
createDestinationDataFile(ABAP_MS, connectProperties);
}
회사 환경에 맞게 설정해야 하는 항목은 아래와 같습니다.
DestinationDataProvider.JCO_ASHOST
SAP 어플리케이션서버
DestinationDataProvider.JCO_SYSNR
인스턴스 번호
DestinationDataProvider.JCO_CLIENT
클라이언트
DestinationDataProvider.JCO_USER
사용자
DestinationDataProvider.JCO_PASSWD
비밀번호
DestinationDataProvider.JCO_LANG
언어
커넥션 풀을 사용할 경우에는 다음의 추가 설정을 진행합니다.
DestinationDataProvider.JCO_POOL_CAPACITY
초기 커넥션풀
DestinationDataProvider.JCO_PEAK_LIMIT
최대 커넥션풀
메시지서버를 사용하여 접속하는 경우입니다.
DestinationDataProvider.JCO_MSHOST
메시지 서버
DestinationDataProvider.JCO_R3NAME
시스템 ID
DestinationDataProvider.JCO_CLIENT
클라이언트
DestinationDataProvider.JCO_USER
사용자
DestinationDataProvider.JCO_PASSWD
비밀번호
DestinationDataProvider.JCO_GROUP
그룹/서버
DestinationDataProvider.JCO_LANG
언어
자바 프로그램 실행시에 createDestinationDataFile매서드가 작업 폴더에 다음 3개의 파일을 생성합니다.
ABAP_AS_WITH_POOL.jcoDestination
ABAP_AS_WITHOUT_POOL.jcoDestination
ABAP_MS_WITHOUT_POOL.jcoDestination
이 파일은 JCoDestinationManager.getDestination매서드 호출시 Jco가 읽어서 사용합니다.
8. 다음은 자바 플그램의 전체 소스 입니다.
import java.io.File;
import java.io.FileOutputStream;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import com.sap.conn.jco.AbapException;
import com.sap.conn.jco.JCoContext;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.JCoField;
import com.sap.conn.jco.JCoFunction;
import com.sap.conn.jco.JCoFunctionTemplate;
import com.sap.conn.jco.JCoStructure;
import com.sap.conn.jco.JCoTable;
import com.sap.conn.jco.ext.DestinationDataProvider;
/**
* basic examples for Java to ABAP communication
*/
public class StepByStepClient
{
static String ABAP_AS = "ABAP_AS_WITHOUT_POOL";
static String ABAP_AS_POOLED = "ABAP_AS_WITH_POOL";
static String ABAP_MS = "ABAP_MS_WITHOUT_POOL";
static
{
Properties connectProperties = new Properties();
connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, "10.11.3.48");
connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, "00");
connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "330");
connectProperties.setProperty(DestinationDataProvider.JCO_USER, "kr20");
connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "linor5246!");
connectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ko");
createDestinationDataFile(ABAP_AS, connectProperties);
connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3");
connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10");
createDestinationDataFile(ABAP_AS_POOLED, connectProperties);
Properties msConnectProperties = new Properties();
msConnectProperties.setProperty(DestinationDataProvider.JCO_MSHOST, "ekrerpvp.ekr.or.kr");
msConnectProperties.setProperty(DestinationDataProvider.JCO_R3NAME, "AEP");
msConnectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "100");
msConnectProperties.setProperty(DestinationDataProvider.JCO_USER,"kr20");
msConnectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "linor5246!");
msConnectProperties.setProperty(DestinationDataProvider.JCO_GROUP, "PRD");
msConnectProperties.setProperty(DestinationDataProvider.JCO_LANG, "ko");
createDestinationDataFile(ABAP_MS, connectProperties);
}
static void createDestinationDataFile(String destinationName, Properties connectProperties)
{
File destCfg = new File(destinationName+".jcoDestination");
try {
FileOutputStream fos = new FileOutputStream(destCfg, false);
connectProperties.store(fos, "for tests only !");
fos.close();
} catch (Exception e){
throw new RuntimeException("Unable to create the destination files", e);
}
}
/**
* This example demonstrates the destination concept introduced with JCO 3.
* The application does not deal with single connections anymore. Instead
* it works with logical destinations like ABAP_AS and ABAP_MS which separates
* the application logic from technical configuration.
* @throws JCoException
*/
public static void step1Connect() throws JCoException
{
JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS);
System.out.println("Attributes:");
System.out.println(destination.getAttributes());
System.out.println();
destination = JCoDestinationManager.getDestination(ABAP_MS);
System.out.println("Attributes:");
System.out.println(destination.getAttributes());
System.out.println();
}
/**
* This example uses a connection pool. However, the implementation of
* the application logic is still the same. Creation of pools and pool management
* are handled by the JCo runtime.
*
* @throws JCoException
*/
public static void step2ConnectUsingPool() throws JCoException
{
JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);
destination.ping();
System.out.println("Attributes:");
System.out.println(destination.getAttributes());
System.out.println();
}
/**
* The following example executes a simple RFC function STFC_CONNECTION.
* In contrast to JCo 2 you do not need to take care of repository management.
* JCo 3 manages the repository caches internally and shares the available
* function metadata as much as possible.
* @throws JCoException
*/
public static void step3SimpleCall() throws JCoException
{
//JCoDestination is the logic address of an ABAP system and ...
JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);
// ... it always has a reference to a metadata repository
JCoFunction function = destination.getRepository().getFunction("STFC_CONNECTION");
if(function == null)
throw new RuntimeException("BAPI_COMPANYCODE_GETLIST not found in SAP.");
//JCoFunction is container for function values. Each function contains separate
//containers for import, export, changing and table parameters.
//To set or get the parameters use the APIS setValue() and getXXX().
function.getImportParameterList().setValue("REQUTEXT", "Hello SAP");
try
{
//execute, i.e. send the function to the ABAP system addressed
//by the specified destination, which then returns the function result.
//All necessary conversions between Java and ABAP data types
//are done automatically.
function.execute(destination);
}
catch(AbapException e)
{
System.out.println(e.toString());
return;
}
System.out.println("STFC_CONNECTION finished:");
System.out.println(" Echo: " + function.getExportParameterList().getString("ECHOTEXT"));
System.out.println(" Response: " + function.getExportParameterList().getString("RESPTEXT"));
System.out.println();
}
/**
* ABAP APIs often uses complex parameters. This example demonstrates
* how to read the values from a structure.
* @throws JCoException
*/
public static void step3WorkWithStructure() throws JCoException
{
JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);
JCoFunction function = destination.getRepository().getFunction("RFC_SYSTEM_INFO");
if(function == null)
throw new RuntimeException("RFC_SYSTEM_INFO not found in SAP.");
try
{
function.execute(destination);
}
catch(AbapException e)
{
System.out.println(e.toString());
return;
}
JCoStructure exportStructure = function.getExportParameterList().getStructure("RFCSI_EXPORT");
System.out.println("System info for " + destination.getAttributes().getSystemID() + ":\n");
//The structure contains some fields. The loop just prints out each field with its name.
for(int i = 0; i < exportStructure.getMetaData().getFieldCount(); i++)
{
System.out.println(exportStructure.getMetaData().getName(i) + ":\t" + exportStructure.getString(i));
}
System.out.println();
//JCo still supports the JCoFields, but direct access via getXXX is more efficient as field iterator
System.out.println("The same using field iterator: \nSystem info for " + destination.getAttributes().getSystemID() + ":\n");
for(JCoField field : exportStructure)
{
System.out.println(field.getName() + ":\t" + field.getString());
}
System.out.println();
}
/**
* A slightly more complex example than before. Query the companies list
* returned in a table and then obtain more details for each company.
* @throws JCoException
*/
public static void step4WorkWithTable() throws JCoException
{
JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);
JCoFunction function = destination.getRepository().getFunction("BAPI_COMPANYCODE_GETLIST");
if(function == null)
throw new RuntimeException("BAPI_COMPANYCODE_GETLIST not found in SAP.");
try
{
function.execute(destination);
}
catch(AbapException e)
{
System.out.println(e.toString());
return;
}
JCoStructure returnStructure = function.getExportParameterList().getStructure("RETURN");
if (! (returnStructure.getString("TYPE").equals("")||returnStructure.getString("TYPE").equals("S")) )
{
throw new RuntimeException(returnStructure.getString("MESSAGE"));
}
JCoTable codes = function.getTableParameterList().getTable("COMPANYCODE_LIST");
for (int i = 0; i < codes.getNumRows(); i++)
{
codes.setRow(i);
System.out.println(codes.getString("COMP_CODE") + '\t' + codes.getString("COMP_NAME"));
}
//move the table cursor to first row
codes.firstRow();
for (int i = 0; i < codes.getNumRows(); i++, codes.nextRow())
{
function = destination.getRepository().getFunction("BAPI_COMPANYCODE_GETDETAIL");
if (function == null)
throw new RuntimeException("BAPI_COMPANYCODE_GETDETAIL not found in SAP.");
function.getImportParameterList().setValue("COMPANYCODEID", codes.getString("COMP_CODE"));
//We do not need the addresses, so set the corresponding parameter to inactive.
//Inactive parameters will be either not generated or at least converted.
function.getExportParameterList().setActive("COMPANYCODE_ADDRESS",false);
try
{
function.execute(destination);
}
catch (AbapException e)
{
System.out.println(e.toString());
return;
}
returnStructure = function.getExportParameterList().getStructure("RETURN");
if (! (returnStructure.getString("TYPE").equals("") ||
returnStructure.getString("TYPE").equals("S") ||
returnStructure.getString("TYPE").equals("W")) )
{
throw new RuntimeException(returnStructure.getString("MESSAGE"));
}
JCoStructure detail = function.getExportParameterList().getStructure("COMPANYCODE_DETAIL");
System.out.println(detail.getString("COMP_CODE") + '\t' +
detail.getString("COUNTRY") + '\t' +
detail.getString("CITY"));
}//for
}
/**
* this example shows the "simple" stateful call sequence. Since all calls belonging to one
* session are executed within the same thread, the application does not need
* to take into account the SessionReferenceProvider. MultithreadedExample.java
* illustrates the more complex scenario, where the calls belonging to one session are
* executed in different threads.
*
* Note: this example uses Z_GET_COUNTER and Z_INCREMENT_COUNTER. Most ABAP systems
* contain function modules GET_COUNTER and INCREMENT_COUNTER that are not remote-enabled.
* Copy these functions to Z_GET_COUNTER and Z_INCREMENT_COUNTER (or implement as wrapper)
* and declare them to be remote enabled.
* @throws JCoException
*/
public static void step4SimpleStatefulCalls() throws JCoException
{
final JCoFunctionTemplate incrementCounterTemplate, getCounterTemplate;
JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS);
incrementCounterTemplate = destination.getRepository().getFunctionTemplate("Z_INCREMENT_COUNTER");
getCounterTemplate = destination.getRepository().getFunctionTemplate("Z_GET_COUNTER");
if(incrementCounterTemplate == null || getCounterTemplate == null)
throw new RuntimeException("This example cannot run without Z_INCREMENT_COUNTER and Z_GET_COUNTER functions");
final int threadCount = 5;
final int loops = 5;
final CountDownLatch startSignal = new CountDownLatch(threadCount);
final CountDownLatch doneSignal = new CountDownLatch(threadCount);
Runnable worker = new Runnable()
{
public void run()
{
startSignal.countDown();
try
{
//wait for other threads
startSignal.await();
JCoDestination dest = JCoDestinationManager.getDestination(ABAP_AS);
JCoContext.begin(dest);
try
{
for(int i=0; i < loops; i++)
{
JCoFunction incrementCounter = incrementCounterTemplate.getFunction();
incrementCounter.execute(dest);
}
JCoFunction getCounter = getCounterTemplate.getFunction();
getCounter.execute(dest);
int remoteCounter = getCounter.getExportParameterList().getInt("GET_VALUE");
System.out.println("Thread-" + Thread.currentThread().getId() +
" finished. Remote counter has " + (loops==remoteCounter?"correct":"wrong") +
" value [" + remoteCounter + "]");
}
finally
{
JCoContext.end(dest);
}
}
catch(Exception e)
{
System.out.println("Thread-" + Thread.currentThread().getId() + " ends with exception " + e.toString());
}
doneSignal.countDown();
}
};
for(int i = 0; i < threadCount; i++)
{
new Thread(worker).start();
}
try
{
doneSignal.await();
}
catch(Exception e)
{
}
}
public static void main(String[] args) throws JCoException
{
step1Connect();
step2ConnectUsingPool();
step3SimpleCall();
step4WorkWithTable();
step4SimpleStatefulCalls();
}
}
9. 위 자바 클래스를 실행하면 다음과 같은 결과를 얻을 수 있습니다.
Attributes:
DEST: ABAP_AS_WITHOUT_POOL
OWN_HOST: linor
PARTNER_HOST: erpd
SYSTNR: 00
SYSID: AED
CLIENT: 330
USER: KR20
LANGUAGE: 3
ISO_LANGUAGE: KO
OWN_CODEPAGE: 4102
OWN_CHARSET: UTF16
OWN_ENCODING: utf-16
OWN_BYTES_PER_CHAR: 2
PARTNER_CODEPAGE: 4102
PARTNER_CHARSET: UTF16
PARTNER_ENCODING: utf-16
PARTNER_BYTES_PER_CHAR: 2
OWN_REL: 721
PARTNER_REL: 700
PARTNER_TYPE: 3
KERNEL_REL: 721
TRACE:
RFC_ROLE: C
OWN_TYPE: E
CPIC_CONVID: 00000000
Attributes:
DEST: ABAP_MS_WITHOUT_POOL
OWN_HOST: linor
PARTNER_HOST: erpd
SYSTNR: 00
SYSID: AED
CLIENT: 330
USER: KR20
LANGUAGE: 3
ISO_LANGUAGE: KO
OWN_CODEPAGE: 4102
OWN_CHARSET: UTF16
OWN_ENCODING: utf-16
OWN_BYTES_PER_CHAR: 2
PARTNER_CODEPAGE: 4102
PARTNER_CHARSET: UTF16
PARTNER_ENCODING: utf-16
PARTNER_BYTES_PER_CHAR: 2
OWN_REL: 721
PARTNER_REL: 700
PARTNER_TYPE: 3
KERNEL_REL: 721
TRACE:
RFC_ROLE: C
OWN_TYPE: E
CPIC_CONVID: 00000000
Attributes:
DEST: ABAP_AS_WITH_POOL
OWN_HOST: linor
PARTNER_HOST: erpd
SYSTNR: 00
SYSID: AED
CLIENT: 330
USER: KR20
LANGUAGE: 3
ISO_LANGUAGE: KO
OWN_CODEPAGE: 4102
OWN_CHARSET: UTF16
OWN_ENCODING: utf-16
OWN_BYTES_PER_CHAR: 2
PARTNER_CODEPAGE: 4102
PARTNER_CHARSET: UTF16
PARTNER_ENCODING: utf-16
PARTNER_BYTES_PER_CHAR: 2
OWN_REL: 721
PARTNER_REL: 700
PARTNER_TYPE: 3
KERNEL_REL: 721
TRACE:
RFC_ROLE: C
OWN_TYPE: E
CPIC_CONVID: 00000000
STFC_CONNECTION finished:
Echo: Hello SAP
Response: SAP R/3 Rel. 700 Sysid: AED Date: 20170818 Time: 130507 Logon_Data: 330/KR20/3
1000 ********사
**** ********사
1000 KR *********사
**** KR Seoul
Thread-12 finished. Remote counter has correct value [5]
Thread-14 finished. Remote counter has correct value [5]
Thread-15 finished. Remote counter has correct value [5]
Thread-16 finished. Remote counter has correct value [5]
Thread-13 finished. Remote counter has correct value [5]
회사와 관련된 정보는 가렸습니다.
10. 이클립스 실행시 dll라이브러리를 찾지 못하는 경우 Run Configuration에서 VM arguments에 다음 내용을 추가합니다.
-Djava.library.path="${workspace_loc:jco3}/lib"
'ABAP > JCO3' 카테고리의 다른 글
02 테스트용 SAP RFC함수 만들기 (0) 2017.08.18 01 JCO3 드라이버 다운로드 (0) 2017.08.18