Mule - Inject flow or session variable into Spring bean - mule

I am trying to pass a variable to a Spring bean like so:
<component doc:name="Java">
<no-arguments-entry-point-resolver />
<prototype-object class="org.test.MyComponent">
<property key="fileName" value="#[sessionVars.filename]" />
</prototype-object>
</component>
But the expression never resolves? Is there a another way to do this?

This is a confusion with the spring configuration and Mule Expression language(MEL).
Point 1:
Even though the component is defined inside the Mule Config file. The elements (tags) <property/> is from the Springs Bean schema definition. So the attribute values of key and value are not interpreted by the MEL.
Point 2: As it is provided as setter injection which is invoked during loading(instantiation) the value of session variable(run time value) will not be available.
One possible solution to this would be to make the component implement Callable interface of Mule. So that you will have access to the MuleMessage which contains the session variable.
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
MuleMessage muleMessage = eventContext.getMessage();
muleMessage.getProperty("propertyName", PropertyScope.SESSION);
Hope this helps.

When the Mule server starts, each of the elements are loaded, and the component and spring-object are created. I don't think you can pass session variable or for that matter any variable other than context-properties to object creation happening at server start-up time.

Related

apache camel REST failing with [Error creating bean with name 'rest-configuration']

My route looks like below -
#Override
public void configure() throws Exception {
from("kafka:adapterTopic")
.to("rest://post:gatewayinbound-dev11.devsite.com");
}
I have tried with this as well,
.to("rest:post:gatewayinbound-dev11.devsite.com");
and this as well,
restConfigutation().host("gatewayinbound-dev11.devsite.com");
from("kafka:adapterTopic")
.to("rest:post:provideStatus/");
I have tried with camel-rest-starter dependency in the classpath and without it as well.
I have tried putting camel-rest instead of camel-rest-starter in the pom.
But nothing is making the exception go away, below is the stacktrace-
{"timestamp":"2020-04-21 18:17:45.327","severity":"ERROR","class":"org.springframework.boot.SpringApplication","crId":"","msg":"Application run failed","exception":"org.apache.camel.RuntimeCamelException","cause":"org.apache.camel.FailedToCreateRouteException: Failed to create route route10 at: >>> To[rest:post:gatewayinbound-dev11.devsite.com] <<< in route: Route(route10)[[From[kafka:adapterTopic]] -> [To[rest:... because of Failed to resolve endpoint: rest:\/\/post:gatewayinbound-dev11.devsite.com due to: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rest-configuration' defined in class path resource [org\/apache\/camel\/model\/rest\/springboot\/RestConfigurationDefinitionAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.camel.spi.RestConfiguration]: Factory method 'configureRestConfigurationDefinition' threw exception; nested exception is java.lang.IllegalArgumentException: Cannot configure option [useXForwardHeaders] with value [true] as the bean class [org.apache.camel.spi.RestConfiguration] has no suitable setter method, or not possible to lookup a bean with the id [true] in Spring Boot registry"
Please help me here. Looking at the examples at Camel's website it looks quite easy to configure a rest producer endpoint but for me it has been very difficult.
Edit-
As Rest component is part of camel-core, I was using camel-core-2.22.1.
Then as suggested by Raúl Cancino, I tried this as well-
to("rest:post:provideStatus?host=gatewayinbound-dev11.devsite.com:443")
please try the following uri format on your to(), as a starting point:
to("rest:post:provideStatus?host=gatewayinbound-dev11.devsite.com:443")
then you can switch to rest configuration
restConfiguration().host("gatewayinbound-dev11.devsite.com:443");
also, using camel-http this would be:
.setHeader(Exchange.HTTP_METHOD,constant(org.apache.camel.component.http.HttpMethods.POST))
.to("https:gatewayinbound-dev11.devsite.com/provideStatus?bridgeEndpoint=true")
Hope it works for you
The problem was with the version of camel-core library my applcation was using (as transitive dependency), when I switched to camel-core-2.24.2 the problem got resolved.
I compared org.apache.camel.spi.RestConfiguration classes from both versions of camel-core, 2.22.1 and 2.24.2 and found that property useXForwardHeaders was missing in older version.

MuleSoft - how to catch an error/exception into Munit test?

Into a flow i raised and error and i would like to test it in Munit.
The documentation doesn't seem to contain and explain this particular case.
what is the text that i need to insert into :
expected error type
expected exception
All errors thrown in Mule contain meta-data including a TYPE.
For example, here is a list of some specific HTTP: errors thrown by the HTTP module:
HTTP:UNSUPPORTED_MEDIA_TYPE
HTTP:CONNECTIVITY
HTTP:INTERNAL_SERVER_ERROR
HTTP:METHOD_NOT_ALLOWED
Each module's documentation should contain all specific error types thrown by that module. Here is the HTTP one example: https://docs.mulesoft.com/connectors/http/http-documentation#throws
In your screenshot for example it uses APIKIT module. APIKIT module has its own errors again. Think of it as certain Java classes throwing custom exceptions specific to that class.
And here is a full list of core error types you can catch like EXPRESSION for example:
https://docs.mulesoft.com/mule-runtime/4.1/mule-error-concept
The attribute expectedErrorType expects an error type ID that needs to be defined inside the application being tested. This attribute allows you to validate that a defined error type in your application is thrown. If you define an errorType that does not exists in your application, the test does not run.
<munit:test name="MUnit-test-suite"
description="Test Error Type"
expectedErrorType="FTP:ILLEGAL_PATH">
...
</munit:test>
This Error Type test expects that an FTP operation will throw an FTP:ILLEGAL_PATH error.
You will need to configure this for your specific type you are expecting.
The attribute expectException expects a literal exception class name (canonical form). When you provide a literal value, it should take the form of the canonical class name of the exception that is expected. In these cases, Mule always throws a MuleMessagingException. MUnit validates the provided classname if the underlying cause of the MuleMessagingException thrown is of the exact same type.
<munit:test name="testExceptions"
description="Test Exceptions"
expectedException="java.lang.RuntimeException">
...
</munit:test>
If you define that your test expects an exception and none is thrown, the test fails immediately.
So you don't need to provide both.

Issues with overriding the Mule Watermark (SF Polling) in flow via ObjectStore:store

I have defined the object store as following:
<objectstore:config name="objectStore" objectStore-ref="_defaultUserObjectStore"/>
And am trying to modify the watermark variable defined by name "lastmodified" in object store via a flow which call
<objectstore:store key="lastmodified" value-ref="#[payload.lastmodified]" overwrite="true" config-ref="objectStore" doc:name="Default User Object Store"/>
Note: payload.lastmodified has appropriate value of "2016-06-29T15:08:45.000Z" in it.
I am not seeing any error on console but when the next time the Poll executes it doesn't read the updated value of the watermark.
Any pointer would be surely helpful.
Thanks.
Instead of the method used above, try using poll-watermarking. Can set you update expression in poll-watermarking and if needed, can use object store also.
I fixed it by making changing the object store config to: <objectstore:config name="objectStore" partition="mule.watermark" doc:name="ObjectStore: Connector"/>

How to read properties from .properties file in Mule

I'm trying to use Mule Credentials Vault security feature.
I've created .properties file, Security Property Placeholder and defined the key and encryption algorithm.
Now I want to use some of the properties from the file when I return HTTP response.
I have the file src/main/resources/data.properties that contains for example:
In my canvas, under Configuration XML I added:
<secure-property-placeholder:config name="Secure_Property_Placeholder" key="24681357" location="data.properties" doc:name="Secure Property Placeholder" encryptionAlgorithm="DES"/>
<set-variable variableName="card.number" value="${number}" />
In my canvas I have message flow that builds xml 'Create XML response based on User'. The value in settings is:
This doesn't work. The error I get is:
-> org.mule.module.launcher.DeploymentInitException: IllegalArgumentException: Could not resolve placeholder 'key' in string value "${key}"
-> Caused by: org.mule.api.lifecycle.InitialisationException: Invalid bean definition with name 'org.mule.autogen.bean.13' defined in null: Could not resolve placeholder 'key' in string value "${key}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'key' in string value "${key}"
-> Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'key' in string value "${key}"
Does anyone know how can I read the properties from .properties file (credentials vault)? And then use it in my flow?
Thanks,
Keren
If you simply want to get the value for the property number and add it into the XML you can use ${number} from .properties. No need to define any other variables in Configuration XML.
<set-payload value="<user><name>Royal Bank of Canada</name><id>Royal_Bank_Of_Canada</id><cc><company>>Visa</company><number>${number}</number><secret>123</secret></cc></user>" doc:name="Set Payload"/>
However note that the property placeholder is resolved at startup so you will not be able to dynamically retrieve a property based on some user input. For this you will have to do some Java coding. This SO post gives you some hints on how this can be achieved. Based on those answers I have created a simple example on how this can be done with a very simple helper bean.
I'm afraid you just can't. The Mule Credentials Vault is an enterprise feature and therefore tipically you won't have access to the source code unless you are a MuleSoft customer.
Even if you were a customer, the api you'd use would be sort of unsupported. I suggest to manually create a custom java component levearing your code and Jasypt (not as a property placeholder but as a library).
The other option, if you are a customer (I guess you are given you are using the credentials vault) is to contact the official support so they take care of it for you.
The property placeholder is used resolve at startup so you will not be able to dynamically retrieve a property based on some user input.
Use ${propertyName} from .properties in MEL to access particular property
From Dataweave you can read it as given below
p('variablename')
where variablename is defined in property files ex: variablename = 15

mule endpoint builder from java code

The below code fetches the global endpoint named SomeInbound and is stored in an invocation variable named someUrl
<set-variable variableName="someUrl" value="#[app.registry['SomeInbound'].getEndpointBuilder().getEndpoint().getUri()]"/>
How can we do the same thing in java(how to get that app object in java and also the other methods following that)
'app' is just a MEL specific context object for accessing parts of the MuleContext etc. In Java you can grab the registry from the MuleContext like so: muleContext.getRegistry() and then use one of the lookup methods to get the object you want.
TO get the muleCOntext, there any many possible ways. Some of which are:
From a test case.
Injection or the #Lookup
annotation:http://www.mulesoft.org/documentation/display/current/Lookup+Annotation
Implementing MuleContextAware:
https://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/context/MuleContextAware.html
Or if you're using a Callable component etc. you can get it from the
MuleEventContext : https://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/MuleEventContext.html#getMuleContext()