5

I want to use SAP JCo to select user data for my Java program.

But all I got is:

Sep 23, 2014 1:34:28 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [StepByStepClient] in context with path [/Formularmanager-test]
threw exception [Servlet execution threw an exception] with root cause
java.lang.NoClassDefFoundError: Could not initialize class com.sap.conn.jco.JCo
  at com.sap.conn.jco.JCoDestinationManager.getDestination(JCoDestinationManager.java:61)
  at com.pferd.itdienste.sap.StepByStepClient.step1Connect(StepByStepClient.java:125)
  at com.pferd.itdienste.sap.StepByStepClient.processRequest(StepByStepClient.java:356)
  at com.pferd.itdienste.sap.StepByStepClient.doGet(StepByStepClient.java:70)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
  at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
  at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
  at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
  at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
  at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:1852)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
  at java.lang.Thread.run(Unknown Source)

For a test I use the example script StepByStepClient and I have modified this only, so I can use it as a Web servlet.

All files from SAP JCo are on C:\sapjco30P_11-10005326 and I have this folder registered in the system pfad variable.

At this moment I don't know where my error is! So I need help, please!

SAP Java Connector

  • Java Runtime
  • Operating System: Windows Server 2012 6.2 for amd64
  • Java VM: 1.7.0_60 Oracle Corporation
  • Default charset: windows-1252

Versions

  • JCo API: 3.0.11 (2014-04-15)
  • JCo middleware: JavaRfc 2.2.12
  • JCo library: 720.612

Library Paths

  • Path to JCo archive: C:\sapjco30P_11-10005326\sapjco3.jar
  • Path to JCo library: C:\sapjco30P_11-10005326\sapjco3.dll

Eclipse Juno XAMPP Tomcat 7

package com.pferd.itdienste.sap;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

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;

@WebServlet(name = "StepByStepClient", urlPatterns = {"/StepByStepClient"})
public class StepByStepClient extends HttpServlet
{
    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, "HOST");
        connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR,  "01");
        connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "200");
        connectProperties.setProperty(DestinationDataProvider.JCO_USER,   "USER");
        connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "PASSWORD");
        connectProperties.setProperty(DestinationDataProvider.JCO_LANG,   "en");
        createDataFile(ABAP_AS, "jcoDestination", connectProperties);

        connectProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "3");
        connectProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT,    "10");
        createDataFile(ABAP_AS_POOLED, "jcoDestination", connectProperties);

        connectProperties.clear();
        connectProperties.setProperty(DestinationDataProvider.JCO_MSHOST, "HOST");
        connectProperties.setProperty(DestinationDataProvider.JCO_R3NAME,  "SID");
        connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, "200");
        connectProperties.setProperty(DestinationDataProvider.JCO_USER,   "USER");
        connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, "PASSWORD");
        connectProperties.setProperty(DestinationDataProvider.JCO_GROUP, "GROUP");
        connectProperties.setProperty(DestinationDataProvider.JCO_LANG,   "en");
        createDataFile(ABAP_MS, "jcoDestination", connectProperties);
    }
   
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            processRequest(request, response);
        } catch (JCoException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            processRequest(request, response);
        } catch (JCoException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>    
    
    static void createDataFile(String name, String suffix, Properties properties)
    {
        File cfg = new File(name+"."+suffix);
        if(!cfg.exists())
        {
            try
            {
                FileOutputStream fos = new FileOutputStream(cfg, false);
                properties.store(fos, "for tests only !");
                fos.close();
            }
            catch (Exception e)
            {
                throw new RuntimeException("Unable to create the destination file " + cfg.getName(), e);
            }
        }
    }
    
    
    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();
    }
    
    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();
    }
    
    public static void step3SimpleCall() throws JCoException
    {
        JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS_POOLED);
        JCoFunction function = destination.getRepository().getFunction("STFC_CONNECTION");
        if(function == null)
            throw new RuntimeException("BAPI_COMPANYCODE_GETLIST not found in SAP.");

        function.getImportParameterList().setValue("REQUTEXT", "Hello SAP");
        
        try
        {
            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();
    }
    
    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");
        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 getXX 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();
    }

    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"));
        }

        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"));
            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 care about the SessionReferenceProvider. MultithreadedExample.java 
     * illustrates the more complex scenario, where the calls belonging to one session are 
     * executed from different threads.
     * 
     * Note: this example uses Z_GET_COUNTER and Z_INCREMENT_COUNTER. The 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 mark they remote enabled 
     * @throws JCoException
     */
    public static void step4SimpleStatefulCalls() throws JCoException
    {
        final JCoFunctionTemplate incrementCounterTemplate, getCounterTemplate;

        JCoDestination destination = JCoDestinationManager.getDestination(ABAP_MS);
        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_MS);
                    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)
        {
        }
        
    }
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws JCoException
    {
        step1Connect();
        step2ConnectUsingPool();
        step3SimpleCall();
        step4WorkWithTable();
        step4SimpleStatefulCalls();
    }
}
Sandra Rossi
  • 11,934
  • 5
  • 22
  • 48
user2372543
  • 51
  • 1
  • 1
  • 4

3 Answers3

0

The jar-file containing the com.sap.conn.jco.JCo is not on the classpath. Are you sure that you have correctly set it as a JVM parameter? Adding it to the PATH-variable is not going to work since your JVM does not read that variable.

Kurt Du Bois
  • 7,550
  • 4
  • 25
  • 33
  • No, but now i have add a system variable "CLASSPATH" with the right path and nothing changed. How can i correctly set is as a JVM parameter? And in eclipse i had add under "build path" -> "Add External class folder" the right folder with the .dll and the .jar file and the .jar file is add as an external jar file. – user2372543 Sep 23 '14 at 14:35
  • Take a look at the error stacktrace: the class "com.sap.conn.jco.JCoDestinationManager" is found and loaded without a problem! And this class is also contained in the sapjco3.jar! The error happens only in the next step, when the class "JCoDestinationManager" tries to load the class "JCo", which is also in sapjco3.jar. This rather looks like the jar file is corrupt?! How else could the JVM find one class, but not the other?! – Lanzelot Apr 17 '20 at 09:43
0

As it is said, the JCo jar file is not accessible during execution.
I think that you you can put the jar (and dll) under the webinf/lib directory of your webapp, or put them in the common lib directory of Tomcat if several app can use the lib.

PATRY Guillaume
  • 4,287
  • 1
  • 32
  • 41
0

For JCO 2, we paste the JCO dll file under c:\Windows\System32

Loic Mouchard
  • 1,121
  • 7
  • 22
  • 2
    Quote from the JCo SDK installation instructions (`installation.html`): _Note:_ Do not copy the `sapjco3.dll` neither into the `{windows-dir}\system32` nor into the `{windows-dir}\SysWOW64` directory. This will break the operability of other JCo versions that are already installed on the same system. Furthermore you would risk that the current installation also would not work anymore, if the `sapjco3.dll` gets replaced in the respective Windows system directory in the future. – Trixx May 10 '18 at 07:21
  • Thanks @Trixx, indeed it was different for SAP JCO 2. – Loic Mouchard May 11 '18 at 10:15
  • No, it was not. I have also got the installation instructions for JCo 2.1 here. The only exception was that the `librfc32.dll` from the classic RFC SDK needed to be installed in the Windows directory. But for the `sapjcorfc.dll` this was also not allowed. – Trixx May 11 '18 at 12:33