I am following an example REST Service Task
I start my process engine using
val configuration = new StandaloneProcessEngineConfiguration(); configuration.setProcessEngineName(processEngineName)
Here is my bpmn file snippet
<process id="approve-loan" name="Loan Approval" isExecutable="true">
<serviceTask id="process_task" activiti:class="com.noggin.bpm.loan.ProcessRequestDelegate" activiti:exclusive="true" name="compute
Task">
<extensionElements>
<activiti:connector>
<activiti:connectorId>http-connector</activiti:connectorId>
<activiti:inputOutput>
<activiti:inputParameter name="url">http://127.0.0.1:5004/Hello/sayhello</activiti:inputParameter>
<activiti:inputParameter name="method">POST</activiti:inputParameter>
<activiti:inputParameter name="headers">
<activiti:map>
<activiti:entry key="Accept">application/json</activiti:entry>
<activiti:entry key="Content-type">application/json</activiti:entry>
</activiti:map>
</activiti:inputParameter>
<activiti:inputParameter name="payload"><![CDATA[{"bundleId":"101","script":"def greet = {\n \"Hello World\"\n }\n greet()"}]]></activiti:inputParameter>
<activiti:outputParameter name="isActive">Result</activiti:outputParameter>
</activiti:inputOutput>
</activiti:connector>
</extensionElements>
I start the process like this
val processEngine = ProcessEngines.getProcessEngine(processEngineName)
val runtime = processEngine.getRuntimeService
val processInstance = runtime.startProcessInstanceByKey(processInstanceKey)
Successfully, I am able to send the payload to ( http://127.0.0.1:5004/Hello/sayhello ).
My question is how to retrieve the response message from the location i started the instance. Since the response will be in a Json message which should be sent back to process initiator.
I believe I saw a similar question from you posted to the Camunda forum yesterday.
Either way, I believe the question and answer is the same.
Let me make sure I understand what you are asking.
1. You are starting the instance using the Java API
2. Your process definition includes a single Service Task that makes a REST call.
3. Your JavaDelegate class populates the "Result" process variable with the response of the REST call.
4. You want to capture the response.
If I have captured your requirement, then I think the problem is in your understanding of how he BPMN engine works.
With the process as you have it modeled, the process instance will start, make the REST call, populate the Response variable and then immediately end.
As you have currently modeled the process, you will not be able to capture the response during process execution.
Your options:
1. Change your model to either send the "Result" using a message service of some sort, or add a wait state where you can retrieve the response.
2. Use the Historical query REST API (or the equivalent Java API) to retrieve the Result payload from the completed instance.
It really depends on your use case as to the most appropriate option to take.
Cheers,
Greg
Related
I need to
start a BluePrism process and
wait until it has completed
in a Java application which runs on a machine without a BluePrism client.
I know that it is possible to start a process using a SOAP call.
How can I find out whether or not the started process is finished and whether or not it completed successfully?
A colleague of mine said that it is possible to get a notification from BluePrism by passing a special parameter in the SOAP request, but I could not find anything on that in the Web Services User Guide.
Update 1: One solution is to adapt this software so that it exposes the BluePrism queues via a REST API.
Update 2: This page suggests running a query like below against the BluePrism database.
SELECT
[BPAProcess].[name],
[BPAProcess].[description],
[BPASession].[sessionid],
[BPASession].[startdatetime],
[BPASession].[enddatetime],
[BPASession].[statusid],
[BPAStatus].[description]
FROM [BPAProcess]
JOIN [BPASession] ON
[BPASession].[processid] = [BPAProcess].[processid]
JOIN [BPAStatus] ON
[BPASession].[statusid] = [BPAStatus].[statusid]
WHERE [BPAStatus].[description] IN ('Completed', 'Stopped', 'Terminated')
AND [BPASession].[sessionid] = 'Your session id'
Update 3: The BluePrism version is 6.4.2.
Update 4: Additional information is available in the BluePrism community.
If you expose the process in question as a web service (System -> Processes -> Exposure) and invoke it this way, the SOAP response will not be returned until the process has completed running. Your Java code can simply wait for the response to be returned from the endpoint to be sure that the process you invoked has completed.
While I can't seem to locate any formal documentation of this behavior, this aligns with the intended design to enable the return of output values from the process/object being invoked back to the SOAP caller. (The output values couldn't possibly be known if the request resolves before the process is finished executing.)
I have spent a few good amount of hours reading about Spring Integration. And today I started experimenting with the framework. There are aspects of how it works that I have trouble understanding despite of all my reading. I hope somebody here can put me back on tracks.
I have the following channel and endpoint defined:
<in:channel id="orderSource"/>
<in:service-activator input-channel="orderSource"
ref="defaultOrderService"
method="placeOrder"/>
Since the channel is a DirectChannel I expect everything to happen within a single thread and get a return value at the end.
The placeOrder method look as follows:
#Override
public Order placeOrder(Order order) {
return order;
}
In my main method I have:
MessageChannel input = context.getBean("orderSource", MessageChannel.class);
Message<Order> message = MessageBuilder.withPayload(new Order(123)).build();
MessagingTemplate messenger = new MessagingTemplate(input);
Message<?> result = messenger.sendAndReceive(message);
Object found = result.getPayload();
And this all works like a charm. The found is the order the service activator sends back.
My problem starts when I want to notify a set of subscribers that the order was placed. For simplicity, let's do this synchronously, like this:
<in:channel id="orderSource"/>
<in:service-activator input-channel="orderSource"
output-channel="savedOrders"
ref="defaultOrderService"
method="validateOrder"/>
<in:publish-subscribe-channel id="savedOrders"/>
<in:outbound-channel-adapter channel="savedOrders"
ref="defaultOrderService"
method="notifyCustomerService"/>
<in:outbound-channel-adapter channel="savedOrders"
ref="defaultOrderService"
method="notifyShipmentManager"/>
<in:outbound-channel-adapter channel="savedOrders"
ref="defaultOrderService"
method="notifyWarehouseManager"/>
The question now is what should the input channel expect in return when I invoke sendAndReceive?
My current code blocks and I never reach the end of the main thread.
How can I make sure I receive a reply containing the result of the service activator as it passed it to all subscribers?
Also I am really curious about what a given channel can expect in terms of returning values when there are asynchronous channels in the flow. I'd like to get the result at end of a transaction and before new thread is spawn, but I don't know how to do that.
Any thoughts, advice or guidance?
Presumably, your "notify" methods return null. If that's the case, there's no "reply" sent to the MessagingTemplate.
Make the final one return the order, or add a <bridge/> to nowhere as a fourth subscriber to the pub-sub channel.
A bridge to nowhere is simply a bridge with no output channel. When a message arrives at an endpoint that produces a reply, and there is no output-channel, the message's replyChannel header is used to route the reply to the originator.
It works with async channels too, but I'd need to understand your requirements there before I can provide guidance.
Also, consider using a Messaging Gateway on the calling side instead of building a message yourself and using the MessagingTemplate. Rather than exposing your caller to the messaging infrastructure, the framework will create a proxy for you that will take care of all that and you just interact with the POJI.
I spent some more time reading and I discovered that this is all a matter of configuring the reply channel either in the message or in the gateway and using bridge just as Gary Rusell suggested did the trick for me.
This is my code, now working:
<in:channel id="arrivals"/>
<in:service-activator input-channel="arrivals"
output-channel="validated"
ref="defaultOrderService"
method="validateOrder"/>
<in:channel id="validated"/>
<in:service-activator input-channel="validated"
output-channel="persisted"
ref="defaultOrderService"
method="placeOrder"/>
<in:publish-subscribe-channel id="persisted"/>
<in:channel id="replyChannel"/>
<in:bridge input-channel="persisted" output-channel="replyChannel"/>
<in:outbound-channel-adapter channel="persisted"
ref="defaultOrderService"
method="notifyCustomerService"/>
<in:outbound-channel-adapter channel="persisted"
ref="defaultOrderService"
method="notifyShipmentManager"/>
<in:outbound-channel-adapter channel="persisted"
ref="defaultOrderService"
method="notifyWarehouseManager"/>
<in:gateway id="orderService"
service-interface="codemasters.services.OrderService"
default-request-channel="arrivals"
default-reply-channel="replyChannel"/>
And using a gateway, this all looks much cooler now:
OrderService service = context.getBean("orderService", OrderService.class);
Order result = service.validateOrder(new Order(4321));
I am intercepting messages that are sent through JBossESB. I am using pipeline interceptors to do so.
The problem is, that altough the sender is a service (for example PortReference < logical:BlueServiceESB#BlueListener >), the name of the receiver is a queue (not a service). That is logical because in some case, multiple services can receive messages from a given queue, but usually, each queue is mapped to only one service.
I would like to know which queue is mapped to which service, so I can display/save this information and have it displayed like message: service ---> service (not service ---> queue).
I know that I can get the name of the queue mapped to a service using the registry like this:
System.setProperty("javax.xml.registry.ConnectionFactoryClass", "org.apache.ws.scout.registry.ConnectionFactoryImpl");
// Retrieving information from the ESB Registry
Registry reg = RegistryFactory.getRegistry();
System.out.println(reg.findAllServices());
List<EPR> eprs = reg.findEPRs("FirstServiceESB", "SimpleListener");
System.out.println(eprs);
I would like to reverse this approach - queue is the input and service (EPR = end point reference = service) is the output. Is there any way how to do this or am I just trying to do the impossible here. I have found no tutorials or questions on this topic whatsoever.
Thanks for any tips!
As this question has 25 up-votes, this seems to be an useful feature. JBossESB is open source software. Thus, implement the feature yourself and commit it to the community! Or just create a change request hopping that somebody else will do it...
Try querying for all of the queues and building a reverse-lookup map. But I don't think there is any function that allows searching for services using a queue.
I'm struggling with one thing in Storm.
So the whole idea is:
Send a request to the storm (probably to DRPC Server). The request will tell Storm what is the source of streams. For example: Image that I have two files 1 - '/var/log/syslog' and 2- ' /var/log/udev' . I want to be able to send the request to the "Storm" to tell it what file to process.
What I don't understand:
When I said send request to the "Storm", - Where should I send it? ( I assume that DRPC server controls what source needs to be send to topology. But how to implement DRPC server? Is there some class like DRPCServer server = new DRPCServer()? And how to tell Spout to look at the DRPCServer?Or is the request needs to be send directly to the Spout? if So how to make it start using specified source? I mean do I need to send request to the open() method?
Not DRPCServer, its DRPCClient
DRPCClient client = new DRPCClient("drpc-host", 3772);
I think you will be really interested after seeing this
UPDATE:
And for more information you can always check the storm-starter project in github by nathanmarz and especially BasicDRPCTopologyand ReachTopology
I am using the Bloomberg API to grab data. Currently, I have 3 processes which get data in the typical way as per the developers guide. Something like:
Service refDataService = session.getService("//blp/refdata");
Request request = refDataService.createRequest("ReferenceDataRequest");
request.append("securities", "IBM US Equity");
request.append("fields", "PX_LAST");
cid = session.sendRequest(request, null);
That works. Now I would like to expand the logic to be something more like an update queue. I would like each process to send their Request to an update queue process, which would in turn be responsible for creating the session and service, and then sending the requests. However, I don't see of any way to create the request without the Service. Also, since the request types (referenceData, historical data, intraday ticks) are so varied and have such different properties, it is not trivial to create a container object which my update queue could read.
Any ideas on how to accomplish this? My ultimate goal is to have a process (I'm calling update queue) which takes in a list of requests, removes any duplicates, and goes out to Bloomberg for the data in 30 second intervals.
Thank you!
I have updated the jBloomberg library to include tick data. You can submit different types of query to a BloombergSession which acts as a queue. So if you want to submit different types of request you can write something like:
RequestBuilder<IntradayTickData> tickRequest =
new IntradayTickRequestBuilder("SPX Index",
DateTime.now().minusHours(2),
DateTime.now());
RequestBuilder<IntradayBarData> barRequest =
new IntradayBarRequestBuilder("SPX Index",
DateTime.now().minusHours(2),
DateTime.now())
.period(5, TimeUnit.MINUTES);
RequestBuilder<ReferenceData> refRequest =
new ReferenceRequestBuilder("SPX Index", "NAME");
Future<IntradayTickData> ticks = session.submit(tickRequest);
Future<IntradayBarData> bars = session.submit(barRequest);
Future<ReferenceData> name = session.submit(refRequest);
More examples available in the javadoc.
If you need to fetch the same information regularly, you can reuse a builder and use it in combination with a ScheduledThreadPoolExecutor for example.
Note: the library is still in beta state so don't use it blindly in an black box that trades automatically!