So I downloaded the Java connector sapjco3.jar and the examples and started to play.

I soon got put off by the fact that all the examples require a username and password to be stored in a file and the idoc example I found was a bit over complicated for someone coming from an ABAP background.

Much Googling later and here is what I ended up with. This stores the system connection details in a file but NOT the username and password.

The idoc is created by calling a RFC function and the bit that casts a JCoStructure into a String (to populate the sdata field) is quite useful (I think).

——— Start Java Code ————–
import java.util.HashMap;
import java.util.Properties;
import java.io.FileInputStream;
import java.io.IOException;

import com.sap.conn.jco.*;
import com.sap.conn.jco.rt.*;
import com.sap.conn.jco.ext.*;

/**
* This is the example that SAP should have delivered It keeps the system name
* etc in a file but not the user and password
*
* It will call a RFC function to create an idoc and print out the returned data
*
* Create a file called ABAP_AS.jcoDestination as below
* jco.client.lang=<language>
* jco.client.client=<client>
* jco.client.sysnr=<system number>
* jco.client.ashost=<hostname>
*
* Enter the required values starting lines: 158,185,196

* Install sapjco3,

* set environment variables: classpath, lib_path and path

* Compile with : javac iDocTest.java

* Run with command java iDocTest
*/
public class iDocTest {

    static String ABAP_AS = “ABAP_AS”;

    static class MyDestinationDataProvider implements DestinationDataProvider {

        private DestinationDataEventListener eL;
        private HashMap<String, Properties> secureDBStorage = new HashMap<String, Properties>();

        public Properties getDestinationProperties(String destinationName) {
            try {
                //read the destination from DB
                Properties p = secureDBStorage.get(destinationName);

                if (p != null) {
                    //check if all is correct, for example
                    if (p.isEmpty()) {
                        throw new DataProviderException(DataProviderException.Reason.INVALID_CONFIGURATION, “destination configuration is incorrect”, null);
                    }

                    return p;
                }

                return null;
            } catch (RuntimeException re) {
                throw new DataProviderException(DataProviderException.Reason.INTERNAL_ERROR, re);
            }
        }

        //An implementation supporting events has to retain the eventListener instance provided
        //by the JCo runtime. This listener instance shall be used to notify the JCo runtime
        //about all changes in destination configurations.
        public void setDestinationDataEventListener(DestinationDataEventListener eventListener) {
            this.eL = eventListener;
        }

        public boolean supportsEvents() {
            return true;
        }

        //implementation that saves the properties in a very secure way
        void changeProperties(String destName, Properties properties) {
            synchronized (secureDBStorage) {
                if (properties == null) {
                    if (secureDBStorage.remove(destName) != null) {
                        eL.deleted(destName);
                    }
                } else {
                    secureDBStorage.put(destName, properties);
                    eL.updated(destName); // create or updated
                }
            }
        }
    } // end of MyDestinationDataProvider

    static Properties getDestinationPropertiesFromUI() {

        Properties userProperties;
        Properties sapProperties;
        String JCO_CLIENT;
        String JCO_LANG;
        String JCO_SYSNR;
        String JCO_HOST;

        sapProperties = new Properties();
        userProperties = new Properties();

// Load ABAP_AS.jcoDestination file
        try {
            sapProperties.load(new FileInputStream(“ABAP_AS.jcoDestination”));

        } catch (IOException ex) {
            ex.printStackTrace();
        }
        // Get fixed connection details from properties file 
        JCO_LANG = sapProperties.getProperty(“jco.client.lang”);
        JCO_HOST = sapProperties.getProperty(“jco.client.ashost”);
        JCO_SYSNR = sapProperties.getProperty(“jco.client.sysnr”);
       JCO_CLIENT = sapProperties.getProperty(“jco.client.client”);
// Set connection details from strings retrieved fromn file above           
        userProperties.setProperty(DestinationDataProvider.JCO_ASHOST, JCO_HOST);
        userProperties.setProperty(DestinationDataProvider.JCO_SYSNR, JCO_SYSNR);
        userProperties.setProperty(DestinationDataProvider.JCO_CLIENT, JCO_CLIENT);
        userProperties.setProperty(DestinationDataProvider.JCO_LANG, JCO_LANG);

// Get username and password 
        System.console().printf(“Enter user:”);
        userProperties.setProperty(DestinationDataProvider.JCO_USER, System.console().readLine());

        System.console().printf(“Enter password:”);
        userProperties.setProperty(DestinationDataProvider.JCO_PASSWD, System.console().readLine());

        return userProperties;

    }

    public static void iDocCall(String destName) throws JCoException {
        //Declare destination for function call
        JCoDestination destination = JCoDestinationManager.getDestination(destName);
        String client = destination.getClient();

        // Declare function and check it exists
        JCoFunction idoc_input = destination.getRepository().getFunction(“IDOC_INBOUND_SINGLE”);
        if (idoc_input == null) {
            throw new RuntimeException(“IDOC_INBOUND_SINGLE not found in SAP.”);
        }

// Declare function fields, structures and tables
//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().   

// Declare:       
// Import Fields   
//      idoc_input.getImportParameterList().setValue(“MASS_PROCESSING”, ” “);

// Structures
        JCoStructure idoc_control = idoc_input.getImportParameterList().getStructure(“PI_IDOC_CONTROL_REC_40”);

//Tables       
        JCoTable idoc_data = idoc_input.getTableParameterList().getTable(“PT_IDOC_DATA_RECORDS_40”);

// Populate function fields, structures and tables     
// To create the idoc we only need to set the control and data
//iDoc Control
        idoc_control.setValue(“MANDT”, client);
        idoc_control.setValue(“DIRECT”, “2”);
        idoc_control.setValue(“MESTYP”, “MBGMCR”);
        idoc_control.setValue(“IDOCTYP”, “MBGMCR02”);
        idoc_control.setValue(“CIMTYP”, “ZMBGMCR02001”);
        idoc_control.setValue(“SNDPOR”, <enter_sndpor>);
        idoc_control.setValue(“SNDPRT”, <enter_sndprt>);
        idoc_control.setValue(“SNDPRN”, <enter_sndprn>);
        idoc_control.setValue(“RCVPOR”, <enter_rcvpor>);
        idoc_control.setValue(“RCVPRT”, <enter_rcvprt>);
        idoc_control.setValue(“RCVPRN”, <enter_rcvprn>);

//iDoc Data           
        JCoRepository repository = destination.getRepository();
        JCoStructure str_head, str_item;
        JCoRecordMetaData meta_head, meta_item;
        String sdata = “”;

//Create structures for sdata population
        meta_head = repository.getStructureDefinition(“E1BP2017_GM_HEAD_01”);
        str_head = JCo.createStructure(meta_head);

        meta_item = repository.getStructureDefinition(“E1BP2017_GM_ITEM_CREATE”);
        str_item = JCo.createStructure(meta_item);

        // Write idoc data
        idoc_data.appendRows(2); // Add 4 rows to internal table
        idoc_data.setValue(“MANDT”, client);
        idoc_data.setValue(“SEGNUM”, “1”);
        idoc_data.setValue(“PSGNUM”, “0”);
        idoc_data.setValue(“SEGNAM”, “E1BP2017_GM_HEAD_01”);

        str_head.setValue(“HEADER_TXT”, “Java test”);
        str_head.setValue(“PSTNG_DATE”, “20131008”);
        str_head.setValue(“REF_DOC_NO”, “12345”);
        sdata = ConvertToSDATA(str_head, meta_head);
        idoc_data.setValue(“SDATA”, sdata);

        idoc_data.nextRow(); // Move to next row
        idoc_data.setValue(“MANDT”, client);
        idoc_data.setValue(“SEGNUM”, “2”);
        idoc_data.setValue(“PSGNUM”, “0”);
        idoc_data.setValue(“SEGNAM”, “E1BP2017_GM_ITEM_CREATE”);
        str_item.setValue(“MATERIAL”, <enter_material>);
        str_item.setValue(“BATCH”, <enter_batch>);
        str_item.setValue(“ENTRY_QNT”, <enter_qty>);
        str_item.setValue(“EXPIRYDATE”, <enter_sled_date>);
        sdata = ConvertToSDATA(str_item, meta_item);
        idoc_data.setValue(“SDATA”, sdata);

//To set or get the parameters use the APIS setValue() and getValue(). 
        idoc_input.getTableParameterList().setValue(“PT_IDOC_DATA_RECORDS_40”, idoc_data);

// Execute the function call
        try {
            idoc_input.execute(destination);
        } catch (AbapException e) {
            System.out.println(e.toString());
            return;
        }

        // Get returned idoc number
        String idoc_number;
        idoc_number = idoc_input.getExportParameterList().getString(“PE_IDOC_NUMBER”);

        // Remove leading zeros from idoc number
        idoc_number = idoc_number.replaceFirst(“^0*”, “”);
        if (idoc_number.isEmpty()) {
            idoc_number = “0”;
        }
        // Write out idoc number
        System.out.println(“Created idoc number ” + idoc_number);

    }

    public static String ConvertToSDATA(JCoStructure data_in, JCoRecordMetaData meta_in) {
        /*
        Simply casting the structure to a string will fail (won’t compile)
        Concatenating the structure fields into a string will remove all the spaces
        so the field alignment is lost.
        The solution is to create a StringBuilder object of the correct length
        Initialize it with all spaces and then, using the structure metadata,
        insert each field at the correct start position
        * NB: This works for idocs where all fields are character types
        */
        String sdata = “”;
        int count = 0;
        int Start = 0;
        int End = 0;
        int Len = 0;

        // Declare string builder as 1000 long and fill with spaces
        StringBuilder strB = new StringBuilder(” “);
        strB.setLength(1000);
        ClearString1000(strB, 1000);

        // Get field count in structure
        count = meta_in.getFieldCount();
        count = count – 1;

        for (int i = 0; i <= count; i++) {
            Len = meta_in.getLength(i);
            End = Start + Len;
            strB.insert(Start, data_in.getValue(i));
            Start = End++;
        }
        sdata = strB.toString();
        return sdata;
    }

    public static StringBuilder ClearString1000(StringBuilder str, int Len) {
        // Sets all characters to space
        for (int i = 1; i <= Len; i++) {
            str.insert(i, ” “);
        }
        return str;
    }

    public static void main(String[] args) throws JCoException {

        MyDestinationDataProvider myProvider = new MyDestinationDataProvider();

        //register the provider with the JCo environment;
        //catch IllegalStateException if an instance is already registered
        try {
            com.sap.conn.jco.ext.Environment.registerDestinationDataProvider(myProvider);
        } catch (IllegalStateException providerAlreadyRegisteredException) {
            //somebody else registered its implementation,
            //stop the execution
            throw new Error(providerAlreadyRegisteredException);
        }

        String destName = “ABAP_AS”;
        iDocTest dest;

        dest = new iDocTest();

        //set properties for the destination and …
        myProvider.changeProperties(destName, getDestinationPropertiesFromUI());

        //… work with it             
        iDocTest.iDocCall(destName);

        //Clear the properties and …
        myProvider.changeProperties(destName, null);
    }
}

——— End Java Code ————–

To report this post you need to login first.