Spring SpEL not compiling even when spring.expression.compiler.mode is set - java

I have a SpEL expression that I am trying to use for an FtpMessageHandler (specifically for outputHandler.setRemoteDirectoryExpressionString("headers['" + ftpOutPath + "']");).
Through debugging I have found that this SpEL expression is not getting compiled. When compilation time comes, SpelCompilerMode is set to OFF. So as a result the expression is not being compiled and just returning null (and my FTP client is trying to just write to the root directory instead of the one I am specifying).
Looking at the Spring SpEL documentation (https://docs.spring.io/spring/docs/5.3.0-SNAPSHOT/spring-framework-reference/core.html#expressions) , it says that in order to enable SpEL compilation you need to set the property spring.expression.compiler.mode. I have done this to no effect - I have set spring.expression.compiler.mode to immediate in my application.properties file, yet SpelCompilerMode is still OFF.
Why is this happening? How can I fix this?
I know someone will ask for a code sample but honestly I have no idea what I can provide as this is all stuff internal to Spring. But here are some samples of related code:
The FtpMessageHandler:
#Value("${my.ftp.outPath}")
private String ftpOutPath;
#Bean
#ServiceActivator(inputChannel = "myChannel")
public MessageHandler getOutputHandle(){
FtpMessageHandler outputHandler = new FtpMessageHandler(mySessionFactory());
outputHandler.setRemoteDirectoryExpressionString("headers['" + ftpOutPath + "']");
return outputHandler;
}
application.yaml
spring:
expression:
compiler:
mode: immediate
my:
ftp:
outPath: myPath

I still am not sure why the expression was not compiling / intrepreting properly, however changing the code to use LiteralExpression worked instead of using the String.
outputHandler.setRemoteDirectoryExpression(new LiteralExpression(ftpOutPath));

Related

Path variable having special characters like # in Spring boot

I'm using Spring Boot 2.4.6. For delete APIs getting 405 method not found. My endpoint is like: beauty/v1/sites/addressTemplates/:templateId
Path variable: ##$%#
Can someone please suggest what can be done to make this behavior as not complaining for 405? Please direct me to other questions in case I'm missing something.
I guess that your issue has nothing to do with Spring. Maybe you are trying to compose the whole URL by using reserved characters.
In a URL, a hash mark, number sign, or pound sign ( # ) points a browser to a specific spot in a page or website. It is used to separate the URI of an object from a fragment identifier. Source.
Which means that an URL which looks like:
beauty/v1/sites/addressTemplates/##$%#
is not exactly what you imagine it to be because # is interpreted in a special way. What you have to do is to percent encode the "special" path variable so it will look like this at the end:
beauty/v1/sites/addressTemplates/%23%40%24%25%23
Then Spring will not complain anymore and will resolve properly the endpoint.

Azure Custom Vision Parameter this.client.endpoint() is required and cannot be null

I'm trying to get a basic Custom Vision image classifier working by following the tutorial in the Azure documentation found here: https://learn.microsoft.com/en-us/azure/cognitive-services/custom-vision-service/quickstarts/image-classification?pivots=programming-language-java
I have followed this tutorial word for word and have spent a couple days trying to work this out. The issue I am having is when running the code I am getting the following stack trace:
Parameter this.client.endpoint() is required and cannot be null.
java.lang.IllegalArgumentException: Parameter this.client.endpoint() is required and cannot be null.
at com.microsoft.azure.cognitiveservices.vision.customvision.training.implementation.TrainingsImpl.createProjectWithServiceResponseAsync(TrainingsImpl.java:2313)
at com.microsoft.azure.cognitiveservices.vision.customvision.training.implementation.TrainingsImpl$TrainingsCreateProjectParameters.execute(TrainingsImpl.java:2401)
at com.microsoft.azure.cognitiveservices.vision.customvision.samples.CustomVisionSamples.ImageClassification_Sample(CustomVisionSamples.java:67)
at com.microsoft.azure.cognitiveservices.vision.customvision.samples.CustomVisionSamples.runSample(CustomVisionSamples.java:46)
at com.microsoft.azure.cognitiveservices.vision.customvision.samples.CustomVisionSamples.main(CustomVisionSamples.java:374)
The endpoint is defined here and passed as a parameter
final String Endpoint = System.getenv("AZURE_CUSTOMVISION_ENDPOINT");
CustomVisionTrainingClient trainClient = CustomVisionTrainingManager.authenticate("https://{Endpoint}/customvision/v3.0/training/", CustomVisionTrainingClientKey).withEndpoint(Endpoint);
CustomVisionPredictionClient predictClient = CustomVisionPredictionManager.authenticate("https://{Endpoint}/customvision/v3.0/prediction/", predictionApiKey).withEndpoint(Endpoint);
While the tutorial doesn't explicitly state to do so I have tried to set the system environment variable AZURE_CUSTOMVISION_ENDPOINT manually with PowerShell and it doesn't work with or without this set.
Am I missing something? Any help would be greatly appreciated!
Fixed my own issue. The environment variables had not set correctly and were null pointers. I replaced the System.getenv call to the string in plain text and this is working correctly.

Using Async-IO of servlet3.1 with Spring

How to use Async-IO(setWriteListener) of Servlet3.1 with Spring-5 ?
Also, I found Link-A which mentions one needs to add Listener to outputStream.
On other hand Link-B says it should work with spring 5 and tomcat 8.5+.
Next I profiled a JVM and found that CoyoteOutputStream.checkNonBlockingWrite always return false with both deferredResult and NON-DeferredResult sample code.
//MY TEST CODE
#GetMapping("/health")
public DeferredResult<DummyDTO> upNRuning(){
DeferredResult<DummyDTO> defferedResult = new DeferredResult<>();
newCachedThreadPool.submit(() ->
defferedResult.setResult(new DummyDTO()));
return defferedResult;
}
I was not able to try Link-A recommandation as i am not sure of NioReadListener implementation and its arguments.
PS:
Environment Spring-boot-2.0.4.RELEASE + Windows

Can't use MySql for Spring Greenhouse project?

I just checked out the Spring Greenhouse project as a first step to learn Spring Security.
The project works fine but I was wondering about the following scenarios:
There are two configurations: standard and embedded. The javadoc says the embedded is default. I am not sure how to make it run in standard mode. Has anybody has tried this before?
Secondly in embedded mode I modified the code slightly with the following code to run it with MySql but to my surprise the application is not starting up at all. It throws the following error:
throw new RuntimeException("Unable to determine database version", e);
#Bean(destroyMethod="shutdown")
public DataSource dataSource() {
// EmbeddedDatabaseFactory factory = new EmbeddedDatabaseFactory();
// factory.setDatabaseName("greenhouse");
// factory.setDatabaseType(EmbeddedDatabaseType.);
DriverManagerDataSource mysqldataSource = new DriverManagerDataSource();
mysqldataSource.setDriverClassName("com.mysql.jdbc.Driver");
mysqldataSource.setUrl("jdbc:mysql://localhost/greenhouse?useConfigs=maxPerformance&characterEncoding=utf8");
mysqldataSource.setUsername("root");
mysqldataSource.setPassword("mysql");
return populateDatabase(mysqldataSource);
}
Can anybody please help me on this?
I figured it out by myself.
There was a tag in web.xml and i changed there from embedded to standard.
The problem was in the sql query which was creating the database version table was not mysl complaint. There were other queries also which were not mysql complaint. I changed the sql query and now eveything worked like as expected. The next thing I am gonna do is use some kind og generic database query generator so that i don't have to change the query if in future I change my mind to use post gre sql in place of my sql.
Thank you for all your help and support.
Judging by the exception you're getting, the file you're interested in is GenericDatabaseUpgrader.java
More than half the code there refers to DatabaseVersion which is a table that is created if absent.
Since I doubt you already have it and judging by the exception type (SQLException), I'm inclined to say it's failing to create/insert/retrieve the referenced table.
You can check if you have the table and go from there.
Also, judging by the code you're trying to inject, I'd also look at connection = dataSource.getConnection() as a possible culprit.
P.S. Regarding standard/embedded, it appears you can VM parameters or maven settings to switch between the two. Please check the official forums and specifically this topic for info

Java Play Mustache NPE Error

We are getting a mustache play error in production (amazon linux EC2 AMI) but not in development (MACs) and we have tried upgrading the jvm, using the jdk instead, and changing from a tomcat deploy model to match our development environments as much as possible but nothing is working. Please any help would be greatly appreciated. We have lots of shared code in java and javascript using mustache and it would be a big deal to rewrite everything if we had to ditch mustache on the java side.
20:48:52,403 ERROR ~
#6al2dd0po
Internal Server Error (500) for request GET /mystuff/people
Execution exception (In {module:mustache-0.2}/app/play/modules/mustache/MustacheTags.java around line 32)
NullPointerException occured : null
play.exceptions.JavaExecutionException
at play.templates.BaseTemplate.throwException(BaseTemplate.java:90)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:257)
at play.templates.Template.render(Template.java:26)
at play.templates.GroovyTemplate.render(GroovyTemplate.java:187)
at play.mvc.results.RenderTemplate.<init>(RenderTemplate.java:24)
at play.mvc.Controller.renderTemplate(Controller.java:660)
at play.mvc.Controller.renderTemplate(Controller.java:640)
at play.mvc.Controller.render(Controller.java:695)
at controllers.MyStuff.people(MyStuff.java:183)
at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:548)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:502)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:478)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:473)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:161)
at Invocation.HTTP Request(Play!)
Caused by: java.lang.NullPointerException
at play.modules.mustache.MustacheTags._template(MustacheTags.java:32)
at play.modules.mustache.MustacheTags$_template.call(Unknown Source)
at /app/views/User/people.html.(line:22)
at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:232)
... 13 more
Seems the issue is with the threadlocal. In Prod as per my logs, the session gets initialized with the main thread.
[2012-06-30 18:35:38,102] INFO 10097[**main**] - Mustache module initialized
However, MustacheTag tries to access with various thread like this during request.
[2012-06-30 17:48:44,669] INFO 66048[**play-thread-1**] - [{module:mustache-0.2}/app/play/modules/mustache/MustacheTags.java:46] _meta() :: MustachePlugin.session():null
So I changed the implementation of MustachePlugin like this.Changed line commented out:
//private static ThreadLocal<MustacheSession> session_ = new ThreadLocal<MustacheSession>();
private static MustacheSession _session = null;
public static MustacheSession session(){
//return session_.get();
return _session;
}
public void onConfigurationRead(){
// some code
_session = new MustacheSession(compiler, root);
// some code
}
And it is working fine now in prod mode! I see no reason why it should have been in a ThreadLocal in the first place as the session gets initialized at startup!
your issue is difficult to reproduce so i'll give few pointers here. you have tried to eliminate of issue being env issue. so other possible issues could be
data issue: many times reason for production issue is usually difference in actual data and test data. check if its data issue which is casuing NPE.
code issue: Is there something at people.html.(line:22) causing issue. first try removing / altering that to check if thats causing issue. Or can you get source code of mustache (exact version which you are using) and see what object its trying to create and where its failing.
Properties file for different environments: do you have different proprties file for each env? If yes, have u missed on any property for prod env?
You have a NullPointerException on MustacheTags.java at line 32.
This means that you are probably calling a method of the Mustache library and passing a null value.
Try logging all the parameters you transfer to this method (MyStuff.java line 183?).
You can look at the source code of MustacheTags here, it might help you understand what values you are passing and what should be passed.

Categories