How can we inject properties into wso2 Micro Integrator and Enterprise Integrator using file.properties? - properties

I want to use the .car file on another server without using integration studio. So I want to be able to change the hostname and port dynamically using a configuration file. My endpoint URL has variables in it {uri.var.x} that's why I can't use $FILE:x to get the complete URL from file.properties.
I have already tried How to read a property injected from file.properties in WSO2 - micro integrator? but it did not work.

You can simply read the Property from the file and assign it to the variable you desire. Then use it in your Endpoint configurations.
<property expression="get-property('file', 'x')" name="uri.var.x"/>
You can store the values in a properties file called file.properties in the MI_HOME/conf folder and it will be loaded automatically. If you are using a different fileName you can pass it to the server startup script like -Dproperties.file.path=/home/dev/dev.properties. Then you can read them through a Property Mediator.
Further, if you want to construct the full URL from multiple properties you can use Xpath functions.
<property expression="concat('https://', get-property('file', 'host'), ':', get-property('file', 'port'))" name="uri.var.x" scope="default" type="STRING" />
If the properties are not picked from the default file, pass the file path like below.
sh micro-integrator.sh -Dproperties.file.path=./conf/file.properties
Update on WSO2 EI
It seems file scope is not supported in EI. But instead, you can read variables from Environment variables with get-property('env', 'NAME_OF_VARIABLE')
<property expression="concat('https://', get-property('env', 'host'), ':', get-property('env', 'port'))" name="uri.var.x" scope="default" type="STRING"/>
If you want to read them from a properties file, you can do something like the below. Assuming you have a properties file like below.
stockQuoteEP=http://localhost:9000/services/SimpleStockQuoteService
ycr=test1234
host=localycr
port=6676
Add the following script to integrator.sh to export the properties as environment variables. You can improve the script as you require.
while read line; do
echo "Exporting $line"
export $line
done < /home/wso2/wso2ei-6.6.0/conf/file.properties
Then in your integration read them as below.
<property expression="concat('https://', get-property('env', 'host'), ':', get-property('env', 'port'))" name="uri.var.x" scope="default" type="STRING"/>
Update 2 on File Scope in Property mediator
As Sanoj mentioned, file scope in the property mediator is only available from MI 4.0 onward vanilla packs. If you have a WSO2 subscription you can get it as an update for both MI and EI.

Related

WSO2 ESB access context property in the response sequence of an HTTP endpoint

I'm calling an HTTP endpoint and getting the response in
a sequence. Response is getting logged in the seq_sla_resp.
<send receive="seq_sla_resp">
<endpoint key="gov:EDI/SLA/endpoints/edi_sla_payment_ep.xml" />
</send>
Inside this response sequence I'm unable to get a property which I set previously during the call (in the main proxy).
<property expression="//m1:sla_row/m1:tran_id/text()"
name="tran_id" scope="default" type="STRING"
xmlns:m1="http://ws.wso2.org/dataservice" />
When I try to log the property in the seq_sla_resp it ends up in the below error message
<log>
<property expression="$tran_id" name="tran_id" xmlns:m0="http://ws.wso2.org/dataservice"/>
</log>
Following is the error.
SynapseXPath Evaluation of the XPath expression $tran_id resulted in an error
org.jaxen.UnresolvableException: Variable tran_id
How can i get the context value in the response sequence.
In the documentaion it says default scope has the largest life span for the property.
Any help is very much appreciated.
I think you would find that your expression would also not work in the inSequence. You should either use expression="$ctx:tran_id" or expression="get-property('tran_id')"
Please note that WSO2 recommends using $ctx instead of the get-property if the scope is default. The get-property methods search in the registry if the value is not available in the message context. Therefore, it affects the performance.
In your case , you can use
<property expression="$ctx:tran_id" name="tran_id" scope="default" xmlns:m0="http://ws.wso2.org/dataservice"/>
Thanks
Kranthi

WiX File Search Conditional

I have a WiX installer project that I'm creating where I'd like the installer to check to see if another application is already installed on the user's machine. If it is, then I'd like to set the install level of one of the features to "1", otherwise it should remain hidden (i.e. install level = 0). To find out where the application is installed, I first do a registry search:
<Property Id="MYAPPINSTALLFOLDER">
<RegistrySearch Id='InstallPathRegistry'
Type='raw'
Root='HKLM'
Key='SOFTWARE\SomeLongAppPath' Name='FileName'
Win64='yes'/>
</Property>
You'll notice that the registry value that I end up getting is actually the directory of the installed application including the actual program name with extension (let's say myapp.exe). So, once I get the full path of the installed application, I check to see if the file exists:
<Property Id="MYAPPINSTALLED">
<DirectorySearch Id="CheckFileDir" Path="[MYAPPINSTALLFOLDER]" AssignToProperty="yes">
<FileSearch Id="CheckFile" Name="myapp.exe" />
</DirectorySearch>
</Property>
Now, what I would expect to see is that if the file actually exists in that location, then the Property called "MYAPPINSTALLED" would be set to 1, otherwise it would be 0. Then, when I setup my features I use something like this:
<Feature Id="ThirdPartyPlugins" Title="Third Party Plugins" Level="0">
<Condition Level="1">MYAPPINSTALLED</Condition>
<ComponentGroupRef Id="MyAppPlugin" />
</Feature>
However, when I run my installer the third party plugin feature is always hidden. I've enabled msi datalogging by setting the property like this:
<Property Id="MsiLogging" Value="voicewarmupx"/>
And when I check the log file I can definitely see that the MYAPPINSTALLFOLDER property gets changed to the correct file path when it does the registry search. However, if I search the log for the property MYAPPINSTALLED, then I can see the following:
AppSearch: Property: MYAPPINSTALLED, Signature: CheckFileDir
Action ended 15:55:06: AppSearch. Return value 1.
So, it looks like it worked, however it doesn't seem to ever set the Property to equal the search value. Am I doing something wrong? Can someone explain why my feature install level never gets set to 1 even though the application file exists?
Edit
Ok, after more debugging... I think the issue is that the directory search is trying to use a path that includes the file name and extension (i.e. C:/Program Files/MyApp/myapp.exe") instead of just the directory where the file comes from. This is because the registry search has the full path including the file name stored (but not just the install directory). If I do a directory search just using the correct absolute directory (not using the registry search) then the process works. So, my follow up question is... my Property MYAPPINSTALLFOLDER contains the full path with file name and extension. Is there a way to strip the file name and extension from this property so that I just have the proper directory name to search for?
You're checking to see if another application is installed but that's rather a long way around. Also, the file search returns a path, not zero or 1, but either way a full verbose log should tell you if the properties are being set. It might help if you could post the entire log somewhere rather than the parts you think are the only relevant ones. e.g. There's probably an AppSearch in the execute sequence for silent installs.
It's requently easier to do a single search for other applications that were installed with MSI packages in these ways:
If you know the other product's UpgradeCode (and version ranges if applicable) then add Upgrade/UpgradeVersion elements with onlydetect set to yes, and that search will set a property if the product is detected.
If you know (or can find out) the Component id of any of the relevant components from that other product, then you can use them in a WiX ComponentSearch. If you get the target property set then that component is installed. This post contains a couple of ways to find out component guids:
How to find out which application requires a certain assembly from GAC?
It's also puzzling that the AppSearch log extract you posted only refers to one property. The Directory/FileSearch is also an AppSearch, so if the MSI actually contains two searches in AppSearch there should be references to all the properties being set. Again, that's a reason to post the entire log and look in the MSI file for those searches. The RegLocator search is documnented to occur before the DRLocator, so why is there no MYAPPINSTALLFOLDER property in the AppSearch log entry? You're not on a 32-bit system are you? (noticing the win64 search).
Per the WiX documentation:
Use the AssignToProperty attribute to search for a file but set the outer property to the directory containing the file. When this attribute is set to yes, you may only nest a FileSearch element with a unique Id or define no child element [of the DirectorySearch].
I added the text in the brackets to make it more clear.
So, after reading this sentence a few times and cross referencing your WiX XML, I think I see what the problem is with your current WiX XML. You perform a separate registry search from the directory search. Instead, you should nest these. There are two ways to perform the search, depending on what you want to do. One way is to simply retrieve the registry value from the registry, and if the value exists, then you make the assumption that the feature's required application is installed, at which point you appropriately set a property that would enable hiding/showing the feature within your installer's feature selection tree. The other way is to actually find the file you're interested in, using the results of the registry search as the basis for the file search.
Below is the XML for just a registry search, which doesn't check that the file actually exists on disk. You're making the assumption that if this registry value exists, the file is installed and available.
<Property Id="MYAPPINSTALLFOLDER">
<RegistrySearch Id='InstallPathRegistry'
Type='raw'
Root='HKLM'
Key='SOFTWARE\SomeLongAppPath' Name='FileName'
Win64='yes'/>
</Property>
<Property Id="SHOW_APP_FEATURE" Value="hidden" />
<SetProperty Id="SHOW_APP_FEATURE" Value="collapse" Sequence="both" After="CostFinalize">
<!-- If MYAPPINSTALLFOLDER is defined and contains any non-empty value, this
evaluates to TRUE; otherwise, it evaluates to FALSE.
-->
MYAPPINSTALLFOLDER
</SetProperty>
<!-- You could also be more explicit:
<SetProperty Id="SHOW_APP_FEATURE" Value="collapse" Sequence="both" After="CostFinalize">
<![CDATA[MYAPPINSTALLFOLDER <> ""]]>
</SetProperty>
-->
<Feature Id="MyAwesomeFeature" Title="My Awesome App Feature"
Display="[SHOW_APP_FEATURE]">
... <!-- Component/ComponentRefs go here -->
</Feature>
If you want to ensure that, even if the registry value exists in the registry, that the file it points to is 1) actually a file path; and 2) that the file actually exists on disk, then you need to perform a nested file search within a directory search, which itself is nested within a registry search. You would again need to use a SetProperty custom action to set a property that would enable the hiding/showing of the feature within your installer's feature selection tree. Here's the XML for this search:
<!-- Performing a FileSearch nested within a DirectorySearch,
which is itself nested within a RegistrySearch
This search twill ensure that the file exists on disk, and
if so, assign the full filename and path to the
MYAPPINSTALLFOLDER property.
-->
<Property Id="MYAPPINSTALLFOLDER">
<RegistrySearch Id='InstallPathRegistry'
Type='raw'
Root='HKLM'
Key='SOFTWARE\SomeLongAppPath' Name='FileName'
Win64='yes'>
<DirectorySearch Id='InstallPathDirectory' AssignToProperty='yes'>
<FileSearch Id='InstallPathFile' Name='myapp.exe' />
</DirectorySearch>
</RegistrySearch>
</Property>
<Property Id="SHOW_APP_FEATURE" Value="hidden" />
<SetProperty Id="SHOW_APP_FEATURE" Value="collapse" Sequence="both" After="CostFinalize">
<!-- If MYAPPINSTALLFOLDER is defined and contains any non-empty value, this
evaluates to TRUE; otherwise, it evaluates to FALSE.
-->
MYAPPINSTALLFOLDER
</SetProperty>
<Feature Id="MyAwesomeFeature" Title="My Awesome App Feature"
Display="[SHOW_APP_FEATURE]">
... <!-- Component/ComponentRefs go here -->
</Feature>
This should allow you to accomplish what you're trying to achieve.

Is the default CQ5 Search Configuration incorrect?

i need to optimize the CQ5 lucene indexing configuration for my application.
I want to provide a custom search configuration but i struggle to really understand the default configuration.
Source: https://helpx.adobe.com/experience-manager/kb/SearchIndexingConfig.html)
First question:
Are the "include"-tags used in the default configuration correct?
For example:
The default configuration uses the tag "include" to include the Property "jcr:content/jcr:lastModified" for the nt:file-Aggregate
<aggregate primaryType="nt:file">
<include>jcr:content</include>
<include>jcr:content/jcr:lastModified</include>
</aggregate>
Compare this to the Jackrabbit wiki which uses the "include-property" for the exact same case. Source: http://wiki.apache.org/jackrabbit/IndexingConfiguration
<aggregate primaryType="nt:file">
<include>jcr:content</include>
<include-property>jcr:content/jcr:lastModified</include-property>
</aggregate>
I only can assume it doesn't matter but i can't find any source to confirm this.
Second question: for the nodeType "cq:PageContent" all properties of four levels are aggregated.
<aggregate primaryType="cq:PageContent">
<include>*</include>
<include>*/*</include>
<include>*/*/*</include>
<include>*/*/*/*</include>
</aggregate>
I assume that because of the aggregation all properties are indexed which are contained within these 4 levels.
Or do i must consider the index rules for the nodeType nt:base which basicly only includes properties which are matching the pattern ".:.".
<index-rule nodeType="nt:base">
<property nodeScopeIndex="false">analyticsProvider</property>
<property nodeScopeIndex="false">analyticsSnippet</property>
...
<property isRegexp="true">.*:.*</property>
</index-rule>
Best regards
The default configuration is ideed incorrect as confirmed by the Adobe CQ5 Support.
For the aggegate to work correctly properties must be included by the "include-property"-Tag
So the default search configuration (or atleast the documentation) is not correct https://helpx.adobe.com/experience-manager/kb/SearchIndexingConfig.html)

How to set boolean in xml-action script

I am trying to set a flag so I do something like this:
<set field="existingFound" value="false" type="Boolean"/>
but the following line prints "true" in the log:
<log message="storeProperty, existingFound (0): ${existingFound}"/>
What is the best way to set flags?
The set.#value attribute is interpreted as a Groovy String (GString) so any non-empty value will be interpreted as true. The set.#from attribute is interpreted as a Groovy expression, so simply using from="false" instead of value="false" will get the desired result.
To see the generated Groovy code from an XML actions block you can write code that will cause an error and then the script will be logged, or you can change the log4j.xml file to turn on "debug" level logging for the XmlActions class (the latest log4j.xml file in the GitHub repository has an example of this). Looking at the Groovy code generated from the XML elements is a good way to track down issues when what is happening just doesn't make sense.

How do I set the xmlns attribute when using XMLFile in Wix 3

I am adding elements to an XML file during installation using the XmlFile element:
<util:XmlFile Id="SetOracleDialectProperty"
Action="createElement"
ElementPath="//hibernate-configuration/session-factory"
Name="property"
Sequence="9"
File="[INSTALLLOCATION]Config\hibernate.config"
Value="NHibernate.Dialect.Oracle10gDialect"/>
The empty file I am writing to looks like this:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
</session-factory>
</hibernate-configuration>
After running the installer I end up with this:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property xmlns="">NHibernate.Dialect.Oracle10gDialect</property>
</session-factory>
</hibernate-configuration>
The problem is that the empty xmlns attribute is overriding the xmlns specified in the root node of the file so the property element is not recognised correctly by nhibernate.
How can I either set the value to match the root node or remove the xmlns attribute?
I have spent some time searching for an answer and the closest I've found is "do what you would do in MSXML" which doesn't help me as it doesn't say how to do it in WiX (e.g. what attribute on XmlFile to use).
EDIT
To explain Rob's answer slightly, in a place where I can use nice formatting:
You add a document fragment by setting Node="document" on the XmlConfig element.
You have to explicitly set the namespace otherwise you get the default one again.
Also although you're adding a "document" it doesn't seem to work if you specify more than one element. You get a mysterious and thoroughly unhelpful "Setup wizard ended prematurely" runtime error.
So my fixed code looks like this:
<util:XmlConfig Id="MsSqlDialect"
Action="create"
ElementPath="//hibernate-configuration/session-factory"
File="[INSTALLLOCATION]Config\hibernate.config"
Node="document">
<![CDATA[
<property xmlns="urn:nhibernate-configuration-2.2" name="dialect">NHibernate.Dialect.Oracle10gDialect</property>
]]>
</util:XmlConfig>
I know this is years later but if anyone else comes across this I think the true solution is this:
<util:XmlFile Id="SetOracleDialectProperty"
Action="createElement"
ElementPath="//hibernate-configuration/session-factory"
Name="urn:nhibernate-configuration-2.2:property"
Sequence="9"
File="[INSTALLLOCATION]Config\hibernate.config"
Value="NHibernate.Dialect.Oracle10gDialect"/>
change is from Name="property" to Name="urn:nhibernate-configuration-2.2:property" - when config is written it will apprear as just as it will recognize it is the default namespace. I had the same problem adjusting manifest files and this approach sorted it.
The problem here is that MSXML states that createElement will always give you the default namespace (just as you are seeing). I think you'll need to switch to the more complex but more powerful XmlConfig. In this case, try using a document fragment to add the entire element with correct namespace instead of depending on MSXML to create it for you.