public void receiveContent(InputStream content) {
// operation logic
}
Special Parameters
TypedValue<Type>
A common use case for Operations and Sources is to receive Media Type information along with the value of the parameter, for example:
In the Mule app example below, you can see that you are receiving a JSON
value, but the operation’s code above does not indicate the MIME Type or encoding of the content
parameter.
<flow name="mediaTypeFlow">
<set-payload value="#[output application/json --- { key : 'value'}]">
<cool-extension:receive-content content="#[payload]" />
</flow>
To retrieve Media Type information (MIME Type and encoding), you simply need to wrap the parameter type into a TypedValue<OriginalType>
.
This example use the same Mule app above with the TypedValue
parameter:
public void receiveContent(TypedValue<InputStream> content) {
DataType dataType = content.getDataType();
MediaType mediaType = dataType.getMediaType();
boolean streamType = dataType.isStreamType();
Long length = content.getLength().orElse(-1L);
InputStream theContent = content.value(); // The proper value
System.out.println(mediaType); // application/json; UTF-8
System.out.println(streamType); // true
System.out.println(length); // 18
}
Use of TypedValue
parameters is highly recommended for use cases
where the MIME Type
information is required to communicate with other systems that rely on this or to be able how to handle the parameter value.
Literal<Type>
Literal<Type>
parameters allow you to get values as they were written
in the Mule app. This means that if the end user writes an expression such as #[attributes.queryParams]
, the operation will able to retrieve a String
with the expression #[attributes.queryParams]
. This prevents Mule runtime from resolving expressions or applying any transformations. This is useful when the evaluation needs to be performed by a third party.
In the case of configurations and connection providers, using literal parameters allows the configuration to be treated as a static one, instead of a dynamic one. This is because the literal value is constant even if that literal is an expression. The runtime will not evaluate it automatically, so it is treated a static value by the extension.
If the value was provided as an expression, the class will provide the expression but offer no way to evaluate it. You need to use parameter resolvers for that.
<flow name="literalFlow">
<cool-extension:literal-value content="#[payload]" />
</flow>
public void literalValue(Literal<InputStream> literal) {
System.out.println(literal.getLiteralValue().get()); // #[payload]
System.out.println(literal.getType()); // java.io.InputStream
}
You need to consider the generic type. A parameter derived from uses of this interface will have its type set according to the generic type. The generic is not optional. |
ParameterResolver<Type>
ParameterResolver<Type>
allows you to defer the resolution of an expression on an operation. This is useful when a parameter that takes an expression as a value is not required. You can improve performance by resolving such an expression on demand from within the connectors’s code instead of resolving it automatically.
Compared to Literal<Type>
parameters, a ParameterResolver<Type>
parameter with an expression continues to be treated as a dynamic parameter whether the value is resolved or not.
You cannot use ParameterResolver inside of configurations or connection providers.
|
Resolving Expressions
When a ParameterResolver<Type>
is received to resolve the expression value, the resolve()
method must be called to return the result of the expression.
|
Getting the Expression Value
ParameterResolver<Type>
parameters can communicate the expression used for the parameter. It returns an Optional<String>
because the parameter can be configured with an expression or not. If it is not configured with an expression, Optional.empty()
will be returned.
Example: With Expression
<flow name="expressionParameterResolver">
<cool-extension:add-products products="#[{Potatoes : 2 , Oranges : 4}]"/>
</flow>
public void addProducts(ParameterResolver<Map<String,Integer>> products) {
System.out.println(products.getExpression().get()); // #[{Potatoes : 2 , Oranges : 4}]
System.out.println(products.resolve()); // {Potatoes=2, Oranges=4}
}
Example: Without Expression
<flow name="noExpressionParameterResolver">
<cool-extension:add-products>
<cool-extension:products>
<cool-extension:product key="Potatoes" value="2"/>
<cool-extension:product key="Oranges" value="4"/>
</cool-extension:product>
</cool-extensions:add-products>
</flow>
public void addProducts(ParameterResolver<Map<String,Integer>> products) {
System.out.println(products.getExpression().isPresent()); // false
System.out.println(products.resolve()); // {Potatoes=2, Oranges=4}
}
Stacking Types
You might need to use more than one of the parameters described above at the same time. For example, you might want to receive the Media Type of a given value and defer its resolution.
To do this, you simply stack the generics for the capabilities you want.
<flow name="stackedTypes">
<cool-extension:add-products products="#[output application/json --- {Potatoes : 2 , Oranges : 4}]"/>
</flow>
public void addProducts(ParameterResolver<TypedValue<InputStream>> products) {
System.out.println(products.getExpression().get()); // #[output application/json --- {Potatoes : 2 , Oranges : 4}]
TypedValue<InputStream> content = products.resolve();
System.out.println(content.getValue()); // {"Potatoes" : "2", "Oranges" : "4"}
}