科尔达服务101
我今天想寫一篇簡短的要點文章。 我真的很好奇我能多快出版此書。 所以走吧
這篇文章是關(guān)于Corda Services(使用Corda 3.2版)的。 這些是什么? 作為經(jīng)常使用Spring的開發(fā)人員,我個人會說它們就像Beans。 Spring Beans可以做的還很多,但是從根本上講,它們非常相似。 無論如何,讓我們停止談?wù)揝pring,而專注于Corda。
您需要知道的最低限度
Corda服務(wù)是Flow外部的類,當前只能從正在執(zhí)行的Flow或其他服務(wù)(依次由Flow調(diào)用)中調(diào)用。 與subFlow相似,它們允許您重用代碼,但出于不同的原因應(yīng)使用它們。 例如,庫查詢功能的集合或節(jié)點內(nèi)的啟動trackBy 。 這些都是我傾向于使用服務(wù)的方式。
Corda服務(wù)是通過使用@CordaService批注以及擴展SingletonSerializeAsToken來定義的。 完成此操作后,在加載Cordapp并啟動節(jié)點時,將初始化您剛剛定義的服務(wù):
@CordaService class MessageRepository(private val serviceHub: AppServiceHub) : SingletonSerializeAsToken() {private companion object {val log = loggerFor()}init {log.info("I am alive!")}fun findAll(pageSpec: PageSpecification): Vault.Page =serviceHub.vaultService.queryBy(QueryCriteria.LinearStateQueryCriteria(), pageSpec) }serviceHub提供對您所需一切的訪問。 在此示例中,服務(wù)訪問vaultService以從節(jié)點的保管庫檢索狀態(tài)。
現(xiàn)在可以根據(jù)需要在Flows或其他服務(wù)中使用它。 以下摘錄摘自我的流程之一:
private fun repository() = serviceHub.cordaService(MessageRepository::class.java)serviceHub適用于所有流量,并提供cordaService功能。 對于輸入,它需要您嘗試檢索的服務(wù)的類。 在這種情況下,正在加載MessageRepository 。
一點點更多信息
這就是開始使用Corda Services所需的全部。 但。 我會為您提供更多信息,以便您不會犯一些與我相同的錯誤。
第一課。 從Flow調(diào)用服務(wù)時。 不要將其注入Flow的構(gòu)造函數(shù)中。 而是從call函數(shù)內(nèi)部的任何位置或此后使用的任何其他函數(shù)調(diào)用它。 如果您不這樣做,則會看到以下錯誤消息:
java.lang.IllegalStateException: This can only be done after the flow has been started.上面是從測試調(diào)用Flow時會得到的錯誤。 如果從RPC調(diào)用,您將得到以下內(nèi)容:
Caused by: java.lang.reflect.InvocationTargetException: null Caused by: java.lang.IllegalStateException: This can only be done after the flow has been started.根據(jù)您選擇的Web框架,可能具有較長的stacktrace。
目前尚不清楚,在這一點上注入服務(wù)會導致這些錯誤,并且您可能會發(fā)現(xiàn)它們是由于其他原因而彈出的。 但是,至少在Corda 3.2 ,我認為可以肯定地說,您不應(yīng)在構(gòu)造函數(shù)內(nèi)部或Flow初始化期間執(zhí)行任何操作。
為了使這一點更加清楚,下面是在較早的代碼片段中插入了該服務(wù)的代碼:
@InitiatingFlow @StartableByRPC class ReplyToMessagesFlow : FlowLogic<List>() {@Suspendableoverride fun call(): List {return messages().map { reply(it) }}private fun messages() =repository().findAll(PageSpecification(1, 100)).states.filter { it.state.data.recipient == ourIdentity }private fun repository() = serviceHub.cordaService(MessageRepository::class.java)@Suspendableprivate fun reply(message: StateAndRef) = subFlow(SendMessageFlow(response(message), message))private fun response(message: StateAndRef): MessageState {val state = message.state.datareturn state.copy(contents = "Thanks for your message: ${state.contents}",recipient = state.sender,sender = state.recipient)} }如您所見,該服務(wù)被注入到repository函數(shù)中,該函數(shù)又被call 。 按照這種結(jié)構(gòu),一切都將正常工作。
第二課。 不要忘記在服務(wù)的構(gòu)造函數(shù)中包含serviceHub: AppServiceHub (可以隨意調(diào)用serviceHub )。 如果不這樣做,它將不會創(chuàng)建服務(wù),并且在嘗試訪問該服務(wù)時會彈出以下錯誤消息:
Caused by: java.lang.IllegalArgumentException: Corda service com.lankydanblog.tutorial.services.MessageRepository does not exist盡管在這種情況下有一線希望……您極不可能這樣做。 因為沒有AppServiceHub實例,使用您自己的服務(wù)實際上無能為力。 您將無權(quán)訪問Vault或任何其他內(nèi)置服務(wù)。 所以,總的來說,這一課是毫無意義的,但我仍然陷入了這個陷阱……
這就是全部?
該死,我想我實際上曾經(jīng)寫過一篇短篇文章! 是好還是壞? 我不是100%確定...
無論如何,我非常努力地想想更多的信息片段。 但是我不能。 使Corda Service正常工作的最低限度的確很容易。
話雖這么說,在過去的幾周中,我了解到您可以在Flows中無法完成的服務(wù)中完成一些非??岫杏玫墓ぷ鳌?我希望在某個時候涵蓋這一主題!
結(jié)論
Corda Services允許您在Flow外部創(chuàng)建類,在此您可以在邏輯上對與Flow的執(zhí)行沒有直接關(guān)系的代碼進行分組。 我最喜歡的使用服務(wù)的方法是將保管庫查詢功能分組到一個類中(這與我在Spring世界中所做的差不多)。 您需要采取一些步驟來確保正確創(chuàng)建服務(wù)。 首先,使用@CordaService對其進行@CordaService并擴展SingletonSerializeAsToken 。 其次,確保以正確的方式將它們注入到Flow中,除了構(gòu)造函數(shù)(或Kotlin中的init )以外,幾乎在任何地方都沒有。 最后,請記住在服務(wù)的構(gòu)造函數(shù)中包含AppServiceHub 。 一旦能夠使用Corda服務(wù),就可以將代碼從Flow中分離出來。 不僅使流程更短,而且使流程更易于理解,同時增加了您花費寶貴時間編寫的代碼的可重用性。
這篇文章使用的代碼可以在我的GitHub上找到 。 該存儲庫中還有很多內(nèi)容未包含在本文中。
如果您認為這篇文章有幫助,可以在Twitter上@LankyDanDev關(guān)注我,以跟上我的新文章。
翻譯自: https://www.javacodegeeks.com/2018/08/corda-services-101.html
總結(jié)
- 上一篇: apache camel_轻量级的开源集
- 下一篇: intent隐式和显式_Neo4j:使隐