Spring Boot "unable to resolve class" with Groovy - spring

I'm new to Groovy, Spring Boot, and Gradle (using gradle as well) and am trying to build a small test program.
I have a main class EvalMain and a InputObj class in a com.eval package.
#Controller
class EvalMain {
#RequestMapping("/")
#ResponseBody
public static String textTest() {
def iO = new InputObj("dsa", "dasdsa", "U1dBRw==");
return iO.xorString();
}
}
when running "spring run EvalMain.groovy" I get the following error:
startup failed:
file:<filepath>EvalMain.groovy: 14: unable to resolve class InputObj
# line 14, column 18.
def iO = new InputObj("dsa", "dasdsa", "U1dBRw==");
I tried throwing an import at the top but then spring boot complained about this too? What am I missing here? Any help would be much appreciated, thanks!
after adding the import:
import com.eval.InputObj;
I get this error:
file:/<filePath>/EvalMain.groovy: 2: unable to resolve class com.eval.InputObj
# line 2, column 1.
import com.eval.InputObj
^
1 error

Not sure if this is a good way to do it, but I was able to run it with "spring run .groovy .groovy" I wonder if there's the equivalent of a makefile?

Try to run spring run *.groovy.
Spring Boot CLI is for quick prototyping a single Groovy script. It tries to autoload all Spring Boot dependencies, but its your responsibility to include your additional dependencies
If you have just multiple source files you have to pass it to the CLI.
If it is an external dependency, include it with a #Grab, see here.
However, you have Gradle and more than one source file. Therefor it might be the time to switch from the Spring Boot CLI to a normal Gradle project.
Just go to the guides and choose "Build with Gradle". Then you will see an example Gradle build file. Also the Gradle Spring Boot plugin documentation provides samples.
You can start your application with gradlew bootRun.

Related

Spring Boot Application - Running jar file gives ResourceFinderException error

Created a jar file for a spring boot multimodule application and ran the jar file using java -jar command. While starting the application, it gives ResourceFinderException. When I analyzed it, the issue is happening because in my ResourceConfig file, i have used the package for my api end points. If I use register(service.class), the application starts fine. Any suggestion how can I provide the package instead of using register? The reason I want to use package is because I have lots of services inside multiple packages and the code looks very ugly if i use register for all the services. The ResourceConfig file looks like below.
public class AppResourceConfig extends ResourceConfig {
public AppResourceConfig {}{
super();
property("jersery.config.beanValidation.enableOutputValidationErrorEntity.server");
**packages("com.api");**
register(GsonProvider.class);
register(RequestContextFilter.class);
register(NotFoundExceptionMapper.class);
register(DefaultExceptionMapper.class);
}
}
Here the issue is with highlighted line: packages("com.api")
If I comment out this code application will be up. Otherwise it is giving org.glassfish.jersey.server.internal.scanning.ResourceFinderException: java.io.FileNotFoundException: api-01.03.00.04-snapshot.jar (No such file or direcotry)
Note: api-01.03.00.04-snapshot.jar is the jar file for one of the module in a project

How to pass spring.config.location="somepath" while building SpringBoot application with command-line Gradle (6.4) build

I have a SpringBoot application where I have application.properties file outside of project (it's not in usual place src/main/resources).
While building application with gradle clean build, it fails as code is not able to find properties files.
I have tried many command to pass vm args, gradle opts but its not working.
gradle clean build -Djvmargs="-Dspring.config.location=/users/home/dev/application.properties" //not working
It fails on test phase when it creates Spring application context and not able to substitute property placeholders. If I skip test as gradle clean build -x test it works.
Though I can run the app with java -jar api.jar --spring.config.location=file:/users/home/dev/application.properties
Please help how I can pass spring.config.location=/users/home/dev/application.properties in gradle build using command line so that build runs with all Junit tests
If I were you, I would not get involved the actual properties to junit test. So I would create a test properties for the project under src/test/resources/application-test.properties and in junit test I would load the test properties.
Example:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = MyProperties.class)
#TestPropertySource("classpath:application-test.properties")
public class MyTestExample{
#Test
public void myTest() throws Exception {
...
}
}
System properties for running Gradle are not automatically passed on to the testing framework. I presume this is to isolate the tests as much as possible so differences in the environment will not lead to differences in the outcome, unless explicitly configured that way.
If you look at the Gradle API for the Test task, you can see that you can configure system properties through through the systemProperty method on the task (Groovy DSL):
test {
systemProperty "spring.config.location", "/path/to/my/configuration/repository/application.properties"
}
If you also want to read a system property from the Gradle command line and then pass that the test, you have to read it from Gradle first, e.g. as a project property, and then pass that value to the test:
test {
if (project.hasProperty('testconfig')) {
systemProperty 'spring.config.location', project.getProperty('testconfig')
}
}
Run it with gradle -Ptestconfig="/path/to/my/configuration/repository/application.properties" build
However, I would discourage using system properties on the build command line if you can avoid it. At the very least, it will annoy you greatly in the long run. If the configuration file can be in different locations on different machines (depending on where you have checkout out the repository and if it is not in the same relative path to your Spring Boot repository), you may want to specify it in a personal gradle.properties file instead.
I think there is a misunderstanding.
spring.config.location is used at runtime
As you validated:
java -jar api.jar --spring.config.location=file:/users/home/dev/application.properties
spring.config.location is used or required at runtime, not at build time.
When your spring boot app is building, an application.properties is required. An approach could be use an src/main/resources/application.properties with template values, but at runtime you will ignore it spring.config.location=file...
For unit tests
In this case as #nikos-bob said, you must use another properties, commonly inside of your src/test/resources
Environment variables instead external properties
We don't want to have hardcoded values in our main git repository src/main/resources/application.properties so the first idea is use an external properties. But this file must be stored in another git repository (equal to main repository ) or manually created.
Spring and other frameworks give us an alternative: Use environment variables.
So instead of manually external creation of application.properties or store it in our git repository, your spring boot app always must have an application.properties but with environment variables:
spring.datasource.url=jdbc:oracle:thin:#${DATABASE_HOST}:${DATABASE_PORT}:${DATABASE_SID}
spring.datasource.username=${DATABASE_USER}
spring.datasource.password=${DATABASE_PASSWORD}
spring.mail.host = ${MAIL_HOST}
spring.mail.username =${MAIL_USERNAME}
spring.mail.password =${MAIL_PASSWORD}
Advantages:
No manually creation of application.properties allowing us a more easy devops automations
No spring.config.location=file.. is required

About Integrate Clojure into springboot framework

I'm currently trying to integrate clojure into gradle springboot project, even though it works, I do have to use RT.loadClassForName("au.edu.uq.core"); before the Clojure.var could access the function, if I comment the RT.loadClassForName("au.edu.uq.core");, there will be an error like:
Exception in thread "main" java.lang.IllegalStateException: Attempting to call unbound fn: #'au.edu.uq.core/hello-from-clojure.
But in the build.gradle I already include classes.dependsOn compileClojure.
There are screenshots of build.gradle, Main Java Class and the clojure namespace. This is a tiny demo project for me to learn gradle, any suggestions to make this build process more elegant?
Starting script is ./gradlew bootRun and ./gradlew run
//This is the Java Main Class
//This is the clojure namespace
//This is the build.gradle
From what I got from the screenshot of the Main class, it seems you are using Clojure.lang.RT to load your function, while the official reference documentation suggests otherwise:
Functions in clojure.core are automatically loaded. Other namespaces
can be loaded via require:
IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("clojure.set"));
My suggestion would be to try something like:
IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("au.edu.uq.core"));
IFn helloFunction = Clojure.var("au.edu.uq.core", "hello-from-clojure");
helloFunction.invoke();

How to pass maven variable to springboot application

I want to pass variable from maven command line to spring boot main class,but i have no idea,here is my maven pom file:
<properties>
<maven.tomcat.home>Here should add argument from command line</maven.tomcat.home>
</properties>
Here is my spring boot main class:
#PropertySource(value ={"file:#maven.tomcat.home#/em/easymobile-application.properties"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
So when i run maven by command line as below ,the application will deploy as war file to tomcat
mvn clean install -Dmaven.tomcat.home=/usr/local/apache-tomcat-8.0.33/webapps
Then i start up tomcat,the error says easymobile-application.properties is not found,so do you know how to load the easymobile-application.properties from maven command line using #PropertySource or something else.Thanks!!
I don't think that's the right approach, assuming at some point you get that to work, what happens if you need / have to deploy the webapp to /usr/local/apache-tomcat-8.0.xx? Would you need to compile the artifact again? That's not good. A better approach is to only produce 1 binary / artifact that could be deployed / installed in every environment: staging / prod / etc..
Like mentioned before, if the app needs files path configuration, I would suggest to use a config properties file instead of a Maven property.
Thanks! I have solved the problem using a simple way ,i just add the path of the folder which contains application.properties in tomcat\bin\catalina.sh
CLASSPATH=:/usr/local/apache-tomcat-8.0.33
the #PropertySource points to "classpath:em/easymobile-application.properties"

Running Spring Batch jobs from the command line

I don't know how to call a Job defined in Spring Batch using CommandLineJobRunner, documentation details are not enough for me.
I've followed the Spring Batch official guide to write Jobs in Spring Batch using Java annotations e.g. #EnableBatchProcessing because I wanted to avoid XML configuration files for the description of the job, the steps, etc.
So far I have:
a configuration class (com.package.bla.bla.ClassContainingTheBatchConfiguration see below) where I've put all the stuff defining ItemReader, ItemProcessor, ItemWriter, Job, and Step (with return jobs.get("nameOfTheJob") see below) using a #Bean annotaion.
a class with a main method with SpringApplication.run(...) and and annotation with #ImportResource("classpath:META-INF/spring/applicationContext.xml") to import some beans I need when processing the data in the Job.
On the Maven side I am currently using some plugins:
maven-jar-plugin specifying <addClasspath>true</addClasspath> and the class containing the main method in the tag <mainClass>
maven-assembly-plugin because I would like a unique executable jar containing all the stuff in the dependencies, I am using <phase>package</package> to be able to build the jar in the package phase, I am also using <goal>single</goal> to be able to properly build the jar using the assembly
maven-compiler-plugin specifying I am using Java 1.7
I think I've configured all the things I need to configure, however after having a Maven BUILD SUCCESS I am not able to run the job from the command line:
java -cp ./target/JAR_FILE_NAME.jar org.springframework.batch.core.launch.support.CommandLineJobRunner com.package.bla.bla.ClassContainingTheBatchConfiguration nameOfTheJob
Is throwing IOException due to the java.io.FileNotFoundException regarding com.package.bla.bla.ClassContainingTheBatchConfiguration. How should I specify the parameters in the command line in order to get the Job executed?
If you are already using SpringApplication from Spring Boot, why not finish the job and use #EnableAutoConfiguration as well, and also the Maven plugin (see for example this guide)? That way you will get something working pretty quickly and you can always add your own features later.
If the first argument to the CommandLineJobRunner is your #Configuration FQCN instead of a resource path, the ClassPathXmlApplicationContext constructor that's called from the CommandLineJobRunner's start() method will break.
int start(String jobPath, String jobIdentifier, String[] parameters, Set<String> opts) {
ConfigurableApplicationContext context = null;
try {
context = new ClassPathXmlApplicationContext(jobPath);
If you've already written a class with a main(), that replaces the CLJR, you shouldn't be passing CLJR as the class name in the command line. Pass that instead.
dont use spring.batch.job.enabled=false
then run using java -jar [jar-files] --spring.batch.job.names=[job-name]

Resources