I have 2 project (sbt), say projectA and projectB. projectA dependsOn projectB. How do i configure akka cluster such that both the projects passes messages using actors?
Both projectA and projectB forms a cluster with seed -nodes.
If you want to send a message to a specific actor you can look up remote actors via actorSelection:
val selection context.actorSelection("akka.tcp://actorSystemName#10.0.0.1:2552/user/actorName")
Lots of details in the docs here: https://doc.akka.io/docs/akka/2.5/remoting.html
Of you can make use of a feature like ClusterSharding or ClusterSingleton where you don't need to create the actors, just send messages and Akka will create them for you.
Related
We are building a POC using Corda 4 and Springboot web server.
The POC is running in DEV MODE in our local network using PostgreSQL as database
The CorDapp developed for POC has four nodes -
Provider Node (Node 1)
Consumer 1 Node (Node 2)
Consumer 2 Node (Node 3)
Notary Node
All the above nodes participate in a deal. A deal consists of three worflows -
Flow 1 : data flows from Node 1 to Node 2
Flow 2 : data flows from Node 2 to Node 1 and Node 3
Flow 3 : data flows from Node 3 to Node 1 and Node 2
When all the three flows are executed the deal is FINISHED.
Suppose "DEAL 1" is started and "Flow 1" and 'Flow 2" are executed. Also for "DEAL 1" assuming "IOUContract.class" is used.
Due to new requirements, contract changed and a new contract class file "IOUContractv2.class" was created.
Now the application has two contracts -
"IOUContract.class" --- Used by "DEAL 1"
"IOUContractv2.class" --- Will be used by new deals
When I am linking above contract classes to the "State" using "BelongsToContract" annotation, the compiler does not allow repeated use of the same annotation.
#BelongsToContract(IOUContract::class)
#BelongsToContract(IOUContractv2::class)
data class State(val iou: IOU,
val sender: Party,
val recipient: Party,
var recipient2: Party,
val state: WorkflowState = WorkflowState.NEW,
override val linearId: UniqueIdentifier = UniqueIdentifier(iou.bndId.toString())) : LinearState, QueryableState {
Questions:
How can I make both contracts use the same state?
Is my method to use two contracts wrong?
Can an aplication have only one Contract?
How to finish the execution of old "Deals" that used old contracts?
To make sure "What you see is what I see", we have "states" in Corda. States evolve over time. This evolution is governed by a set of rules. These rules are written in a "contract". A state transition is always associated with one contract at any point of time. As you have mentioned, you may wish to change these rules. In this case, you have to do a contract upgrade as Alessandro rightly pointed out. Since you are using Corda 4, you can use implicit Signature Constraints to do the contract upgrade. Follow below steps to upgrade your contract.
Stop your node.
Sign the jar. By default, if you do not disable signing in Corda
version 4, the jar is signed when you run the deployNodes task. Stop your node.
Sign the jar. To externally sign the jar use the jarsigner. By default, if you do not disable signing in Corda version 4, the jar is signed when you run the deployNodes task.
Replace the old jar with this newly signed jar.
Replace the old jar with this newly signed jar.
I am going through this documentation and I have several uncertainties.
Performing explicit contract and state upgrades
Preserve the existing state and contract definitions
Write the new state and contract definitions
Create the new CorDapp JAR
Distribute the new CorDapp JAR
Stop the nodes
Re-run the network bootstrapper (only if you want to whitelist the
new contract)
Restart the nodes
Authorise the upgrade
Perform the upgrade
Migrate the new upgraded state to the Signature Constraint from the
zone constraint
Questions:
1. Preserve the existing state and contract definitions
2. Write the new state and contract definitions
3. Create the new CorDapp JAR
How do I do that? is it meant only to preserve jars with contracts and states on nodes, not preserving them in source code? If I do not preserve them in source code then how can I create the upgrade method?
interface UpgradedContract<in OldState : ContractState, out NewState : ContractState> : Contract {
val legacyContract: ContractClassName
fun upgrade(state: OldState): NewState
}
If I do not preserve old state in source code, then shoud I name the jar differently each time I need to do an upgrade?
Can old jars be reoved from the node when the upgrade was completed?
6. Re-run the network bootstrapper (only if you want to whitelist the
new contract)
8. Authorise the upgrade
Am I right that only those 2 steps are related to Explicit contact upgrades? And If I use implicit flow with signature, then I need to skip only those two steps, while the others are still aplicable and must be performed?
9. Perform the upgrade
Should this be done for each state separately by the owner of the state? In that case should I run it on each node for specific contrcats where the node is the participant of the state? (In doc it is mentioned to be run on single node - but what id=f a single node is not participant of some state)
Other questions
This section describes explicit contracts and states update.
https://docs.corda.net/upgrading-cordapps.html#performing-explicit-contract-and-state-upgrades while signature constraint section (https://docs.corda.net/api-contract-constraints.html#signature-constraints) does not describe an update process for states.
is it the same as for explicit upgrades with the difference only in steps 6,8 or it is somewhat completely different?
Do I need to create the function transforming old states to new states in that case? if not , then how the old states will be handled by new flows?
I see you have many some great questions about contract upgrades. Here is an article that is written by one of our dev-relation engineers. https://medium.com/corda/contract-upgrades-and-constraints-in-corda-425055a9a47f
Feel free to follow up any additional questions that you have.
If you are new to Corda, feel free to join the Corda community channels #http://slack.corda.net/
While performing legacy contract upgrades, you need both the old and new contract jars installed on your node. (present in the cordapps folder).
You can create a new Gradle module say v2-contract and write the new contract in this. This is where you will write your UpgradedContract. You will need to refer to the old v1-conract jar as well as it needs to know what the old state was. To do this add a gradle dependency in v2-contract like below.
dependencies {
// Corda dependencies.
cordapp project(v1_contract)
}
The old jar can be removed from the cordapps folder, once all the states have been upgraded to new v2-contract.
a. For HashConstraints there is no need to run the bootstrapper again. You will write the new contract by implementing UpgradedContractWithLegacyConstraint,run the jar task to build this new jar, add it to the cordapps folder, run the Authorise Flow from all nodes, run the Initiate flow from one of he node's terminal. This is the explicit way of upgrading.
b. However if you are using Whitelistzoneconstraint, you want to make sure to add the new v2-contract jar's hash to whitelist param in network param. You will need to run the network Bootstrapper to whitelist this new v2-contracts jar hash. https://docs.corda.net/network-bootstrapper.html#whitelisting-contracts.
Once you do that you can either go for an explicit upgrade by implementing UpgradedContract, or you can use implicit upgrade.
c. If you are using Signature Constraints, no need to run the network Bootstrapper for the new jar, write the new v2-contract, build it using gradle jar task, replace old jar with new jar. This is the implicit way of upgrading.
You should run the Authorise Flow for all the participants only.
Other questions
There is no explicit upgrade in Signature constraints. You need to make sure you write your state in a backward compatible way, build new jar, replace old jar with new jar. The states will refer to the new contract then.
Hope that helps. Feel free to post more questions on the above answer or ping on Slack.
We are building a POC using Corda and Springboot web server.
Following are the versions of Corda platform, Springboot server, and other essential dependencies used for building the POC-
cordaReleaseGroup=net.corda
cordaVersion=4.0
gradlePluginsVersion=4.0.45
kotlinVersion=1.2.71
junitVersion=4.12
quasarVersion=0.7.10
spring_version = '4.3.11.RELEASE'
spring_boot_version = '2.0.2.RELEASE'
spring_boot_gradle_plugin_version = '2.1.1.RELEASE'
jvmTarget = "1.8"
log4jVersion =2.11.2
platformVersion=4
slf4jVersion=1.7.25
nettyVersion=4.1.22.Final
The CorDapp developed for POC has four nodes -
Notary Node
Provider Company Node
Consumer Company 1 Node
Consumer Company 1 Sub Contact Node
The POC is running in dev mode in our local network.
We require to test the POC in the Corda Testnet.
We went through the following documentation on Corda Testnet -
1: Join Corda TestNet
URL : https://docs.corda.net/releases/release-V4.0/corda-testnet-intro.html?highlight=joining%20corda%20testnet
2: Deploying Corda to Corda Testnet from your local environment
https://docs.corda.net/releases/release-V4.0/deploy-locally.html?highlight=deploying%20corda%20corda%20testnet%20from%20your%20local%20environment
We understood from the above documentation that we can download only one "Corda node" using one registration. Will we have to join the Corda Testnet using four different accounts in order to download four Corda nodes?
Is our understanding correct?
As per my understanding you can spin up multiple nodes with a refresh of the Testnet node installation page, or by creating a node and then clicking 'next', which should take you back to the node list and present a button to allow creation of another node.
It should provide you with a unique ONE_TIME_DOWNLOAD_KEY each time, and automatically assign you a randomised alphanumeric O (organisation) value to use within the nodes configuration file, helping the network map (and thus other nodes on the network) to distinguish your nodes individually.
Make sure you don't unintentionally run copies of the same node with the same identity, otherwise the network map will just assume there has been a change in the address of the original node and route P2P traffic to the newest instance.
Take a look at the node.conf docs to understand node configuration further:
https://docs.corda.net/corda-configuration-file.html
In pipeline, I need to get channel domain to which current application is assigned.
I get current ApplicationBO instance but I haven't been able to get channel domain from it (I tried inspecting it in debugger, but I can only get domain for the application but not for the channel).
This is how currently applications and channels are assigned:
Company organization:
Channel 1
App 1 <--- Get Channel1 if in this app
Channel 2
App 2 <--- Get Channel2 if in this app
Both applications share the common cartridge which contains pipeline in which I need to get current channel
There are two options:
Call pipeline DetermineRepositories-Channel which returns you a Repository object (that is the Channel). On the Repository use object path Repository:RepositoryDomain to get the Domain. I'm not sure how big the performance implication is though..
Use object path ApplicationBO:Extension("PersistentObjectBOExtension"):PersistentObject:Domain to get the owning domain of the application itself. That will always be the channel(Domain). Because that's where storefront applications are born.
In case you need to convert the Domain object to a Repository object you can use pipelet GetRepositoryByRepositoryDomain.
We currently use Rebus and we have a shared project that holds the command messages (payloads, etc).
Both the client and the bus projects reference this shared "messages" project. When the client sends a message to the bus, the bus knows how to handle it because it has references to the same namespace:
To illustrate, we have 3 projects:
project.rebus.bus
project.rebus.messages (command messages)
project.rebus.client
Solution1 - bus
project.rebus.bus
PingHandler<Ping>
project.rebus.messages (Ping message)
Solution2 - client
project.rebus.client
bus.send(new Ping {...})
project.rebus.messages (Ping message)
The scenario works because both project.rebus.bus and project.rebus.client share the same project.rebus.messages, all good.
How do we setup project.rebus.bus, when it needs to handle messages from a third party vendor, where we can't have a shared project.rebus.messages project?
Is it possible?
Example:
Our rebus bus - bus
project.rebus.bus
ThirdPartyTestHandler<ThirdPartyTestMessage>
project.rebus.messages (ThirdPartyTestMessage message)
Third party vendor - client
SomeCompanyOutThere.rebus.client
bus.send(new ThirdPartyTestMessage {...})
SomeCompanyOutThere.rebus.messages (ThirdPartyTestMessage message)
Thanks!
It's pretty common to see projects where the messages assemblies are distributed as NuGet packages.
This way, the "owner" of the message types (i.e. the app with the handlers if it's commands, we're talking about, or the app that publishes the events if it's events we're talking about) can have the project in its solution, and then a NuGet package can be built from it.
All other apps (which then become "clients" in this particular relationship) can then include that NuGet package and this way get access to the message types.
I suggest you do the same with the 3rd party assembly, if you intend to use that as messages.