SAP接口编程 之 JCo3.0系列(01):JCoDestination
SAP接口编程 之 JCo3.0系列(01):JCoDestination
JCo3.0是Java语言与ABAP语言双向通讯的中间件。与之前1.0/2.0相比,是重新设计的产品。API和架构设计与NCo3.0比较类似,前面也说过,NCo3.0的设计参考了JCo3.0。从本篇开始,系统介绍JCo3.0编程的技术要点。
JCo3.0安装
从https://service.sap.com/connectors 可以下载JCo3.0,注意下载的时候根据操作系统和JVM版本(32位还是64)选择不同的版本。安装就是解压,将文件解压到目标文件夹。以Windows系统为例,主要的文件包括:
sapjco3.dll
sapjco3.jar
SAP强烈推荐将这两个文件放在同一文件夹下。测试安装是否成功,可以在命令窗口下,进入安装文件夹,运行下面的命令:
java -jar sapjco3.jar
如果安装成功,应该显示如下界面:
JCoDestination
JCoDestination代表后台SAP系统,程序员不用关心与SAP的连接,jco3.0运行时环境负责管理连接和释放连接。我们先以一个简单的例子看看jco3.0 JCoDestination类的一些要点。
我使用的编程环境是Eclipse,环境准备如下:
- 新建一个Java项目,项目名为JCo3Demo。
- 将sapjco3.jar加入到项目的build path中。注意前面所说的sapjco3.jar和sapjco3.dll要放在同一个文件夹下。
- 在Eclipse Java项目文件夹下,新建一个文本文件,文件名命名为ECC.jocdestination, 文件的内容如下(SAP系统的连接参数的设置):
#SAP Logon parameters!
#Tue Dec 08 16:41:30 CST 2015
jco.client.lang=EN
jco.client.client=001
jco.client.passwd=xxxxxx
jco.client.user=STONE
jco.client.sysnr=00
jco.client.ashost=192.168.65.100
对照SAP GUI,不难理解:
环境准备好了,先来一段最简单的代码:
package jco3.demo1;
import java.util.Properties;
import org.junit.Test;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
public class JCoDestinationDemo
{
public JCoDestination getDestination() throws JCoException
{
/**
* Get instance of JCoDestination from file: ECC.jcodestination
* which should be located in the installation folder of project
*/
JCoDestination dest = JCoDestinationManager.getDestination("ECC");
return dest;
}
@Test
public void pingDestination() throws JCoException
{
JCoDestination dest = this.getDestination();
dest.ping();
}
}
代码说明:
getDestination()方法中,JCoDestinationManager.getDestination("ECC")从ECC.jcodestination文件中获取连接参数,创建JCoDestination对象的实例。
这里有一个重要的约定,JCoDestinationManager.getDestination("ECC")方法,会从Eclipse Java项目的根目录,查找ECC.jcodestination文件(文件路径和扩展名不能改变)是否存在,如果存在,从文件的内容中获取连接参数。这是DestinationDataProvider接口的一个默认实现,在开发和测试的时候还是很方便的,但如果在真实项目中使用,安全性和灵活性就不够。后面会介绍解决方法。pingDestination()方法调用JcoDestination对象的ping()方法测试SAP系统的连接。@Test: 使用junit进行测试
配置文件的生成
刚才我们手工编辑了ECC.jcodestination文件,对于这个配置文件,因为很多连接参数来自于DestinationDataProvider接口,如果想通过代码来创建配置文件,可以使用如下代码:
package jco3.demo2;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import org.junit.Test;
import com.sap.conn.jco.ext.DestinationDataProvider;
public class DestinationFile
{
private Properties setProperties()
{
// logon parameters and other properties
Properties connProps = new Properties();
connProps.setProperty(DestinationDataProvider.JCO_ASHOST, "192.168.65.100");
connProps.setProperty(DestinationDataProvider.JCO_SYSNR, "00");
connProps.setProperty(DestinationDataProvider.JCO_USER, "STONE");
connProps.setProperty(DestinationDataProvider.JCO_PASSWD, "xxxxxx");
connProps.setProperty(DestinationDataProvider.JCO_CLIENT, "001");
connProps.setProperty(DestinationDataProvider.JCO_LANG, "EN");
return connProps;
}
private void doCreateFile(String fName, String suffix, Properties props) throws IOException
{
/**
* Write contents of properties into a text file
* which was named [fName+suffix.jcodestination]
*/
File cfg = new File(fName+"."+suffix);
if (!cfg.exists()){ // file not exists
// Create file output stream, not using append mode
FileOutputStream fOutputStream = new FileOutputStream(cfg, false);
// store the properties in file output stream
// and also add comments
props.store(fOutputStream, "SAP logon parameters:");
fOutputStream.close();
}else{
throw new RuntimeException("File alreay exists.");
}
}
@Test
public void createConfigFile() throws IOException
{
Properties props = this.setProperties();
String fileName = "SAP_AS"; // sap application server
// jcodestination suffix is required by JCoDestinationManager
this.doCreateFile(fileName, "jcodestination", props);
}
}
代码说明:
setProperties()方法属性参照DestinationDataProvider类的常量设置Properties的实例。doCreateFile()方法根据需求的文件名,扩展名在Eclipse项目的根文件夹下,创建一个文本文件,文件的内容就是Properties实例的内容。createConfigFile()方法,调用上面的两个方法,创建配置文件。
更改配置文件名的路径和扩展名
我们看到,默认情况下,SAP对配置文件的路径和扩展名都不能改变,如果我们想把文件放在任意位置,扩展名也使用其他的扩展名,有没有办法?答案是有,方法是实现DestinationDataProvider接口,并改写(override)getDestinationProperties()方法,然后通过Environment.registerDestinationDataProvider()方法进行注册。
OK, 一起来看看代码,代码分为三个部分:
- 第一部分: 创建
FileDestinationDataProviderImp类,实现DestinationDataProvider接口- 第二部分: 创建
FileDestinationDataProvider类,注册FileDestinationDataProviderImp的实例,并提供getDestination()方法供调用- 第三部分:调用FileDestinationDataProvider类的getDestination()方法
第一部分:DestinationDataProvider接口的实现:
package jco3.demo2;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import com.sap.conn.jco.ext.DestinationDataEventListener;
import com.sap.conn.jco.ext.DestinationDataProvider;
public class FileDestinationDataProviderImp implements DestinationDataProvider
{
private File dir;
private String destName; // destination name
private String suffix;
public void setDestinationFile(File dir, String destName, String suffix)
{
this.dir = dir;
this.destName = destName;
this.suffix = suffix;
}
private Properties loadProperties(File dir, String destName, String suffix) throws IOException
{
Properties props = null;
// create a file with name: fullName in destDirectory
File destFile = new File(dir, destName+"."+suffix);
if (destFile.exists()){
FileInputStream fInputStream = new FileInputStream(destFile);
props = new Properties();
props.load(fInputStream);
fInputStream.close();
}else{
throw new RuntimeException("Destination file does not exist.");
}
return props;
}
@Override
public Properties getDestinationProperties(String destName)
{
Properties props = null;
try {
props = this.loadProperties(this.dir, this.destName, this.suffix);
} catch (IOException e) {
e.printStackTrace();
}
return props;
}
@Override
public void setDestinationDataEventListener(DestinationDataEventListener listener)
{
throw new UnsupportedOperationException();
}
@Override
public boolean supportsEvents()
{
return false;
}
}
第二部分: 创建FileDestinationDataProvider类,注册FileDestinationDataProviderImp的实例,并且提供getDestination()方法。
package jco3.demo2;
import java.io.File;
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;
public class FileDestinationDataProvider
{
public static JCoDestination getDestination() throws JCoException
{
File directory = new File("."); // current directory;
String fileName = "SAP_AS";
String suffix = "txt";
FileDestinationDataProviderImp destDataProvider = new FileDestinationDataProviderImp();
destDataProvider.setDestinationFile(directory, fileName, suffix);
Environment.registerDestinationDataProvider(destDataProvider);
JCoDestination dest = JCoDestinationManager.getDestination(fileName);
return dest;
}
}
我们看到,getDestination方法中,文件的路径,文件的扩展名,都是我们自己定义的。文件名作为JCoDestinationManager.getDestination方法的destination name。从这里也可可以看到,JCoDestinationManager.getDestination方法从哪里查找连接参数,是依赖于Environment注册的DestinationDataProvider实现。
第三部分:测试代码FileDestinationDataProvider的getDestination方法:
package jco3.demo2;
import org.junit.Test;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;
public class TestFileDestinationProvider
{
@Test
public void pingSAPDestination() throws JCoException
{
JCoDestination dest = FileDestinationDataProvider.getDestination();
dest.ping();
}
}
DestinationDataProvider另一种实现
记得nco3.0可以将登陆参数写在代码中吗,如果我们也想将连接参数直接写在代码中,怎么做呢?刚才说过了,关键就是实现DestinationDataProvider接口,并改写getDestinationProperties()方法。不多说,上代码。
第一部分:DestinationDataProvider接口实现
package jco3.demo3;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import com.sap.conn.jco.ext.DestinationDataEventListener;
import com.sap.conn.jco.ext.DestinationDataProvider;
public class DestinationDataProviderImp implements DestinationDataProvider
{
/**
* DestinationDataProvider is an interface
* We define DestinationDataProviderImp class to implements this interface
* so that we can define the logon parameters more flexibly
* not just in xxx.jcodestionation file.
*
* The key point is that we override getDestinationProperties() method
* Afterwards, instance of DestinationDataProvider should be registered
* using Environment.registerDestinationDataProvider() method to take effect
*/
@SuppressWarnings("rawtypes")
private Map provider = new HashMap();
@SuppressWarnings("unchecked")
public void addDestinationProperties(String destName, Properties props)
{
provider.put(destName, props);
}
@Override
public Properties getDestinationProperties(String destName)
{
if (destName == null){
throw new NullPointerException("Destinantion name is empty.");
}
if (provider.size() == 0){
throw new IllegalStateException("Data provider is empty.");
}
return (Properties) provider.get(destName);
}
@Override
public void setDestinationDataEventListener(DestinationDataEventListener listener)
{
throw new UnsupportedOperationException();
}
@Override
public boolean supportsEvents()
{
return false;
}
}
第二部分:创建DestinationProivder类,提供getDestination()方法,注册DestinationDataProviderImp类的实例:
package jco3.demo3;
import java.util.Properties;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.ext.DestinationDataProvider;
import com.sap.conn.jco.ext.Environment;
public class DestinationProvider
{
private static Properties setProperties()
{
// logon parameters and other properties
Properties connProps = new Properties();
connProps.setProperty(DestinationDataProvider.JCO_ASHOST, "192.168.65.100");
connProps.setProperty(DestinationDataProvider.JCO_SYSNR, "00");
connProps.setProperty(DestinationDataProvider.JCO_USER, "STONE");
connProps.setProperty(DestinationDataProvider.JCO_PASSWD, "xxxxxx");
connProps.setProperty(DestinationDataProvider.JCO_CLIENT, "001");
connProps.setProperty(DestinationDataProvider.JCO_LANG, "EN");
return connProps;
}
public static JCoDestination getDestination() throws JCoException
{
String destName = "SAP_AS";
Properties props = setProperties();
DestinationDataProviderImp destDataProvider = new DestinationDataProviderImp();
destDataProvider.addDestinationProperties(destName, props);
Environment.registerDestinationDataProvider(destDataProvider);
JCoDestination dest = JCoDestinationManager.getDestination(destName);
return dest;
}
}
第三部分:测试DestinationProvider的getDestination()方法:
package jco3.demo3;
import org.junit.Test;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoException;
public class TestDestionProvider
{
@Test
public void pingSAPDestination() throws JCoException
{
JCoDestination dest = DestinationProvider.getDestination();
dest.ping();
}
}
SAP接口编程 之 JCo3.0系列(01):JCoDestination的更多相关文章
- SAP接口编程 之 JCo3.0系列(02) : JCo Client Programming
SAP接口编程 之 JCo3.0系列(02) : JCo Client Programming 字数545 阅读52 评论0 喜欢1 JCo3.0调用SAP函数的过程 大致可以总结为以下步骤: 连接至 ...
- SAP接口编程 之 JCo3.0系列(04) : 会话管理
在SAP接口编程之 NCo3.0系列(06) : 会话管理 这篇文章中,对会话管理的相关知识点已经说得很详细了,请参考.现在用JCo3.0来实现. 1. JCoContext 如果SAP中多个函数需要 ...
- SAP接口编程 之 JCo3.0系列(03) : Table参数
Table参数作为export parameter BAPI_COMPANYCODE_GETDETAIL是一个适合演示的函数,没有import paramter参数,调用后COMPANYCODE_GE ...
- SAP接口编程 之 JCo3.0系列(05) : Exception Handling
JCO3.0的Exception,常用的Exception如下: JCoException 继承自java.lang.Exception,是JCo3中Exception的基类. JCoRuntimeE ...
- LXD 2.0 系列(四):资源控制
LXD 提供了各种资源限制.其中一些与容器本身相关,如内存配额.CPU 限制和 I/O 优先级.而另外一些则与特定设备相关,如 I/O 带宽或磁盘用量限制.-- Stéphane Graber 本文导 ...
- java io系列01之 "目录"
java io 系列目录如下: 01. java io系列01之 "目录" 02. java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括 ...
- Java 集合系列 01 总体框架
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Java 之 I/O 系列 01 ——基础
Java 之 I/O 系列 目录 Java 之 I/O 系列 01 ——基础 Java 之 I/O 系列 02 ——序列化(一) Java 之 I/O 系列 02 ——序列化(二) 整理<疯狂j ...
- Spring Boot 2.0系列文章(七):SpringApplication 深入探索
关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/04/30/springboot_SpringApplication/ 前言 在 Spring B ...
随机推荐
- HTML5与CSS3权威指南
第一章:Web时代的变迁 HTML5放心使用的理由: 兼容性:HTML5在老板本的浏览器上也可以正常运行: 实用性:HTML5内部并没有封装什么很复杂的,不切实际的功能,而只是封装了简单实用的功能: ...
- WPF:MenuItem样式
基础信息 1.MenuItem 样式 <Window.Resources> <Style TargetType="{x:Type MenuItem}"> & ...
- WIN7 64位系统注册银行支付组件
WIN7 64位系统注册银行支付组件目前只尝试注册了银联的chinapay.dll和工行的icbcebankutil.dll 1.将dll文件拷贝到windows\syswow64\文件夹下(Win7 ...
- c#记事本
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- Prime Path 分类: 搜索 POJ 2015-08-09 16:21 4人阅读 评论(0) 收藏
Prime Path Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14091 Accepted: 7959 Descripti ...
- linux脚本随笔-01
#### 获取配置文件配置路径,javapath为配置项,var为具体的配置值 eval $(awk -F "javapath=" '{if($2=="") { ...
- 在 Server 端存取 Excel 檔案的利器:NPOI Library
转处 http://msdn.microsoft.com/zh-tw/ee818993.aspx Codeplex 軟體套件(Package)資訊 套件名稱 NPOI 作者 tonyqus, huse ...
- Apache Commons CLI 开发命令行工具示例
概念说明Apache Commons CLI 简介 虽然各种人机交互技术飞速发展,但最传统的命令行模式依然被广泛应用于各个领域:从编译代码到系统管理,命令行因其简洁高效而备受宠爱.各种工具和系统都 提 ...
- Storm系列之一——Storm Topology并发
1.是什么构成一个可运行的topology? worker processes(worker进程),executors(线程)和tasks. 一台Storm集群里面的机器可能运行一个或多个worker ...
- 【Java】聊聊常用的摘要算法,比如MD5
摘要算法的特性 摘要算法的目的的将信息进行简单地摘要,将任意长的信息摘要成固定长的信息.比如MD5,将任意长的信息摘要成128位的摘要. 不可逆的,将报文摘要成一段信息后,无法通过摘要信息还原会报文. ...