Rendering XML from draw.io as an image using mxCellRenderer - mxgraph

I am trying to programmatically read in an XML file generated by draw.io, an online flowchart/diagram creation service. Draw.io is built using mxGraph at its core, which has recently been externally named jgraphx (thus the tag on this post), though the class names have remained the same.
This StackOverflow post shows how to read in the raw XML data from the file and convert it to an mxGraph object, and this page of the mxGraph Javadocs describes how to convert from the mxGraph object to a renderable image.
Unfortunately for me, however, despite following both guides, the image that is "rendered" is always null and an IllegalArgumentException is thrown (because the image is null). My code is as follows:
String xmlFile = "work/test.xml";
String imageFile = "work/test.png";
mxGraph graph = new mxGraph();
try {
Document doc = mxXmlUtils.parseXml(mxUtils.readFile(xmlFile));
mxCodec codec = new mxCodec(doc);
codec.decode(doc.getDocumentElement(), graph.getModel());
} catch (IOException e) {
e.printStackTrace();
}
RenderedImage image = mxCellRenderer.createBufferedImage(graph, null, 1, \\
Color.WHITE, false, null);
try {
ImageIO.write(image, "png", new File(imageFile));
} catch (IOException e) {
e.printStackTrace();
}
As you can see, this code should read in the XML data, create an mxGraph object from that data, then render the mxGraph object as an image in the current working directory. Instead, however, nothing happens and no image is created.
Has anyone ever experienced something like this? Am I overlooking something? Is there a better way to do what I'm trying to do? Any help would be appreciated.
FYI, here is a Pastebin with a sample XML file in case you want to try it for yourself.

With some help from the draw.io support guys, I found the answer: the XML is obfuscated, yes, but not irretrievably so. It is simply compressed and needs to be decompressed. To do so:
Base64 decode
Inflate
URL decode
I found this link which does all 3 of the above steps in one fell swoop: https://jgraph.github.io/drawio-tools/tools/convert.html.
Once I had the decompressed XML my code ran perfectly and generated the expected output.
See example implementation here:
https://github.com/laingsimon/render-diagram/blob/master/drawio-renderer/src/main/java/com/simonlaing/drawiorenderer/models/DiagramDecoder.java

Related

JSON Path Extractor - missing DummySampler

I have a problem with jMeter and JSON Path Extractor.
I downloaded zip file for this plugin and copy content to ext file as it is written on the page. Then I also downloaded jmeter-plugins-manager-0.10.jar and copy it into ext folder.
Next step - downloaded a sample:
https://jmeter-plugins.org/img/examples/JSONPathExtractorExample.jmx
When i try to import it i'm getting exception:
missing
com.thoughtworks.xstream.mapper.conversionException:kg.apc.jmeter.samplers.DummySampler:kg.apc.jmeter.samplers.DummySampler
EDITED:
I love samples and documentation for libraries. There is no information about install additional jars... just download:
https://jmeter-plugins.org/?search=jpgc-dummy
And show must go on
Since JMeter 3.0 you don't need any plugin for JSON.
There is natively a new one :
http://jmeter.apache.org/usermanual/component_reference.html#JSON_Path_PostProcessor
Regarding the issue maybe you can report the problem to jmeter-plugins project
i used JSR223 Sampler where i parse input json and validate it's values in pure JavaScript. It seems more simple.
Here is and example code:
var json = JSON.parse(SampleResult.getResponseDataAsString());
//get your jmeter context
var ctx = org.apache.jmeter.threads.JMeterContextService.getContext()
var vars = ctx.getVariables();
if(json[0].itemId != 1){
AssertionResult.setFailureMessage(json);
AssertionResult.setFailure(true);
} else {
//and put data to this context, that you can use it in other components.
vars.put('validationJsonRequest', true);
}
To see added data just use Debug Sampler or Debug post processor (which you can investigate in View Result Tree)

Embedding a file with a variable in AS3 + flixel

I have recently picked up flixel (I have programmed before, but I have not in a while) and I have come across a problem. I am attempting to create maps, and eventually there will be multiple maps available.
I currently have a .txt file that has information that eventually goes into an array. Then I go from array to map with loadmap. It is maybe a simple way to accomplish this task, and maybe their are better ways (I have not explored all the possibilities with flixel, and if there are any opinions, go ahead and let me know) but it works good for now.
As I have previously said, I am trying to do this with multiple maps. I could do this by using [Embed(source = "")] for each .txt file, but this may end up being annoying. So, here is my question: Is there a possible way Embed a file based upon a variable?
My Map class looks like this:
public function Map(MapSet:String, TileSet:String)
{
super(MapSet, TileSet);
//more stuff
}
Now I have tried:
[Embed(scource="data/MapSets/" + MapSet + ".txt", mimeType = "application/octet-stream")]private var loadedMap:Class
and then I use:
map = new Map("Map1x1", "ForestTiles");
add(map);
Is there a possibility of doing this in a different way? Or maybe I am doing something wrong? All opinions are welcome.
It's beneficial to know what code does when using it.
Embed is a meta tag. It tells the compiler to include a certain file into the .swf file.
That means this does not happen at runtime.
When this embed code is "executed", your variables don't even exist yet.
That's why your code cannot work.
Despite not working, your solution is still valid:
If you find it tedious to generate code, write a program that does this for you. Create/use a program that finds all valid files in the given directory and creates all the embed tags. Run this program before the compiler.
To embed a text file and use as a string, try this:
// create source var TextSource
[Embed(source="textFile.txt",mimeType="application/octet-stream")]
private var TextSource:Class;
var myByteArray:ByteArray = new TextSource();
var myString:String = myByteArray.readUTFBytes(myByteArray.length);
// then use for your function
map = new Map("Map1x1", myString);

Using JSON templates in Play 2.0

I'm getting this error:
Compilation error [package views.json.Runs does not exist]
when it clearly does exist. I can't figure out what I could be doing wrong.
the action in the Runs controller:
#BodyParser.Of(play.mvc.BodyParser.Json.class)
public static Result view(Long task_id, Long run_id) {
Run run = Run.find.byId(run_id);
return ok(views.json.Runs.view.render(run));
}
app/views/Runs/view.scala.json:
#(run: Run)
{
"started": "#run.started",
"completed": "#run.completed"
}
I've gotten a few html templates working, but this is the first JSON template I've tried with 2.0. I'm not sure what else to try since it's already about as basic as possible. Anyone have any ideas?
Update: I've gotten several suggestions for workarounds, but I'm still interested in knowing how to get the templates working, if only to better understand the changes to 2.0.
Only html, xml and txt appear to be supported by default. For other file extensions and formats, you'd have to register additional "templateTypes" in $PLAY_HOME/framework/src/sbt-plugin/src/main/scala/PlaySettings.scala (see also: SBT Settings, near the bottom).
It may be helpful to look at the standard template types definitions which are in $PLAY_HOME/framework/src/play/src/main/scala/play/api/templates/Templates.scala.
You could also cheat and serve your json from a txt file, but do response().setContentType("application/json") before calling the render method.
For Json, why don't you directly produce a Json string using the Json helper:
public static Result view(Long task_id, Long run_id) {
Run run = Run.find.byId(run_id);
return ok(play.libs.Json.toJson(run));
}
I recommend following the documentation and let the Json library serialize your data instead of writing the Json text on your own: See Serving Json Response.
I still don't understand, why does people want to render theirs JSON with views.
Note: this is the same way as #nico_ekito showed before and I agree with him totally , below code just demonstrates how to select part of the object for JSON
public static Result view(Long task_id, Long run_id){
Run run = Run.find.byId(run_id);
ObjectNode result = Json.newObject();
result.put("started", run.started);
result.put("completed", run.completed);
return ok(Json.toJson(result));
}

Remove DTD from XML SSIS

Hi all im struggling with this one. Ive got a foreach loop that will loop over a folder that contains xml files that i want to import there data into a database. The problem is the xml files have a dtd, theres nothing i can do to prevent this from being attached to the xml file. So i need some way of removing the dtd. Ive searched google and various forums and come up blank. Just wondered if anyone has any ideas?
I came up with a good solution in that im using a script task in my ssis, that opens the file, removes the dtd and then saves the file!!
public void Main()
{
try
{
XmlDocument XDoc = new XmlDocument();
XDoc.Load(Dts.Variables["FileName"].Value.ToString());
XmlDocumentType XDType = XDoc.DocumentType;
XDoc.RemoveChild(XDType);
XDoc.Save(Dts.Variables["FileName"].Value.ToString());
}
catch (Exception ex)
{
}
Dts.TaskResult = (int)ScriptResults.Success;
}
I would look for a solution in your preferred programming or scripting language (.NET, Perl, whatever) and then incorporate that into the package. For example, use an Execute Process task to call a command-line tool, or a Script Task that uses the standard .NET XML support.

AMF as a REST format, using BlazeDS and AS3's URLLoader

I have a ColdFusion server with an HTTP API that's currently returning either JSON or XML formatted responses. Internally, all of these responses are represented using the ColdFusion 'struct' type, and then converted to the appropriate format before being presented to the requesting client.
The client team using this API has requested that in addition to JSON and XML, we also return AMF objects. Now, I've seen (and have myself made) arguments against using AMF as a 'returned format' in a REST scenario rather than as an RPC format. I'm not interested in comments about whether or not it's a good idea -- I'd just like to know if it will work. If not, I'm hoping for clear reasons why it won't. If it will work, I'd love some guidance on how to 'makeitgo'.
So, in the interest of achieving that proof of concept example, I'm trying to serialize a two-element ColdFusion Array using BlazeDS, then consume that serialized object in a Flash Player 10/AS3 test.
Here's what the code looks like on the server side:
//the test object I'm trying to return (keeping it simple)
var testArray = ArrayNew(1);
testArray[1]="test";
testArray[2]="monkey";
//set up output stream to requesting client
var pc = getPageContext();
var response = pc.getResponse();
var out = response.getOutputStream();
response.setHeader("Content-Type", "application/x-amf");
//not sure if AmfMessageSerializer is the appropriate class to be using here
var amfMessageSerializer = createObject("java", "flex.messaging.io.amf.AmfMessageSerializer");
var amfTrace = createObject("java", "flex.messaging.io.amf.AmfTrace"); //needed by initialize() method
amfMessageSerializer.initialize(variables.SerializationContext.getSerializationContext(), out, amfTrace);
amfMessageSerializer.writeObject(testArray);
out.close();
Now, this generates some kind of binary data. If I stick that in a .cfm and try to load the page, I get something I can read in a hex editor that looks like it contains the array members I set. One note here: part of the response message includes "flex.messaging.io.ArrayCollection." I'm not knowledgeable enough to know what this tells me yet: anyone who can provide details about typing between the two environments will have many thanks from me.
The next step is to try and consume this on the FlashPlayer side. Here's what the stripped down AS3 looks like:
myURLloader.dataFormat = URLLoaderDataFormat.BINARY;
myURLloader.addEventListener(Event.COMPLETE, completeHandler);
myURLloader.load(myURLRequest);
function completeHandler( event : Event) : void
{
var serverResponse : ByteArray = new ByteArray();
serverResponse = event.target.data;
//read the response into a generic object
var responseObject : Object = new Object();
responseObject = serverResponse.readObject(); //fails here: error #2006
}
As indicated by the comment, this fails with error #2006 "Supplied index is out of bounds." I've searched around for common causes of this error, but haven't found any clear answers. I've tried resetting the byteArray.position to both the beginning and the end of the byteArray before attempting readObject() -- changing it to the end spits out error #2030 "End of file was encountered" (as one might expect), but I've verified that the .position defaults to 0, which generates the #2006 error.
I'm pretty sure that the issue here lies with the choice of BlazeDS calls I've used; I think I might be serializing a message when I want to be serializing an object. Unfortunately, the JavaDoc autogenerated docs for BlazeDS are ... less than enlightening. All of the more readable resources I've found focus on Flash Remoting and RPC examples. Surprising, I know; but it is what it is. I'm using Adobe BlazeDS docs; if anyone else has a better resource I'd be quite appreciative.
As a reminder to anyone answering: I realize this isn't a typical use of AMF. I'm not interested in responses that suggest the typical RPC method or to switch to Flash Remoting rather than HTTP/GET. What I need is an AMF serialized response from an HTTP request which can be deserialized on a Flash Player client. I don't have a choice in this matter. I do need to know if this is possible, and if so I'm hoping for some guidance on how to make it work. I welcome any and all suggestions aside from "Just don't use AMF!" or "Just switch to Flash Remoting!"
Update: made a little bit of progress with this:
1) on the server side, I used the ASObject class of blazeDS to create a simple ASObject and populate it with a key-value pair.
2) on both the client and server side, I had to make sure to set the object encoding to AMF0. The same technique in AMF3 generates that #2006/Out of bounds error, and I'm not yet sure why.
Here's what the code now looks like on the server-side:
//set up output stream to requesting client
var pc = getPageContext();
var response = pc.getResponse();
var out = response.getOutputStream();
response.setHeader("Content-Type", "application/x-amf");
//not sure if AmfMessageSerializer is the appropriate class to be using here
var amfMessageSerializer = createObject("java", "flex.messaging.io.amf.AmfMessageSerializer");
amfMessageSerializer.setVersion(variables.MessageIOConstants.AMF0);
var amfTrace = createObject("java", "flex.messaging.io.amf.AmfTrace"); //needed by initialize() method
amfMessageSerializer.initialize(variables.SerializationContext.getSerializationContext(), out, amfTrace);
var ASObject = createObject("java", "flex.messaging.io.amf.ASObject");
ASObject.put("testKey", "testValue"); //simple key-value map to return to caller
amfMessageSerializer.writeObject(testArray);
out.close();
The primary difference here is that rather than trying to serialize a CF Array, I'm building a response object (of type ASObject) manually.
On the client side, the code now looks like this:
myURLloader.dataFormat = URLLoaderDataFormat.BINARY;
myURLloader.addEventListener(Event.COMPLETE, completeHandler);
myURLloader.load(myURLRequest);
function completeHandler( event : Event) : void
{
var serverResponse : ByteArray = new ByteArray();
serverResponse = event.target.data;
serverResponse.objectEncoding = ObjectEncoding.AMF0; //important
//read the response into a generic object
var responseObject : Object = new Object();
responseObject = serverResponse.readObject();
trace(responseObject.testKey); //displays "testValue", as expected
}
The difference here is that I've explicitly set the ObjectEncoding to AMF0 (defaults to AMF3).
If I switch the objectEncoding to AMF3 on both server and client, I'd expect things to work, but I still get the 2006: out of bounds error. The ByteArray.length property is the same in both the AMF0 and AMF3 cases, but the content of the returned object is different (when viewed in a hex editor).
Changing the objectEncoding in the first example I provided had no effect on the error that was being produced.
So, then, the issue seems to have been an attempt to serialize the ColdFusion array: the AMFSerializer doesn't know how to handle it. It needs to explicitly be built as an ASObject. I'll build a sanitize function to do the conversion between the two types.
I feel like progress has been made (and thanks for all the feedback in comments and answers), but I've still got a lot of unanswered questions. Does anyone have any input on why this might be failing when I try to encode in AMF3, but not for AMF0? I don't have any attachment to one or the other, but I don't like this 'throw things at the wall and see which ones stick' method of solving the problem... I'd like to know why it's failing =/
I did that a some time ago..you can check my blog post from here, maybe it can help you. I was using Java on the server side, not CF.