Uploaded image for project: 'Corda'
  1. CORDA-1749

RPC client of Corda Enterprise doesn't work with Spring Boot

    Details

    • Type: Bug
    • Status: Done (View workflow)
    • Priority: Medium
    • Resolution: Done
    • Affects Version/s: R3 Corda 3.0 GA
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None

      Description

      Corda Enterprise GA RPC Client doesn't work from within the Spring Boot container and potentially other containers which use classloader level isolation.

      This happens because the serialisation engine uses System Class Loader for class lookup: https://github.com/corda/enterprise/blob/eee2563bfafecbcda8c53563983d8a938511d6d7/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/serialization/amqp/AMQPClientSerializationScheme.kt#L55 and in such containers as Spring Boot, application level classes are not visible to the System Class Loader. Due to that, any RPC call fails with a serialisation exception (see below).

      This issue has been raised by NTTData, who are one of the first ones who tried the GA in action. Stefano Franz temporarily fixed the issue by creating a custom version of the `corda-serialisation.jar` for NTTData, which uses thread-local classloader instead.

      This bug is particularly critical as it will affect every spring-boot application.

      No easy workaround has been discover so far.

      To reproduce the issue - make any RPC call from a spring-boot application.

      Exception:

      java.io.NotSerializableException: Unexpected throwable: net/corda/serialization/internal/carpenter/SimpleFieldAccess
              at net.corda.serialization.internal.amqp.DeserializationInput.des(DeserializationInput.kt:95)
              at net.corda.serialization.internal.amqp.DeserializationInput.deserialize(DeserializationInput.kt:108)
              at net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme.deserialize(AMQPSerializationScheme.kt:169)
              at net.corda.serialization.internal.SerializationFactoryImpl$deserialize$1$1.invoke(SerializationScheme.kt:136)
              at net.corda.core.serialization.SerializationFactory.withCurrentContext(SerializationAPI.kt:77)
              at net.corda.serialization.internal.SerializationFactoryImpl$deserialize$1.invoke(SerializationScheme.kt:136)
              at net.corda.serialization.internal.SerializationFactoryImpl$deserialize$1.invoke(SerializationScheme.kt:106)
              at net.corda.core.serialization.SerializationFactory.asCurrent(SerializationAPI.kt:91)
              at net.corda.serialization.internal.SerializationFactoryImpl.deserialize(SerializationScheme.kt:136)
              at net.corda.nodeapi.RPCApi$ServerToClient$Companion.fromClientMessage(RPCApi.kt:370)
              at net.corda.client.rpc.internal.RPCClientProxyHandler.artemisMessageHandler(RPCClientProxyHandler.kt:301)
              at net.corda.client.rpc.internal.RPCClientProxyHandler.access$artemisMessageHandler(RPCClientProxyHandler.kt:97)
              at net.corda.client.rpc.internal.RPCClientProxyHandler$initSessions$1.invoke(RPCClientProxyHandler.kt:503)
              at net.corda.client.rpc.internal.RPCClientProxyHandler$initSessions$1.invoke(RPCClientProxyHandler.kt:97)
              at net.corda.client.rpc.internal.RPCClientProxyHandlerKt$sam$org_apache_activemq_artemis_api_core_client_MessageHandler$0.onMessage(RPCClientProxyHandler.kt)
              at org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl.callOnMessage(ClientConsumerImpl.java:1002)
              at org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl.access$400(ClientConsumerImpl.java:50)
              at org.apache.activemq.artemis.core.client.impl.ClientConsumerImpl$Runner.run(ClientConsumerImpl.java:1125)
              at org.apache.activemq.artemis.utils.actors.OrderedExecutor.doTask(OrderedExecutor.java:42)
              at org.apache.activemq.artemis.utils.actors.OrderedExecutor.doTask(OrderedExecutor.java:31)
              at org.apache.activemq.artemis.utils.actors.ProcessorBase.executePendingTasks(ProcessorBase.java:66)
              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
              at org.apache.activemq.artemis.utils.ActiveMQThreadFactory$1.run(ActiveMQThreadFactory.java:118)
      Caused by: java.lang.NoClassDefFoundError: net/corda/serialization/internal/carpenter/SimpleFieldAccess
              at java.lang.ClassLoader.defineClass1(Native Method)
              at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
              at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
              at net.corda.serialization.internal.carpenter.CarpenterClassLoader.load(ClassCarpenter.kt:39)
              at net.corda.serialization.internal.carpenter.ClassCarpenterImpl.generate(ClassCarpenter.kt:231)
              at net.corda.serialization.internal.carpenter.ClassCarpenterImpl.generateClass(ClassCarpenter.kt:197)
              at net.corda.serialization.internal.carpenter.ClassCarpenterImpl.build(ClassCarpenter.kt:151)
              at net.corda.serialization.internal.carpenter.MetaCarpenterBase.step(MetaCarpenter.kt:79)
              at net.corda.serialization.internal.carpenter.MetaCarpenter.build(MetaCarpenter.kt:109)
              at net.corda.serialization.internal.amqp.SerializerFactory.runCarpentry(SerializerFactory.kt:293)
              at net.corda.serialization.internal.amqp.SerializerFactory.processSchema(SerializerFactory.kt:286)
              at net.corda.serialization.internal.amqp.SerializerFactory.processSchema$default(SerializerFactory.kt:260)
              at net.corda.serialization.internal.amqp.SerializerFactory$get$2.invoke(SerializerFactory.kt:229)
              at net.corda.serialization.internal.amqp.SerializerFactory$get$2.invoke(SerializerFactory.kt:53)
              at net.corda.serialization.internal.amqp.SerializerFactory.get(SerializerFactory.kt:227)
              at net.corda.serialization.internal.amqp.DeserializationInput.readObject$serialization(DeserializationInput.kt:158)
              at net.corda.serialization.internal.amqp.DeserializationInput.readObjectOrNull$serialization(DeserializationInput.kt:136)
              at net.corda.serialization.internal.amqp.DeserializationInput$deserialize$1.invoke(DeserializationInput.kt:113)
              at net.corda.serialization.internal.amqp.DeserializationInput.des(DeserializationInput.kt:91)
              ... 23 common frames omitted
      Caused by: java.lang.ClassNotFoundException: net.corda.serialization.internal.carpenter.SimpleFieldAccess
              at java.lang.ClassLoader.findClass(ClassLoader.java:530)
              at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
              at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
              ... 42 common frames omitted
      

        Attachments

          Issue links

            Activity

              People

              • Assignee:
                Stefano.Franz Stefano Franz
                Reporter:
                Ivan.Schasny Ivan Schasny
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: