Overwrite msg in mirth - e4x

I have two destinations now and the first calls a SOAP webservice.
I want to take the response of that destination by:
msg = new XML(responseMap.get('Destination1').getMessage());
and convert it to a mutable XML object.
Doing:
logger.error(msg);
<S:Body><PRPA_IN201306UV02> ... </PRPA_IN201306UV02></S:Body>
Shows the valid msg as I want it, but when I do:
msg['S:Body'] it returns nothing.
Any suggestions would help.

msg.S::Body is what you want. Make sure you define the S namespace before you use it.

Related

How to access invoke response object variable in following steps of assembly

the assembly of my API Connect API contains two invokes. The first is calling an internal routing API to get some routing information. The response of this routing API should not be passed to the second invoke.
If I do not configure a 'response object variable' in the invoke of the routing API, the original request body is overwritten and the second API gets the result from the routing API as request body. And if I specify a 'response object variable' in the routing invoke, I can not access the content (json) of this variable in the following steps.
How can I solve this issue?
Thx 4 help.
Rather than relying on reading the request object, you can read from your configured 'response object variable' later on in the flow. For instance, if your first invoke has a response object variable set to 'resp1', you can access the JSON payload using '$(resp1.body)' later on in the flow. Using this technique will allow you to store the response of each invoke in a separate object, avoiding the overwriting issue. These response object variables can be read just like any other context variable in the flow.
For more info, check out these links in the Knowledge Center:
Invoke Policy: https://www.ibm.com/support/knowledgecenter/en/SSMNED_5.0.0/com.ibm.apic.toolkit.doc/rapim_ref_ootb_policyinvoke.html
Context Variables:
https://www.ibm.com/support/knowledgecenter/SSMNED_5.0.0/com.ibm.apic.toolkit.doc/capim_context_references.html
I don't understand this part:
[...] "And if I specify a 'response object variable' in the routing
invoke, I can not access the content (json) of this variable in the
following steps." [...]
Why can't you access the content of this variable in the following steps?
Save copy of the request...
... that you received. What I'd do is always save a copy of the data received in the invoke to a processed variable instead of the (raw) original request.
In your GatewayScript try something like this:
let objRequest = apim.getvariable("request");
let body = null;
Here I recommend you to change the body (if json) to a standard js object
if(objRequest && objRequest.hasOwnProperty("body")){
try{
body = JSON.parse(objRequest.body);
}catch(e){
body = objRequest.body;
}
}
Remember to stringify the complete object before saving it as global variable. Is the only way to store it (because you can only store a string value in this kind of variables)
apim.setvariable("objRequest", JSON.stringify(objRequest));
Retrieve copy of the request...
...that you have saved in global variables you can get it from any other GatewayScript that you want this way:
let objRequest = JSON.parse(apim.getvariable("objRequest"));
Be careful not to assign an existent name to the apim.setvariable(name, value) because if you use "request" as name instead of "objRequest" (or other), you'll be replacing the original request element, and we don't want that to happen.
If you need to set or retrieve the status.code...
...you can do it with:
let statusCode = objRequest.body.status.code;

Invalid_request_parameter (create and sending envelopes)

I'm trying to use a service of DocuSign API in an abap project. I want to send a document to a specific email so it can be signed. But im getting the following error:
"errorCode": "INVALID_REQUEST_PARAMETER",## "message": "The request contained at least one invalid parameter. Query parameter 'from_date' must be set to a valid DateTime, or 'envelope_ids' or 'transaction_ids' must be specified.
I tried the following:
CALL METHOD cl_http_client=>create_by_url
EXPORTING
url = l_url (https://demo.docusign.net/restapi/v2/accounts/XXXXXX')
proxy_host = co_proxy_host
proxy_service = co_proxy_service
IMPORTING
client = lo_http_client
lo_http_client->request->set_method( method = 'POST').
CALL METHOD lo_http_client->request->set_header_field
EXPORTING
name = 'Accept'
value = 'application/json'.
CALL METHOD lo_http_client->request->set_header_field
EXPORTING
name = 'X-DocuSign-Authentication'
value = get_auth_header( ). (json auth header)
CALL METHOD lo_http_client->request->set_cdata
EXPORTING
data = create_body( ).
This is my body:
CONCATENATE
`{`
`"emailSubject": "DocuSign REST API Quickstart Sample",`
`"emailBlurb": "Shows how to create and send an envelope from a document.",`
`"recipients": {`
`"signers": [{`
`"email": "test#email",`
`"name": "test",`
`"recipientId": "1",`
`"routingOrder": "1"`
`}]`
`},`
`"documents": [{`
`"documentId": "1",`
`"name": "test.pdf",`
`"documentBase64":` `"` l_encoded_doc `"`
`}],`
`"status": "sent"`
`}` INTO re_data.
The api request to get the Baseurl is working fine. (I know the error is quite specific what the problem is, but i cant find any sources on the docusign api documentation that one of the mentioned parameters should be added to the request)
Thank you in regards
The error message seems to indicate that you're Posting to an endpoint that requires certain query string parameters -- but you're not specifying them as expected in the query string. I'd suggest you check the DocuSign API documentation for the operation you are using, to determine what query string parameters it requires, and then ensure that you're including those parameters in your request URL.
If you can't figure this out using the documentation, then I'd suggest that you update your post to clarify exactly what URL (endpoint) you are using for the request, including any querystring parameters you're specifying in the URL. You can put fake values for things like Account ID, of course -- we just need to see the endpoint you are calling, and what qs params you're sending.
To create an envelope, use
https://demo.docusign.net/restapi/v2/accounts/XXXXXX/envelopes
instead of
https://demo.docusign.net/restapi/v2/accounts/XXXXXX
Thank you for all the answers, i found the mistake. Creating the request wasn´t the problem. I was using the wrong "sending"-method -_-.
now its working :)
lo_rest_client->post( EXPORTING io_entity = lo_request_entity ).

SmartGWT not able to parse data in the DataSource.transformResponse() method

I need some help please...
I am working with a GWT enabled web application. I am using the gwt-2.3.0 SDK.
I have a method that extends the DataSource class and uses the transformResponse method:
public class DeathRecordXmlDS extends DataSource {
protected void transformResponse(DSResponse response, DSRequest request, Object data){
super.transformResponse(response, request, data);
}
}
As I understand, the transformResponse() method should get control and at this point, I will have access to the data that is being provided to the Client side of my application. I am trying to work with the Object data parameter (the third parameter) that is passed in.
I am expecting an XML formatted string to be passed in. The XML will contain data (a count field) that I need to access and use.
I don't seem to be getting an XML string. Here's what I know...
I do see the XML data being passed to my webapp (the client). I can see this because I inspect the webpage that I am working with and I see the Response data. Here's an example of something that I expect to receive:
XML data from Query:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Collection numRecords="0">
<DeathRecords/>
</Collection>
The above XML is valid (I checked it in a Validator). This is a case where there was no data (No Death Records) being returned to my application. The numRecords XML attribute is set to "0". Of course, If I do have records returned the numRecords will contain the number of records and I'll get that same number of DeathRecord nodes.
I am not getting the above data (or, I don't know how to work with it) in the transformResponse() method.
Here's what I've done to try to figure this out...
The Object data parameter... it is a JavaScriptObject. I know this because I did a .getClass().getName() on it:
DeathRecordXmlDS::transformResponse() data.getClass().getName(): com.google.gwt.core.client.JavaScriptObject$
Then, to try to work with it, I converted it to a String:
com.google.gwt.core.client.JavaScriptObject dataJS = (com.google.gwt.core.client.JavaScriptObject)data;
System.out.println("DeathRecordXmlDS::transformResponse() data as a JavaScriptObject: "+dataJS.toString());
The contents of 'data' formatted as a String look like:
DeathRecordXmlDS::transformResponse() data as a JavaScriptObject: [XMLDoc <Collection>]
So, it looks like I have something that has to do with my 'Collection' node, but not a String of XML data that I can parse and get to my numRecords attribute.
What do I need to do to gain access to the XML in the transformResponse() method?
Thanks!
I think your data object is already translated to a javascript collection.
Maybe you could use the utility class XMLTools to retrieve your numRecords information:
Integer numRecords = Integer.parseInt(XMLTools.selectString(data, "Collection/#numRecords"));
After working on this for an additional period of time I was able to read the XML data that I am working with. I used the following piece of code:
try{
JsArray<JavaScriptObject> nodes = ((JavaScriptObject) XMLTools.selectNodes(data, "/Collection/#numRecords")).cast();
for (int i = 0; i < nodes.length(); i++) {
com.google.gwt.dom.client.Element element = (com.google.gwt.dom.client.Element) nodes.get(i);
numRecords = element.getNodeValue();
}
} catch(Exception e){
// If Parsing fails, capture the exception
System.out.println("DeathRecordXmlDS::transformResponse() Not able to parse the XML");
}
I think the first step to solving this was understanding that the parameter 'data' of type Object was really a JavaScriptObject. I learned this after looking at the .getClass() and .getName(). This helped me understand what I was working with:
System.out.println("DeathRecordXmlDS::transformResponse() data.getClass().getName(): "+data.getClass().getName());
Once I knew it was a JavaScriptObject, I was able to do a little more focused of a Google search for what I was trying to accomplish. I was a little surprised that the XMLTools.selectNodes() function worked the way it did, but the end result is that I was able to read the numRecords attribute.
Thanks for the suggestion!

Custom XML response in sails.js blueprint for a model?

I am new to sails.js and I have a simple blueprint model set up. Right now, my controller and model are pretty much empty except for attribute definitions on the model.
After the model is created via POST, I would like the response to be a custom XML response (some plain text I generate essentially), not the standard JSON response. I figured that I could overwrite the entire create method on the controller, essentially copy-and-pasting the code from the default and just overwriting the response, but that seems really heavy too me.
There must be a better way to do this?
Note that I am only attempting to do this for this specific model, not generally.
Thanks!
The best way is to simply add the header as DigitalDesignDj mentioned.
/**
* TestController
*/
module.exports = {
create: function(res, req) {
// get your data
var xml = 'some xml string';
res.setHeader( "Content-type", "text/xml" );
res.send(xml);
}
}
To change headers for a specific response.
response.setHeader( "Content-type", "text/xml" );
When you already have some XML for the response.send()
If your result was to do this for all actions on that single model you could simply overwrite the toJSON method to generate XML instead of JSON in the model itself. Then if your running blueprints, it will spit out XML instead of json when you hit those endpoints.
However your question is specific to the create action. In this instance, I would ask if your running alternate view files for non ajax requests. And if not, just drop an view files into the create action that views/foo/create.[ejs,jade,ect...] with your xml layout. The response will see the view file and override the json output with that file. This means you have to change no code just add that single file.
Their are a dozen ways to accomplish this, and your question would need more detail (as mentioned on the comments) for a specific answer to your use case.

Perl: Getting complete request from SOAP::WSDL object

I'm working with SOAP::WSDL and another company's custom WSDL file. Every time they make a change for me and I recreate my modules, something breaks. Finding the problem is rather tedious because I don't find a proper way to access the actual request that is sent to the SOAP server.
The only way to get to the request so far has been to use tcpdump in conjunction with wireshark to extract the request and result. That works, but since I don't have root privileges on the dev machine I have to get an admin over every time I want to do that. I feel there must be another way to get to the HTTP::Request object inside the SOAP::WSDL thing. But if the server returns a fault, I don't even have a response object, but rather a SOAP::WSDL::SOAP::Typelib::Fault11 object that has no visible relation to the request.
I've also tried using the debugger but I'm having trouble finding the actual request part. I've not yet understood how to tell the debuger to skip to a specific part deep inside a complex number of packages.
I stumbled across this, having the same problem myself. I found the answer is using both options that raina77ow listed.
$service->outputxml(1);
returns the whole SOAP envelope xml, but this needs to be combined with
$service->no_dispatch(1);
With no_dispatch set, the SOAP request is printed, instead of the reply from the request. Hopefully this can help others.
Have you tried to use SOAP::WSDL::Client tracing methods - and outputxml in particular? It returns the raw SOAP envelope which is to be sent to the server.
You can also use no_dispatch configuration method of SOAP::WSDL package:
When set, call() returns the plain request XML instead of dispatching
the SOAP call to the SOAP service. Handy for testing/debugging.
I found a way to at least print out the generated XML code.
First, I looked at SOAP::WSDL::Client as raina77ow suggested. That wasn't what I needed, though. But then I came across SOAP::WSDL::Factory::Serializer. There, it says:
Serializer objects may also be passed directly to SOAP::WSDL::Client
by using the set_serializer method.
A little fidgeting and I came up with a wrapper class for SOAP::WSDL::Serializer::XSD which is the default serializer used by SOAP::WSDL. A look at the code helped, too.
Here's the module I wrote. It uses SOAP::WSDL::Serializer::XSD as a base class and overloads the new and serialize methods. While it only passes arguments to new, it grabs the returned XML from serialize and prints it, which suffices for debugging. I'm not sure if there's a way to put it somewhere I can easily get it from.
package MySerializer;
use strict;
use warnings;
use base qw(SOAP::WSDL::Serializer::XSD);
sub new {
my $self = shift;
my $class = ref($self) || $self;
return $self if ref $self;
# Create the base object and return it
my $base_object = $class->SUPER::new(#_);
return bless ($base_object, $class);
}
sub serialize {
my ($self, $args_of_ref) = #_;
# This is basically a wrapper function that calls the real Serializer's
# serialize-method and grabs and prints the returned XML before it
# giving it back to the caller
my $xml = ref($self)->SUPER::serialize($args_of_ref);
print "\n\n$xml\n\n"; # here we go
return $xml;
}
1;
And here's how I call it:
my $serializer = MySerializer->new();
$self->{'_interface'} = Lib::Interfaces::MyInterface->new();
$self->{'_interface'}->set_serializer($serializer); # comment out to deactivate
It's easy to deactivate. Only put a comment in the set_serializer line.
Of course printing a block of XML to the command line is not very pretty, but it gets the job done. I only need it once in a while why coding/testing, so this is fine I guess.