How to add custom XML element to Message using PacketInterceptor in Openfire plugin using XMPP - openfire

I want to add custom XML to an incoming message packet. To do that as part of plugin implementation I have written a PacketInterceptor, which intercepts the message and adds an extension. Till this point everything is fine but when this message is received by the receiver, the information stored in custom xml is striped off. Only the xml element with namespaces is shown.
Incoming messages are regular text messages as shown below-
<message to='18#mcasax01/SomeResource' from='myroom#conference.mcasax01/testbot2' id='63S0G-27' type='groupchat'>
<body>Hi</body>
</message>
When I add custom XML to this message body, it looks as below after adding the XML in PacketInterceptor logs-
<message to='18#mcasax01/SomeResource' from='myroom#conference.mcasax01/testbot2' id='63S0G-27' type='groupchat'>
<body>Hi</body>
<data value="imgURL1"/>
</message>
But when this message is received by the receiver the value attribute in data is striped off and below message is received by the participant -
<message to='17#mcasax01/SomeResource' from='myroom#conference.mcasax01/testbot2' id='63S0G-27' type='groupchat'>
<body>Hi</body>
<data xmlns='jabber:client'></data>
</message>
Please note that both the text and attributes are getting stripped off from data XML node.
Below is java code snippet for your reference
public void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed) throws PacketRejectedException {
// Some code
Message messagePacket = (Message) packet;
Document document = DocumentHelper.createDocument();
Element root = document.addElement("data");
Element root1 = root.addAttribute("value", "imgURL1");
PacketExtension pe = new PacketExtension(root1);
messagePacket.addExtension(pe);
}

When implementing the interceptPacket method you need to pay careful attention to the different parameters. The same XMPP packet will be intercepted multiple times. Make sure you are only intercepting incoming packets that are not processed. You do this by writing a conditional on the boolean values passed to the method.
As for ensuring the XML is created properly, you should use the addChildElement method not the addExtension method on the Message object.
I've successfully used the addChildElement method before to add a timestamp to the XMPP message before it is sent to the receiver. The API for addChildElement is straightforward and avoids you having to create an entirely new document.

Related

mule invoke java component as array parameter

properties file:
#torun='GSD11','GSD12'
torun='GSD11'
<flow name="deleteInvoiceFlow" doc:name="deleteInvoiceFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="${hostname}" port="${port}" path="deleteInvoice" doc:name="HTTP"/>
<invoke object-ref="client" method="deleteInvoice" methodArguments="${torun}" methodArgumentTypes="java.lang.String" />
</flow>
<spring:bean id="client" name="client" class="com.util.DeleteTable"/>
Java: DeleteTable:
public String deleteInvoice(#Payload String deleteCompany) throws SQLException{
It works well for single parameter from the properties as shown above in properties file. But If i run application with below companies in properties
`torun='GSD11','GSD12'
it gives error message as
1 (java.lang.ArrayIndexOutOfBoundsException). Message payload is of type: String
How do I enable to receive parameteras array?
the Mule message's Payload is a Object. Thus allowing it to handle any kind of object.
If you check the MuleMessage interface you'll see it.
In your code above your sending whatever comes from your inbound endpoint (http) to your spring bean, and you are assuming it's going to be a string.
Now the payload can certainly change in an http inbound endpoint depending on what type of request you receive (get/post/put/etc) so be careful with that.
Going back to your question, if you're positive the payload is going to be an array you can just change the firm of your method to that. If not I'll advise you change it to object and validate what's coming and cast accordingly.
HTH
Mule docs says:
http://www.mulesoft.org/documentation/display/current/Invoke+Component+Reference
methodArguments="#[1], #[2]"
methodArgumentTypes="java.lang.Float, java.lang.Float"
but my list is random and it grows to 100s to 1000s, I don't want to put 1000s of argument types.
As a workaround solution I am loading the mule-app.propertes in java component and reading the property content.
public String deleteInvoice(){
Properties prop = new Properties();
InputStream input = DeleteTable.class.getClassLoader().getResourceAsStream("mule-app.properties");
prop.load(input);
return prop.getProperty("torun");
}

Mule:Extracting parent flow message in subflow/synchronous flow

Is there a way in mule to extract parent flow message in sub/synchronous flow after sub message source has generated its message and modify it.Sub flow is having its own message source.
You can always get the message of parent flow in sub flow ..
Now extracting a message depends on its data type ...
For example if the payload type is xml and you need to extract particular value of a node, you can use XPATH...
Similarly for JSON payload there is different techniques of extracting it..
And now if you want the entire payload of parent flow and not just part of it, then you can always use #[message.payload] expression in subflow

For a BizTalk WCF-SQL adapter in Solicit-Response Send port. How to let adapter handle the response data like XmlPolling?

For a SP using For Xml returns a xml as response, If this sp was consumed by a WCF receive location, we can specify the Polling as XmlPolling to let adapter keep the responsed xml "as-is". But for a wcf-sql Solicit-Response Send port, It seems no same way to do it. Currently, the best result I can get is let adapter treat the xml response as a CDATA. Like below:
<usp_MySPResponse xmlns="http://schemas.microsoft.com/Sql/2008/05/TypedProcedures/dbo">
<StoredProcedureResultSet0>
<StoredProcedureResultSet0 xmlns="http://schemas.microsoft.com/Sql/2008/05/ProceduresResultSets/dbo/usp_MySP">
<UnNamedColumn0><![CDATA[ <!-- The XML content of sp returned goes here -->
....
Assuming the Stored Procedure uses the FOR XML clause, there are two binding properties you must set for the result to be recognized as Xml:
XmlStoredProcedureRootNodeName
XmlStoredProcedureRootNodeNamespace
It's these two properties that tell the Adapter it's a FOR XML Stored Procedure. These are essentially the same as the legacy SQL Adapter.
Details here: http://msdn.microsoft.com/en-us/library/dd787898.aspx
There is no way around this so your BizTalk Schema must match these values.
Reading the link https://learn.microsoft.com/en-us/biztalk/adapters-and-accelerators/adapter-sql/execute-stored-procedures-having-a-for-xml-clause-in-sql-server-using-biztalk carefully, it says that the request schema must be generated selecting from "Procedures", undeniably not "TypedProcedures". The request message will therefore be in the namespace http://schemas.microsoft.com/Sql/2008/05/Procedures/dbo which is not explicitly mentioned in
https://learn.microsoft.com/en-us/biztalk/adapters-and-accelerators/adapter-sql/message-schemas-for-procedures-and-functions but the action for a "for xml"-typed procedure is specified there. To summarize: A request message is thus:
<YOURSPNAME xmlns="http://schemas.microsoft.com/Sql/2008/05/Procedures/dbo" />
and the port configuration action header is
<BtsActionMapping xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Operation Name="YOURSPNAME" Action="XmlProcedure/dbo/YOURSPNAME" />
</BtsActionMapping>
Note the discrepancy between the request message's namespace and the operation action, only the action has "Xml" in it. And don't forget to specify the (FOR XML) binding parameters, as answered by Johns-305.

Parsing multi-part messages using WCF custom MessageEncoder

I am writing a WCF client to a SOAP service that returns a mime multi-part result with binary data (actually, a PDF file). It uses a custom message encoder.
The service doesn't seem to mind if I make the request a single-part format, so I am able to get a result back. There are two problems with the result from what I can see:
It only seems to return the first part of the multi-part message.
The data I get back cannot be decoded by my custom encoder.
I have tried utilizing MTOM binding, but that messes up the request. It fails to add the "boundary" parameter in the content-type, so the server cannot understand the request.
I think what I want is a basic text SOAP request, but a response decoded MTOM-style. I have no idea how to set that up, however.
The closest solution I have found is this: http://blogs.msdn.com/b/carlosfigueira/archive/2011/02/16/using-mtom-in-a-wcf-custom-encoder.aspx
But it seems like a very invasive change to my project.
I figured this out. First of all, I was incorrect when I said that I was only getting the first part of the multi-part message using the MTOM encoder; I was getting the whole thing. I was looking at it in the debugger and the bottom must have gotten clipped in the debug viewer. Chalk it up to my inexperience manually looking at and deciphering multi-part messages.
To the second point, all I had to do was use the MTOM encoder when the Content-Type was multipart/related and everything worked just fine. If you read the referenced article above, it's all about dynamically detecting whether the message is multipart or regular text, and choosing the proper encoder based on that. Essentially, it's a custom encoder that has both a text encoder and MTOM encoder built into it, and switches back and forth based on the content-type of the incoming message.
Our project requires some post processing of the response message before it's handed off to the main program logic. So, we get the incoming SOAP content as an XML string, and do some XML manipulation on it.
This is a slight departure from the solution recommended in the article. All that's required in the article's solution is reading the message using the right encoder into a System.ServiceModel.Channels.Message, and returning that. In our solution, we need to interrupt this process and do the post-processing.
To do that, implement the following in your custom encoder:
public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
{
//First, get the incoming message as a byte array
var messageData = new byte[buffer.Count];
Array.Copy(buffer.Array, buffer.Offset, messageData, 0, messageData.Length);
bufferManager.ReturnBuffer(buffer.Array);
//Now convert it into a string for post-processing. Look at the content-type to determine which encoder to use.
string stringResult;
if (contentType != null && contentType.Contains("multipart/related"))
{
Message unprocessedMessageResult = this.mtomEncoder.ReadMessage(buffer, bufferManager, contentType);
stringResult = unprocessedMessageResult.ToString();
}
else {
//If it's not a multi-part message, the byte array already has the complete content, and it simply needs to be converted to a string
stringResult = Encoding.UTF8.GetString(messageData);
}
Message processedMessageResult = functionToDoPostProccessing(stringResult);
return processedMessageResult;
}

get attachment from System.ServiceModel.Channels.Message

Does any one know how to get attachment from System.ServiceModel.Channels.Message?
When client requests from the server, and server is returning a xop element with attachment in the response. But I don't know how to get the attachment from the Message obj returned from the service call.
I don't fully understand all the circumstances, but there are several options the first is to use appropriate message encoder in binding, for example CustomBinding with MtomMessageEncodingBindingElement element. In that case, XmlDictionaryReader returned by Message.GetReaderAtBodyContents() will automatically replace xop:Include elements by corresponding attachment. In case, if there are needs to manipulate attachments at lower level, or in case if non-MTOM encoding is used, you will need to write appropriate message encoder that will meets you requirements.