Spring property resolution in Mule Groovy script - spring

I'm trying to access Spring initialized properties within a Mule Groovy script without success.
Loading the property file in Mule application XML:
<context:property-placeholder location="application.properties"/>
Contents of property file:
key=value
Accessing the property from inside the application XML works fine:
<logger message="key: ${key}" level="INFO" doc:name="Logger" />
Produces the following output:
key: value
Attempting the same in a groovy script:
log.info "key: ${key}"
Results in exception:
Exception stack is:
1. No such property: key for class: Script1 (groovy.lang.MissingPropertyException)
org.codehaus.groovy.runtime.ScriptBytecodeAdapter:53 (null)
2. groovy.lang.MissingPropertyException: No such property: key for class: Script1 (javax.script.ScriptException)
org.codehaus.groovy.jsr223.GroovyScriptEngineImpl:326 (http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/script/ScriptException.html)
3. Failed to invoke ScriptComponent{main-flow.component.32928685}. Component that caused exception is: ScriptComponent{main-flow.component.32928685}. Message payload is of type: ContentLengthInputStream (org.mule.component.ComponentException)
org.mule.component.AbstractComponent:144 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/component/ComponentException.html)
********************************************************************************
Root Exception stack trace:
groovy.lang.MissingPropertyException: No such property: key for class: Script1
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:53)
at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:52)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:307)
at Script1.run(Script1.groovy:18)
<snip>
I'm assuming that all properties are available somewhere within the Groovy script context references available to the script, but I've found no documentation on how to navigate to them. I've looked through the JavaDocs, but have been unable to piece together the proper method for Spring initialized property resolution. Any help is greatly appreciated.
Thanks,
Steve

I found the answer to my question in the following post. In short,
Spring property placeholders are resolved at configuration time and not stored anywhere, so they cant be loaded afterwards.
If you need to store it you can always inject them into a bean and retrieve that from the registry.
Based on the answer provided above, this behavior may have changed in newer releases of the Mule runtime, but my experience using version 3.5.4 is consistent with the other post's description of how Spring properties are evaluated by the MEL interpreter.
Steve

Which version of Mule runtime are you using ?
I am able to get the value from properties file using following example in Mule runtime 3.7.3:-
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="teFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/test" doc:name="HTTP"/>
<logger message="key: ${key}" level="INFO" doc:name="Logger" />
<scripting:component doc:name="Groovy">
<scripting:script engine="Groovy"><![CDATA[
System.out.print("In Groovy Script "+${key}+"\n");
log.info "In Groovy logger: ${key}";
]]></scripting:script>
</scripting:component>
</flow>
application.properties contains:-
key=555
And the output is in the Mule console as follows:-

Related

Logback destination configuration from application.yml

I'm trying to configure my logback in XML import destination configuration from application.yml.
When I set static destination in XML then everything is fine but if not then I'm getting this exception on startup:
Could not invoke method addDestination in class net.logstash.logback.appender.LogstashTcpSocketAppender with parameter of type java.lang.String java.lang.reflect.InvocationTargetException
ERROR in net.logstash.logback.appender.LogstashTcpSocketAppender[STASH] - No destination was configured. Use <destination> to add one or more destinations to the appender
My dependencies:
spring-boot: '1.5.4.RELEASE'
net.logstash.logback:logstash-logback-encoder:4.9
logback-spring.xml
<springProperty name="LOGBACK_URL" source="logback.destination.url"/>
<springProperty name="LOGBACK_PORT" source="logback.destination.port"/>
<appender name="STASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>${LOGBACK_URL}:${LOGBACK_PORT}</destination>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">...
</encoder>
</appender>
applicaiton.yml
logback:
destination:
url: kibana.test
port: 1234
I'm trying to avoid migrating this config to java and hope it's unnecessary. Thanks in advance !
EDIT
I've resolved this problem by adding default value which is space in xml configuration like below:
<destination>${LOGBACK_URL:- }:${LOGBACK_PORT:- }</destination>
just leaving it here for anyone facing similar issue, in my case, I had to remove the http:// from the url inside destination tag.

Mule Cache - Cluster In Memory - deserialization issue

My Mule 3.9 application exposes a rest end point.
Application is clustered and on-prem managed through Runtime Manager
Condition is: the end point which kicks off the batch process should be singleton meaning only 1 process should be running on the entire cluster. If a rest endpoint is invoked again, it should result into http status 409
For this use case, I have utilized Mule Caching - Clustered - In Memory version with below configuration
<ee:object-store-caching-strategy name="caching_strategy" doc:name="caching_strategy" keyGenerationExpression="some_key" synchronized="false" entryTTL="14400000" persistent="false" />
My flow looks like below -
<flow name="some-flow" doc:description="some-flow">
<message-properties-transformer scope="invocation" doc:name="Intialize Message Properties" mimeType="application/java">
<add-message-property key="messageId" value="#[message.rootId]"/>
</message-properties-transformer>
<ee:cache doc:name="inititiation" cachingStrategy-ref="caching_strategy" >
<logger message="process cache miss" level="INFO" doc:name="process cache miss"/>
<set-payload doc:name="initialize cache map" value="#[{'id' : flowVars.messageId}]" />
</ee:cache>
<choice doc:name="Is process already running ?" >
<when expression="#[payload.id == flowVars.messageId]">
<logger message="New process started" level="INFO" />
</when>
<otherwise>
<logger message="Process is already running" level="WARN" />
</otherwise>
</choice>
</flow>
As you can see, I am putting java.util.HashMap with 1 key-value pair in cache and checking if it already exists or not
<set-payload doc:name="initialize cache map" value="#[{'id' : flowVars.messageId}]" />
Actual functionality works great in the cluster and serves the purpose !
HOWEVER application logs are full of below **WARN** statements
org.mule.util.store.MonitoredObjectStoreWrapper -
Running expirty on org.mule.util.store.ObjectStorePartition#4648ce75 threw java.lang.IllegalArgumentException:
Cannot deserialize with a null classloader:
Cannot deserialize with a null classloader
I am not sure what is issue? The object which is in the cache is java.util.HashMap which is serializable and only key-value pair is of String.
I sense some class loader issue, but could not bring myself close to it.
Does anybody have any clue?
Thanks
Vikas
Had my hands on the ground and managed to resolve the issue with below configuration -
<ee:object-store-caching-strategy name="caching_strategy" doc:name="caching_strategy" keyGenerationExpression="some_key" synchronized="false" >
<!-- this is because my flow eturns different message than cache"
<ee:serializable-event-copy-strategy/>
<!-- manged store without persistance -->
<managed-store storeName="MyTaskInMemoryStoreForClusteredCaching"
maxEntries="1" entryTTL="14400000"
expirationInterval="3660000" persistent="false"/>
</ee:object-store-caching-strategy>

The camel message exchange property is not being resolved when used in validator uri component

I am trying to validate the xml file against the xsd using the validator component of camel using blueprint DSL.
<to id="validateXML" uri="validator:file:D:/data/schema/flow.xsd" /> --> working
<to id="validateXML" uri="validator:file:${property.flowXsdPath}" /> --> Not working
flowXsdPath is an exchange property which is set to the xsd location defined by the variable xsdPathVar as given below:
exchange.setProperty("flowXsdPath", exchange.getContext().resolvePropertyPlaceholders(xsdPathVar));
I get exception "Failed to create Producer for endpoint: Endpoint[validator://file:$%7Bproperty.flowXsdPath%7D]. Reason: java.io.FileNotFoundException: ${property.flowXsdPath} (The system cannot find the file specified)"
Though I can access the property value in a log message just before validating the xml file, like this
<log message="File ${file:name} XSD Location = ${property.flowXsdPath}" />
2017-10-16 11:48:44,037 | INFO | processXMLFiles] | file-jms-hums-route | ID-ITEM-XXXXX-49898-1508134722113-0-3 | File 20150603-161237-A412-MFSC.xml XSD Location = D:/data/schema/FSC.xsd
Could you please help how can I access this property inside validator file component?
You should use Dynamic To <toD> instead of <to> to send a message to a dynamic computed Endpoint.
See the related section in http://camel.apache.org/message-endpoint.html

JMSAppender - cannot find topic

I've tried to use JMSAppender following the instructions found here. I'm trying to use it in the MuleStudio environment with ActiveMQ.
I added the following to my log4j.xml file:
<appender name="jms" class="org.apache.log4j.net.JMSAppender">
<param name="InitialContextFactoryName" value="org.apache.activemq.jndi.ActiveMQInitialContextFactory" />
<param name="ProviderURL" value="tcp://localhost:61616" />
<param name="TopicBindingName" value="logTopic" />
<param name="TopicConnectionFactoryBindingName" value="ConnectionFactory" />
</appender>
<logger name="org.apache.activemq">
<appender-ref ref="console" />
</logger>
I created a jndi.properties file in the classpath with the contents:
topic.logTopic=logTopic
I added activemq-core-5.7.0.jar into MuleStudio's classpath.
When I try to run the Mule application, I get the exception show below that the topic name could not be found.
I used ActiveMQ's console to manually create the topic, but that didn't change anything.
What am I doing wrong?
The console log output:
log4j: Class name: [org.apache.log4j.net.JMSAppender]
log4j: Setting property [initialContextFactoryName] to [org.apache.activemq.jndi.ActiveMQInitialContextFactory].
log4j: Setting property [providerURL] to [tcp://localhost:61616].
log4j: Setting property [topicBindingName] to [logTopic].
log4j: Setting property [topicConnectionFactoryBindingName] to [ConnectionFactory].
log4j: Getting initial context.
log4j: Looking up [ConnectionFactory]
log4j: About to create TopicConnection.
log4j: Creating TopicSession, non-transactional, in AUTO_ACKNOWLEDGE mode.
log4j: Looking up topic name [logTopic].
log4j:ERROR Could not find name [logTopic].
log4j:ERROR Error while activating options for appender named [jms].
javax.naming.NameNotFoundException: logTopic
at org.apache.activemq.jndi.ReadOnlyContext.lookup(ReadOnlyContext.java:235)
at javax.naming.InitialContext.lookup(InitialContext.java:411)
at org.apache.log4j.net.JMSAppender.lookup(JMSAppender.java:245)
at org.apache.log4j.net.JMSAppender.activateOptions(JMSAppender.java:222)
at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:307)
at org.apache.log4j.xml.DOMConfigurator.parseAppender(DOMConfigurator.java:295)
at org.apache.log4j.xml.DOMConfigurator.findAppenderByName(DOMConfigurator.java:176)
at org.apache.log4j.xml.DOMConfigurator.findAppenderByReference(DOMConfigurator.java:191)
at org.apache.log4j.xml.DOMConfigurator.parseChildrenOfLoggerElement(DOMConfigurator.java:523)
at org.apache.log4j.xml.DOMConfigurator.parseRoot(DOMConfigurator.java:492)
at org.apache.log4j.xml.DOMConfigurator.parse(DOMConfigurator.java:1001)
at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:867)
at org.apache.log4j.xml.DOMConfigurator.doConfigure(DOMConfigurator.java:773)
at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:483)
at org.apache.log4j.LogManager.<clinit>(LogManager.java:127)
at org.apache.log4j.Logger.getLogger(Logger.java:117)
at org.mule.module.logging.LoggerReferenceHandler.<init>(LoggerReferenceHandler.java:28)
at org.mule.module.logging.MuleLogFactory.<init>(MuleLogFactory.java:41)
at org.apache.commons.logging.LogFactory.<clinit>(LogFactory.java:32)
at org.mule.module.launcher.CompositeDeploymentListener.<init>(CompositeDeploymentListener.java:24)
at org.mule.tooling.server.application.ApplicationDeployer.main(ApplicationDeployer.java:108)
Need to do the following:
create a jndi.properties file in the mule/conf dir that has topic.logTopic=logTopic
put the following jars in the mule/lib/boot: activemq-client-5.8.0.jar,
geronimo-j2ee-management_1.1_spec-1.0.1.jar, geronimo-jms_1.1_spec-1.1.1.jar
add the following to your log4j.properties for the service
# settings for specific packages
log4j.logger.org.mule=INFO
log4j.logger.com.mule.support=INFO
#log4j.logger.org.mule.api.processor.LoggerMessageProcessor=${custom-level}
log4j.logger.httpclient.wire.header=DEBUG, jms
log4j.logger.org.apache.activemq=INFO, stdout
## Configure 'jms' appender. You'll also need jndi.properties file in order to make it work
log4j.appender.jms=org.apache.log4j.net.JMSAppender
log4j.appender.jms.InitialContextFactoryName=org.apache.activemq.jndi.ActiveMQInitialContextFactory
log4j.appender.jms.ProviderURL=tcp://localhost:61616
log4j.appender.jms.TopicBindingName=logTopic
log4j.appender.jms.TopicConnectionFactoryBindingName=ConnectionFactory

Working example on Spring Mediator in WSO2 ESB 4.6.0

Hi i am working on Spring Mediator in WSO2 ESB 4.6.0, using this and this tutorial
I am getting the Error as follows:
ERROR - SpringMediator Cannot look up Spring configuration conf/sample/resources/spring/springsample.xml
ERROR - SpringMediatorCannot reference application context with key : conf/sample/resources/spring/springsample.xml
Could you please explain me how to solve this.
I got to work this as below,
The class should extends AbstractMediator and override the mediate() method as follows,
package com.test.spring.mediator.workingexampleonspringmediator;
import org.apache.synapse.MessageContext;
import org.apache.synapse.mediators.AbstractMediator;
public class HelloWorld extends AbstractMediator{
private String message;
public void setMessage(String message){
this.message = message;
}
public boolean mediate(MessageContext arg0) {
System.out.println("HELLO "+message);
return true;
}
}
Then place the jar in [ESBHOME]/repository/components/lib folder
In mediate method it prints a message with the argument like HELLO 'arg'
And I added the following file to registry (/_system/config/repository/spring/springtest.xml),
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="springtest" class="com.test.spring.mediator.workingexampleonspringmediator.HelloWorld" singleton="false">
<property name="message"><value>ISURU</value></property>
</bean>
</beans>
My proxy is as follows,
<proxy xmlns="http://ws.apache.org/ns/synapse" name="testSpring" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<log level="full">
<property name="START" value="__________________________"/>
</log>
<spring:spring xmlns:spring="http://ws.apache.org/ns/synapse" bean="springtest" key="conf:/repository/spring/springtest.xml"/>
<log level="full">
<property name="END" value="______________________"/>
</log>
</inSequence>
</target>
<description></description>
</proxy>
In the proxy you can see the bean=[bean id of the springtest.xml] and class=qualified name of the class
In my ESB terminal, I got the following out put with the given property value in springtest.xml,
[2013-11-07 17:38:30,654] INFO - LogMediator To: /services/testSpring.testSpringHttpSoap12Endpoint, WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: urn:uuid:bcae82e9-4027-43c5-bd7a-cbfa885aaf33, Direction: request, START = __________________________, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Body/></soapenv:Envelope>
HELLO ISURU
[2013-11-07 17:38:30,692] INFO - LogMediator To: /services/testSpring.testSpringHttpSoap12Endpoint, WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: urn:uuid:bcae82e9-4027-43c5-bd7a-cbfa885aaf33, Direction: request, END = ______________________, Envelope: <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"><soapenv:Body/></soapenv:Envelope>
You must restart the ESB after placing the jar in repository/components/lib
These are the steps for spring mediator in brief as Isuru explained above
Create spring mediator library by extending AbstractMediator
Copy into ESB_HOME/repository/components/lib
Re-start the server
Register springtest.xml file in the Registry
(http://madhukaudantha.blogspot.com/2012/07/wso2-esb-proxy-from-registry.html up to step 5 as Isuru explained)
Then, create a Custom proxy with Spring Mediator.
In there,
add Bean as “springtest” (defined bean id for the mediator class within the xml file)
Select the Key as where the configuration registry file stored according to the 4th step.
Ex : If you have stored that springtest.xml file into path “_system/config/repository/”
Select Key as “/_system/config/repository/springtest.xml”
Note:
Verify in ESB_HOME/repository/components/dropins folder for OSGI
bundle of the mediator of the created spring mediator library which
is copied into ESB_HOME/repository/components/lib. If it is not there
after restarting server, it may be a problem in created mediator
library.
As well as, put unique package name for the mediator class to avoid
conflicts with other mediator class in
ESB_HOME/repository/components/lib.
Keep in mind to add unique bean id for the .xml file which is
registered in the registry when you registered .xml file in 4th step.
This is because of the esb finds the springsample.xml file in the path repository/conf/sample/resources
<parameter name="root">file:repository/conf/sample/resources/</parameter>
But the springsample.xml file location is in repository/samples/resources/ . Therefore it should be corrected as the following,
<parameter name="root">file:repository/samples/resources/</parameter>
In documentation, the configuration is not correct, If you start the esb by the command wso2esb-samples -sn 470 (as mentioned in the documentation) the esb will load the file in repository/samples/synapse_sample_470.xml where in this file above parameter is correctly configured.
Hope this will solve your problem :)
UPDATED:
According to your comment, as your are directly using sample spring example, this occur due to permission of the file trying to access, Or this can be due to file path error. So please try with absolute file url.
when i send a message, the only error message i got is this one
ERROR - SpringMediator No bean named 'springtest' is defined
so it means, the config file has been found. But what about the instanciation of the bean inside, i cannot see any explicit error. The jar file is in components/lib and i can see it also in dropins folder.
:/

Resources