we have a flow where we have property file reference as given below
"context:property-placeholder location="httpdemo.${country}.properties"
now we want ${country} value to be replaced by actual value at the time of deployment.
As we know one way to achieve it is setting the value of country as environment variable on the ESB and deploying it. But we don’t want to do that because of below reasons:
We deploy same code base for multiple countries in parallel
Environment properties can be set only during start of mule runtime so if I set env variable as country=UK and have deployed for UK. Later I want to deploy for MY again I need to restart ESB by setting country=MY which we don’t want to do.
Please let me know if there is any other better way
We had a similar situation where we needed to have multiple versions of the same application running parallely. The solution we used for this was to package the property file along with the build and not have the dynamic element (environment based) to it. For eg; in this case we construct httpdemo.usa.properties and packaged it along with the app. This was fairly easy for us since we use Jenkins to manage our builds and releases. When the build is released, we reference a configuration file from Jenkins which contains all the specific "country" related properties. You can even pass this country as a parameter to the build definition. Using a custom maven plugin we replace the property file within the app with the new properties from the Jenkins property file.
Another solution to your problem could be to follow a naming convention to your apps specific to the "country" you want to use and fetch the properties using spring beans. For eg;
<spring:beans>
<spring:bean id="CountryProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<spring:property name="singleton" value="true"/>
<spring:property name="location" value="${app.name}.properties"/>
</spring:bean>
</spring:beans>
<http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="5000" doc:name="HTTP Listener Configuration"/>
<flow name="dynamic_propsFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test" doc:name="HTTP"/>
<logger message="#[app.registry.CountryProperties['country.full.name']]" level="INFO" doc:name="Logger"/>
</flow>
My properties are like below:
File - dynamic_props_usa.properties
population=10
country.full.name=united.states.of.america
File - dynamic_props_mexico.properties
population=100
country.full.name=mexico
${app.name} gives you the name of the app that is deployed. In case my app is named dynamic_props_usa, it refers the dynamic_props_usa.properties. If it is, dynamic_props_mexico, it refers dynamic_props_mexico.properties. Hope this helps!
Define context property placeholder to have a file reference in the package and have an option to override the same with server if needed at runtime as below,
<context:property-placeholder location="classpath:app-${mule.env}.properties, file:${mule.config.path}/app-${mule.env}.properties" ignore-resource-not-found="true" ignore-unresolvable="true" />
You can run your on premise Mule server with the option -M-Dmule.country=your-value
You may want to take a look at the documentation
Related
We currently have our mule projects organized where we have our mule flows in several flow files. We find that this helps in allowing us to reuse flows. However, it has an added side-effect. By having dependencies amongst other flow files, we are finding that our munit tests now have to load an extensive number of flow files that slows up our munit tests because we have to load many more files. We also don't want to stick our flows into one huge file either.
We want to know if there is a happy medium or a strategy with how we should be splitting our flow files so that it minimizes the impact of performance when it comes to tests and application loading?
Thanks,
Juan
I suggest that you use a general global configuration xml, where you place all your configurations and endpoint connectors. That way, you will only load the global.xml and not every other flow you are referencing.
Global.xml contains:
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<http:request-config name="REST_Request_Configuration" host="localhost" port="80" basePath="example" doc:name="HTTP Request Configuration"/>
<http:request-config name="REST_Request_Configuration2" host="google.com" port="80" doc:name="HTTP Request Configuration" basePath="/translate/v2">
On your test suite you only need to load one classpath/xml:
<spring:beans>
<spring:import resource="classpath:global.xml"/>
<spring:import resource="classpath:workflow_you_are_testing.xml"/>
</spring:beans>
Hope this helps.
I'd define the default mule-config.xml, with the connector configurations and flow file for each task in the project. Doesn't necessarily mean each flow file will contain single flow but flows related to same task conainining sub-flows or private flows as needed. However, the flow functionality which is reuseable like alert emails, database operations, put that in separate commons-config.xml flow file.
For unit-testing, I'd create another mule-test-config.xml under src/test/resources to contain mock connectors like database or any other. The connectors to use as it is like http or some other, copy them as it is to mule-test-config.
Now to test particular flow, you'd need flow file + mule-test-config + commons-config (if any shared flow)
How to use Move to Pattern & File Age property of File EndPoint in MULE.
I tried to give moveToPattern="#[function:datestamp]-#[message.inboundProperties['originalFilename']]" but it is not working as expected.
For File Age, I provided 50000. According to my understanding, if the last modified date of the file is 22.01.2015:20:07:20, then the file should be moved from this folder to another folder at 22.01.2015:20:12:20. But it is not happening. Please explain by giving an example.
What is the difference between connector reference & endpoint reference.
The 'file age' property defines the time a file must wait before it's processed. Once it's processed, it is going to move to the directory specified in the 'moveToDirectory'.
The file connector is a global connector where you can specify some properties that can be applied to all of your file endpoint configuration.
<file:connector name="File" autoDelete="true"
outputAppend="true" streaming="true" validateConnections="true"
doc:name="File" />
A file endpoint is a generic endpoint that can be referred from all your endpoints. For example, you have different endpoints with the same configuration, thus you can specify all the properties on a global endpoint, so when you need to change something, you only change the global one.
<file:endpoint name="fileEndpoint"
path="${file.path}" outputPattern="${file.outputPattern}" moveToDirectory="${file.moveToDir}"
connector-ref="File" doc:name="File" fileAge="5000"/>
The file inbound/outbound endpoints can then refer the global endpoints.
<file:outbound-endpoint responseTimeout="10000"
ref="fileEndpoint" doc:name="File - Log" />
The documentation for fileAge in the file transport reference is:
Setting this value (minimum age in milliseconds for a file to be processed) is useful when consuming large files, as Mule waits before reading this file until the file last modification timestamp indicates that the file is older than this value
In your case 50000 milliseconds would be 50 seconds, thus a file dropped at 22.01.2015:20:07:20 should be picked as soon as 22.01.2015:20:08:10.
Since it is not happening, there must be something wrong in your configuration. Please share your file transport configuration (if any) and your full endpoint configuration.
I have a flow with file endpoint and groovy.
I want to make the file path configerable.
Please suggest.
I am using file node to trigger the flow. So if anybody can suggest me that how to trigger groovy alone then there will be no need to use file endpoint.
Please suggest any solution.
What you want to do here is configure a file endpoint like so and use this as your inbound endpoint to trigger the flow:
<file:endpoint name="inputFile" path="${input.path}">
<!-- Add any filters (e.g. regex) here -->
</file:endpoint>
Then, you should create a mule-app.properties file inside of src/main/resources that will include something like the following:
# Input Properties
input.path=/path/to/file
Lastly, include the following at the top of your Mule config file (after <mule> but before your flow):
<spring:beans>
<context:property-placeholder location="classpath:mule-app.properties" />
</spring:beans>
Doing this should allow you to achieve what you've outlined above. Hope this helps!
I need to programmatically start or stop a flow or endpoint from another flow. Can this be done? Is there risk of message loss?
<flow name="control>
<vm:inbound-endpoint path="in">
<script:component>
<!-- start/stop -->
</script:component>
</flow>
<flow name="startable-stoppable>
<any-transport:inbound-endpoint/>
<component/>
</flow>
After some research I've found that the best option in my case is to start/stop the connectors associated with the endpoints I want to control.
<script:component>
<script:script engine="groovy">
muleContext.getRegistry().lookupConnector('connectorName').start() // or stop()
</script:script>
</script:component>
A disadvantage of this approach is that all the endpoints associated with the connector will be affected. If this is a problem, every endpoint should have its own connector.
You can control the lifecycle of Mule moving parts with JMX: use JConsole to find out what MBean you need to access from your scripted component.
i would like to define some sort of "retry policy" for a custom componenet i built, meaning retry on the initiailise function of the compoenent.
Is that supported by some XML tag (retry policy??) or would i have to implement the retries inside the initialise function itself? (which would mean i would have to handle the threads and stuff if i want to handle it like the "blocking" property of the EE edition)
And suppose there is some sort of retry attempts - what would happen if the component is still attempting to reinitialise while an inbound endpoint event is triggered? (or would that endpoint not register until the flow manages to start the component?)
In case i wasnt clear - this is the short example:
<flow>
<quartz:inbound-endpoint jobName="eventTimer">
<quartz:event-generator-job />
</quartz:inbound-endpoint>
<component>
<singleton-object class="com.SomeComponent" />
</component>
<vm:outbound-endpoint path="ChatMsgs"
exchange-pattern="one-way" />
</flow>
I'd like to set a "non-blocking" retry policy on the component and i would like the flow not to start until the component manages to initialise, is that asking too much of mule? :)
Thanks in advance
Non-blocking retry policies are now part of CE (since 3.2.0).
To have your component integrated with Mule's lifecycle and retry policies, I suggest you develop it as a Mule module using DevKit (see "Mule’s Lifecycle Support" in http://blogs.mulesoft.org/introducing-the-new-devkit/). Though marketed as an "API connector toolkit", DevKit does way way more things...
Of course, this would make your component Mule specific but with the benefit of making it a first-class citizen of Mule's infrastructure.