Professional Documents
Culture Documents
Tips&Tricks JCo Programming
Tips&Tricks JCo Programming
Thomas G. Schuessler is
the founder of ARAsoft, a
company offering products,
consulting, custom
development, and training
to customers worldwide,
specializing in integration
between SAP and non-SAP
components and applications.
Thomas is the author of
SAPs BIT525 and BIT526
classes. Prior to founding
ARAsoft in 1993, he worked
with SAP AG and SAP
America for seven years.
105
January/February 2004
Figure 1
ABAP
Description
Java
Type Constant
1-byte integer
int
JCO.TYPE_INT1
2-byte integer
int
JCO.TYPE_INT2
4-byte integer
int
JCO.TYPE_INT
Character
String
JCO.TYPE_CHAR
Numerical character
String
JCO.TYPE_NUM
BigDecimal
JCO.TYPE_BCD
Date
Date
JCO.TYPE_DATE
Time
Date
JCO.TYPE_TIME
Float
double
JCO.TYPE_FLOAT
Raw data
byte[]
JCO.TYPE_BYTE
String (variable-length)
String
JCO.TYPE_STRING
byte[]
JCO.TYPE_XSTRING
106
Tips and Tricks for SAP Java Connector (JCo) Client Programming
Figure 2
Figure 3
Figure 4
long
byte[]
char
int
double
short
java.lang.Object
java.lang.String
107
Figure 5
January/February 2004
Contents
getString()
getDate() or getTime()
00000000
0000-00-00
null
99999999
9999-99-99
9999-12-31
240000
24:00:00
23:59:59
Figure 6
108
Tips and Tricks for SAP Java Connector (JCo) Client Programming
Figure 7
JCO.Function function =
createFunction("BAPI_COMPANYCODE_GETLIST");
mConnection.execute(function);
JCO.Structure bapiReturn = function.getExportParameterList()
.getStructure("RETURN");
if ( ! (bapiReturn.getString("TYPE").equals("") ||
bapiReturn.getString("TYPE").equals("S")) ) {
System.out.println(bapiReturn.getString("MESSAGE"));
System.exit(0);
}
JCO.Table table =
function.getTableParameterList().getTable("COMPANYCODE_LIST");
int records = table.getNumRows();
for (int i = 0; i < records; i++) {
table.setRow(i);
function = createFunction("BAPI_COMPANYCODE_GETDETAIL");
function.getImportParameterList()
.setValue(table.getString("COMP_CODE"),
"COMPANYCODEID");
mConnection.execute(function);
bapiReturn = function.getExportParameterList()
.getStructure("RETURN");
if ( ! (bapiReturn.getString("TYPE").equals("") ||
bapiReturn.getString("TYPE").equals("S")) ) {
System.out.println(bapiReturn.getString("MESSAGE"));
}
}
109
Figure 8
January/February 2004
Figure 9
110
Tips and Tricks for SAP Java Connector (JCo) Client Programming
getExportParameterList(), and
getTableParameterList() methods. (See Figure 7
for sample code using these methods.)
Although most developers get used to the standard
programming model after comparatively little time,
some still feel uncomfortable. For these developers,
JCo offers an alternative, the Request/Response
programming model. Instead of explicitly creating
a JCO.Function object, the application creates an
object of type JCO.Request. This object then allows
access to all parameters defined as Import or Tables.
To invoke the RFM, you use the
execute(JCO.Request request) method of object
type JCO.Client. This overloaded version of the
execute(JCO.Function function) method returns
an object of type JCO.Response, which allows access
to all Export and Tables parameters. Figure 8 shows
a sample method (similar to the createFunction()
method in Figure 6) that can be used to encapsulate
the creation of a JCO.Request object. Figure 9
contains the application code from Figure 7, rewritten
to use the Request/Response programming model.
There are no performance penalties for using the
Request/Response model, so your choice should
be based entirely on your personal preferences.
Each development project should probably define
a standard for this choice, so that developers have
no problem when maintaining other peoples code.
111
January/February 2004
Figure 10
import com.sap.mw.jco.*;
static final String POOL_NAME = "ARAsoft";
try {
if (JCO.getClientPoolManager().getPool(POOL_NAME) == null) {
OrderedProperties logonProperties =
OrderedProperties.load("/logon.properties");
JCO.addClientPool(POOL_NAME, 10, logonProperties);
}
JCO.Pool pool = JCO.getClientPoolManager().getPool(POOL_NAME);
}
catch (Exception ex) {
ex.printStackTrace();
}
112
Tips and Tricks for SAP Java Connector (JCo) Client Programming
Figure 11
jco.client.client=001
jco.client.user=userid
jco.client.passwd=secret
jco.client.ashost=hostname
jco.client.sysnr=00
Figure 12
function.getTableParameterList().setActive(false, "TABLE_PARAM");
113
January/February 2004
Figure 13
import com.sap.mw.jco.*;
import de.arasoft.java.ARAsoftException;
import de.arasoft.sap.jco.BapiMessageInfo;
import de.arasoft.sap.jco.StandardRepositoryManager;
public class CompanyCodes {
JCO.Repository mRepository;
JCO.Client mConnection;
static final String POOL_NAME = "ARAsoft";
public CompanyCodes() {
try {
if (JCO.getClientPoolManager().getPool(POOL_NAME) == null) {
OrderedProperties logonProperties =
OrderedProperties.load("/logon.properties");
JCO.addClientPool(POOL_NAME, 10, logonProperties);
}
JCO.Pool pool = JCO.getClientPoolManager().getPool(POOL_NAME);
mRepository =
StandardRepositoryManager.getSingleInstance()
.getRepository(pool, true);
mConnection = JCO.getClient(POOL_NAME);
JCO.Function function =
createFunction("BAPI_COMPANYCODE_GETLIST");
mConnection.execute(function);
BapiMessageInfo returnMessage =
new BapiMessageInfo(function.getExportParameterList()
.getStructure("RETURN"));
if ( ! returnMessage.isBapiReturnCodeOkay() ) {
System.out.println(returnMessage.getFormattedMessage());
System.exit(0);
}
JCO.Table table =
function.getTableParameterList().getTable("COMPANYCODE_LIST");
function = createFunction("BAPI_COMPANYCODE_GETDETAIL");
// Create a table based on a structure
114
Tips and Tricks for SAP Java Connector (JCo) Client Programming
Figure 13 (continued)
JCO.Table infos =
new JCO.Table(function.getExportParameterList()
.getStructure("COMPANYCODE_DETAIL"));
infos.ensureBufferCapacity(table.getNumRows());
int records = table.getNumRows();
for (int i = 0; i < records; i++) {
table.setRow(i);
function = createFunction("BAPI_COMPANYCODE_GETDETAIL");
function.getImportParameterList()
.setValue(table.getString("COMP_CODE"),
"COMPANYCODEID");
mConnection.execute(function);
returnMessage =
new BapiMessageInfo(function.getExportParameterList()
.getStructure("RETURN"));
if ( ! returnMessage.isBapiReturnCodeOkay(false, false,
null, "FN021") ) {
System.out.println(returnMessage.getFormattedMessage());
System.exit(0);
}
// Copy the data of the structure to the table
infos.copyFrom(function.getExportParameterList()
.getStructure("COMPANYCODE_DETAIL"));
}
infos.writeHTML("c:\\infos.html");
}
catch (Exception ex) {
ex.printStackTrace();
}
finally {
JCO.releaseClient(mConnection);
}
}
public static void main(String[] args) {
CompanyCodes app = new CompanyCodes();
}
}
115
Figure 14
January/February 2004
Exception Handling
Synchronization in JCo
116
Tips and Tricks for SAP Java Connector (JCo) Client Programming
Figure 15
117
Figure 16
January/February 2004
118
Tips and Tricks for SAP Java Connector (JCo) Client Programming
Figure 17
import com.sap.mw.jco.util.SyncDateFormat;
private static final SyncDateFormat dateISO =
new SyncDateFormat("yyyy-MM-dd");
private static final SyncDateFormat timeISO =
new SyncDateFormat("HH:mm:ss");
private static final SyncDateFormat dateTimeISO
= new SyncDateFormat("yyyy-MM-ddHH:mm:ss");
public static Date combineDateAndTime(Date date, Date time) {
try {
return dateTimeISO.parse(dateISO.format(date) +
timeISO.format(time));
}
catch (Exception ex) { return null; }
}
public static Date combineDateAndTime(JCO.Field date, JCO.Field time) {
try {
return combineDateAndTime(date.getDate(), time.getDate());
}
catch (Exception ex) { return null; }
}
119
Figure 18
January/February 2004
120
Tips and Tricks for SAP Java Connector (JCo) Client Programming
Figure 19
Figure 20
121
Figure 21
January/February 2004
JCO.Function function =
createFunction("BAPI_COMPANYCODE_GETLIST");
mConnection.execute(function);
JCO.Structure bapiReturn = function.getExportParameterList()
.getStructure("RETURN");
if ( ! isBapiReturnCodeOkay(bapiReturn) ) {
System.out.println(bapiReturn.getString("MESSAGE"));
System.exit(0);
}
Figure 22
122
Tips and Tricks for SAP Java Connector (JCo) Client Programming
Figure 23
JCO.Function function =
createFunction("BAPI_COMPANYCODE_GETLIST");
mConnection.execute(function);
if ( ! isBapiReturnCodeOkay(function) ) {
System.exit(0);
}
123
January/February 2004
Appendix A:
Class ARAsoftException
package de.arasoft.java;
/*
* Copyright (c) 2001 ARAsoft GmbH
* All Rights Reserved.
*/
/**
* Exception class
*
* @author ARAsoft GmbH
* @version 1.0
* @since 1.0
*/
public class ARAsoftException extends Exception {
private Exception mOriginalException = null;
private final static Copyright copyright = new Copyright();
/**
* Constructor.
*/
public ARAsoftException() {
super();
}
/**
* Constructor to be used if we wrap another exception.
* @param originalException The original exception
*/
public ARAsoftException(java.lang.Exception originalException) {
super(originalException.toString());
mOriginalException = originalException;
}
/**
* Constructor with a message string.
* @param s Exception string
*/
public ARAsoftException(String s) {
super(s);
}
124
/**
* Constructor to be used if we wrap another exception and have an
* additional message string.
* @param s Exception string
* @param originalException The original exception
*/
public ARAsoftException(String s, Exception originalException) {
super(s);
mOriginalException = originalException;
}
/**
* Returns the original exception.
* @return The original exception.
*/
public Exception getOriginalException() {
return mOriginalException;
}
/**
* Returns the exception message.
* @return The exception message.
*/
public String getMessage() {
if (mOriginalException == null)
return super.getMessage();
return super.getMessage() + '\n' +
"Original exception:" + '\n' +
mOriginalException.toString();
}
}
125
January/February 2004
Appendix B:
Class StandardRepositoryManager
package de.arasoft.sap.jco;
import java.util.TreeMap;
import com.sap.mw.jco.*;
import de.arasoft.java.ARAsoftException;
/*
* Copyright (c) 2002 ARAsoft GmbH
* All Rights Reserved.
*/
/**
* A singleton object that manages JCO.Repository objects.
*
* @author ARAsoft GmbH
* @version 2.5
* @since 2.5
*/
public class StandardRepositoryManager {
static private StandardRepositoryManager repositoryManager = null;
static private TreeMap items = null;
protected StandardRepositoryManager() {
items = new TreeMap();
}
/**
* Returns the singleton instance of this class.
* @return The singleton instance.
*/
static public synchronized StandardRepositoryManager
getSingleInstance() {
if ( repositoryManager == null )
repositoryManager = new StandardRepositoryManager();
return repositoryManager;
}
/**
* Creates a JCO.Repository object for the SAP system to which the pool
* is connected.
* Throws an exception if a repository for this system already exists.
126
127
January/February 2004
client = JCO.getClient(pool.getName());
String name = client.getAttributes().getSystemID();
JCO.releaseClient(client);
client = null;
return this.existsRepository(name);
}
catch (Exception ex) {
throw new ARAsoftException(ex);
}
finally {
if ( client != null ) {
JCO.releaseClient(client);
}
}
}
/**
* Returns the JCO.Repository object for the SAP system to which the
* pool is connected.
* Throws an exception if no repository exists.
* @return The repository object.
* @param pool The JCO.Pool object.
*/
public synchronized JCO.Repository getRepository(JCO.Pool pool)
throws ARAsoftException {
return this.getRepository(pool, false);
}
/**
* Returns the JCO.Repository object for the SAP system to which the
* pool is connected. If no repository exists and
* <code>createIfItDoesNotExist</code>
* is <code>true</code>, a new repository is created,
* otherwise an exception is thrown.
* @return The repository object.
* @param pool The JCO.Pool object.
* @param createIfItDoesNotExist Should a new repository be created
*
if none exists?
*/
public synchronized JCO.Repository getRepository
(JCO.Pool pool, boolean createIfItDoesNotExist)
throws ARAsoftException {
JCO.Client client = null;
try {
client = JCO.getClient(pool.getName());
String name = client.getAttributes().getSystemID();
JCO.releaseClient(client);
client = null;
try {
return this.getRepository(name);
128
}
catch (ARAsoftException ax) {
if ( createIfItDoesNotExist ) {
return this.createRepository(pool);
} else {
throw ax;
}
}
}
catch (Exception ex) {
throw new ARAsoftException(ex);
}
finally {
if ( client != null ) {
JCO.releaseClient(client);
}
}
}
/**
* Returns the JCO.Repository object for the specified SAP system.
* If no repository exists an exception is thrown.
* @return The repository object.
* @param systemId The system ID of the SAP system.
*/
public synchronized JCO.Repository getRepository(String systemId)
throws ARAsoftException {
JCO.Repository repository = (JCO.Repository) items.get(systemId);
if ( repository == null )
throw new ARAsoftException
("No repository exists for system '"
+ systemId + "'.");
return repository;
}
/**
* Removes the specified JCO.Repository object.
* @param repository The repository to be removed.
*/
public synchronized void removeRepository(JCO.Repository repository)
{
String name = repository.getName();
if ( items.containsValue(repository) ) {
items.remove(name);
}
}
}
129
January/February 2004
Appendix C:
Class OrderedProperties
import java.util.*;
import java.io.*;
public class OrderedProperties extends java.util.Properties {
ArrayList orderedKeys = new ArrayList();
public OrderedProperties() {
super();
}
public OrderedProperties(java.util.Properties defaults) {
super(defaults);
}
public synchronized Iterator getKeysIterator() {
return orderedKeys.iterator();
}
public static OrderedProperties load(String name)
throws Exception {
OrderedProperties props = null;
java.io.InputStream is =
OrderedProperties.class.getResourceAsStream(name);
props = new OrderedProperties();
if (is != null) {
props.load(is);
return props;
}
else {
throw new IOException("Properties could not be loaded.");
}
}
public synchronized Object put(Object key, Object value) {
Object obj = super.put(key, value);
orderedKeys.add(key);
return obj;
}
public synchronized Object remove(Object key) {
Object obj = super.remove(key);
orderedKeys.remove(key);
return obj;
}
}
130
Subscribe Risk-Free
SAP Professional Journal is backed by a 100% money-back guarantee. If at any point, for any reason, you are not
completely satisfied, we will refund your subscription payment IN FULL. Don't wait any longer to benefit from the most
respected technical journal for SAP expertise. This is the most in-depth publication written specifically for SAP
professionals like you. Subscribe to SAP Professional Journal today at www.SAPpro.com or call us at 781-751-8799.
www.SAPpro.com