AttachmentsClassLoader fails when calling setURLStreamHandlerFactory
See original GitHub issue- A clear description of the issue
AttachmentsClassLoader
blindly attempts to set a custom URLStreamHandlerFactory
by calling URL.setURLStreamHandlerFactory
. The problem with this approach is the method can be called at most once in a given Java Virtual Machine, so an error is thrown if a factory has already been set elsewhere, e.g. by Tomcat during integration testing.
For JDK8 this can be solved with using a decorator and reflection (example). As of Java 9 you can use SPI to provide handlers.
- Any logs or stack traces that you can provide (use a site like https://pastebin.com for larger logs)
e.g. when TransactionBuilder.toSignedTransaction is called:
java.lang.Error: factory already defined
at java.net.URL.setURLStreamHandlerFactory(URL.java:1112) ~[na:1.8.0_181]
at net.corda.core.serialization.internal.AttachmentsClassLoader.<clinit>(AttachmentsClassLoader.kt:45) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder$build$2.apply(AttachmentsClassLoader.kt:146) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder$build$2.apply(AttachmentsClassLoader.kt:136) ~[corda-core-4.0-SNAPSHOT.jar:na]
at java.util.HashMap.computeIfAbsent(HashMap.java:1127) ~[na:1.8.0_181]
at java.util.Collections$SynchronizedMap.computeIfAbsent(Collections.java:2672) ~[na:1.8.0_181]
at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder.build(AttachmentsClassLoader.kt:145) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder.withAttachmentsClassloaderContext(AttachmentsClassLoader.kt:153) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.LedgerTransaction.verifyInternal$core(LedgerTransaction.kt:135) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.LedgerTransaction.verify(LedgerTransaction.kt:121) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.TransactionBuilder.addMissingDependency(TransactionBuilder.kt:181) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.TransactionBuilder.toWireTransactionWithContext$core(TransactionBuilder.kt:168) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.TransactionBuilder.toWireTransactionWithContext$core$default(TransactionBuilder.kt:136) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.TransactionBuilder.toWireTransaction(TransactionBuilder.kt:133) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.TransactionBuilder.toSignedTransaction(TransactionBuilder.kt:701) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.node.ServiceHub$DefaultImpls.signInitialTransaction(ServiceHub.kt:228) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.node.ServiceHub$DefaultImpls.signInitialTransaction(ServiceHub.kt:242) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.node.services.api.ServiceHubInternal$DefaultImpls.signInitialTransaction(ServiceHubInternal.kt) ~[corda-node-4.0-SNAPSHOT.jar:na]
at net.corda.node.internal.AbstractNode$ServiceHubInternalImpl.signInitialTransaction(AbstractNode.kt:994) ~[corda-node-4.0-SNAPSHOT.jar:na]
at net.corda.core.node.ServiceHub$DefaultImpls.signInitialTransaction(ServiceHub.kt:251) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.node.services.api.ServiceHubInternal$DefaultImpls.signInitialTransaction(ServiceHubInternal.kt) ~[corda-node-4.0-SNAPSHOT.jar:na]
at net.corda.node.internal.AbstractNode$ServiceHubInternalImpl.signInitialTransaction(AbstractNode.kt:994) ~[corda-node-4.0-SNAPSHOT.jar:na]
same error when calling TransactionBuilder.verify
java.lang.Error: factory already defined
at java.net.URL.setURLStreamHandlerFactory(URL.java:1112) ~[na:1.8.0_181]
at net.corda.core.serialization.internal.AttachmentsClassLoader.<clinit>(AttachmentsClassLoader.kt:45) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder$build$2.apply(AttachmentsClassLoader.kt:146) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder$build$2.apply(AttachmentsClassLoader.kt:136) ~[corda-core-4.0-SNAPSHOT.jar:na]
at java.util.HashMap.computeIfAbsent(HashMap.java:1127) ~[na:1.8.0_181]
at java.util.Collections$SynchronizedMap.computeIfAbsent(Collections.java:2672) ~[na:1.8.0_181]
at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder.build(AttachmentsClassLoader.kt:145) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.serialization.internal.AttachmentsClassLoaderBuilder.withAttachmentsClassloaderContext(AttachmentsClassLoader.kt:153) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.LedgerTransaction.verifyInternal$core(LedgerTransaction.kt:135) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.LedgerTransaction.verify(LedgerTransaction.kt:121) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.TransactionBuilder.addMissingDependency(TransactionBuilder.kt:181) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.TransactionBuilder.toWireTransactionWithContext$core(TransactionBuilder.kt:168) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.TransactionBuilder.toWireTransactionWithContext$core$default(TransactionBuilder.kt:136) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.TransactionBuilder.toWireTransaction(TransactionBuilder.kt:133) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.TransactionBuilder.toLedgerTransaction(TransactionBuilder.kt:483) ~[corda-core-4.0-SNAPSHOT.jar:na]
at net.corda.core.transactions.TransactionBuilder.verify(TransactionBuilder.kt:491) ~[corda-core-4.0-SNAPSHOT.jar:na]
at mypackage.yo.workflow.YoFlow.call(YoWorkflow.kt:73) ~[cordapp-workflow-0.19-SNAPSHOT.jar:na]
at mypackage.yo.workflow.YoFlow.call(YoWorkflow.kt:41) ~[cordapp-workflow-0.19-SNAPSHOT.jar:na]
- The version/tag/release or commit hash it occurred on
https://github.com/corda/corda/commit/2d043828a0de2903102dd2a17776d82d8b39f933
Issue Analytics
- State:
- Created 5 years ago
- Comments:7 (6 by maintainers)
Top Results From Across the Web
setURLStreamHandlerFactory and "java.lang.Error: Factory ...
I've come across an unexpected error caused by calling URL.setURLStreamHandlerFactory(factory); in an Android application that is being ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Is the actual problem here that the driver API is putting too much stuff onto the node classpath? The URL stream handler factory thing is a very unfortunate part of the Java API but nonetheless, the node JVM process is our domain - roaming tomcats are dangerous, and so should be shot and have their heads mounted on the walls.
I recall someone mentioning that the driver works in a weird way and just adds everything in the host JVM onto the node classpath, which isn’t how things would work in production at all. I’m not sure why it works that way for tests, but I wonder if that’s the real issue here.
We can merge this as a temporary workaround but we should mark it as to be removed as part of cleanup.
Fixed - thanks @manosbatsis