Gracefully Shutdown Spring Boot Application from Shell Script - java

I have a spring boot application which I run using an executable jar file. Currently to stop the service we are just killing the process. I saw that we can use the following methods to shutdown the application gracefully.
ApplicationContext ctx = SpringApplication.run(Application.class, args);
and then somewhere in the code I can call ctx.close() Or we can use the following static method.
SpringApplication.exit(ApplicationContext, ExitCodeGenerator)
It works for us currently, but we are actually calling this ctx.close() method inside a controller as follows.
#RequestMapping("/shutdownSpringBoot")
public void shutdownApplication() {
MyApplication.ctx.close(); // I'm saving the context returned by spring boot in a static variable inside my main class
}
When we hit this controller method via http the application is gracefully shutdown. But we dont want to do it this way. Is it possible to write a shell / batch script to trigger the java class inside which I can call the ctx.close() method ? We are looking for a shutdown script like the one we get from a standalone tomcat container (shutdown.bat / shutdown.sh), so that we can give our application as a jar file to our customers and they can start or stop the application by executing those scripts. (Which they are used to).
Thanks,
Sanjay

I think you can simply detect that you are running your jar as a command line utility by inspecting command line parameters and instead of loading whole Spring context and booting up the web application, you just HTTP access the local shutdownSpringBoot URL using built-in Java HTTP client.

You can create a shell script and directly shutdown the springboot application. Just make sure you register shutdown hook to your spring boot application. In the shutdown hook, you can close the context. You can check my answer here

I use PID file writer to write file and store Jar and Pid in folder with same name as of application name and shell scripts also have same name with start and stop in the end.
Main Class
#SpringBootApplication
public class MyApplication {
public static final void main(String[] args) {
SpringApplicationBuilder app = new SpringApplicationBuilder(MyApplication.class);
app.build().addListeners(new ApplicationPidFileWriter());
app.run();
}
}
YML FILE
spring.pid.fail-on-write-error: true
spring.pid.file: /server-path-with-folder-as-app-name-for-ID/appName/appName.pid
Here is the start script(start-appname.sh):
shellScriptFileName=$(basename -- "$0")
shellScriptFileNameWithoutExt="${shellScriptFileName%.*}"
appName=${shellScriptFileNameWithoutExt:6}
PROCESS=$1
PIDS=`ps aux |grep [j]ava.*$appName.*jar | awk {'print $2'}`
if [ -z "$PIDS" ]; then
echo "No instances of $appName is running..." 1>&2
else
for PID in $PIDS; do
echo "Waiting for the process($PID) to finish on it's own for 3 mins..."
sleep 3m
echo "FATAL:Killing $appName with PID:$PID."
kill -9 $PID
done
fi
# Preparing the java home path for execution
JAVA_EXEC='/usr/bin/java'
# Java Executable - Jar Path Obtained from latest file in directory
JAVA_APP=$(ls -t /server-path-with-folder-as-app-name/$appName/$appName*.jar | head -n1)
# JVM Parameters and Spring boot initialization parameters
JVM_PARAM="-Xms512m -Xmx1024m -Dspring.profiles.active=sit -Dcom.webmethods.jms.clientIDSharing=true"
# To execute the application.
FINAL_EXEC="$JAVA_EXEC $JVM_PARAM -jar $JAVA_APP"
# Making executable command using tilde symbol and running completely detached from terminal
`nohup $FINAL_EXEC </dev/null >/dev/null 2>&1 &`
echo "$appName has been started successfully."
Here is the stop script(stop-appname.sh):
shellScriptFileName=$(basename -- "$0")
shellScriptFileNameWithoutExt="${shellScriptFileName%.*}"
appName=${shellScriptFileNameWithoutExt:5}
# Script to stop the application
PID_PATH="server-path-with-folder-as-app-name-for-PID/$appName/$appName.pid"
if [ ! -f "$PID_PATH" ]; then
echo "Process Id FilePath($PID_PATH) Not found"
else
pid=`cat $PID_PATH`
if [ ! -e /proc/$pid -a /proc/$pid/exe ]; then
echo "$appName was not running.";
else
kill $pid;
echo "Gracefully stopping $appName with PID:$pid..."
fi
fi

Related

Shutdown Spring MVC App that was run on CMD [duplicate]

In the Spring Boot Document, they said that 'Each SpringApplication will register a shutdown hook with the JVM to ensure that the ApplicationContext is closed gracefully on exit.'
When I click ctrl+c on the shell command, the application can be shutdown gracefully. If I run the application in a production machine, I have to use the command
java -jar ProApplicaton.jar. But I can't close the shell terminal, otherwise it will close the process.
If I run command like nohup java -jar ProApplicaton.jar &, I can't use ctrl+c to shutdown it gracefully.
What is the correct way to start and stop a Spring Boot Application in the production environment?
If you are using the actuator module, you can shutdown the application via JMX or HTTP if the endpoint is enabled.
add to application.properties:
Spring Boot 2.0 and newer:
management.endpoints.shutdown.enabled=true
Following URL will be available:
/actuator/shutdown - Allows the application to be gracefully shutdown (not enabled by default).
Depending on how an endpoint is exposed, the sensitive parameter may be used as a security hint.
For example, sensitive endpoints will require a username/password when they are accessed over HTTP (or simply disabled if web security is not enabled).
From the Spring boot documentation
Here is another option that does not require you to change the code or exposing a shut-down endpoint. Create the following scripts and use them to start and stop your app.
start.sh
#!/bin/bash
java -jar myapp.jar & echo $! > ./pid.file &
Starts your app and saves the process id in a file
stop.sh
#!/bin/bash
kill $(cat ./pid.file)
Stops your app using the saved process id
start_silent.sh
#!/bin/bash
nohup ./start.sh > foo.out 2> foo.err < /dev/null &
If you need to start the app using ssh from a remote machine or a CI pipeline then use this script instead to start your app. Using start.sh directly can leave the shell to hang.
After eg. re/deploying your app you can restart it using:
sshpass -p password ssh -oStrictHostKeyChecking=no userName#www.domain.com 'cd /home/user/pathToApp; ./stop.sh; ./start_silent.sh'
As to #Jean-Philippe Bond 's answer ,
here is a maven quick example for maven user to configure HTTP endpoint to shutdown a spring boot web app using spring-boot-starter-actuator so that you can copy and paste:
1.Maven pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.application.properties:
#No auth protected
endpoints.shutdown.sensitive=false
#Enable shutdown endpoint
endpoints.shutdown.enabled=true
All endpoints are listed here:
3.Send a post method to shutdown the app:
curl -X POST localhost:port/shutdown
Security Note:
if you need the shutdown method auth protected, you may also need
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
configure details:
You can make the springboot application to write the PID into file and you can use the pid file to stop or restart or get the status using a bash script. To write the PID to a file, register a listener to SpringApplication using ApplicationPidFileWriter as shown below :
SpringApplication application = new SpringApplication(Application.class);
application.addListeners(new ApplicationPidFileWriter("./bin/app.pid"));
application.run();
Then write a bash script to run the spring boot application . Reference.
Now you can use the script to start,stop or restart.
All of the answers seem to be missing the fact that you may need to complete some portion of work in coordinated fashion during graceful shutdown (for example, in an enterprise application).
#PreDestroy allows you to execute shutdown code in the individual beans. Something more sophisticated would look like this:
#Component
public class ApplicationShutdown implements ApplicationListener<ContextClosedEvent> {
#Autowired ... //various components and services
#Override
public void onApplicationEvent(ContextClosedEvent event) {
service1.changeHeartBeatMessage(); // allows loadbalancers & clusters to prepare for the impending shutdown
service2.deregisterQueueListeners();
service3.finishProcessingTasksAtHand();
service2.reportFailedTasks();
service4.gracefullyShutdownNativeSystemProcessesThatMayHaveBeenLaunched();
service1.eventLogGracefulShutdownComplete();
}
}
Use the static exit() method in the SpringApplication class for closing your spring boot application gracefully.
public class SomeClass {
#Autowired
private ApplicationContext context
public void close() {
SpringApplication.exit(context);
}
}
As of Spring Boot 2.3 and later, there's a built-in graceful shutdown mechanism.
Pre-Spring Boot 2.3, there is no out-of-the box graceful shutdown mechanism.
Some spring-boot starters provide this functionality:
https://github.com/jihor/hiatus-spring-boot
https://github.com/gesellix/graceful-shutdown-spring-boot
https://github.com/corentin59/spring-boot-graceful-shutdown
I am the author of nr. 1. The starter is named "Hiatus for Spring Boot". It works on the load balancer level, i.e. simply marks the service as OUT_OF_SERVICE, not interfering with application context in any way. This allows to do a graceful shutdown and means that, if required, the service can be taken out of service for some time and then brought back to life. The downside is that it doesn't stop the JVM, you will have to do it with kill command. As I run everything in containers, this was no big deal for me, because I will have to stop and remove the container anyway.
Nos. 2 and 3 are more or less based on this post by Andy Wilkinson. They work one-way - once triggered, they eventually close the context.
I don't expose any endpoints and start (with nohup in background and without out files created through nohup) and stop with shell script(with KILL PID gracefully and force kill if app is still running after 3 mins). I just create executable jar and use PID file writer to write PID file and store Jar and Pid in folder with same name as of application name and shell scripts also have same name with start and stop in the end. I call these stop script and start script via jenkins pipeline also. No issues so far. Perfectly working for 8 applications(Very generic scripts and easy to apply for any app).
Main Class
#SpringBootApplication
public class MyApplication {
public static final void main(String[] args) {
SpringApplicationBuilder app = new SpringApplicationBuilder(MyApplication.class);
app.build().addListeners(new ApplicationPidFileWriter());
app.run();
}
}
YML FILE
spring.pid.fail-on-write-error: true
spring.pid.file: /server-path-with-folder-as-app-name-for-ID/appName/appName.pid
Here is the start script(start-appname.sh):
#Active Profile(YAML)
ACTIVE_PROFILE="preprod"
# JVM Parameters and Spring boot initialization parameters
JVM_PARAM="-Xms512m -Xmx1024m -Dspring.profiles.active=${ACTIVE_PROFILE} -Dcom.webmethods.jms.clientIDSharing=true"
# Base Folder Path like "/folder/packages"
CURRENT_DIR=$(readlink -f "$0")
BASE_PACKAGE="${CURRENT_DIR%/bin/*}"
# Shell Script file name after removing path like "start-yaml-validator.sh"
SHELL_SCRIPT_FILE_NAME=$(basename -- "$0")
# Shell Script file name after removing extension like "start-yaml-validator"
SHELL_SCRIPT_FILE_NAME_WITHOUT_EXT="${SHELL_SCRIPT_FILE_NAME%.sh}"
# App name after removing start/stop strings like "yaml-validator"
APP_NAME=${SHELL_SCRIPT_FILE_NAME_WITHOUT_EXT#start-}
PIDS=`ps aux |grep [j]ava.*-Dspring.profiles.active=$ACTIVE_PROFILE.*$APP_NAME.*jar | awk {'print $2'}`
if [ -z "$PIDS" ]; then
echo "No instances of $APP_NAME with profile:$ACTIVE_PROFILE is running..." 1>&2
else
for PROCESS_ID in $PIDS; do
echo "Please stop the process($PROCESS_ID) using the shell script: stop-$APP_NAME.sh"
done
exit 1
fi
# Preparing the java home path for execution
JAVA_EXEC='/usr/bin/java'
# Java Executable - Jar Path Obtained from latest file in directory
JAVA_APP=$(ls -t $BASE_PACKAGE/apps/$APP_NAME/$APP_NAME*.jar | head -n1)
# To execute the application.
FINAL_EXEC="$JAVA_EXEC $JVM_PARAM -jar $JAVA_APP"
# Making executable command using tilde symbol and running completely detached from terminal
`nohup $FINAL_EXEC </dev/null >/dev/null 2>&1 &`
echo "$APP_NAME start script is completed."
Here is the stop script(stop-appname.sh):
#Active Profile(YAML)
ACTIVE_PROFILE="preprod"
#Base Folder Path like "/folder/packages"
CURRENT_DIR=$(readlink -f "$0")
BASE_PACKAGE="${CURRENT_DIR%/bin/*}"
# Shell Script file name after removing path like "start-yaml-validator.sh"
SHELL_SCRIPT_FILE_NAME=$(basename -- "$0")
# Shell Script file name after removing extension like "start-yaml-validator"
SHELL_SCRIPT_FILE_NAME_WITHOUT_EXT="${SHELL_SCRIPT_FILE_NAME%.*}"
# App name after removing start/stop strings like "yaml-validator"
APP_NAME=${SHELL_SCRIPT_FILE_NAME_WITHOUT_EXT:5}
# Script to stop the application
PID_PATH="$BASE_PACKAGE/config/$APP_NAME/$APP_NAME.pid"
if [ ! -f "$PID_PATH" ]; then
echo "Process Id FilePath($PID_PATH) Not found"
else
PROCESS_ID=`cat $PID_PATH`
if [ ! -e /proc/$PROCESS_ID -a /proc/$PROCESS_ID/exe ]; then
echo "$APP_NAME was not running with PROCESS_ID:$PROCESS_ID.";
else
kill $PROCESS_ID;
echo "Gracefully stopping $APP_NAME with PROCESS_ID:$PROCESS_ID..."
sleep 5s
fi
fi
PIDS=`/bin/ps aux |/bin/grep [j]ava.*-Dspring.profiles.active=$ACTIVE_PROFILE.*$APP_NAME.*jar | /bin/awk {'print $2'}`
if [ -z "$PIDS" ]; then
echo "All instances of $APP_NAME with profile:$ACTIVE_PROFILE has has been successfully stopped now..." 1>&2
else
for PROCESS_ID in $PIDS; do
counter=1
until [ $counter -gt 150 ]
do
if ps -p $PROCESS_ID > /dev/null; then
echo "Waiting for the process($PROCESS_ID) to finish on it's own for $(( 300 - $(( $counter*5)) ))seconds..."
sleep 2s
((counter++))
else
echo "$APP_NAME with PROCESS_ID:$PROCESS_ID is stopped now.."
exit 0;
fi
done
echo "Forcefully Killing $APP_NAME with PROCESS_ID:$PROCESS_ID."
kill -9 $PROCESS_ID
done
fi
Spring Boot provided several application listener while try to create application context one of them is ApplicationFailedEvent. We can use to know weather the application context initialized or not.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.context.ApplicationListener;
public class ApplicationErrorListener implements
ApplicationListener<ApplicationFailedEvent> {
private static final Logger LOGGER =
LoggerFactory.getLogger(ApplicationErrorListener.class);
#Override
public void onApplicationEvent(ApplicationFailedEvent event) {
if (event.getException() != null) {
LOGGER.info("!!!!!!Looks like something not working as
expected so stoping application.!!!!!!");
event.getApplicationContext().close();
System.exit(-1);
}
}
}
Add to above listener class to SpringApplication.
new SpringApplicationBuilder(Application.class)
.listeners(new ApplicationErrorListener())
.run(args);
SpringApplication implicitly registers a shutdown hook with the JVM to ensure that ApplicationContext is closed gracefully on exit. That will also call all bean methods annotated with #PreDestroy. That means we don't have to explicitly use the registerShutdownHook() method of a ConfigurableApplicationContext in a boot application, like we have to do in spring core application.
#SpringBootConfiguration
public class ExampleMain {
#Bean
MyBean myBean() {
return new MyBean();
}
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(ExampleMain.class, args);
MyBean myBean = context.getBean(MyBean.class);
myBean.doSomething();
//no need to call context.registerShutdownHook();
}
private static class MyBean {
#PostConstruct
public void init() {
System.out.println("init");
}
public void doSomething() {
System.out.println("in doSomething()");
}
#PreDestroy
public void destroy() {
System.out.println("destroy");
}
}
}
Spring Boot now supports graceful shut down (currently in pre-release versions, 2.3.0.BUILD-SNAPSHOT)
When enabled, shutdown of the application will include a grace period
of configurable duration. During this grace period, existing requests
will be allowed to complete but no new requests will be permitted
You can enable it with:
server.shutdown.grace-period=30s
https://docs.spring.io/spring-boot/docs/2.3.0.BUILD-SNAPSHOT/reference/html/spring-boot-features.html#boot-features-graceful-shutdown
They are many ways to shutdown a spring application. One is to call close() on the ApplicationContext:
ApplicationContext ctx =
SpringApplication.run(HelloWorldApplication.class, args);
// ...
ctx.close()
Your question suggest you want to close your application by doing Ctrl+C, that is frequently used to terminate a command. In this case...
Use endpoints.shutdown.enabled=true is not the best recipe. It means you expose an end-point to terminate your application. So, depending on your use case and your environment, you will have to secure it...
A Spring Application Context may have register a shutdown hook with the JVM runtime. See ApplicationContext documentation.
Spring Boot configure this shutdown hook automatically since version 2.3 (see jihor's answer). You may need to register some #PreDestroy methods that will be executed during the graceful shutdown (see Michal's answer).
Ctrl+C should work very well in your case. I assume your issue is caused by the ampersand (&) More explanation:
On Ctrl+C, your shell sends an INT signal to the foreground application. It means "please interrupt your execution". The application can trap this signal and do cleanup before its termination (the hook registered by Spring), or simply ignore it (bad).
nohup is command that execute the following program with a trap to ignore the HUP signal. HUP is used to terminate program when you hang up (close your ssh connexion for example). Moreover it redirects outputs to avoid that your program blocks on a vanished TTY. nohupdoes NOT ignore INT signal. So it does NOT prevent Ctrl+C to work.
I assume your issue is caused by the ampersand (&), not by nohup. Ctrl+C sends a signal to the foreground processes. The ampersand causes your application to be run in background. One solution: do
kill -INT pid
Use kill -9 or kill -KILL is bad because the application (here the JVM) cannot trap it to terminate gracefully.
Another solution is to bring back your application in foreground. Then Ctrl+C will work. Have a look on Bash Job control, more precisely on fg.
I am able to do it on Spring Boot Version >=2.5.3 using these steps.
1. Add following actuator dependency
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
2. Add these properties in application.properties to do a graceful shutdown
management.endpoint.shutdown.enabled=true
management.endpoints.web.exposure.include=shutdown
server.shutdown=GRACEFUL
3. When you start the application, you should see this in the console
(based on number of endpoints you have exposed)
Exposing 1 endpoint(s) beneath base path '/actuator'
4. To shutdown the application do:
POST: http://localhost:8080/<context-path-if-any>/actuator/shutdown
A lot of the actuator answers are mostly correct. Unfortunately, the configuration and endpoint information has changed so they aren't 100% correct. To enable the actuator, add for Maven
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
or for Gradle
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}
For configuration, add the following to the application.properties. This will expose all endpoints in the actuator:
management.endpoints.web.exposure.include=*
management.endpoint.shutdown.enabled=true
To expose just the shutdown endpoint, change to:
management.endpoints.web.exposure.include=shutdown
management.endpoint.shutdown.enabled=true
Finally the shutdown endpoint is not available using GET - only POST. So you have to use something like:
curl -X POST localhost:8080/actuator/shutdown
If you are using maven you could use the Maven App assembler plugin.
The daemon mojo (which embed JSW) will output a shell script with start/stop argument. The stop will shutdown/kill gracefully your Spring application.
The same script can be used to use your maven application as a linux service.
If you are in a linux environment all you have to do is to create a symlink to your .jar file from inside /etc/init.d/
sudo ln -s /path/to/your/myboot-app.jar /etc/init.d/myboot-app
Then you can start the application like any other service
sudo /etc/init.d/myboot-app start
To close the application
sudo /etc/init.d/myboot-app stop
This way, application will not terminate when you exit the terminal. And application will shutdown gracefully with stop command.
For Spring boot web apps, Spring boot provides the out-of-box solution for graceful shutdown from version 2.3.0.RELEASE.
An excerpt from Spring doc
Refer this answer for the Code Snippet
If you are using spring boot version 2.3 n up , There is an in-build way to shutdown app gracefully.Add below in application.properties
server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=20s
If you are using lower spring boot version, You can write a custom shutdown hook and handle different beans, how they should shutdown or in which order they should shutdown. Example code below.
#Component
public class AppShutdownHook implements ApplicationListener<ContextClosedEvent> {
private static final Logger logger = LoggerFactory.getLogger(AppShutdownHook.class);
#Override
public void onApplicationEvent(ContextClosedEvent event) {
logger.info("shutdown requested !!!");
try {
//TODO Add logic to shutdown, diff elements of your application
} catch (Exception e) {
logger.error("Exception occcured while shutting down Application:", e);
}
}
}
try to use following command under the server running cmd or bash terminal.
kill $(jobs -p)
Recommendation get from Microservices With Spring Boot And Spring Cloud - Build Resilient And Scalable Microservices book.
Try this : Press ctrl+C
- [INFO]
------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO]
------------------------------------------------------------------------ [INFO] Total time: 04:48 min [INFO] Finished at:
2022-09-07T18:17:35+05:30 [INFO]
------------------------------------------------------------------------
Terminate batch job (Y/N)?
Type Y to terminate

How can I deploy cloudfoundry-uaa as a docker image based on tomcat?

We were using the cf-uaa's gradle tasks to create a docker image but those have been removed in the latest version. I've loaded the war in a recent version, but the service does not seem to be starting correctly.
I've been building the war from the v74 tag, adding it to tomcat:8.5.45-jdk12-openjdk-oracle or tomcat:9.0.24-jdk12-openjdk-oracle, and setting the various env vars that we were passing in to the previous image. I'm not seeing any log entries after the initial tomcat output stating that my war has been deployed and the server startup time.
The Dockerfile is basically just an adaptation of what was being passed in the previous image:
FROM tomcat:8.5.45-jdk12-openjdk-oracle
#FROM tomcat:9.0.24-jdk12-openjdk-oracle
ENV LOGIN_CONFIG_URL WEB-INF/classes/required_configuration.yml
ENV UAA_CONFIG_PATH /uaa
RUN bash -c "rm -r /usr/local/tomcat/webapps/ROOT"
RUN bash -c "rm -r /usr/local/tomcat/webapps/host-manager"
RUN bash -c "rm -r /usr/local/tomcat/webapps/manager"
RUN bash -c "rm -r /usr/local/tomcat/webapps/examples"
RUN bash -c "rm -r /usr/local/tomcat/webapps/docs"
ADD *.war /usr/local/tomcat/webapps/uaa.war
RUN bash -c "echo $LOGIN_CONFIG_URL"
EXPOSE 8080
I would expect to see the service responding to my requests, or some errors in the log indicating that the war failed to deploy. I am not currently getting any log output generated from the application code. When I send a request to the service, the response is a 500 with the an error header from the service.
X-Cf-Uaa-Error:Server failed to start. Possible configuration error.
update: I've located the uaa logs within .../tomcat/logs/uaa.log I'm not seeing anything indicating that the service failed to deploy, but I am also not seeing anything to indicate that it is picking up the env vars I have set in the container. I recreated the service using the war from the original setup which started successfully using the uaa.yml which I mounted as a volume. Comparing the logs, the original setup's first log entry is YamlProcessor which does not show up in the v75 logs at all. In fact, no debug entries show up at all, which suggests to me that my LOG_LEVEL env var is not propagating either.
Update 2: We reverted the image base to FROM tomcat:8.5-jre8 and started seeing flyway errors in the uaa.log. Our previous datasource url format was url: jdbc:postgresql://${POSTGRES_NAME}:5432/${DB}?currentSchema=uaa which caused a flyway exception. After removing the schema reference, it created the tables in the public schema. By creating the uaa schema manually before starting the service, it was able to run with the original format. The flyway version has updated, so perhaps there something new that needs to be set.
The application seems to be running, but when I try to get a token at /uaa/oauth/token I get a 500 with this error in the logs: Caused by: java.lang.NoSuchMethodError: java.nio.CharBuffer.limit(I)Ljava/nio/CharBuffer;
Since Jan 2021, UAA server docker images is now be available on cloudfoundry/uaa dockerhub repository.
docker pull cloudfoundry/uaa:75.0.0
See its Dockerfile for more details.
Can you try following ?
https://github.com/hortonworks/docker-cloudbreak-uaa
This works very well.

How to add module to Wildfly using CLI

I'm trying to create a Wildfly docker image with a postgres datasource.
When I build the dockerfile it always fails with Permission Denied when I try to install the postgres module.
My dockerfile looks look this:
FROM wildflyext/wildfly-camel
RUN /opt/jboss/wildfly/bin/add-user.sh admin admin --silent
ADD postgresql-9.4-1201.jdbc41.jar /tmp/
ADD config.sh /tmp/
ADD batch.cli /tmp/
RUN /tmp/config.sh
Which calls the following:
#!/bin/bash
JBOSS_HOME=/opt/jboss/wildfly
JBOSS_CLI=$JBOSS_HOME/bin/jboss-cli.sh
JBOSS_MODE=${1:-"standalone"}
JBOSS_CONFIG=${2:-"$JBOSS_MODE.xml"}
function wait_for_wildfly() {
until `$JBOSS_CLI -c "ls /deployment" &> /dev/null`; do
sleep 10
done
}
echo "==> Starting WildFly..."
$JBOSS_HOME/bin/$JBOSS_MODE.sh -c $JBOSS_CONFIG > /dev/null &
echo "==> Waiting..."
wait_for_wildfly
echo "==> Executing..."
$JBOSS_CLI -c --file=`dirname "$0"`/batch.cli --connect
echo "==> Shutting down WildFly..."
if [ "$JBOSS_MODE" = "standalone" ]; then
$JBOSS_CLI -c ":shutdown"
else
$JBOSS_CLI -c "/host=*:shutdown"
fi
And
batch
module add --name=org.postgresql --resources=/tmp/postgresql-9.4-1201.jdbc41.jar --dependencies=javax.api,javax.transaction.api
/subsystem=datasources/jdbc-driver=postgresql:add(driver-name=postgresql,driver-module-name=org.postgresql,driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource)
run-batch
The output when building is:
==> Starting WildFly...
==> Waiting...
==> Executing... Failed to locate the file on the filesystem copying /tmp/postgresql-9.4-1201.jdbc41.jar to
/opt/jboss/wildfly/modules/org/postgresql/main/postgresql-9.4-1201.jdbc41.jar:
/tmp/postgresql-9.4-1201.jdbc41.jar (Permission denied)
What permissions are required, and where do I set the permission(s)?
Thanks
It seems the JAR file is not readable by the jboss user (the user comming from parent image). The postgresql-9.4-1201.jdbc41.jar is added under the root user - find details in this GitHub discussion.
You could
either add permissions to JAR file before adding it to the image
or add permissions to JAR file in the image after the adding
or change ownership of the file in the image
The simplest solution could be the first one. The other 2 solutions need also switching user to root (USER root in dockerfile) and then back to jboss.
Here a advice : make a cli file like this :
connect
module add --name=sqlserver.jdbc --resources=#INSTALL_FOLDER#/libext/jtds-1.3.1.jar --dependencies=javax.api,javax.transaction.api
/subsystem=datasources/jdbc-driver=sqlserver:add(driver-module-name=sqlserver.jdbc,driver-name=sqlserver,driver-class-name=#JDBC_DRIVER#)
/subsystem=datasources/data-source=#DATASOURCENAME#:add(jndi-name=java:jboss/#JNDI_NAME#,enabled="true",use-java-context="true",driver-name=sqlserver,connection-url="#JDBC_URL#",user-name=#JDBC_USER#,password=#JDBC_PASSWORD#,validate-on-match=true,background-validation=true)
replace #VAR# by our own value... and It should work!
Be caution than JBOSS/Wildfly 10 think relatively for jar --resources by default but wildfly 8 think absolute path this could make you weird ! ;-)
cheers!

Running a java service using Ubuntu upstart

I can't define a valid upstart conf script to run a java service using upstart with the following requirements:
I have to specify classpath using folders because I have many jars in multiple folders
I have to listen to the shutdown signal fired by service myservicename stop
Based on that answer, I implemented a shutdown hook listener so I need upstart to send me the termination signal and wait for my application to terminate.
Here is my buggy upstart script:
description "masa"
author "Muhammad Gelbana <m.glba#gmail.com>"
start on runlevel [2345]
stop on shutdown
kill timeout 120
script
LOGS_DIR=/home/mgelbana/services/RealServices/logs
IPK_DB=/home/mgelbana/services/RealServices/config/db-ipk.properties
PRO_DB=/home/mgelbana/services/RealServices/config/db-reporting-engine.properties
MAIN_CLASS=com.sger.masaTA
mkdir -p $LOGS_DIR
CLASSPATH="/home/mgelbana/services/RealServices/masa-RealService-TA.jar"
for i in /home/mgelbana/services/commons/*.jar; do
CLASSPATH="$CLASSPATH:$i"
done
for i in /home/mgelbana/services/RealServices/lib/*.jar; do
CLASSPATH="$CLASSPATH:$i"
done
echo '\n\n\n====================================================='
echo 'Service startup:\t'`date`
echo 'Main class:\t\t'`echo $MAIN_CLASS`
echo 'Logs directory:\t\t'`echo $LOGS_DIR`
echo 'masa database configuration:\t'`echo $IPK_DB`
echo 'Pro configuration file:\t'`echo $PRO_DB`
echo 'Starting engine...'
java -Dta.id=2 -DIPK_DB=$IPK_DB -DPRO_DB=$PRO_DB -cp $CLASSPATH $MAIN_CLASS
end script
The following error is shown in the /var/log/upstart/myservicename.log log:
/proc/self/fd/9: 9: /proc/self/fd/9: Syntax error: word unexpected (expecting "do")
Thank you.

Wait until tomcat finishes starting up

I have a script that needs to run after tomcat has finished starting up and is ready to start deploying applications. I'm using $TOMCAT_HOME/bin/startup.sh which returns immediately. How can I wait until tomcat has finished starting up?
There are probably several ways to do this. The trick we use is:
#!/bin/bash
until [ "`curl --silent --show-error --connect-timeout 1 -I http://localhost:8080 | grep 'Coyote'`" != "" ];
do
echo --- sleeping for 10 seconds
sleep 10
done
echo Tomcat is ready!
Hope this helps!
It's not hard to implement programaticaly. You can implement org.apache.catalina.LifecycleListener and then you'll have
public void lifecycleEvent(LifecycleEvent lifecycleEvent) {
if(lifecycleEvent.getType().equals(Lifecycle.START_EVENT))
//do what you want
}
}
in web.xml :
<Context path="/examples" ...>
...
<Listener className="com.mycompany.mypackage.MyListener" ... >
...
</Context>
Please notice that some things could differ between 6-9 Tomcats.
Are you still looking for an answer? It depends on your definition of started. If your definition of started is "Now its safe to stop" then you might want to verify if port 8005 is listening.
Depends on what you mean by finishing. What do you want to wait for?
You could, for example, have a script that hits a URL repeatedly until it gets a desirable result that would only be available once the app is properly initialized.
You could also have a context listener that writes out an "I'm ready" file that you use to signal the readiness of your application. (If you do this, be sure the file doesn't exist before starting your app container).
I needed this to test from jenkins if the tomcat from the remote server started for a system check.
until [[ `ssh -o StrictHostKeyChecking=no root#${DEPLOY_HOST} 'netstat -tulpn | grep 8005'` != "" ]] ; do echo "waiting for tomcat"; sleep 6; done
There isn't an easy method. As far as startup.sh and catalina.sh are concerned, tomcat is running when they finish. Although, internally, tomcat is still initializing and starting contexts.
It would help to know if you were trying to find out if your context finished loading or if you are just wanting a general, "Tomcat is runnnig although your contexts might not be completely loaded..."
If it is the latter you could create a web app that simply has a context listener that will execute a script using Runtime. If you were handy, you could make the webapp configuable via the web.xml file to accept a parameter that points to the script to execute.
Personally, I would just watch catalinas log for a specific string depending on how your setup and what exact phase your looking for.
I have done it with the following code in jenkins pipelinescript with tomcat.
Before i just call
sudo /bin/systemctl restart tomcat
And have an entry in my sudoers file for the jenkins user.
Now here is the oneliner:
until [ "$(curl -w '%{response_code}' --no-keepalive -o /dev/null --connect-timeout 1 -u USERNAME:PASSWORD http://localhost:8080/manager/text/list)" == "200" ]; do echo --- sleeping for 1 second; sleep 1; done
Better readable:
until [ "$(curl -w '%{response_code}' --no-keepalive -o /dev/null --connect-timeout 1 -u USERNAME:PASSWORD http://localhost:8080/manager/text/list)" == "200" ];
do echo --- sleeping for 1 second;
sleep 1;
done

Categories