Given an established network of Corda nodes, I would like to exchange information between parties without hitting the Vault.
My architecture looks something like this:
ClientA <-RPC-> NodeA+CorDapp <-Public-> NodeB+CorDapp <-RPC-> ClientB
While sending the data is very straight forward, I am trying to figure out how ClientB can be notified when something shows up in NodeB?
You can use the Flow Framework for that.
So I presume you're doing something like initiating a flow session from NodeA with NodeB and then performing a Send to send over some data?
val flowSession = initiateFlow(NodeB)
flowSession.send(someData)
Over on NodeB, the responding flow will receive this data and you can use whatever you like within the realm of Java to notify ClientB. If you want to notify Client by triggering an RPC, you can do that.
#InitiatedBy(Initiator::class)
class Responder(val counterpartySession: FlowSession) : FlowLogic<Unit>() {
#Suspendable
override fun call() {
val yourData = counterpartySession.receive<String>().unwrap { it }
//Some code to alert Client B
}
}
Related
Is it possible to pass anonymous object implementations over Corda's RPC interface? - For example:
Workflow
#CordaSerializable
interface ExampleInterface {
val number: Int
}
#StartableByRPC
class SquareFlow(private val example: ExampleInterface) : FlowLogic<Int>() {
#Suspendable
override fun call(): Int = example.number * example.number
}
RPC Client
val value = object : ExampleInterface {
override val number: Int = 5
}
return rpc.startFlowDynamic(SquareFlow::class.java, value).returnValue.getOrThrow()
Exception
net.corda.client.rpc.RPCException: java.util.List<*> -> Unable to create an object serializer for type class com.example.client.ExampleService$square$value$1: No unique deserialization constructor can be identified
Either annotate a constructor for this type with #ConstructorForDeserialization, or provide a custom serializer for it
Whilst this is an example, what I actually want to do is pass object : TypeReference<SomeType>(){} over RPC.
As per Corda's docs anonymous objects are not supported by their AMQP
serialization which is used in the RPC client which you can read here. This is likely due to a public constructor being needed for serialization and deserialization I imagine.
Additionally I assume you are referencing Jackson's TypeReference class which uses generics which are only available at compile time. Due to how Corda's serialization works the generic won't be available at runtime so when the TypeReference is passed from the rpc application to the corda node the corda node will not know what the generic is. I haven't tried this myself but I believe some exception will be thrown whenever the flow attempts to suspend or possibly before in the RPC client.
You can probably pass a jackson JavaType class to a flow without a problem as I believe it is whitelisted as serializable in Corda by default, if not look at how to whitelist the class here using the SerializationWhitelist. You can obtain the JavaType by instantiating a TypeFactory and calling constructType(new TypeReference<SomeType> {}). then just pass the JavaType to your flows constructor.
Hi everyone i am working on a project in which i need to send a response in JSON format to the CLI that the Transaction have completed let me give you an example.Consider that i have stated a flow Start ExampleFlow pojo: {iouValue: 7}, otherParty: "O=PartyB,L=London,C=GB" and the result will be Starting
Generating transaction based on new IOU.
Verifying contract constraints.
Signing transaction with our private key.
Gathering the counter party's signature.
Collecting signatures from counterparties.
Verifying collected signatures.
Obtaining notary signature and recording transaction.
Broadcasting transaction to participants
Done
Flow completed with result: SignedTransaction(id=F95406D901209BA77396C1A4D375585C6E051414EE22BE441FC02E5AE147A050)
but what i want is that their should be a JSON format result not all of it but something like this
{response: success }
i just want some success response in JSON format
i am using IOU project
thanks
You can achieve that by establishing an RPC connection with your node; call the flow, then return the JSON object.
There are a couple of approaches that you can follow, and I recommend that you go through the samples repository https://github.com/corda/samples to explore them:
Create a webserver (SpringBoot application) that server REST API's that call your flows and return a JSON object: https://github.com/corda/samples/tree/release-V4/spring-webserver
Create a simple Java app that establishes an RPC connection with your node and serves as a client to call a certain method/flow: https://github.com/corda/samples/blob/release-V4/cordapp-example/clients/src/main/java/com/example/server/JavaClientRpc.java
If you follow the webserver sample, you can add a method to your controller that does something like:
#GetMapping(value = "/my-api", produces = MediaType.APPLICATION_JSON_VALUE)
private ResponseEntity<YourObject> getSomething() {
// Some code that calls your flow and returns YourObject.
return ResponseEntity.ok().body(YourObject);
}
so i got the answer what u need to do is add this dependency in client build.gradle
cordaCompile "net.corda:corda-jackson:$corda_release_version"
after that you just need to implement this code snip
String json = "";
try {
ObjectMapper mapper = JacksonSupport.createNonRpcMapper();
json = mapper.writeValueAsString(results);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return json;
result can be any datatype you want to convert to json
Im using C# AsterNET to manage my Asterisk commands and events, and now I do have a new feature to work on.
This is simple (I think) but I'm stucked right now.
Scenario
I do have two queues, 8100 and 8300, and 2 extensions being 8101 and 8301. When I do have a call from PSTN it is driven to 8100 queue. When the 8101 extension become available I do add this extension to the 8100 queue, so the calling PSTN device will be redirected to this 8101 extension.
Everything is working fine till here.
Sometimes I do park the calling device and let 8301 knows it using my app, so 8301 user using the same app can send a command asking for that parked channel to be redirect to his SIP Phone. Also working fine.
Scope
Now I want to have some feature to let 8101 transfer this calling device to my other queue, the 8300. So I just tried to reuse my parked method and redirect method
internal void Park(string channel, int parkTimeout)
{
ParkAction pa = new ParkAction(channel, channel, parkTimeout.ToString());
ManagerResponse mr = manager.SendAction(pa);
}
internal void RedirectFromParking(string channel, string exten)
{
RedirectAction ra = new RedirectAction
{
Priority = 1,
Context = "default",
Channel = channel,
Exten = exten
};
ManagerResponse mr = manager.SendAction(ra);
}
Park("abc123456", 10000);
RedirectFromParking("abc123456", "8300")
Issue
I'm parking fine but when I try to redirect from parking to my queue the calling device is just disconnected and the connection is lost.
How can I transfer a parked call to my queue or transfer it directly to the queue (would be better) without needing to originate?
Just do hold instead of parking and make your own list of such calls.
To transfer to a queue I can do a blind transfer as documented on Asterisk website. Links below:
ManagerAction_BlindTransfer
ManagerEvent_BlindTransfer
To achieve this using AsterNET, I can use the same RedirectAction I was using but I do need to change the context. It can't be default for context, as default we are letting Asterisk manage it and somehow it can't handle as I expetected. So it need to be clearly specified as internar transfer. The event raised after this context transfer is the Manager_BlindTransfer.
Manager_Action_RedirectAction
So using my SIP Phone I manage to transfer a call while I was debugging that raised event method, so I could catch the context used in. Using the correct context
ManagerConnection manager = new ManagerConnection(address, port, user, password);
manager.BlindTransfer += Manager_BlindTransfer;
private void Manager_BlindTransfer(object sender, BlindTransferEvent e)
{
}
After this I created another method to transfer to directly to a queue using the correct context.
internal void TransferToQueue(string channel, string queue)
{
RedirectAction ma = new RedirectAction
{
Priority = priority,
Context = "from-internal-xfer",
Channel = channel,
Exten = queue
};
ManagerResponse mr = manager.SendAction(ma);
}
TransferToQueue("abc123456", "8300")
Summary
Was just a matter of the correct context to be used in.
from-internal-xfer
I'm going to make application monitoring system. I'm using spring-boot actuator and I can make some information like metrics, health and etc. See a attatchment.
As you can see, there are so many things such as memory, heap to counter and gauges.(sample.actuator.SampleController.hello.* are made by com.codahale.metrics.annotation.Timed)
And I want to send those information to graphite to monitor. Google said those code.
#Configuration
public class MonitoringConfig {
#Autowired
private MetricRegistry metricRegistry;
#Bean
public GraphiteReporter graphiteReporter() {
Graphite graphite = new Graphite(new InetSocketAddress("70.50.8.111",
2003));
GraphiteReporter reporter = GraphiteReporter
.forRegistry(metricRegistry).prefixedWith("boot")
.build(graphite);
reporter.start(1000, TimeUnit.MILLISECONDS);
return reporter;
}
}
but reporter send only counter and gauge. For inserting other information to reporter, what should I do?
Please help....
I'm in the process of building a small tool for my employer, and attempting to implement it using Akka 2 + Scala.
One of the systems I'm interfacing with has a a SOAP api, which has an interesting implementation:
----Request-------
Client ----Request----> Server
Client <---Req Ack----- Server
----Response------
Client <---Response---- Server
Client ----Resp Ack---->Server
Keeping track of the requests is done via a task id sent by the req-ack.
My question is to the SO community and anyone who has experience with akka are the following:
What would be an ideal way to handle http messages using akka for this particular scenario? I have seen examples with Akka-Mist, which looks like it's been discontinued in favor of play-mini, then there's akka-camel, which I can't seem to be able to find the library for as part of the akka 2.0.3 distribution, so I'm a little confused as to what approach I should take. Is there a recommended way to wrap a encapsulate a servlet's behavior inside an akka actor?
Thank you all in advance.
Your question is VERY open ended so I will make some assumptions about your requirements.
Request assumption: There are a lot of requests being generated upon some event.
Create a router having actors that wrap the async-http-client (https://github.com/sonatype/async-http-client). Once the async-http-client completes a request it would send a message having the ID contained in the Req Ack to a coordination actor. The coordination actor would aggregate the ID's.
The following is largely pseudocode but it's close enough to the real API that you should be able to figure out the missing pieces.
case class Request(url:String)
case class IDReceived(id:String)
case class RequestingActor extends Actor {
override def receive = {
case Request(url) => {
//set up the async client and run the request
//since it's async the client will not block and this actor can continue making generating more requests
}
}
}
class AsyncHttpClientResponseHandler(aggregationActor:ActorRef) extends SomeAsyncClientHandler {
//Override the necessary Handler methods.
override def onComplete = {
aggregationActor ! IDReceived(//get the id from the response)
}
}
class SomeEventHandlerClass {
val requestRouter = actorSystem.actorOf(Props[RequestingActor].withRouter(FromConfig(//maybe you've configured a round-robin router)), requestRouterName)
def onEvent(url:String) {
requestRouter ! Request(url)
}
}
case class AggregationActor extends Actor {
val idStorage = //some form of storage, maybe a Map if other information about the task ID needs to be stored as well. Map(id -> other information)
override def receive = {
case IDReceived(id) => //add the ID to idStorage
}
}
Response assumption: You need to do something with the data contained in the response and then mark the ID as complete. The HTTP frontend only needs to deal with this one set of messages.
Instead of trying to find a framework with Akka integration just use a simple HTTP frontend that will send messages into the Akka network you've created. I can't imagine any advantage gained by using play-mini and I think it would obscure some of the lines delineating work separation and control. That's not always the case but given the lack of requirements in your question I have nothing else to base my opinion on.
case class ResponseHandlingActor extends Actor {
val aggregationActor = actorSystem.actorFor(//the name of the aggregation router within the Actor System)
override def receive = {
case Response(data) => {
//do something with the data. If the data manipulation is blocking or long running it may warrant its own network of actors.
aggregationActor ! ResponseReceived(//get the id from the response)
}
}
}
class ScalatraFrontEnd() extends ScalatraServlet {
val responseRouter = actorSystem.actorOf(Props[RequestingActor].withRouter(FromConfig(//maybe you've configured a round-robin router)), requestRouterName)
post("/response") {
responseRouter ! Response(//data from the response)
}
}
Creating a system similar to this gives you nice separation of concerns, makes it really easy to reason about where processing takes place and plenty of room for scaling the system or extending it.