2

I want to use S/4 HANA SDK in my existing java project in SCP Neo. I was advised to generate a new project, then move my existing code to the generated project under application. I generated a new project with the architect type specified in S/4 HANA SDK tutorial step 2 and copy existing my code to the application module. When I tried to deploy my application in SCP Neo and tried to start it. It didn't start and in the SCP log, I saw the following error. Please advise how to fix it? (my existing also uses a logger).

Best regards

Fred Z

24 Feb 23:14:15 UTC - org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/s4scheduler-application]
2019 02 24 23:14:15#+00#ERROR#org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/s4scheduler-application]##anonymous#localhost-startStop-1#na#ogfigrvps3#s4schedulerapplication#web##na#na#na#na#Error configuring application listener of class [com.sap.cloud.sdk.s4hana.connectivity.ErpDestination] java.lang.LinkageError: loader constraint violation: when resolving method "org.slf4j.impl.StaticLoggerBinder.getLoggerFactory()Lorg/slf4j/ILoggerFactory;" the class loader "<unnamed>" (instance of org.apache.catalina.loader.ParallelWebappClassLoader@3b3235ca, child of java.net.URLClassLoader@61baa894) of the current class, org/slf4j/LoggerFactory, and the class loader "System" (instance of sun.misc.Launcher$AppClassLoader@277050dc, child of sun.misc.Launcher$ExtClassLoader@2b71fc7e, urls: 'file:/usr/lib/jvm/sapjvm_8/sapjvm_8/lib/jvmx.jar', 'file:/usr/lib/jvm/sapjvm_8/sapjvm_8/lib/tools.jar', 'file:/usr/sap/ljs/bin/jul-to-slf4j.jar', 'file:/usr/sap/ljs/bin/slf4j-api.jar', 'file:/usr/sap/ljs/bin/logback-classic.jar', 'file:/usr/sap/ljs/bin/logback-core.jar', 'file:/usr/sap/ljs/bin/logback-config/', 'file:/usr/sap/ljs/bin/com.sap.core.js.logging.jar', 'file:/usr/sap/ljs/bin/bootstrap.jar', 'file:/usr/sap/ljs/bin/tomcat-juli.jar') for the method's defining class, org/slf4j/impl/StaticLoggerBinder, have different Class objects for the type org/slf4j/ILoggerFactory used in the signature
at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:418)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
at com.sap.cloud.sdk.cloudplatform.logging.CloudLoggerFactory.<clinit>(CloudLoggerFactory.java:21)
at com.sap.cloud.sdk.cloudplatform.connectivity.DestinationDeclarator.<clinit>(DestinationDeclarator.java:29)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:151)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4714)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5256)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:754)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:730)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:985)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1857)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:836)
Fred Z
  • 29
  • 3
  • Possible duplicate of [SLF4J error: class loader have different class objects for the type](https://stackoverflow.com/questions/29504180/slf4j-error-class-loader-have-different-class-objects-for-the-type) – Matt Ke Feb 25 '19 at 02:06
  • Can you check if you include (different versions of) slf4j multiple times? Did you add any dependencies or made other changes to the pom.xml files generated by the archetype? – Henning Heitkötter Feb 25 '19 at 07:20
  • 1
    To add on to Henning's comment: you can check this by running `mvn dependency:tree` in the `application` directory of your app. – Dennis H Feb 25 '19 at 07:49
  • Hi all, yes. I am not developing a brand new application. I tried to move existing app to S4 SDK. The existing libraries my code uses do use slf4j of different versions. what's the best way to resolve this? – Fred Z Feb 26 '19 at 04:49
  • Can you please add the output of `mvn dependency:tree -Dincludes=*slf4j*` (run in the root directory of your project) to your question. Then we can directly give you a suggestion. – Christoph Schubert Feb 27 '19 at 07:58
  • Here is the output of mve dependency:tree -Dincludes=*slf4j* [INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) @ s4scheduler-application --- [INFO] com.sap.iag.cloud.sdk:s4scheduler-application:war:1.0-SNAPSHOT [INFO] +- org.slf4j:slf4j-api:jar:1.7.25:compile [INFO] \- org.slf4j:jcl-over-slf4j:jar:1.7.25:runtime [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS – Fred Z Mar 03 '19 at 21:06
  • From this alone I can't see any error... could you post the complete output of `mvn dependency:tree` please? – Dennis H Mar 04 '19 at 08:07
  • Hi, here is the full output – Fred Z Mar 05 '19 at 07:48

1 Answers1

1

Solutions

Depending on whether some.other.group.id:some-other-artifact-id is under your control you have two options, with option 1 being the preferred one.

  1. If you can change the dependencies of some-other-artifact-id, remove any concrete logger implementations with the scopes compile and provided, and replace them with the slf4j-api. If necessary, e.g. for tests, you can use concrete implementations in scopes test or runtime. This is in general best practice for libraries, as libraries cannot know which actual logger is used in the actual application built with the library.

  2. If you have no direct control over the dependencies in some-other-artifact-id you can remove the dependency by adding the following to the dependencies block of your pom.xml:

    <dependency>
        <groupId>some.other.group.id</groupId>
        <artifactId>some-other-artifact-id</artifactId>
        <exclusions>
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    

Background

The important part of the dependency tree is extracted below:

[INFO] --- maven-dependency-plugin:3.1.1:tree (default-cli) @ some-application ---
[INFO] some.group.id:some-artifact-id:jar:1.0
...
[INFO] +- org.slf4j:slf4j-api:jar:1.7.25:compile
[INFO] +- org.slf4j:jcl-over-slf4j:jar:1.7.25:runtime
[INFO] +- some.other.group.id:some-other-artifact-id:jar:1.0:compile
...
[INFO] |  +- org.apache.httpcomponents:httpclient:jar:4.5.6:compile
[INFO] |  |  \- commons-logging:commons-logging:jar:1.2:compile
...

You have the jcl-over-slf4j and the commons-logging dependency on your classpath. As the first one is a "drop-in" replacement of the second one you now basically have two sets of implementations for the same classes which results in runtime errors.

Further reading

Christoph Schubert
  • 1,089
  • 1
  • 8
  • 16