ChronicleQueue - how to read custom object from tailer - chronicle-queue

I am very new to ChronicleQueue and I am unable to find a straight forward example of how can I read back my custom object from a tailer.
public class MyData extends AbstractMarshallable
I have my class containing some strings and numbers, I am able to write to queue using appender, but there is no straight forward api to call. how can i get a object of MyData from tailer.readDocument api?

Try with below code:
final DocumentContext context = queue.createTailer().readingDocument();
final MyData container = new MyData();
if (context.isPresent()) {
context.wire().getValueIn().marshallable(container);
}
this assumes that appending is performed in the following manner:
try (DocumentContext ctx = appender.writingDocument()) {
ctx.wire().getValueOut().marshallable(myData);
}

Related

Kafka Streams Code implemented as a library and function called

So, I have created a Kafka Application that basically uses filter function. Now, I have created the jar file of this application.
I want to import this application as a library in some other program and call the method to start the filtering process. Then I also want to stop this filtering using some command or API call. How can I do this??
I have provide the topology builder function below for which I want to convert into a library and call from other application.
public static Topology builderFunc(String id) {
final Serializer<JsonNode> jsonNodeSerializer = new JsonSerializer();
final Deserializer<JsonNode> jsonNodeDeserializer = new JsonDeserializer();
final Serde<JsonNode> jsonNodeSerde = Serdes.serdeFrom(jsonNodeSerializer, jsonNodeDeserializer);
final StreamsBuilder builder = new StreamsBuilder();
KStream<String, JsonNode> inputStream =
builder.stream("input-records", Consumed.with(Serdes.String(), jsonNodeSerde));
inputStream.filter((key, value) -> key.equals(id))
.to("output-records", Produced.with(Serdes.String(), jsonNodeSerde));
final Topology topology = builder.build();
return topology;
}

Google diff-match-patch : How to unpatch to get Original String?

I am using Google diff-match-patch JAVA plugin to create patch between two JSON strings and storing the patch to database.
diff_match_patch dmp = new diff_match_patch();
LinkedList<Patch> diffs = dmp.patch_make(latestString, originalString);
String patch = dmp.patch_toText(diffs); // Store patch to DB
Now is there any way to use this patch to re-create the originalString by passing the latestString?
I google about this and found this very old comment # Google diff-match-patch Wiki saying,
Unpatching can be done by just looping through the diff, swapping
DIFF_INSERT with DIFF_DELETE, then applying the patch.
But i did not find any useful code that demonstrates this. How could i achieve this with my existing code ? Any pointers or code reference would be appreciated.
Edit:
The problem i am facing is, in the front-end i am showing a revisions module that shows all the transactions of a particular fragment (take for example an employee details), like which user has updated what details etc. Now i am recreating the fragment JSON by reverse applying each patch to get the current transaction data and show it as a table (using http://marianoguerra.github.io/json.human.js/). But some JSON data are not valid JSON and I am getting JSON.parse error.
I was looking to do something similar (in C#) and what is working for me with a relatively simple object is the patch_apply method. This use case seems somewhat missing from the documentation, so I'm answering here. Code is C# but the API is cross language:
static void Main(string[] args)
{
var dmp = new diff_match_patch();
string v1 = "My Json Object;
string v2 = "My Mutated Json Object"
var v2ToV1Patch = dmp.patch_make(v2, v1);
var v2ToV1PatchText = dmp.patch_toText(v2ToV1Patch); // Persist text to db
string v3 = "Latest version of JSON object;
var v3ToV2Patch = dmp.patch_make(v3, v2);
var v3ToV2PatchTxt = dmp.patch_toText(v3ToV2Patch); // Persist text to db
// Time to re-hydrate the objects
var altV3ToV2Patch = dmp.patch_fromText(v3ToV2PatchTxt);
var altV2 = dmp.patch_apply(altV3ToV2Patch, v3)[0].ToString(); // .get(0) in Java I think
var altV2ToV1Patch = dmp.patch_fromText(v2ToV1PatchText);
var altV1 = dmp.patch_apply(altV2ToV1Patch, altV2)[0].ToString();
}
I am attempting to retrofit this as an audit log, where previously the entire JSON object was saved. As the audited objects have become more complex the storage requirements have increased dramatically. I haven't yet applied this to the complex large objects, but it is possible to check if the patch was successful by checking the second object in the array returned by the patch_apply method. This is an array of boolean values, all of which should be true if the patch worked correctly. You could write some code to check this, which would help check if the object can be successfully re-hydrated from the JSON rather than just getting a parsing error. My prototype C# method looks like this:
private static bool ValidatePatch(object[] patchResult, out string patchedString)
{
patchedString = patchResult[0] as string;
var successArray = patchResult[1] as bool[];
foreach (var b in successArray)
{
if (!b)
return false;
}
return true;
}

Camel check header value after split

I have a problem in my Camel Route when I try to check the value of a header.
So what is happening is that I go to a processor, do my stuff, then I create 2 different message that I put inside the body.
After that I go back on my route, I split my body so I can route the 2 differents messages, and there I use a .choice().when() on the header CamelFileName to check if it contains some value.
It doesn't find the value and then doesn't go inside the .when()
Here is the source code to make it more clear :
// My route
from("myQuartz")
.routeId("myId")
.bean(myProcessor.class)
.split(body())
.to("log:test?showAll=true&multiline=true")
.log('[${header.CamelFileName}]')
.choice()
.when(header('CamelFileName').contains('myString1'))
// do my stuff
.endChoice()
.when(header('CamelFileName').contains('myString2'))
// do my other stuff
.endChoice()
.otherwise()
.log("It did not go inside the when")
.to("log:test?showAll=true&multiline=true")
.endChoice()
.end()
So here I am simply trying to check if the CamelFileName header contains a string (it's not a variable), but it keep going inside the otherwise.
The log just after the split show me that the CamelFileName header is correct and do contains the string I am looking for.
I tried different ways of checking the value inside the when() such as using a simple(), but it doesn't work.
My file is a groovy file.
Thanks for your help.
EDIT :
So to explain what is inside my body I will show you the processor source code.
I create two DefaultMessage,
I set them a body and a CamelFileName header,
I put them into a list and then I put that list into my exchange body.
After that I go back to the route and I split the body so it will separate the two messages and route them.
Here is what's happening in my processor :
// Message 1
DefaultMessage message1 = new DefaultMessage()
message1.setBody(bodyContent)
def fileName1 = "myString1_blablabla.txt"
message1.setHeader("CamelFileName",fileName1)
listMessages.add(message1)
// Message 2
DefaultMessage message2 = new DefaultMessage()
message2.setBody(bodyContent)
def fileName2 = "myString2_blablabla.txt"
message2.setHeader("CamelFileName",fileName2)
listMessages.add(message2)
exchange.in.setBody(listMessages)
I've setup a simpler test for your route. It routes data to the proper when clause. When you split(), the headers get copied for each exchange, so I'm not sure why you would expect (given your route) why the elements of the list would have different header values.
public class SampleTest extends CamelTestSupport{
#Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from("direct:start")
.setHeader("CamelFileName", simple("myString1"))
.split(body())
.choice()
.when(header("CamelFileName").contains("myString1"))
.to("mock:myString1")
.endChoice()
.when(header("CamelFileName").contains("myString2"))
.to("mock:myString2")
.endChoice()
.otherwise()
.to("mock:otherwise")
.endChoice()
.end();
}
};
}
#Test
public void test() throws Exception {
//Setup mock body
java.util.List<String> myList = new java.util.ArrayList<String>();
myList.add("1");
myList.add("2");
MockEndpoint mock1 = getMockEndpoint("mock:myString1");
MockEndpoint mock2 = getMockEndpoint("mock:myString2");
MockEndpoint mockOtherwise = getMockEndpoint("mock:otherwise");
mock1.expectedMessageCount(myList.size());
mock2.expectedMessageCount(0);
mockOtherwise.expectedMessageCount(0);
template.sendBody("direct:start", myList);
assertMockEndpointsSatisfied();
}
}

HTTPService not properly JSON-encoding nested objects on send()

i am creating an object like this:
var myObj:Object = new Object();
myObj["someProperty"] = {
anotherProperty: "someValue",
whateverProperty: "anotherValue"
}
now i want to send it to a web server (rails):
var service:HTTPService = new HTTPService();
service.url = "http://server.com/some/path/entry.json";
service.method = URLRequestMethod.POST;
service.send( myObj );
the problem is that the server receives the json like this:
{"someProperty"=>"[object Object]"}
is this a problem with HTTPService? should i use the good old loader/urlrequest and serialize myself? by the way, serializing and then passing the string doesn't work, webserver receives empty request as GET.
but i kinda want to use the httpservice class though...
You can use a SerializationFilter with your HTTPService to correctly serialize the data you pass as an object to HTTPService.send().
The way in which this works is to create a custom SerializationFilter to perform the specific action required. In your case, you want to convert the outgoing body Object to a JSON format String. To do this you should override the serializeBody method:
package
{
import mx.rpc.http.AbstractOperation;
import mx.rpc.http.SerializationFilter;
import com.adobe.serialization.json.JSON;
public class JSONSerializationFilter extends SerializationFilter
{
override public function serializeBody(operation:AbstractOperation, obj:Object):Object
{
return JSON.encode(obj);
}
}
}
You can assign an instance of this filter to your HTTPService before calling send():
var service:HTTPService = new HTTPService();
service.url = "http://server.com/some/path/entry.json";
service.method = URLRequestMethod.POST;
//add the serialization filter
service.serializationFilter = new JSONSerializationFilter();
service.send( myObj );
Once assigned, this filter will be invoked for all the operations this HTTPService instance performs. You can also add more override methods to your custom filter to handle the incoming response.
I highly recommend using Mike Chamber's JSON serialization library for encoding / decoding (serializing) data in JSON.
Basically, you need to convert your object into a JSON representation. The JSONEncoder class is useful for this.
There's a useful (old but still very relevant for using HTTPService + JSON) tutorial that goes through it, but essentially you should call JSON.encode() on what your "someProperty" value is.
i.e.:
var dataString:String = JSON.encode(dataValue);
dataString = escape(dataString);
myObj["someProperty"] = dataString;

Can I stop my WCF generating ArrayOfString instead of string[] or List<string>

I am having a minor problem with WCF service proxies where the message contains List<string> as a parameter.
I am using the 'Add Service reference' in Visual Studio to generate a reference to my service.
// portion of my web service message
public List<SubscribeInfo> Subscribe { get; set; }
public List<string> Unsubscribe { get; set; }
These are the generated properties on my MsgIn for one of my web methods.
You can see it used ArrayOfString when I am using List<string>, and the other takes List<SubscribeInfo> - which matches my original C# object above.
[System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
public System.Collections.Generic.List<DataAccess.MailingListWSReference.SubscribeInfo> Subscribe {
get {
return this.SubscribeField;
}
set {
if ((object.ReferenceEquals(this.SubscribeField, value) != true)) {
this.SubscribeField = value;
this.RaisePropertyChanged("Subscribe");
}
}
}
[System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
publicDataAccess.MailingListWSReference.ArrayOfString Unsubscribe {
get {
return this.UnsubscribeField;
}
set {
if ((object.ReferenceEquals(this.UnsubscribeField, value) != true)) {
this.UnsubscribeField = value;
this.RaisePropertyChanged("Unsubscribe");
}
}
}
The ArrayOfString class generated looks like this. This is a class generated in my code - its not a .NET class. It actually generated me a class that inherits from List, but didn't have the 'decency' to create me any constructors.
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
[System.Runtime.Serialization.CollectionDataContractAttribute(Name="ArrayOfString", Namespace="http://www.example.com/", ItemName="string")]
[System.SerializableAttribute()]
public class ArrayOfString : System.Collections.Generic.List<string> {
}
The problem is that I often create my message like this :
client.UpdateMailingList(new UpdateMailingListMsgIn()
{
Email = model.Email,
Name = model.Name,
Source = Request.Url.ToString(),
Subscribe = subscribeTo.ToList(),
Unsubscribe = unsubscribeFrom.ToList()
});
I really like the clean look this gives me.
Now for the actual problem :
I cant assign a List<string> to the Unsubscribe property which is an ArrayOfString - even though it inherits from List. In fact I cant seem to find ANY way to assign it without extra statements.
I've tried the following :
new ArrayOfString(unsubscribeFrom.ToList()) - this constructor doesn't exist :-(
changing the type of the array used by the code generator - doesn't work - it always gives me ArrayOfString (!?)
try to cast List<string> to ArrayOfString - fails with 'unable to cast', even though it compiles just fine
create new ArrayOfString() and then AddRange(unsubscribeFrom.ToList()) - works, but I cant do it all in one statement
create a conversion function ToArrayOfString(List<string>), which works but isn't as clean as I want.
Its only doing this for string, which is annoying.
Am i missing something? Is there a way to tell it not to generate ArrayOfString - or some other trick to assign it ?
Any .NET object that implements a method named "Add" can be initialized just like arrays or dictionaries.
As ArrayOfString does implement an "Add" method, you can initialize it like this:
var a = new ArrayOfString { "string one", "string two" };
But, if you really want to initialize it based on another collection, you can write a extension method for that:
public static class U
{
public static T To<T>(this IEnumerable<string> strings)
where T : IList<string>, new()
{
var newList = new T();
foreach (var s in strings)
newList.Add(s);
return newList;
}
}
Usage:
client.UpdateMailingList(new UpdateMailingListMsgIn()
{
Email = model.Email,
Name = model.Name,
Source = Request.Url.ToString(),
Subscribe = subscribeTo.ToList(),
Unsubscribe = unsubscribeFrom.To<ArrayOfString>()
});
I prefer not to return generic types across a service boundary in the first place. Instead return Unsubscribe as a string[], and SubscriptionInfo as SubscriptionInfo[]. If necessary, an array can easily be converted to a generic list on the client, as follows:
Unsubscribe = new List<string>(unsubscribeFrom);
Subscribe = new List<SubscriptionInfo>(subscribeTo);
Too late but can help people in the future...
Use the svcutil and explicitly inform the command line util that you want the proxy class to be serialized by the XmlSerializer and not the DataContractSerializer (default). Here's the sample:
svcutil /out:c:\Path\Proxy.cs /config:c:\Path\Proxy.config /async /serializer:XmlSerializer /namespace:*,YourNamespace http://www.domain.com/service/serviceURL.asmx
Note that the web service is an ASP.NET web service ok?!
If you are using VS 2008 to consume service then there is an easy solution.
Click on the "Advanced..." button on the proxy dialog that is displayed when you add a Service Reference. In the Collection Type drop down you can select System.Generic.List. The methods returning List should now work properly.
(Hope this is what you were asking for, I'm a little tired and the question was a tad difficult for me to read.)