mirror of
https://github.com/corda/corda.git
synced 2025-01-30 08:04:16 +00:00
CORDA-2653 - ensure that during initialisation of a Corda Service, the current thread has a context classloader. (#4907)
This commit is contained in:
parent
eb7928d761
commit
52ec48d63d
@ -575,21 +575,33 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
||||
|
||||
private fun installCordaServices() {
|
||||
val loadedServices = cordappLoader.cordapps.flatMap { it.services }
|
||||
loadedServices.forEach {
|
||||
try {
|
||||
installCordaService(it)
|
||||
} catch (e: NoSuchMethodException) {
|
||||
log.error("${it.name}, as a Corda service, must have a constructor with a single parameter of type " +
|
||||
ServiceHub::class.java.name)
|
||||
} catch (e: ServiceInstantiationException) {
|
||||
if (e.cause != null) {
|
||||
log.error("Corda service ${it.name} failed to instantiate. Reason was: ${e.cause?.rootMessage}", e.cause)
|
||||
} else {
|
||||
log.error("Corda service ${it.name} failed to instantiate", e)
|
||||
|
||||
// This sets the Cordapp classloader on the contextClassLoader of the current thread, prior to initializing services
|
||||
// Needed because of bug CORDA-2653 - some Corda services can utilise third-party libraries that require access to
|
||||
// the Thread context class loader
|
||||
|
||||
val oldContextClassLoader : ClassLoader? = Thread.currentThread().contextClassLoader
|
||||
try {
|
||||
Thread.currentThread().contextClassLoader = cordappLoader.appClassLoader
|
||||
|
||||
loadedServices.forEach {
|
||||
try {
|
||||
installCordaService(it)
|
||||
} catch (e: NoSuchMethodException) {
|
||||
log.error("${it.name}, as a Corda service, must have a constructor with a single parameter of type " +
|
||||
ServiceHub::class.java.name)
|
||||
} catch (e: ServiceInstantiationException) {
|
||||
if (e.cause != null) {
|
||||
log.error("Corda service ${it.name} failed to instantiate. Reason was: ${e.cause?.rootMessage}", e.cause)
|
||||
} else {
|
||||
log.error("Corda service ${it.name} failed to instantiate", e)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log.error("Unable to install Corda service ${it.name}", e)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log.error("Unable to install Corda service ${it.name}", e)
|
||||
}
|
||||
} finally {
|
||||
Thread.currentThread().contextClassLoader = oldContextClassLoader
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,7 @@ import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertNotEquals
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.*
|
||||
|
||||
class CordaServiceTest {
|
||||
private lateinit var mockNet: MockNetwork
|
||||
@ -77,6 +74,12 @@ class CordaServiceTest {
|
||||
service.startServiceFlowAndTrack()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Corda service can access a non-null thread context classloader`() {
|
||||
val service = nodeA.services.cordaService(CordaServiceThatRequiresThreadContextClassLoader::class.java)
|
||||
service.thatWeCanAccessClassLoader()
|
||||
}
|
||||
|
||||
/**
|
||||
* Reproduce CORDA-2296
|
||||
* Querying the vault from a services constructor failed because the criteriaBuilder
|
||||
@ -142,4 +145,19 @@ class CordaServiceTest {
|
||||
serviceHub.vaultService.trackBy(ContractState::class.java, criteria)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See: CORDA-2653
|
||||
* This is to check that a corda service is presented with a non-null thread context classloader
|
||||
*/
|
||||
@CordaService
|
||||
class CordaServiceThatRequiresThreadContextClassLoader(val serviceHub: AppServiceHub) : SingletonSerializeAsToken() {
|
||||
init {
|
||||
assertNotNull(Thread.currentThread().contextClassLoader, "thread context classloader should not be null during service initialisation")
|
||||
}
|
||||
|
||||
fun thatWeCanAccessClassLoader() {
|
||||
assertNotNull(Thread.currentThread().contextClassLoader, "thread context classloader should not be null during service initialisation")
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user