How do I tell Camel that I will end the message processing myself - apache-camel

I am writing a component (an endpoint) that will receive the Camel Exchange like this:
from("file|activemq|whatever").to(myEndpoint);
Upon receiving, I want it to pass the exchange to a set of subroutines, which may work asynchronously, and which will eventually decide that they have finished, possibly composed a response in an Out message of the Exchange. All may happen outside the Camel Context, I am working only with the Exchange object.
Then my subroutines should invoke something that will tell Camel that it should propagate the response back, do other stuff as per the source and middle components requirements (for example, if it is a file:/, rename a file) and consider the routing ow this Exchange completed.
I was thinking that I would invoke the Exchange's Uint of Work done method.
Unfortunately I am noticing that Camel still tries to end the exchange by itself too, in wrong time and state. For example, for file source, it fails to rename the file which already has been removed.
Here is some of my code:
Here I define an endpoint:
_proceeder = new DefaultEndpoint() {
private final String _defaultUri = "rex:producer-" + UUID.randomUUID().toString();
#Override
protected String createEndpointUri() {
return _defaultUri;
}
#Override
public Producer createProducer() throws Exception {
return new DefaultAsyncProducer(this) {
#Override
public boolean process(final Exchange exchange1, final AsyncCallback callback) {
final ExchangeWrapper exchange = new ExchangeWrapper(_uri, exchange1, MessageSystem.this);
_LOG.debug("Got input for {}. Processing...", _uri);
exchange._taken(); // 1. all subsequent will increase by 1
/// some majick....
final boolean done = exchange._released(); // if all were released immediately, itll be 0 and sent back now. otherwise the last to release will send it back.
if (done) {
_LOG.debug("Processed input for {} synchronously", _uri);
//callback.done(true);
} else {
_LOG.debug("Processed input for {} asynchronously, awaiting response", _uri);
//exchange1.addOnCompletion(new Synchronization() {
// #Override
// public void onComplete(Exchange exchange) {
// onFailure(exchange);
// }
//
// #Override
// public void onFailure(Exchange exchange) {
// callback.done(false);
// }
//});
}
return done;
}
};
}
#Override
public Consumer createConsumer(Processor processor) throws Exception {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
#Override
public boolean isSingleton() {
return true;
}
};
_proceeder.setCamelContext(context);
Needless to say that I don't understand why I am given an AsyncCallback in my DefaultAsyncProducer.process() method; regardless of me calling its done() method, the system doesn't see this and still ends the exchange by itself once more. But it is not the question.
here is the ExchangeWrapper _released and _done methods:
private void _done() throws Exception {
UnitOfWork uow = _exchange.getUnitOfWork();
uow.done(_exchange);
//try{
// uow.stop();
//}catch(Exception e){
//
//}
_exchange.setUnitOfWork(null);
}
private boolean _released() {
final boolean ret;
final int cnt;
final int trancnt;
synchronized (_exchange) {
cnt = _exchange.getProperty("rex.takenCount", Integer.class) - 1;
_exchange.setProperty("rex.takenCount", cnt);
trancnt = _exchange.getProperty("rex.takenAsTransient", Integer.class);
}
if (_LOG.isDebugEnabled()) {
_LOG.debug("Input for {} released. {} times left, {} transient", new Object[]{_exchange.getProperty("rex.uri", String.class), cnt, trancnt});
}
if (cnt <= 0 || cnt <= trancnt) {
if (_LOG.isDebugEnabled()) {
_LOG.debug("Message for {} is processed by all non-transient receivers. Setting done...", new Object[]{_exchange.getProperty("rex.uri", String.class)});
}
_done();
ret = true;
if (_LOG.isDebugEnabled()) {
_LOG.debug("Message for {} is set done", new Object[]{_exchange.getProperty("rex.uri", String.class)});
}
} else {
ret = false;
}
return ret;
}
So basically I wrap the Exchange to keep state and decide when the processing should be stopped.
While digging into the Camel internals I've seen some similar counters that keep track of how many times the Exchange has been taken for processing, but I'd like to be in control, thus my own wrapper.
So what should I call instead of
_exchange.getUnitOfWork().done(_exchange);
to tell the Camel Internal Processor and others that there is no need to mark the exchange done because I am doing it?
My latest finding is to call uow.stop(); so that it clears all the 'after' processors etc, but I suddenly understood that I may try and hack Camel myself for a long time, but it's better to ask people who know exactly what to do without trying and guessing.
These are the examples of my Routes:
RouteBuilder rb = new RouteBuilder(_context) {
#Override
public void configure() throws Exception {
if (_tokenizer != null) {
from(_uri).split().method(_tokenizer, "tokenizeReader").streaming().to(_proceeder);
} else {
from(_uri).to(_proceeder);
}
}
};
If I could avoid building routes, instantiating endpoints and producers, and employ standalone processors, I'd happily do, but I don't want to ditch what the marvelous Camel project has to offer in terms of splitting, streaming, marshalling etc etc; and all of this seems to be built around routes.

May be I am not clear with what are you trying to achieve with this, but let me try.
Upon receiving, I want it to pass the exchange to a set of
subroutines, which may work asynchronously, and which will eventually
decide that they have finished
So for this you can write a processor and configure it at the end of your route .Within your processor you can use a thread pool, submit to it the subroutine tasks, wait for their completion and decide if you want to change the message body ( correct way explained here with a good diagram explaining flow of an exchange through a route) and camel will automatically take care of returning the response to the caller of the route based on exchange pattern. For example in your case if the route begins from file/activemq route then it is event based/one way exchange and no response will be sent to the caller as there is no caller client as such. It will be just an event which will initiate the exchange.
Update :
For using the async processing feature in camel for enhanced scalability take a look at this example with code from the highly recommended Camel in Action book

Related

Unbounded Collection based stream in Flink

Is it possible to create an unbounded collection streams in flink. Like in a map if we add a element flink should process as in the socket stream. It should not exit once the initial elements are read.
You can create a custom SourceFunction that never terminates (until cancel() is called, and emits elements as they appear. You'd want to have a class that looks something like:
class MyUnboundedSource extends RichParallelSourceFunction<MyType> {
...
private transient volatile boolean running;
...
#Override
public void run(SourceContext<MyType> ctx) throws Exception {
while (running) {
// Call some method that returns the next record, if available.
MyType record = getNextRecordOrNull();
if (record != null) {
ctx.collect(record);
} else {
Thread.sleep(NO_DATA_SLEEP_TIME());
}
}
}
#Override
public void cancel() {
running = false;
}
}
Note that you'd need to worry about saving state for this to support at least once or exactly once generation of records.

How to handle call waiting in IncallService

Using incallservice I successfully replaced the caller screen. I am able to call and receive calls. But a problem occurs when the second call is in waiting stage. I tried searching the forum but I found no help on how to handle call waiting.
Currently I am handling call waiting by totally ignoring it.
Alternatively I tried disconnecting it in the background as I am only interested in getting a number of waiting calls. I tried the following
public class CallService extends InCallService {
private BroadcastReceiver headsetReceiver = null;
#Override
public void onCallAdded(Call call) {
super.onCallAdded(call);
Log.d("bbbbbb", "inside");
if (constants.CALL_IN_PROGRESS == false) {
new OngoingCall().setCall(call);
CallActivity.start(this, call);
}else {
call.disconnect();
}
}
#Override
public void onCallRemoved(Call call) {
super.onCallRemoved(call);
handy_methods hm = new handy_methods(this);
String saved_number = hm.read_sharedpreference("incomingNumber");
String latestCallNumber = call.getDetails().getHandle().toString().replace("tel:%2B", "+");
if (saved_number.equals(latestCallNumber.replace("tel:", ""))) {
Log.d("aaaaaa", "s5");
new OngoingCall().setCall(null);
}
}
}
}
but call.disconnect() is not handling the waiting call. I just want to disconnect the second call. Can anyone please help me.
Thank you

apache camel polling a rest endpoint

I have a rest endpoint sample.org which returns a json response of the form
{
"response" : "pending"
}
My route looks like this
from("http://sample.org")
.marshal(xmlFormatConverterUtil.getxmlJsonDataFormat()) //To convert into json as I receive data in xml format which needs to be converted to json
I read about polling consumer but couldn't find an example on how to keep polling the endpoint, till it returns response as "success".
Should a polling consumer be used ? If so can an example relevant to my case be illustrated. Any other resource to poll rest endpoints will be highly useful.
You need to start from a timer instead and then call the rest endpoint. Then you can check the result and if its then stop the route using controlbus. The filter can be used to check if its pending and then just stop continue routing, and then the next timer will try again.
Someting along this pseudo route
from timer
to http
marshal
filter (if pending)
stop
end
to something with positive response
to controlbus stop route
You can find more details at
http://camel.apache.org/timer
http://camel.apache.org/controlbus
http://camel.apache.org/how-can-i-stop-a-route-from-a-route.html
http://camel.apache.org/message-filter.html
I had a similar problem and ended up writing a custom endpoint for polling.
It works as a producer and polls the specified uri until a specified predicate has been met or polling reaches the maximum number of tries.
from("direct:start")
.to("poll:http://example.com/status?maxRetries=3&successPredicate=#statusSuccess")
The polling endpoint uses a simple processor that uses a polling consumer for polling.
public class PollProcessor implements Processor {
private final String uri;
private final long requestTimeoutMs;
private final long period;
private final int maxTries;
private final Predicate<Exchange> successPredicate;
public PollProcessor(String uri, long requestTimeoutMs, long period, int maxTries, Predicate<Exchange> successPredicate) {
Preconditions.checkArgument(maxTries > 0);
Preconditions.checkArgument(period >= 0);
Preconditions.checkNotNull(successPredicate);
this.uri = uri;
this.requestTimeoutMs = requestTimeoutMs;
this.period = period;
this.maxTries = maxTries;
this.successPredicate = successPredicate;
}
#Override
public void process(Exchange exchange) throws Exception {
PollingConsumer consumer = exchange.getContext().getEndpoint(uri).createPollingConsumer();
for (int tryNumber = 1; tryNumber <= maxTries; ++tryNumber) {
Exchange pollExchange = consumer.receive(requestTimeoutMs);
if (successPredicate.test(pollExchange)) {
exchange.setOut(pollExchange.getOut());
exchange.setException(pollExchange.getException());
return;
}
log.warn("Polling {} failed try number {}, waiting {} ms for next try...", uri, tryNumber);
Thread.sleep(period);
}
throw new RuntimeException("Polling failed maximum allowed number of tries [" + maxTries + "], see log for details.");
}
}

Flink executes dataflow twice

I'm new to Flink and I work with DataSet API. After a whole bunch of processing as the last stage I need to normalize one of the values by dividing it by its maximum value. So, I have used the .max() operator to take the max and later I'm passing the result as constructor's argument to the MapFunction.
This works, however all the processing is performed twice. One job is executed to find max values, and later another job is executed to create final result (starting execution from the beginning)... Is there any workaround to execute whole dataflow only once?
final List<Tuple6<...>> maxValues = result.max(2).collect();
assert maxValues.size() == 1;
result.map(new NormalizeAttributes(maxValues.get(0))).writeAsCsv(...)
#FunctionAnnotation.ForwardedFields("f0; f1; f3; f4; f5")
#FunctionAnnotation.ReadFields("f2")
private static class NormalizeAttributes implements MapFunction<Tuple6<...>, Tuple6<...>> {
private final Tuple6<...> maxValues;
public NormalizeAttributes(Tuple6<...> maxValues) {
this.maxValues = maxValues;
}
#Override
public Tuple6<...> map(Tuple6<...> value) throws Exception {
value.f2 /= maxValues.f2;
return value;
}
}
collect() immediately triggers an execution of the program up to the dataset requested by collect(). If you later call env.execute() or collect() again, the program is executed second time.
Besides the side effect of execution, using collect() to distribute values to subsequent transformation has also the drawback that data is transferred to the client and later back into the cluster. Flink offers so-called Broadcast variables to ship a DataSet as a side input into another transformation.
Using Broadcast variables in your program would look as follows:
DataSet maxValues = result.max(2);
result
.map(new NormAttrs()).withBroadcastSet(maxValues, "maxValues")
.writeAsCsv(...);
The NormAttrs function would look like this:
private static class NormAttr extends RichMapFunction<Tuple6<...>, Tuple6<...>> {
private Tuple6<...> maxValues;
#Override
public void open(Configuration config) {
maxValues = (Tuple6<...>)getRuntimeContext().getBroadcastVariable("maxValues").get(1);
}
#Override
public PredictedLink map(Tuple6<...> value) throws Exception {
value.f2 /= maxValues.f2;
return value;
}
}
You can find more information about Broadcast variables in the documentation.

How to properly canalize multithreaded message flow in a single threaded service?

In a WPF application, I have a 3rd party library that is publishing messages.
The messages are like :
public class DialectMessage
{
public string PathAndQuery { get; private set; }
public byte[] Body { get; private set; }
public DialectMessage(string pathAndQuery, byte[] body)
{
this.PathAndQuery = pathAndQuery;
this.Body = body;
}
}
And I setup the external message source from my app.cs file :
public partial class App : Application
{
static App()
{
MyComponent.MessageReceived += MessageReceived;
MyComponent.Start();
}
private static void MessageReceived(Message message)
{
//handle message
}
}
These messages can be publishing from multiple thread at a time, making possible to call the event handler multiple times at once.
I have a service object that have to parse the incoming messages. This service implements the following interface :
internal interface IDialectService
{
void Parse(Message message);
}
And I have a default static instance in my app.cs file :
private readonly static IDialectService g_DialectService = new DialectService();
In order to simplify the code of the parser, I would like to ensure only one message at a time is parsed.
I also want to avoid locking in my event handler, as I don't want to block the 3rd party object.
Because of this requirements, I cannot directly call g_DialectService.Parse from my message event handler
What is the correct way to ensure this single threaded execution?
My first though is to wrap my parsing operations in a Produce/Consumer pattern. In order to reach this goal, I've try the following :
Declare a BlockingCollection in my app.cs :
private readonly static BlockingCollection<Message> g_ParseOperations = new BlockingCollection<Message>();
Change the body of my event handler to add an operation :
private static void MessageReceived(Message message)
{
g_ParseOperations.Add(message);
}
Create a new thread that pump the collection from my app constructor :
static App()
{
MyComponent.MessageReceived += MessageReceived;
MyComponent.Start();
Task.Factory.StartNew(() =>
{
Message message;
while (g_ParseOperations.TryTake(out message))
{
g_DialectService.Parse(message);
}
});
}
However, this code does not seems to work. The service Parse method is never called.
Moreover, I'm not sure if this pattern will allow me to properly shutdown the application.
What have I to change in my code to ensure everything is working?
PS: I'm targeting .Net 4.5
[Edit] After some search, and the answer of ken2k, i can see that I was wrongly calling trytake in place of take.
My updated code is now :
private readonly static CancellationTokenSource g_ShutdownToken = new CancellationTokenSource();
private static void MessageReceived(Message message)
{
g_ParseOperations.Add(message, g_ShutdownToken.Token);
}
static App()
{
MyComponent.MessageReceived += MessageReceived;
MyComponent.Start();
Task.Factory.StartNew(() =>
{
while (!g_ShutdownToken.IsCancellationRequested)
{
var message = g_ParseOperations.Take(g_ShutdownToken.Token);
g_DialectService.Parse(message);
}
});
}
protected override void OnExit(ExitEventArgs e)
{
g_ShutdownToken.Cancel();
base.OnExit(e);
}
This code acts as expected. Messages are processed in the correct order. However, as soon I exit the application, I get a "CancelledException" on the Take method, even if I just test the IsCancellationRequested right before.
The documentation says about BlockingCollection.TryTake(out T item):
If the collection is empty, this method immediately returns false.
So basically your loop exits immediately. What you may want is to call the TryTake method with a timeout parameter instead, and exit your loop when a mustStop variable becomes true:
bool mustStop = false; // Must be set to true on somewhere else when you exit your program
...
while (!mustStop)
{
Message yourMessage;
// Waits 500ms if there's nothing in the collection. Avoid to consume 100% CPU
// for nothing in the while loop when the collection is empty.
if (yourCollection.TryTake(out yourMessage, 500))
{
// Parses yourMessage here
}
}
For your edited question: if you mean you received a OperationCanceledException, that's OK, it's exactly how methods that take a CancellationToken object as parameter must behave :) Just catch the exception and exit gracefully.

Resources