javasaprfcjcoidoc

Sending iDOC from Java to SAP


We have iDOC files that are generated from our system. Now we are trying to send them to SAP via RFC connection. I already etablished an RFC connection AS A CLIENT but i am unable to send iDOC!

I tried to create a sample iDOC to test it but it doesn't work!

Exception in thread "main" java.lang.NoSuchMethodError: com.sap.conn.idoc.jco.SAPRepository$ConnectionProvider.execute(Lcom/sap/conn/jco/JCoFunction;Lcom/sap/conn/jco/rt/AbapRepository;)V
    at com.sap.conn.idoc.jco.SAPRepository.queryRootSegmentMetaData40(SAPRepository.java:1204)
    at com.sap.conn.idoc.jco.SAPRepository.queryRootSegmentMetaData(SAPRepository.java:1110)
    at com.sap.conn.idoc.jco.SAPRepository.getRootSegmentMetaData(SAPRepository.java:909)
    at com.sap.conn.idoc.rt.DefaultIDocDocument.<init>(DefaultIDocDocument.java:124)
    at com.sap.conn.idoc.rt.DefaultIDocDocument.<init>(DefaultIDocDocument.java:61)
    at com.sap.conn.idoc.jco.JCoIDocDocument.<init>(JCoIDocDocument.java:51)
    at com.sap.conn.idoc.jco.JCoIDocRuntime.createIDocDocument(JCoIDocRuntime.java:133)
    at com.sap.conn.idoc.jco.JCoIDocRuntime.createIDocDocument(JCoIDocRuntime.java:35)
    at com.sap.conn.idoc.rt.DefaultIDocRuntime.createIDocDocument(DefaultIDocRuntime.java:175)
    at com.sap.conn.idoc.rt.DefaultIDocRuntime.createIDocDocument(DefaultIDocRuntime.java:18)
    at com.idoc.sender.IDocClientExample.main(IDocClientExample.java:49)

I even tried to send a sample iDOC XML but i am also facing another error, tried to change the XML many times but i am facing the same problem again an again!

com.sap.conn.idoc.IDocParseException: (7) IDOC_ERROR_PARSE_FAILURE: Invalid character encountered in XML input data source:
state=READING_XMLDECLARATION, charPosition=14, lineNumber=1, columnNumber=15, invalidChar=U+003D,
sourceSnippet=...@<?xml version="1.0" encoding="UTF-8"?><DEBMAS06><IDOC><EDI_DC40><DOCNUM>20120114120000</DOCNUM><IDO...
                               ^
    at com.sap.conn.idoc.rt.xml.DefaultIDocXMLParser.throwIDocParseException(DefaultIDocXMLParser.java:2223)
    at com.sap.conn.idoc.rt.xml.DefaultIDocXMLParser.parseProlog(DefaultIDocXMLParser.java:1635)
    at com.sap.conn.idoc.rt.xml.DefaultIDocXMLParser.parse(DefaultIDocXMLParser.java:320)
    at com.sap.conn.idoc.rt.xml.DefaultIDocXMLProcessor.parse(DefaultIDocXMLProcessor.java:112)
    at com.sap.conn.idoc.rt.xml.DefaultIDocXMLProcessor.parse(DefaultIDocXMLProcessor.java:54)
    at com.sap.conn.idoc.rt.xml.DefaultIDocXMLProcessor.parse(DefaultIDocXMLProcessor.java:31)
    at com.idoc.sender.IDocClientExample.main(IDocClientExample.java:57)

This is the code i am using to create the iDOC and send the iDOC XML:

package com.idoc.sender;


import com.sap.conn.idoc.*;
import com.sap.conn.idoc.jco.JCoIDoc;
import com.sap.conn.jco.JCoDestination;
import com.sap.conn.jco.JCoDestinationManager;

import java.io.BufferedReader;
import java.io.FileReader;


public class IDocClientExample {

 public static void main(String[] args) {

  try {

   String iDocXML = null;
   FileReader fileReader;

   try {
    fileReader = new FileReader("TestSalesOrder.xml");
    BufferedReader br = new BufferedReader(fileReader);
    StringBuffer sb = new StringBuffer();
    String line;
    while ((line = br.readLine()) != null) {
     sb.append(line);
    }

    iDocXML = sb.toString();

    br.close();
    fileReader.close();
   } catch (Exception ex) {
    ex.printStackTrace();
   }

   // see provided configuration file xxxx.jcoDestination
   JCoDestination destination = JCoDestinationManager.getDestination("xxxx");
   IDocRepository iDocRepository = JCoIDoc.getIDocRepository(destination);
   String tid = destination.createTID();
   IDocFactory iDocFactory = JCoIDoc.getIDocFactory();

   System.out.println(destination.getAttributes());


   // a) create sample new idoc
   IDocDocument doc = iDocFactory.createIDocDocument(iDocRepository, "SYSTAT01");
   IDocSegment segment = doc.getRootSegment();
   segment.addChild("E1MARAM");
   JCoIDoc.send(doc, IDocFactory.IDOC_VERSION_DEFAULT, destination, tid);


   // b) use existent xml file
   IDocXMLProcessor processor = iDocFactory.getIDocXMLProcessor();
   IDocDocumentList iDocList = processor.parse(iDocRepository, iDocXML);
   JCoIDoc.send(iDocList, IDocFactory.IDOC_VERSION_DEFAULT, destination, tid);
   destination.confirmTID(tid);

  } catch (Exception e) {
   e.printStackTrace();
  }
  System.out.print("program end");
 }
}
// a) create sample new idoc
IDocDocument doc = iDocFactory.createIDocDocument(iDocRepository, "SYSTAT01");
IDocSegment segment = doc.getRootSegment();
segment.addChild("E1MARAM");
JCoIDoc.send(doc, IDocFactory.IDOC_VERSION_DEFAULT, destination, tid);


// b) use existent xml file
IDocXMLProcessor processor = iDocFactory.getIDocXMLProcessor();
IDocDocumentList iDocList = processor.parse(iDocRepository, iDocXML);
JCoIDoc.send(iDocList, IDocFactory.IDOC_VERSION_DEFAULT, destination, tid);
destination.confirmTID(tid);

} catch (Exception e) {
 e.printStackTrace();
}
System.out.print("program end");
}
}

This is my connection file:

jco.client.lang=EN
jco.client.client=100
jco.client.passwd=xxxx
jco.client.user=xxxx
jco.client.sysnr=01
jco.client.ashost=xxxx

This is my xml file:

<?xml version="1.0" encoding="UTF-8"?>
<DEBMAS06>
<IDOC>
<EDI_DC40>
<DOCNUM>20120114120000</DOCNUM><IDOCTYP>DEBMAS06</IDOCTYP>
<MESTYP>DEBMAS</MESTYP>
<SNDPOR>HTTPDEMO</SNDPOR>
<SNDPRT>LS</SNDPRT>
<SNDPRN>HTTPDEMO</SNDPRN>
<RCVPOR>SAPxxx</RCVPOR>
<RCVPRT>LS</RCVPRT>
<RCVPRN>xxxCLNT100</RCVPRN>
</EDI_DC40>
<E1KNA1M segment="1">
<KUNNR>47</KUNNR>
<NAME1>Test Customer</NAME1>
<KTOKD>0004</KTOKD>
<SORTL>TEST</SORTL>
<ORT01>City</ORT01>
<LAND1>PL</LAND1>
<LZONE>A</LZONE>
<SPRAS>L</SPRAS>
<STRAS>Street</STRAS>
</E1KNA1M>
</IDOC>
</DEBMAS06>

I am using sapjco3-x86-64bit-3.0.5 and sapidoc-3.0.1!

Testing the creation of iDOC and sending IDOC XML is just for test but in our case, we have the iDOC ready!

My question is, how can i send iDOC directly from my disk to SAP via RFC? If i can't do so, how can i slove the error of creating iDOC or sending iDOC XML? My second question, once i am able to send iDOC, do i have to etablish a new SERVER RFC connection so i can receive iDOC from SAP?

** EDIT **

Now i ma able to send and receive IDoc properly. My problem is how i can get the IDoc as a Flat IDoc.

I can receive my IDoc as XML IDoc with this code:

package com.idoc.actif;

import com.sap.conn.idoc.IDocDocumentList;
import com.sap.conn.idoc.IDocXMLProcessor;
import com.sap.conn.idoc.jco.*;
import com.sap.conn.jco.server.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;


public class IDocServerExample
{
    public static void main(String[] a)
    {   
        try
        {
            // see provided examples of configuration files xxxx.jcoServer and  xxxx.jcoDestination
            JCoIDocServer server = JCoIDoc.getServer("xxxx");
            server.setIDocHandlerFactory(new MyIDocHandlerFactory());

            server.setTIDHandler(new MyTidHandler());

            MyThrowableListener listener = new MyThrowableListener();
            server.addServerErrorListener(listener);
            server.addServerExceptionListener(listener);
            //server.setConnectionCount(1);
            server.start();

        }
        catch (Exception e) 
        {
            e.printStackTrace();
        }
     }

    static class MyIDocHandler implements JCoIDocHandler
    {
        public void handleRequest(JCoServerContext serverCtx, IDocDocumentList idocList)
        {

            FileOutputStream fos=null;
            OutputStreamWriter osw=null;
            try
            {
                //receiving XML IDoc, how to get the IDoc as a Flat IDoc (SAP is sending the IDoc as Flat)???
                IDocXMLProcessor xmlProcessor = JCoIDoc.getIDocFactory().getIDocXMLProcessor();
                fos=new FileOutputStream(serverCtx.getTID());
                osw=new OutputStreamWriter(fos, "UTF8");
                xmlProcessor.render(idocList, osw, IDocXMLProcessor.RENDER_WITH_TABS_AND_CRLF);
                osw.flush();
            }
            catch (Throwable thr)
            {
                thr.printStackTrace();
            }
            finally
            {
                try
                {
                    if (osw!=null)
                        osw.close();
                    if (fos!=null)
                        fos.close();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }

    static class MyIDocHandlerFactory implements JCoIDocHandlerFactory
    {
        private JCoIDocHandler handler = new MyIDocHandler();
        public JCoIDocHandler getIDocHandler(JCoIDocServerContext serverCtx)
        {
            return handler;
        }
    }

    static class MyThrowableListener implements JCoServerErrorListener, JCoServerExceptionListener
    {

        public void serverErrorOccurred(JCoServer server, String connectionId, JCoServerContextInfo ctx, Error error)
        {
            System.out.println(">>> Error occured on " + server.getProgramID() + " connection " + connectionId);
            error.printStackTrace();
        }
        public void serverExceptionOccurred(JCoServer server, String connectionId, JCoServerContextInfo ctx, Exception error)
        {
            System.out.println(">>> Error occured on " + server.getProgramID() + " connection " + connectionId);
            error.printStackTrace();
        }
    }

    static class MyTidHandler implements JCoServerTIDHandler
    {
        public boolean checkTID(JCoServerContext serverCtx, String tid)
        {
            System.out.println("checkTID called for TID="+tid);
            return true;
        }


        public void confirmTID(JCoServerContext serverCtx, String tid)
        {
            System.out.println("confirmTID called for TID="+tid);
        }


        public void commit(JCoServerContext serverCtx, String tid)
        {
            System.out.println("commit called for TID="+tid);
        }


        public void rollback(JCoServerContext serverCtx, String tid)
        {
            System.out.print("rollback called for TID="+tid);
        }
    }
}

Solution

  • I guess that there is an incompatibility between the two SAP libraries that you use. I recommend to install the latest patch levels first. Currently this is JCo version 3.0.17 and the Java IDoc Library 3.0.12.

    I only do not understand what you are doing with the StringBuffer here. If you would like to read IDoc-XML from a file, then the IDocXMLProcessor offers appropriate parse methods for this - the best would be

    IDocXMLProcessor.parse(IDocRepository repository, InputStream xmlStream)
    

    so that it also can take care of different file encodings as specified in the contained XML encoding attribute. If you choose a java.io.Reader or a String then you have to take care for this on your own (which you don't do in your example).

    But in principle your code doesn't seem to be wrong at first sight. In contrast to the IDoc-XML itself which is lacking the mandatory BEGIN="1" and SEGMENT="1" attributes for the <IDOC> and <EDI_DC40> tags.