I have a Spring boot application which consists of a scheduled task and a rest controller. The scheduled task connects to Gmail with Javamail to parse certain emails and store them in a MongoDB database and the controller is to query that data in the databse.
I am deploying this application in GKE. When I do, I see the following log messages and my task does not run:
The controller is accessible but as you can see the application starts but then the taskScheduler executor service shuts down. I can't find information in the logs about why this is happening. When I run it locally it works, so I thought it could be related to Docker, but I ran the application from a Docker container (also locally) and it worked as well.
I have another spring boot application that runs some scheduled tasks deployed on GKE and working the only difference is that it does not expose any rest controllers.
Do you have any idea what might be the cause of this issue?
Here's my main class
#EnableScheduling
#EnableMongoRepositories
#SpringBootApplication
public class EmailApplication {
public static void main(String[] args) {
SpringApplication.run(EmailCheckerApplication.class, args);
}
}
Here's my scheduled task. This does not run at all.
#Scheduled(fixedDelay = 60000) // I also tried with #Scheduled(cron = "0 */1 * * * *")
public void checkEmails() {
try {
//connects to Gmail
Message[] messages = getMessages();
//parse emails & store them in DB
closeAll();
} catch (Exception e) {
LOGGER.finest("Error Parsing emails: " + e.getMessage());
}
}
Here's my Dockerfile
FROM adoptopenjdk/openjdk13:jre-13.0.2_8-alpine
COPY build/libs/email-checker-0.0.1.jar /tmp
RUN chmod 744 /tmp/email-checker-0.0.1.jar
CMD ["java", "-jar", "-Dspring.profiles.active=${SPRING_PROFILES_ACTIVE}", "/tmp/email-checker-0.0.1.jar"]
Here's my dependencies in build.gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation group: 'javax.mail', name: 'mail', version: '1.4.7'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '2.4.2'
compile group: 'org.springframework.data', name: 'spring-data-mongodb', version: '3.1.3'
compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-mongodb', version: '2.4.2'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Edit
Weird, if I run kubectl logs -n service <pod-name> -f
I don't see the log messages of the ExecutorServices shutting down, but I don't see the log messages of the scheduled task either.
Here's the last log messages
I solved the issue. Actually there were two issues, but the main one is that when my application was trying to connect to Gmail, it was throwing an exception saying that Web login was required. So I realized that Spring boot was ignoring LOGGER.finest in my catch block. I was able to spot that first by adding a bunch of LOGGER.info before every single line of code in my scheduled task and then changing LOGGER.finest to LOGGER.info.
So to solve the main issue I followed some suggestions in this SO question and to solve the issue with LOGGER.finest I added the property logging.level.my-package=DEBUG in my application.properties (change my-package to a package in your application you want to set the log level to). If you have different profiles for lower environments and production, you can set it to ERROR in the production profile.
Related
Trying to import the Play Json Library with Gradle 7 to be used in Gatling Scala code plugin 3.8.3.2. It seems to be the finest tool to work Json in this context. I get this error not found: object play at the line where the import play.api.libs.json._ is.
Altought the Official Play Readme indicates that compile group: 'com.typesafe.play', name: 'play-json_2.13', version: -version- should be used, it does not work.
Any idea on how to make the Play Library available?
The key is the gatling configuration that generally is placed in gradle.build:
gatling {
// WARNING: options below only work when logback config file isn't provided
logLevel = 'WARN' // logback root level
logHttp = 'NONE' // set to 'ALL' for all HTTP traffic in TRACE, 'FAILURES' for failed HTTP traffic in DEBUG
enterprise {
// Enterprise Cloud (https://cloud.gatling.io/) configuration reference: https://gatling.io/docs/gatling/reference/current/extensions/gradle_plugin/#working-with-gatling-enterprise-cloud
// Enterprise Self-Hosted configuration reference: https://gatling.io/docs/gatling/reference/current/extensions/gradle_plugin/#working-with-gatling-enterprise-self-hosted
}
}
It is a default Gatling configuration to which you must refer when using Play's Framework Readme snippet, like this:
dependencies {
gatling 'com.google.code.gson:gson:2.8.0'
gatlingImplementation 'org.apache.commons:commons-lang3:3.4'
gatlingRuntimeOnly 'cglib:cglib-nodep:3.2.0'
}
So, in order to include the dependencies, you need to prepend gatling to the code provided in the Play Readme.
Here's my working gradle.build file:
plugins {
id 'scala'
id 'io.gatling.gradle' version '3.8.3.2'
}
gatling {
logLevel = 'WARN' // logback root level
logHttp = 'NONE' // set to 'ALL' for all HTTP traffic in TRACE, 'FAILURES' for failed HTTP traffic in DEBUG
}
repositories {
mavenCentral()
}
dependencies {
// https://mvnrepository.com/artifact/com.typesafe.play/play-json
gatlingImplementation group: 'com.typesafe.play', name: 'play-json_2.13', version: '2.9.2'
}
For Gatling scala specific
Updating the build.gradle file with gatling group dependency solved the issue
dependencies { gatling group: 'com.typesafe.play', name: 'play-json_2.13', version: '2.9.3' }
I created a module project using servicebuild template (gradebook-api, gradebook-service), but i have an error after an export package com.liferay.training.gradebook.validator in api below
Bundle-Name: gradebook-api
Bundle-SymbolicName: com.liferay.training.gradebook.api
Bundle-Version: 1.0.0
Export-Package: \
com.liferay.training.gradebook.exception,\
com.liferay.training.gradebook.model,\
com.liferay.training.gradebook.service,\
com.liferay.training.gradebook.service.persistence,\
com.liferay.training.gradebook.validator
-check: EXPORTS
-includeresource: META-INF/service.xml=../gradebook-service/service.xml
i have a problem in the BuildService gradle task that's says :
Some problems were found with the configuration of task
':modules:gradebook:gradebook-api:buildService' (type
'BuildServiceTask').
File 'C:\Liferay\ide-workspace\training-workspace\modules\gradebook\gradebook-api\service.xml'
specified for property 'inputFile' does not exist.
No value has been specified for property 'apiDir'.
And this is a how I add the api module as dependency in service.
dependencies {
compileOnly group: "com.liferay", name: "com.liferay.petra.io"
compileOnly group: "com.liferay", name: "com.liferay.petra.lang"
compileOnly group: "com.liferay", name: "com.liferay.petra.string"
compileOnly group: "com.liferay", name: "com.liferay.portal.aop.api"
compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel"
compileOnly group: "org.osgi", name: "org.osgi.annotation.versioning"
compileOnly group: "org.osgi", name: "org.osgi.core"
compileOnly group: "org.osgi", name: "org.osgi.service.component.annotations"
compileOnly group: "javax.portlet", name: "portlet-api"
compileOnly group: "javax.servlet", name: "javax.servlet-api"
compile project(":modules:gradebook:gradebook-api")
}
buildService {
apiDir = "../gradebook-api/src/main/java"
}
group = "com.liferay.training.gradebook"
I am trying to create new Liferay workspace but i got the same error (May be this is an error with Gradle)
Be sure, you run gradle task in the corresponding folder (in gradebook-service folder). I got similar error when I ran it in upper folder which contains api and service folder.
Until recently I have only worked on LR 7.0, but the last day or so have been playing with 7.3. I encountered the exact issue you describe.
The only solution I found was to copy service.xml from gradebook-service into the root of both my gradebook-api and gradebook-web modules and also add the following to the build.gradle files of both the gradebook-api and gradebook-web modules:
buildService {
apiDir = "../gradebook-api/src/main/java"
}
After that service builder ran successfully. There may be a cleaner way around it, but this worked for me.
service.xml should stay in service module only. Here, it look you need few checks.
api module dependency should be compileonly. not in compile
scope.
block order also matters in gradle file. move below block
at the top of the file.
buildService {
apiDir = "../gradebook-api/src/main/java"
}
not sure why you need -check:exports header in bnd file. As, that is not required normally.
In the Gradle task tab, go to your specific module service folder and then build it from there. Don't forget to refresh your gradle by pressing Cntrl+F5.
This Worked for me.
I had the same situation and just added the buildService{...} in build.gradle in the api module.
buildService {
apiDir = "../gradebook-api/src/main/java"
}
After: BUILD SUCCESSFUL
I want to exclude two jars from test and only use them when the application is actually running.
dependencies {
runtimeOnly('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')
runtimeOnly('org.springframework.cloud:spring-cloud-starter-config')
}
How do I explicitly tell Gradle 5 not to load these jars during the running of tests? I have already disabled their use but they keep getting loaded anyway. I was hoping for something simple like below, but I've been unable to find a conclusive answer.
test.exclude {
group 'org.springframework.cloud'
}
EDIT
Copy paste solution
configurations.testCompile.exclude(group: 'org.springframework.cloud', module: 'spring-cloud-starter-netflix-eureka-client')
configurations.testCompile.exclude(group: 'org.springframework.cloud', module: 'spring-cloud-starter-config')
Inside your dependencies block, you can do something like:
configurations.testCompile.exclude(group: 'the-group', module: 'the-module')
Hope this helps!
So, I have been trying to write JUnit tests for my APIs which interact with Elasticsearch. This is like Integration test where I need to setup Elasticsearch before I can run my code.
For all the tests, I need to create a test task which will do following:
Download the zip from
compile group: 'org.elasticsearch.distribution.zip', name: 'elasticsearch', version: '6.1.1', ext: 'pom'
Run elasticsearch executable present in /bin of unzipped file. When running this executable, take as argument elasticsearch.yml file in the command.
Once the all the tests are run, stop the elasticsearch executable, and clean the zipped folder.
Things that I can improve is that if zip file is already present in my gradle cache, then don't download it again and again.
Thanks
Add following dependency to your build.gradle file
configurations {
elasticDist
}
...
dependencies {
elasticDist group: 'org.elasticsearch.distribution.zip', name: 'elasticsearch', version: '6.1.2', ext: 'zip'
}
Add tasks to unzip and cleanup, setup dependencies
task unzip(type: Copy) {
// to download distribution
dependsOn configurations.elasticDist
from { // use of closure defers evaluation until execution time
configurations.elasticDist.collect { zipTree(it) }
}
into file("${buildDir}/your/destination")
}
task cleanElastic(type:Delete) {
delete file("${buildDir}/your/destination")
}
test.dependsOn('unzip')
test.finalizedBy('cleanElastic')
Using your test framework of choice, configure setUp and tearDown to start and stop elastic respectively.
I have a Configuration bean.
#Component
public class Config {
#Value("classpath:${app.file.name.srgbicc}")
public Resource icc;
#PostConstruct
void init(){
try {
tempdir = Files.createTempDir();
newIcc = copyIccFileToTemp();
}catch (IOException e){
throw new RuntimeException(e);
}
}
private File copyIccFileToTemp() throws IOException {
File tempIcc = new File(tempdir, icc.getFilename());
FileUtils.copyFile(icc.getFile(),tempIcc);
return tempIcc;
}
}
On icc.getFile() there is a FileNotFoundException
application.properties
app.file.name.srgbicc = sRGB.icc
I looked in my classpath and found the following situation:
build/classes/main (no icc file)
build/resources/main (icc file, application.properties)
When printed out my classpath during application start I only found ...myApp/build/classes/main.
No ../build/resources/main or ../src/main/resources entries there.
So I was wondering why is the resources not on the classpath?
according to http://docs.spring.io/spring-boot/docs/1.1.5.RELEASE/reference/htmlsingle/#build-tool-plugins-gradle-running-applications
this should be.
Of course if I put the icc file in build/classes/main its all working as expected, but it is not supposed to be there. right?
I tried to run the application with gradle run or gradle bootRun in intellij I use static main. The good thing is that the application fails consistently independent of how I start it.
My Project layout
myApp
src
main
java
pkg
Config.java
resources
sRGB.icc
application.properties
For the reference:
IntelliJ 13
spring-boot 1.1.5
Fgradle 2.0
Update
Here is a stripped down example of my code
https://gist.github.com/Vad1mo/bb5d23ca251341236fbd
I removed #PostConstruct in the config.init and run the application with gradle build all test are success when i rund from intellij the tests fail. this is strange that i know have different behavior
I solved the problem now.
What helped me was just to do a simple clean build and rebuild project in intellij. I was using to much eclipse and maven so I expected it to happen automagically.