How to resolve dynamic property name using Spring SPEL? - spring

I've an instance variable the value of which should be set by looking up a dynamic property name.
Class Test {
#Value("#{T(java.lang.String).format('filter.%s.disable', getClass().getSimpleName())}")
private boolean disable;
}
disable should evaluate to true when filter.Test.disable = true and false otherwise. I also want to set a default value false if the property is not defined, which is usually done using the following syntax, but I'm not sure in this case.
#Value("${property:default}")
I'm getting the error:
Caused by: java.lang.IllegalArgumentException: Invalid boolean value
[filter.BeanExpressionContext.disable]
Also tried #Value("${'dcs.cloud.filter.'#{getClass().getSimpleName()}'.disable'}") and some other combinations of # and $ to no avail.
The SPEL doc shows useless parser.parseExpression calls to evaluate expressions, which uses a different syntax, and no one does in reality. Looks like they picked out code from the unit tests instead of real examples.

You can't access the class in which the expression is declared that way. getClass() there acts on the root object for the expression evaluation (the BeanExpressionContext in this case).
It's not clear why you can't just use filter.Test.disable here (unless, perhaps you are trying to get the actual class when Test is subclassed).
You can't do that.
It might be easier to implement EnvironmentAware and set the boolean by getting the property from the environment.

Related

JMeter Custom Plugin Variable Substitution

Context
I am developing a custom JMeter plugin which generates test data dynamically from a tree like structure.
The editor for the tree generates GUI input fields as needed, and therefore I have no set of defined configuration properties which are set in the respective TestElement. Instead, I serialize the tree as a whole in the GUI class, set the result as one property and deserialize it in the config element where it is processed further during test execution.
Problem
This works just fine, except that JMeter variable/function expressions like ${foo} or ${_bar(..)} in the dynamic input fields are not evaluated. As far as I understand the JMeter source code, the evaluation is triggered somehow if the respective property setters in org.apache.jmeter.testelement.TestElement are used which is not possible for my plugin.
Unfortunately, I was not able to find a proper implementation which can be used in my config element to evaluate such expressions explicitly after deserialization.
Question
I need a pointer to JMeter source code or documentation for evaluating variable/function expressions explicitly.
After I manages to setup the JMeter-Project properly in my IDE, I found org.apache.jmeter.engine.util.CompoundVariable which can be used like this:
CompoundVariable compoundVariable = new CompoundVariable();
compoundVariable.setParameters("${foo}");
// returns the value of the expression in the current context
compoundVariable.execute();

Get Class of Map in FreeMarker

I want to get a variable's class type in freemarker, used var.class.simpleName;
but if var is a Map, freemarker will process class as a key to find value in var.
it throw exception. how can I do this ? thanks for any suggestion.
First I have to ask why do you need that, because FreeMarker templates aren't supposed to know even if var is Map at all. Maybe your data-model is not what the template needs.
Anyway, for now, I would write a custom TemplateMethodModelEx for this purpose, something that you can use like ${classOf(var)}. Inside the TemplateMethodModelEx implementation you will receive a TemplateModel as the argument value, and then you can check if it's an AdapterTemplateModel, and if so you can get back the original object and get its class. (If it's not a AdapterTemplateModel, then it perhaps isn't even a wrapped Java object, so it doesn't make sense to ask what the class of the original object is.) However, the DefaultObjectWrapper with incompatibleImprovements set to less than 2.3.22 doesn't give AdapterTemplateModel to wrapped Map-s... so in 2.3.21 you will still have to use BeansWrapper, but you can at least set simpleMapWrapper to true.
In 2.3.22 it will be actually possible to write ${var?api.class}... you might use the nightly build. Though it only supposed to solve the problem where you can't access business methods because the primary type of the business class is Map.

How to define #Value as optional

I have the following in a Spring bean:
#Value("${myValue}")
private String value;
The value is correctly injected. However, the variable needs to be optional, it is passed in as a command line parameter (which is then added to the Spring context using a SimpleCommandLinePropertySource), and this argument will not always exist.
I have tried both the following in order to provide a default value:
#Value("${myValue:}")
#Value("${myValue:DEFAULT}")
but in each case, the default argument after the colon is injected even when there is an actual value - this appears override what Spring should inject.
What is the correct way to specify that #Value is not required?
Thanks
What is the correct way to specify that #Value is not required?
Working on the assumption that by 'not required' you mean null then...
You have correctly noted that you can supply a default value to the right of a : character. Your example was #Value("${myValue:DEFAULT}").
You are not limited to plain strings as default values. You can use SPEL expressions, and a simple SPEL expression to return null is:
#Value("${myValue:#{null}}")
If you are using Java 8, you can take advantage of its java.util.Optional class.
You just have to declare the variable following this way:
#Value("${myValue:#{null}}")
private Optional<String> value;
Then, you can check whether the value is defined or not in a nicer way:
if (value.isPresent()) {
// do something cool
}
Hope it helps!
If you want to make the configuration property optional just pass an empty string like this:
#Value("${app.optional.value:}")
I guess you are you using multiple context:property-placeholder/ declarations?
If so, this is a known issue since 2012, but not fixed, apparently due to both lack of interest and no clean way of fixing it. See https://github.com/spring-projects/spring-framework/issues/14623 for discussion and some ways to work around it. It's explained in an understandable way by http://www.michelschudel.nl/wp/2017/01/25/beware-of-multiple-spring-propertyplaceholderconfigurers-and-default-values/

informatica-powercenter Mapping variable in Java

How do I access a mapping parameter ($$myvariable) from a Java Transformation in Informatica Powercenter?
What I want to do is to make a Java transformation reusable by making a part of it configurable, and a variable seemed suitable for that, however I haven't been able to access (read) a variable from the Java code.
I see three options
use an expression transformation with a variable port that passes
the variable into an input port defined in the java transformation
Use shell variables and get them with the Java 'System.getenv' call for example:
final String myconfig = System.getenv("MYCONFIG");
use a Java expression to get to the variable
Integer getEmpID() throws SDKException
{
return (Integer)invokeJExpression("SETCOUNTVARIABLE($$MyVar)", new Object [] {} );
}

How Does Queryable.OfType Work?

Important The question is not "What does Queryable.OfType do, it's "how does the code I see there accomplish that?"
Reflecting on Queryable.OfType, I see (after some cleanup):
public static IQueryable<TResult> OfType<TResult>(this IQueryable source)
{
return (IQueryable<TResult>)source.Provider.CreateQuery(
Expression.Call(
null,
((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(
new Type[] { typeof(TResult) }) ,
new Expression[] { source.Expression }));
}
So let me see if I've got this straight:
Use reflection to grab a reference to the current method (OfType).
Make a new method, which is exactly the same, by using MakeGenericMethod to change the type parameter of the current method to, er, exactly the same thing.
The argument to that new method will be not source but source.Expression. Which isn't an IQueryable, but we'll be passing the whole thing to Expression.Call, so that's OK.
Call Expression.Call, passing null as method (weird?) instance and the cloned method as its arguments.
Pass that result to CreateQuery and cast the result, which seems like the sanest part of the whole thing.
Now the effect of this method is to return an expression which tells the provider to omit returning any values where the type is not equal to TResult or one of its subtypes. But I can't see how the steps above actually accomplish this. It seems to be creating an expression representing a method which returns IQueryable<TResult>, and making the body of that method simply the entire source expression, without ever looking at the type. Is it simply expected that an IQueryable provider will just silently not return any records not of the selected type?
So are the steps above incorrect in some way, or am I just not seeing how they result in the behavior observed at runtime?
It's not passing in null as the method - it's passing it in as the "target expression", i.e. what it's calling the method on. This is null because OfType is a static method, so it doesn't need a target.
The point of calling MakeGenericMethod is that GetCurrentMethod() returns the open version, i.e. OfType<> instead of OfType<YourType>.
Queryable.OfType itself isn't meant to contain any of the logic for omitting returning any values. That's up to the LINQ provider. The point of Queryable.OfType is to build up the expression tree to include the call to OfType, so that when the LINQ provider eventually has to convert it into its native format (e.g. SQL) it knows that OfType was called.
This is how Queryable works in general - basically it lets the provider see the whole query expression as an expression tree. That's all it's meant to do - when the provider is asked to translate this into real code, that's where the magic happens.
Queryable couldn't possibly do the work itself - it has no idea what sort of data store the provider represents. How could it come up with the semantics of OfType without knowing whether the data store was SQL, LDAP or something else? I agree it takes a while to get your head round though :)

Resources