Spring Boot - SpEL - Check List Contains - #ConditionalOnExpression - spring

Given that I have the following properties:
values[0]=A
values[1]=B
values[2]=C
I need to check that values contains A in a #ConditionalOnExpression annotation. As of yet, I have not found an example of how to do it. I have tried this, but it does not work:
#ConditionalOnExpression("${values}.contains('A')")
It results in:
java.lang.IllegalStateException: Failed to load ApplicationContext

You need $ expresion surrounded by single quotes
#ConditionalOnExpression("'${values}'.contains('A')")

Related

How to autowire 2 symfony services, which use the same interface and addtional arguments

I have two services, which both use the same interface and one is injected in the other.
With this configuration in the service.yaml everything worked well:
# fix autowiring for 2 services using the same interface
App\Domain\ListService: ~
App\Domain\SapService\SapListService: ~
App\Domain\ListService $sapListService: '#App\Domain\SapService\SapListService'
App\Domain\ListServiceInterface: '#App\Domain\ListService'
following the official documentation found here.
Now one of my services needs the information in which environment the class is currently running.
In a simple service configuration I would write it like this:
App\Service\FooService:
arguments:
$env: '%env(APP_ENV)%'
But how do I add the environment information in my more complex situation?
I tried this:
App\Domain\ListService: ~
App\Domain\SapService\SapListService: ~
App\Domain\ListService $sapListService: '#App\Domain\SapService\SapListService'
arguments:
$env: '%env(APP_ENV)%'
App\Domain\ListServiceInterface: '#App\Domain\ListService'
which throws this error:
The file "/var/www/src/../config/services.yaml" does not contain valid YAML: Unable to parse at line 52 (near " arguments:").
What is the proper formatting to parse the environment information into my service?
I tried manual wiring like this:
public function __construct(
ListServiceInterface $sapListService,
#[Autowire('%env(APP_ENV)%')]
string $env
) {
$this->sapListService = $sapListService;
$this->env = $env;
}
which gives me the error:
In DefinitionErrorExceptionPass.php line 54:
Cannot autowire service "App\Domain\ListService": argument "$env" of method "__construct()" is type-hinted "string", you should configure its
value explicitly.
Looks like the Autowire annotation is only available with symfony 6
You should use the namespace in the redis config to separate the different environments and not use the APP_ENV var to create the keys to store.
I guess the best solution is to prefix the cache key with the environment via the cache configuration in the cache.yaml file.
The solution is described here

getting Could not resolve placeholder while reading yml values in spring boot

I'm using spring boot and using this value in my application.yml
config:
username: abc
password: xyz
In my class, I'm utilizing it this way -
#Value("${config.username}")
private String username;
I'm getting the following error -
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'config.username' in value "${config.username}"
However if I use this in my application.yml file, it works. Can you please tell me what I'm doing wrong here?
config.username: abc
config.password: xyz
check your placeholder is Tab or Space ? make sure no Tab in your yml file.
was facing the same problem when trying to read from application.yml file instead of application.properties file. maven clean & then maven install resolved the issue for me.

logging.level.root doesn't work in springboot

I want to setting the default logging level to error on springboot
enter image description here
But the console still has the dubug and info output. It seems that logging.level.root=error doesn't work.
Be carefull if you are using Spring Boot Devtools, the properties defined in $HOME/.config/spring-boot folder will override all other properties as specified in Spring Boot documentation : https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html
I found a environment variable named debug,even though its value is a string not true,which caused the problem.Actually,I tried to remove the variable before,but I didn't restart the eclipse.Now,I remove the varibale named DEBUG and restart the eclipse,and it success.

Spring Spel XPATH Expression for Namespace but no prefix

Issue: Trying to build the correct XPATH using SpEL xpath to correlate on a the "Name" tag value where the root tag has a namespace but no prefix.
Error: Unexpected token. Expected 'rparen())' but was 'identifier'
It's complaining about & #39; where I am trying to make a single quote for the xpath evaluation.
XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns="http://www.foo.com">
<id></id>
<Name>test</Name>
</root>
Spring Config
<aggregator
id="agg1"
input-channel="requestChannel"
output-channel="outputChannel"
discard-channel="garbageCanChannel"
ref="blah"
method="combine"
expire-groups-upon-completion="true"
correlation-strategy-expression="#xpath(payload, '//*[local-name()]='Name'/text()')"
release-strategy="blah"
release-strategy-method="timeToRelease"
send-partial-result-on-expiry="false"
send-timeout="60000"
group-timeout="60000"
/>
Update:
So after downloading spring source and tracing the issue. It's seem that during the tokenization execution in the method below, Spring is treating the "Name" as a identifier instead of as part of the string literal. At least this is the difference between a working instance and a failing instance.Most likely i'm not escaping it correctly.
Class:InternalSpelExpressionParser.java
Method:doParseExpression
this.expressionString = "#xpath(payload, '//*[local-name()=Name]')"//This works
[[HASH(#)](0,1), [IDENTIFIER:xpath](1,6), [LPAREN(()](6,7), [IDENTIFIER:payload](7,14), [COMMA(,)](14,15), [LITERAL_STRING:'//*[local-name()=Name]'](16,45), [RPAREN())](45,46)]
this.expressionString = "#xpath(payload, '//*[local-name()='Name']')"//Thisfails
[[HASH(#)](0,1), [IDENTIFIER:xpath](1,6), [LPAREN(()](6,7), [IDENTIFIER:payload](7,14), [COMMA(,)](14,15), [LITERAL_STRING:'//*[local-name()='](16,35), [IDENTIFIER:Name](35,44), [LITERAL_STRING:']'](44,47), [RPAREN())](47,48)]
Solution:
...
correlation-strategy-expression="#xpath(payload, '//*[local-name()=''Name'']/text()')"
Correct String Literal:
-You can see that it is now correct because the tokenization process is putting everything within the string literal token.
[[HASH(#)](0,1), [IDENTIFIER:xpath](1,6), [LPAREN(()](6,7), [IDENTIFIER:payload](7,14), [COMMA(,)](14,15), [LITERAL_STRING:'//*[local-name()=''Name'']/text()'](16,56), [RPAREN())](56,57)]
Additional Debug Notes:
When pulling out the spring git here:
https://github.com/spring-projects/spring-framework
Take all of the projects.
At the root is "import=into-eclipse.bat" or "import-into-idea" that I did not see. You can execute that to fully build and check-out everything you need locally and import the projects so you can trace a issue.
Your expression as posted will produces invalid XPath. It should have closing square bracket just before /text() instead :
'//*[local-name()='Name']/text()'
Or maybe using double single-quotes to escape, as suggested here :
'//*[local-name()=''Name'']/text()'

How do I load ${catalina.home}/conf/application.properties in a Spring / Tomcat webapp?

How do I load ${catalina.home}/conf/application.properties in a Spring / Tomcat webapp?
Looking around on StackOverflow and Google I see many discussions which claim it's possible. However, it's just not working for me. In line with the advice from my research my Spring applicationContext.xml file contains the following line:
<context:property-placeholder location="${catalina.home}/conf/application.properties"/>
But I get this in the logs:
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/Users/username/Servers/apache-tomcat-6.0.36/conf/application.properties]
From the log entry I can see that ${catalina.home} is expanding correctly. When I expand it by hand in the applicationContext.xml file it returns the same error. The following returns the contents of the application.properties file as expected:
cat /Users/username/Servers/apache-tomcat-6.0.36/conf/application.properties
So the path is clearly correct. Is this a webapp security or Tomcat server configuration issue?
The location of a context:property-placeholder is a Resource, which means that if you provide just a file path (as opposed to a full URL with a protocol) then the path will be resolved against the base directory of the webapp - it is trying to load /Users/username/Servers/apache-tomcat-6.0.36/webapps/<appname>/Users/username/Servers/apache-tomcat-6.0.36/conf/application.properties, which does not exist. If you prefix it with file: it'll work as you require:
<context:property-placeholder location="file:${catalina.home}/conf/application.properties"/>
For annotation based configuration you can use:
#PropertySource("file:${catalina.home}/conf/application.properties")

Resources