SAP JCo 3.0 + Tomcat 6.0

Hallo to you!

previously it was all about deploying java applications to Tomcat. Today I’ll explain how to use JAVA-Connector JCo 3.0 on a tomcat webserver.

while JCo 2.0 is pretty good covered, JCo 3.0 is not.

requirements:

jco lib: libsapjco3.so

jco jar: sapjco3.jar

libsapjco3.so must be copied into the JDK folder.

under ubuntu thi is:

/usr/lib/jvm/java-1.5.0-sun/jre/lib/i386

sapjco3.jar must be copied into to classpath of the application that shall be deployed on tomcat. Additionally, sapjco3.jar must be copied in the lib folder of your tomcat6 server installation.

After this you can deploy the app like stated in the previous article.

for questions regarding SAP/JCo you can write me an email or leave a comment

I’ve got one solution for all who want to run jco on tomcat but run into two problems:

1. you can register the DestinationDataProvider only once

2. the method Environment.isDestinationDataProviderRegistered() produces the following exception after several runs

java.lang.ExceptionInInitializerError: Error getting the version of the native layer: java.lang.UnsatisfiedLinkError: com/sap/conn/rfc/driver/CpicDriver.nativeCpicGetVersion

The error is probably caused by a bug in JCo itself. Also possible is that i just have wrong configuration settings. Regardless of that,a solution is regisrtering the DataProvider within an empty try catch block and with that not calling the erroneous jco method..

Code with isDestinationDataProviderSet():

public SAPConnection(SAPServerData serverData){
		this.serverConnectionProperties = new Properties();
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_ASHOST, serverData.getHost());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_SYSNR, serverData.getSystemNr());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_CLIENT, serverData.getClient());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_USER, serverData.getUser());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_PASSWD, serverData.getPassword());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_LANG, serverData.getLanguage());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10");
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "5");
		//this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_EXPIRATION_PERIOD, Integer.toString(serverData.getTimeout()));

		//set properties of testsystem provider
		provider.changePropertiesForABAP_AS(serverConnectionProperties);

		//avoid multiple provider loading, which would lead to an exception
		if(!Environment.isDestinationDataProviderRegistered()){
			//register provider
			Environment.registerDestinationDataProvider(provider);
		}

		//try to establish connection
		try{
			this.destination = JCoDestinationManager.getDestination(SAP_SERVER);
			this.repository=this.destination.getRepository();
		}
		catch( JCoException e){
			e.printStackTrace();
			return;
		}
	}

Code without isDestinationDataProviderRegistered():

public SAPConnection(SAPServerData serverData){
		this.serverConnectionProperties = new Properties();
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_ASHOST, serverData.getHost());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_SYSNR, serverData.getSystemNr());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_CLIENT, serverData.getClient());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_USER, serverData.getUser());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_PASSWD, serverData.getPassword());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_LANG, serverData.getLanguage());
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_PEAK_LIMIT, "10");
		this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_POOL_CAPACITY, "5");
		//this.serverConnectionProperties.setProperty(DestinationDataProvider.JCO_EXPIRATION_PERIOD, Integer.toString(serverData.getTimeout()));

		//set properties of testsystem provider
		provider.changePropertiesForABAP_AS(serverConnectionProperties);

		//avoid multiple provider loading, which would lead to an exception.
		try {
			//register provider
			Environment.registerDestinationDataProvider(provider);
		} catch (Exception e1) {}

		//try to establish connection
		try{
			this.destination = JCoDestinationManager.getDestination(SAP_SERVER);
			this.repository=this.destination.getRepository();
		}
		catch( JCoException e){
			e.printStackTrace();
			return;
		}
	}

6 Gedanken zu “SAP JCo 3.0 + Tomcat 6.0

  1. hast du eine eine komplette verbindungsklasse mit einer testklasse. mit SAPJCo3

  2. leider funktioniert deine e-mail adresse nicht. wenn du mir eine andere hinterlässt, kann ich dir mit beidem weiterhelfen

    vg, nico

  3. Wie implementiere ich aber mehrfache destinations? Ich habe den anwengungsfall, dass ich gleichzeitig eine Verbindung zum SAP R3 aber auch zum SAP GTS aufrecht erhalten will. Bisher habe ich lediglich erreicht, dass ich durch register und unregister jeweils den richtigen provider ansprechen kann. Wenn aber zu schnell hintereinander beide angesprochen werden und der einen Call den anderen überholt die destination für den ersten call abgebaut worder sein. Wenn ich das Thread save programmiere habe ich aber viel zu lange warte zeiten weil manche Calls gegen das SAP R3 lange brauchen.

    Aus diesen Grund benötige ich zwei DestinationProvider gleichzeitig. Kann ich mehrere Environments betreiben?

    Ich verwende tomcat 5 und jco 3.

  4. Hallo Eduard,

    das habe ich noch nicht probiert. Du kannst höchstens versuchen, mehrere WAR files zu deployen, die über einen lokalen Socket mit einer Controller-Klasse kommunizieren.

  5. Habe es jetzt hinbekommen verschiedene Systeme anzusprechen. Ich habe angenommen ich bräuchte für jedes System (SAP R3 oder SAP GTS etc.) jeweils einen DestinationDataProvider. Genau an diesem Punkt lag ich falsch.

    Ich habe jetzt einen eigenen CustomDestinationDataProvider mit dem DestinationDataProvider Interface implementiert. In dem CustomDestinationProvider habe ich eine Map mit DestinationName als Key und die Properties als Value angelegt. Beim initialen registrieren des DestinationDataProviders werden beide destination properties über die map mitgenommen. Der DestinationDataProvider hat damit auch beide destinations im Bauch. Danach kann ich auch über JCoDestinationManager.getDestination(destination) meine speziefische destination holen.
    Funktioniert einwandfrei.

Schreibe einen Kommentar