How to move property value from Properties file to payload object using spring integration elements - spring

Sample.properties
=================
http.header.amisys.accept.value=arun/vnd.dsths.services-v1+xml
1)Above XSL automatically loaded when my server starts.
2)I have tried <int:enricher> element but it is not helped me.
Sample Code : Below is bit of code I have tried, Can any one suggest me on this.
<int:channel id="PQLegacySecurity-InputChannel" />
<int:chain input-channel="PQLegacySecurity-InputChannel" >
<!-- Split the Search Request Params from Xml -->
<int-xml:xpath-splitter>
<int-xml:xpath-expression expression="//LegacySecurity" namespace map="xmlMessageNamespace" />
</int-xml:xpath-splitter>
<int:enricher >
<int:payload name="testPayload" expression="${http.header.amisys.accept.value}"/>
</int:enricher>
</int:chain>
Actual Payload Object:Below is the xml which does not contain testPayload property.
<?xml version="1.0" encoding="UTF-8"?><LegacySecurity>
<businessArea>%%%%%%</businessArea>
<LegacySystem>%%%%%</LegacySystem>
<LegacyUserID>%%%%%</LegacyUserID>
<LegacyPassword>%%%%%</LegacyPassword>
<OtherLogin/>
<OtherPassword/>
<AddSecurLogin/>
<AddSecurPassword/>
</LegacySecurity>
Expected Payload Object: Below Object contains new element testPayload node which I should able to add
<?xml version="1.0" encoding="UTF-8"?><LegacySecurity>
<businessArea>%%%%%%</businessArea>
<LegacySystem>%%%%%</LegacySystem>
<LegacyUserID>%%%%%</LegacyUserID>
<LegacyPassword>%%%%%</LegacyPassword>
<OtherLogin/>
<OtherPassword/>
**<testPayload>arun/vnd.dsths.services-v1+xml</testPayload>**
<AddSecurLogin/>
<AddSecurPassword/>
</LegacySecurity>

You can use an xslt transformer. Something like the below, though you will need to figure out correct use of the transformer from the spring docs.
Notice you can pass a parameter through to the XSLT
<int-xml:xslt-transformer result-transformer="toDocumentTransformer" result-type="StringResult" xsl-resource="/xslt/addTestPayload.xslt">
<int-xml:xslt-param name="testPayload" value="${http.header.amisys.accept.value}"/>
</int-xml:xslt-transformer>
In the XSLT file, use this to pick up the parameter:
<xsl:param name="testPayload" />
If you have other changes you need to make to the message you can use the same xslt.

Related

Update parameter value in XML format

I have parameters stored in an XML file. Below is a sample of the file.
<?xml version="1.0" encoding="UTF-8"?>
<root>
<terminal id="A">
<terminalCapacity>3</terminalCapacity>
<terminalMembers id="1">
<memberID>0001</memberID>
<memberCapacity>2</memberCapacity>
</terminalMembers>
</terminal>
<terminal id="B">
<terminalCapacity>4</terminalCapacity>
<terminalMembers id="1">
<memberID>0002</memberID>
<memberCapacity>1</memberCapacity>
</terminalMembers>
<terminalMembers id="2">
<memberID>0003</memberID>
<memberCapacity>3</memberCapacity>
</terminalMembers>
</terminal>
</root>
Each terminalID is associated to a type of simpleModule found in my NED file. The idea is to programmatically update these values throughout the simulation run. The current logic revolves around getting the current parameters in XML format and update the memberCapacity field.
From the Omnet cPar and cXMLElement documentation, I tried using the par("moduleParameter").xmlValue()->getXML() function, but this returns the XML as a string. I also tried using the getAttribute() function, but to no success.
Don't do this. par("moduleParameter").xmlValue() will give you the in memory object tree of the XML document, but that is not meant for modification. Your XML file seems to be just a hierarchical structure and modules and their parameters can mirror that exactly. There is absolutely no reason to reinvent the wheel when you can mirror that with INI file parameters.

How to extract values (list and unique tags) from xml in Nifi?

I have a xml file that contains some tags, one is unique other are same tags. I'd like to get values from these tags and convert them to another xml tag. Here is example of xml file:
<?xml version="1.0" encoding="UTF-8"?>
<entry dataset="Swiss-Prot" created="2005-04-26" modified="2019-11-13" version="158" xmlns="http://uniprot.org/uniprot" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<accession>Q96IY4</accession>
<accession>A8K464</accession>
<accession>Q15114</accession>
<accession>Q5T9K1</accession>
<accession>Q5T9K2</accession>
<accession>Q9P2Y6</accession>
<name>CBPB2_HUMAN</name>
<protein>
<recommendedName>
<fullName>Carboxypeptidase B2</fullName>
<ecNumber evidence="7">3.4.17.20</ecNumber>
</recommendedName>
<alternativeName>
<fullName>Carboxypeptidase U</fullName>
<shortName>CPU</shortName>
</alternativeName>
<alternativeName>
<fullName>Plasma carboxypeptidase B</fullName>
<shortName>pCPB</shortName>
</alternativeName>
<alternativeName>
<fullName>Thrombin-activable fibrinolysis inhibitor</fullName>
<shortName>TAFI</shortName>
</alternativeName>
</protein>...other tags
</entry>
I though of using EvaluateXQuery processor and EvaluateXPath. EvaluateXQuery is using for getting accession and alternativeName tags. EvaluateXPath is using for getting name, recommendedName (fullName) tags.
Is it possible to use both and combine them to only xml or hust necessary to use EvaluateXQuery processor, like this:
<accessions>Q96IY4, A8K464, Q15114,...</accessions>
<name>CBPB2_HUMAN</name>
<recommendedName>Carboxypeptidase B2</recommendedName>
<alternativeNames>Carboxypeptidase U-CPU, Plasma carboxypeptidase B-pCPB,...</alternativeNames>
Can you help me, please?
Thank you!
Hi you may use processor execute groovy script and parse xml with a script to get your values and put them into attributes.

Replace element by XPath

I try to replace some element of my input XML in Citrus Framework.
My Spring context contains:
<citrus:namespace-context>
<citrus:namespace prefix="def" uri="http://sample.com/xmlns/2005"/>
</citrus:namespace-context>
My input file starts with:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<ns0:canonicalMessageHeader xmlns:ns0="http://sample.com/xmlns/2005">
<ns0:headerVersion>1.0</ns0:headerVersion>
<ns0:bodyVersion>1.0</ns0:bodyVersion>
<ns0:trackingInfo>
<ns0:eventHandlerInitInfo>
<ns0:processInfo>
<ns0:adapterTrackingId>214F27DF-E1FB-4E84-9122-390C5876ABD2:1</ns0:adapterTrackingId>
...
My endpoint is configured in that way:
<send endpoint="jms:topic:Order.Request?timeout=10000&connectionFactory=DEVconnectionFactoryFrom">
<message>
<resource file="com/sample/citrus/messages/input/SalesOrderTo.xml"/>
<element value="${track}" path="SOAP-ENV:Envelope/SOAP-ENV:Header/def:canonicalMessageHeader/def:trackingInfo/def:eventHandlerInitInfo/def:processInfo/def:adapterTrackingId"/>
I have the following error:
Can not evaluate xpath expression 'SOAP-ENV:Envelope/SOAP-ENV:Header/def:canonicalMessageHeader/def:trackingInfo/def:eventHandlerInitInfo/def:processInfo/def:adapterTrackingId'
at com/sample/citrus/SalesOrderToIT(sequential:45)
at com/sample/citrus/SalesOrderToIT(send:48-82)
Caused by: javax.xml.xpath.XPathExpressionException: org.apache.xpath.domapi.XPathStylesheetDOM3Exception: Prefix must resolve to a namespace: def
What's the possible cause of this error?
Best Regards
Global namespace declaration support is missing in Citrus when overwriting message elements in a send operation via XPath. This issue has been tracked: https://github.com/christophd/citrus/issues/331
In the meantime you have to use the exact same namespace prefix as in the message template file - in your case ns0:
Also you could throw away XPath overwrite and use the dot notated Node overwrite like this:
<send endpoint="jms:topic:Order.Request?timeout=10000&connectionFactory=DEVconnectionFactoryFrom">
<message>
<resource file="com/sample/citrus/messages/input/SalesOrderTo.xml"/>
<element value="${track}" path="Envelope.Header.canonicalMessageHeader.trackingInfo.eventHandlerInitInfo.processInfo.adapterTrackingId"/>
</message>
</send>
The dot notation is not based on namespaces but uses the local element names for finding the element in the message template. Obviously not as powerful as XPath but it works with current version of the framework.
You defined nso as namespace prefix in XML but then use def on the XPath, should be nso.

XSL - Externalizing Xpath queries to a property file

I went through various posts, regarding reading properties from external property files. Looks like there is a function - getProperty, which can read values from a property file, using a key. I am using saxon parser with spring integration. I am trying something like this, as described in the post :-
spring context file:
<int-xml:xslt-transformer id="xsltTransformer" input-channel="bulkStringInboundChannel"
output-channel="toBridgeChannel" result-type="StringResult" **transformer-factory-class="net.sf.saxon.TransformerFactoryImpl"**
xsl-resource="classpath:/META-INF/spring/integration/intake/intake-flow/bulkTransformer.xsl" />
XSL style sheet:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
....
<xsl:variable name="props" select="document('prop.xml')" />
<xsl:value-of select="f:getProperty('query1')"/>
....
Prop.xml:
query1 = /Batch/RequestID/text()
Error description:
XPST0003: XPath syntax error at char 23 on line 30 in {f:getProperty('query1')}:
XTSE0650: No template exists named getProperty
I now have two questions- first of all, how do I get rid of these errors?
Second, can I store xPath queries in property files? The post describes a method, to read a property file and use the value pertaining to its key. However, I am thinking that getProperty will just print the query's text equivalent instead of evaluating the query and processing it. Is there a way to achieve this?
Post - How to read a .properties file inside a .xsl file?
I can't help you with the Spring side of the question, but as for the Saxon side, you can call the JDK method System.getProperty() using code like this:
<xsl:value-of select="System:getProperty('user.dir')" xmlns:System="java:java.lang.System"/>
Java extensibility requires Saxon-PE or higher.
If the value of the property that you read is an XPath expression, you can then execute it using the XSLT 3.0 xsl:evaluate instruction - which also requires Saxon-PE or higher.

Spring Integration - Move File After Xpath-splitter

i'm working with spring integration and i have the next case: i'm reading a XML file with an int-file:inbound-channel-adapter and i split the file with a int-xml:xpath-splitter, the thing is that i need to move the file after been splitted.
I want all features of int-xml:xpath-splitter plus moving the file, should i implement a custom splitter extending XPathMessageSplitter? or is there any other way to do that with an out-of-box components?
Thanks.
<int-xml:xpath-splitter id="salesTransSplitter"
input-channel="salesInputChannel"
output-channel="splitterOutChannel" order="1">
<int-xml:xpath-expression expression="/sales_transactions/trans"/>
</int-xml:xpath-splitter>
Something like this should work...
<int-file:inbound ... channel="foo" />
<int:publish-subscribe-channel id="foo" />
<int-xml:xpath-splitter input-channel="foo" ... order="1" />
<int-service-activator input-channel="foo" order="2"
expression="payload.renameTo(new java.io.File('/newDir/' + payload.name)" output-channel="nullChannel" />
If you want to test the rename was successful, send to some other channel other than nullChannel - boolean true means success.
EDIT
Sorry about that; order should be supported on every consuming endpoint, I will open a JIRA issue.
The order is not strictly necessary; if no order is present, the order they appear in the configuration will be used; I just prefer to make it explicit.
There are (at least) two work arounds:
Remvoe the order attribute from BOTH consumers and they will be invoked in the order they appear in the XML.
Configure the XPath splitter as a normal splitter, which does support order...
<int:splitter id="salesTransSplitter" order="1"
input-channel="salesInputChannel"
output-channel="splitterOutChannel" order="1">
<bean class="org.springframework.integration.xml.splitter.XPathMessageSplitter">
<constructor-arg value="/sales_transactions/trans" />
</bean>
</int-xml:xpath-splitter>

Resources