multicast to a String collection - apache-camel

Is there an easy may to send a message to many endpoints, defined in a List<String>?
For exemple, I would like to do :
from("file://c:/inbox").to(myStringList);

Yes you will need to turn that list into an array as shown. Though doing this in pure Java is a bit ugly as the code shows:
String[] s = myStringList.toArray(new String[myStringList.size()]);
from("file://c:/inbox").to(s);

Related

Use content of a tuple as variable session

I extracted from a previous response an Object of tuple with the following regex :
.check(regex(""""idSc":(.{1,8}),"pasTemps":."codePasTemps":(.),"""").ofType[(String,String)].findAll.saveAs ("OBJECTS1"))
So I get my object :
OBJECTS1 -> List((1657751,2), (1658105,2), (4557378,2), (1657750,1), (916,1), (917,2), (1658068,1), (1658069,2), (4557379,2), (1658082,1), (4557367,1), (4557368,1), (1660865,2), (1660866,2), (1658122,1), (921,1), (922,2), (923,2), (1660875,1), (1660876,2), (1660877,2), (1658300,1), (1658301,1), (1658302,1), (1658309,1), (1658310,1), (2996562,1), (4638455,1))
After that I did a Foreach and need to extract every couple to add them in next requests So we tried :
.foreach("${OBJECTS1}", "couple") {
exec(http("request_foreach47"
.get("/ctr/web/api/seriegraph/bydates/${couple(0)}/${couple(1)}/1552863600000/1554191743799")
.headers(headers_27))
}
But I get the message : named 'couple' does not support index access
I also though that to use 2 regex on the couple to extract both part could work but I haven't found any way to use a regex on a session variable. (Even if its not needed for this case but possible im really interessed to learn how as it could be usefull)
If would be really thankfull if you could provided me help. (Im using Gatling 2 but can,'t use a more recent version as its for work and others scripts have been develloped with Gatling2)
each "couple" is a scala tuple which can't be indexed into like a collection. Fortunately the gatling EL has a function that handles tuples.
so instead of
.get("/ctr/web/api/seriegraph/bydates/${couple(0)}/${couple(1)}/1552863600000/1554191743799")
you can use
.get("/ctr/web/api/seriegraph/bydates/${couple._1}/${couple._2}/1552863600000/1554191743799")

How to use Collections.binarySearch() in a CodenameOne project

I am used to being able to perform a binary search of a sorted list of, say, Strings or Integers, with code along the lines of:
Vector<String> vstr = new Vector<String>();
// etc...
int index = Collections.binarySearch (vstr, "abcd");
I'm not clear on how codenameone handles standard java methods and classes, but it looks like this could be fixed easily if classes like Integer and String (or the codenameone versions of these) implemented the Comparable interface.
Edit: I now see that code along the lines of the following will do the job.
int index = Collections.binarySearch(vstr, "abcd", new Comparator<String>() {
#Override
public int compare(String object1, String object2) {
return object1.compareTo(object2);
}
});
Adding the Comparable interface (to the various primitive "wrappers") would also would also make it easier to use Collections.sort (another very useful method :-))
You can also sort with a comparator but I agree, this is one of the important enhancements we need to provide in the native VM's on the various platforms personally this is my biggest peeve in our current VM.
Can you file an RFE on that and mention it as a comment in the Number issue?
If we are doing that change might as well do both.

How to handle errors in custom MapFunction correctly?

I have implemented MapFunction for my Apache Flink flow. It is parsing incoming elements and convert them to other format but sometimes error can appear (i.e. incoming data is not valid).
I see two possible ways how to handle it:
Ignore invalid elements but seems like I can't ignore errors because for any incoming element I must provide outgoing element.
Split incoming elements to valid and invalid but seems like I should use other function for this.
So, I have two questions:
How to handle errors correctly in my MapFunction?
How to implement such transformation functions correctly?
You could use a FlatMapFunction instead of a MapFunction. This would allow you to only emit an element if it is valid. The following shows an example implementation:
input.flatMap(new FlatMapFunction<String, Long>() {
#Override
public void flatMap(String input, Collector<Long> collector) throws Exception {
try {
Long value = Long.parseLong(input);
collector.collect(value);
} catch (NumberFormatException e) {
// ignore invalid data
}
}
});
This is to build on #Till Rohrmann's idea above. Adding this as an answer instead of a comment for better formatting.
I think one way to implement "split + select" could be to use a ProcessFunction with a SideOutput. My graph would look something like this:
Source --> ValidateProcessFunction ---good data--> UDF--->SinkToOutput
\
\---bad data----->SinkToErrorChannel
Would this work? Is there a better way?

D-Bus how to create and send a Dict?

I have a process which exposes a method to DBus with one of the arguments taking the following type signature a{sv}:
Dict of {String, Variant}
The libDBus documentation for dbus_message_append_args fails to provide adequate reference for this. Some information appears in the specification under container-types, specifically:
A DICT_ENTRY works exactly like a struct, but rather than parentheses
it uses curly braces, and it has more restrictions. The restrictions
are: it occurs only as an array element type; it has exactly two
single complete types inside the curly braces; the first single
complete type (the "key") must be a basic type rather than a container
type. Implementations must not accept dict entries outside of arrays,
must not accept dict entries with zero, one, or more than two fields,
and must not accept dict entries with non-basic-typed keys. A dict
entry is always a key-value pair.
On attempting to append a dict I receive the following error message:
type dict_entry isn't supported yet in dbus_message_append_args_valist
Although I'm actually using dbus_message_append_args(I guess the error message is somewhat off).
There are two other alternatives to dbus_message_append_args() using either:
dbus_message_iter_append_basic()
and
dbus_message_iter_append_fixed_array()
While I can create an empty Dict container with the following:
const char * container_d_sig = "{sv}";
DBusMessageIter iter, sub;
dbus_message_iter_init_append(msg, &iter);
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, container_d_sig, &sub);
dbus_message_iter_close_container(&iter, &sub);
Neither of the append methods appear to support adding a struct. Not sure what to try here...
First, about D-Bus libraries: you talk about dbus-glib in several places but the functions you refer to are not part of dbus-glib but libdbus. If you are still trying to find the best way to use D-Bus, I suggest you forget both of these: libdbus is very low-level (it's documentation even starts with "If you use this low-level API directly, you're signing up for some pain") and dbus-glib is deprecated. The best D-Bus API currently is GDBus which is part of GLib GIO: it's a far better designed API than either of the other two, well tested and supported.
Now, as for the actual question, documentation for dbus_message_append_args() does say it quite clearly:
To append variable-length basic types, or any more complex value, you
have to use an iterator rather than this function.
In other words you should use dbus_message_iter_open_container() to prepare the iterator until it is pointing to somewhere where you can use dbus_message_iter_append_basic(). Note that in your example the dictionary is a container, the dictionary entry is a container and the variant is a container... In other words it gets pretty complex quite fast. If you really want to do it, look at e.g. Connman code for examples.
As I mentioned, the sane route is GDBus. There creating even much more complex signatures is pretty easy as you can use the GVariantBuilder API:
GVariantBuilder builder;
g_variant_builder_init (&builder, G_VARIANT_TYPE("a{sv}"));
g_variant_builder_add (&builder, "{sv}", "name1", my_variant);
/* Now use the builder results with g_dbus_connection_call()
or g_dbus_proxy_call() */
I know this question was asked awhile ago, but I had a very similar question recently, and after several hours of trial and error this is some code I came up with that works for me. Hopefully it helps someone else...
DBusMessage* testMessage()
{
DBusMessage* mssg = dbus_message_new_signal("/fi/w1/wpa_supplicant1/Interfaces/0", "fi.w1.wpa_supplicant1.Interface", "PropertiesChanged");
DBusMessageIter iter, aIter;
dbus_message_iter_init_append(mssg, &iter);
if (!dbus_message_iter_open_container(&iter, 'a', "{sv}", &aIter))
return nullptr;
DBusMessageIter eIter;
if (!dbus_message_iter_open_container(&aIter, 'e', NULL, &eIter)) {
dbus_message_iter_abandon_container_if_open(&iter, &aIter);
return nullptr;
}
const char* key = "test key";
dbus_message_iter_append_basic(&eIter, 's', static_cast<void*>(&key));
DBusMessageIter vIter;
if (!dbus_message_iter_open_container(&eIter, 'v', "i", &vIter)) {
dbus_message_iter_abandon_container_if_open(&aIter, &eIter);
dbus_message_iter_abandon_container_if_open(&iter, &aIter);
return nullptr;
}
dbus_int32_t val = 42;
dbus_message_iter_append_basic(&vIter, 'i', static_cast<void*>(&val));
dbus_message_iter_close_container(&eIter, &vIter);
dbus_message_iter_close_container(&aIter, &eIter);
dbus_message_iter_close_container(&iter, &aIter);
return mssg;
}
This is C++ but should be pretty easy to adapt for C. The returned message has a signature of a{sv}. The dbus docs are helpful-ish.

How can I pass a Swift array as an argument to a thread?

I'm trying to spawn a new thread to do some background processing, based on a String that I've broken down into an array of characters. Here's what my code looks like:
var testString : String = NSString(data:data!, encoding:NSUTF8StringEncoding)
var testStringArray : Array<Character> = []
for character in testString
{
if(!(self.isCharacterStrippable(character)))
{
testStringArray.append(character)
}
}
NSThread.detachNewThreadSelector("fillKeysFromArray:", toTarget: self, withObject: testStringArray)
I get a compiler error telling me that "Array does not conform to protocol AnyObject".
Short of writing an object wrapper for my array, or setting it as an instance variable (both of which seem like overkill), is there any way I can get this array passed through to the new thread?
Using Grand Central Dispatch is going to be much easier in the long run. You can run your function on a background thread with something like:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
[weak self] in // This is so that we don't create a reference cycle
self?.fillKeysFromArray(testStringArray);
return
}
You can read up on Grand Central Dispatch and all the nice things it provides when it comes to threading and concurrency in Apple's Concurrency Programming Guide.
The root cause is that detachNewThreadSelector can only accept a NSMutableArray for the withObject parameter. If you make testStringArray a variable of type NSMutableArray you can get rid of the compiler error message.
Having said that, you should seriously consider the advices from Bryan Chen and Mike S to switch to GCD.

Resources