Spring integration : Facing issue while updating the header value again - spring

Trying to place a file in multiple directories using single outbound adapter using spring-integration-file.
In order to achieve that, having a loop in front of the file:outbound-gateway to modify message header target directory on each iteration and send all of them to the same channel again and again till the target count decreases to 0.
Able to loop back to the header enricher channel.but Since we are enriching the header value for the same header name again. the value is not getting updated for header name TARGET_DIR. There is no exception also.
Would like to know some solution if its possible to update the header value again and again for the same header name or is it possible to give the dynamic header name at runtime.
Have tried to delete the TARGET_DIR header using header:filter while looping back. But did not work out.
!-- header enricher -->
<integration:header-enricher input-channel="filesHeaderEnricherChannel" output-channel="filesOut">
<integration:header name="TARGET_COUNT" method="getTargetCount" ref="headerEnricher"/>
<integration:header name="TARGET_DIR" method="getTargetPath" ref="headerEnricher"/>
</integration:header-enricher>
<integration:chain id="filesOutChain" input-channel="filesOut" output-channel="filesOutChainChannel">
<integration:transformer expression="headers.FILE"/>
<file:outbound-channel-adapter id="fileMover"
auto-create-directory="true"
directory-expression="headers.TARGET_DIR"
mode="REPLACE">
<file:request-handler-advice-chain>
<ref bean="retryAdvice" />
</file:request-handler-advice-chain>
</file:outbound-channel-adapter>
</integration:chain>
<!-- decreasing the count on each loop -->
<!-- looping to header enricher channel again as output channel to update the target directory -->
<integration:filter input-channel="filesOutChainChannel" expression="headers.TARGET_COUNT != 0" output-channel="filesHeaderEnricherChannel"
discard-channel="filesArchiveChannel">
</<integration:filter>

You are missing the fact that header-enricher has an extra option:
<xsd:attribute name="default-overwrite">
<xsd:annotation>
<xsd:documentation>
Specify the default boolean value for whether to overwrite existing
header values. This will
only
take effect for
sub-elements that do not provide their own 'overwrite' attribute. If the
'default-overwrite'
attribute is not
provided, then the specified header values will NOT overwrite any
existing ones with the same
header
names.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
As well as the sub-element header has its own:
<xsd:attribute name="overwrite">
<xsd:annotation>
<xsd:documentation>
Boolean value to indicate whether this header value should overwrite an
existing header value for
the same name.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string" />
</xsd:simpleType>
</xsd:attribute>
See also docs on the matter: https://docs.spring.io/spring-integration/docs/current/reference/html/message-transformation.html#header-enricher

Related

Multiple attribute-resolver.xml for different SPs

I have different SPs that use my IDP Shibboleth, but for each of them I want to send different attributes in the SAML response.
Is there a way to achieve this?
Maybe use different attribute-resolver files, or maybe the same one but with some configuration on the AttributeDefinition that I can set so that shibboleth knows what values to resolve?
I haven't found anything regarding this on their wiki.
I would suggest you look into the topic of attribute mapping. With this, you can define filters on your Service Providers. Collect all attributes you need for all SPs on your IDP and then filter the ones you need on your Service Provider.
Example: SP 1 needs an attribute called email_1 and SP 2 needs email_2.
Then your attribute-resolver.xml might look something like this:
<AttributeDefinition xsi:type="Simple" id="email_1">
<InputDataConnector ref="myDB" attributeNames="email_1"/>
<AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:uid"/>
<AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.3" friendlyName="email_1" encodeType="false"/>
</AttributeDefinition>
<AttributeDefinition xsi:type="Simple" id="email_2">
<InputDataConnector ref="myDB" attributeNames="email_2"/>
<AttributeEncoder xsi:type="SAML1String" name="urn:mace:dir:attribute-def:uid2"/>
<AttributeEncoder xsi:type="SAML2String" name="urn:oid:0.9.2342.19200300.100.1.4" friendlyName="email_2" encodeType="false"/>
</AttributeDefinition>
<DataConnector id="myDB" xsi:type="RelationalDatabase">
<SimpleManagedConnection jdbcDriver="com.mysql.jdbc.Driver"
jdbcURL="jdbc:mysql://localhost:3306/login"
jdbcUserName="bla"
jdbcPassword="blabla"/>
<QueryTemplate>
<![CDATA[
SELECT
mail_1,
mail_2
FROM login
WHERE
mail_1 = '$resolutionContext.principal'
]]>
</QueryTemplate>
<Column columnName="mail_1" attributeID="mail_1"/>
<Column columnName="mail_2" attributeID="mail_2"/>
</DataConnector>
Then, on your Service Provider 1 in attribute-map.xml, you filter out only the attribute you need:
<Attribute name="urn:oid:0.9.2342.19200300.100.1.3" id="mail_1" />
<Attribute name="urn:mace:dir:attribute-def:uid" id="mail_1" />
So when the SP1 receives both mail_1 and mail_2 attributes, mail_2 will be rejected because it's not in your attribute-map.xml file.

Is there a Mule 4/Dataweave 2 equivalent for dw:input-variable in a transform message

I'm trying to manually translate a program from Mule 3 to Mule 4, and a lot of the transforms have something like
<dw:input-variable doc:sample="sample_data\json_63.json" variableName="dsRespPayloads"/>
I don't know what the equivalent is in Mule 4 or if there is one. This is leading me to a problem where a flow defines a variable calls another flow, and in that second flow it tries to transform the message using the variable defined in the first.
In Mule 4 it keeps saying Property: dsRespPayloads was not found.
and it's giving me errors over it. Also the tree on the left just says Unknown for Payload and Attributes
Any help or explanation about what's going on would be appreciated.
Are you saying you define a variable in flowOne and in the flowTwo, you calls this variable
something like that ???
<flow name="flow1" doc:id="29ba6da8-7458-4f35-adff-1d9db5738fbc" >
<set-variable value="Hello" doc:name="Set Variable" doc:id="055abd42-b240-4113-b08d-dde00b8ea590" variableName="dsRespPayloads"/>
</flow>
<flow name="dataweaveLabFlowTwo" doc:id="ae122a1a-b9d0-490d-a7e4-2c138e5d4c01" >
<logger level="INFO" doc:name="Logger" doc:id="e4f4bf3a-29f9-4d4e-b2c9-d4a86bd2eb29" message='#[" $(vars.dsRespPayloads)"]' />
</flow>
In Mule 4 you can not set the mime types for inputs at the transformer level. You need to set them in the connector where they are generated, in set-payload or set-variable, before they reach the transformer.
Example:
<set-variable variableName="x" value='{"a":"b", "c":1}' mimeType="application/json" doc:name="Set Variable" />

How to copy value of custom field/property to another custom field/property of database-bean?

i need following things but unfortunately i am unable to do it,
can any one help then appreciate....!!!
NOTE : classANumber, classABNumber both field is not available into Database - it's custom field for our bean.
ABC.hbm.xml
<property name="classANumber" lazy="false" type="java.lang.String" formula="(select ac.classNumber from accessClass ac)"/>
<property name="classABNumber" lazy="false" type="java.lang.String" formula="(select abc.classNumber from accessBothClass abc where ac.classCombileNumber = classANumber)"/>
Above is my .hbm.xml file configuration.
Actually, I want to use value of 'classANumber' property into another custom-field's value searching query.

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>

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

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.

Resources