Reputation: 13853
I have a webapp which uses Jetty as it's embedded application server. I have also set up a Main class for it, which starts the server when I run it using the following command:
java -jar foo.war
To this part everything is working as expected. The problem I'm currently having is while integrating this with Jenkins.
If I execute java -jar foo.war
as a batch command, the server starts but the build doesn't finish - it just keeps showing the server console (it makes sense after all, since everything is part of the same process). I guess I'm supposed to spawn a new process, but how do I spawn a new process and "notify" the main process after the server was started?
I need to run my acceptance tests (aka selenium tests) only after the application server was started.
Jenkins is running (unfortunately) under Windows Server. Not sure if that's relevant, but below is the code which I use to start the application server (slightly simplified):
public static void main(String[] args) throws Exception {
Server server = new Server(8082);
server.setHandler(getHandlers(server));
server.setStopAtShutdown(true);
server.start();
server.join();
}
private static HandlerList getHandlers(Server server) {
ProtectionDomain protectionDomain = WebServer.class.getProtectionDomain();
URL location = protectionDomain.getCodeSource().getLocation();
WebAppContext webapp = new WebAppContext(location.toExternalForm(), "/");
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] {
webapp
});
return handlers;
}
Upvotes: 1
Views: 2393
Reputation: 13853
I created a small CLI program (using JCommander) which is responsible for starting and stopping the server. As an example:
java -jar jetty-cli -start -warFile C:\\app.war
java -jar jetty-cli -stop -password shutdownpassword
Starting the Server
I spawn a new process (Using Runtime.getRuntime()
), execute the runnable war file and capture the console output until I know the server has started. I wouldn't say I'm happy with this approach (I don't like capturing the server output to detect when the server has started). Anyway:
//Server
server.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() {
@Override
public void lifeCycleStarted(LifeCycle event) {
System.out.println(STARTED_MESSAGE);
}
});
//CLI
Process warProcess = Runtime.getRuntime().exec("java -jar " + options.getWarFile());
InputStream inputStream = warProcess .getInputStream();
InputStreamReader streamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(streamReader);
String line;
while ((line = bufferedReader .readLine()) != null) {
if (line.contains(STARTED_MESSAGE)) {
System.exit(0);
}
}
Stopping the Server:
I used Jetty's own ShutdownHandler
, which shuts the server down on a valid POST request to http://localhost:<port>/shutdown/?token=<shutdowntoken>
.
private Handler createShutdownHandler(Server server) {
return new ShutdownHandler(server, "shutdownpassword");
}
So all I need to do is a POST request to http://localhost:8080/shutdown?token=shutdownpassword
.
Upvotes: 0
Reputation: 49555
The server.join();
call will make the current thread (the one running main()
) wait until the server is stopped.
The server.setStopAtShutdown(true)
is also not required when embedding inside of a unit test.
Just do the following.
@BeforeClass
for example)server.start();
server.stop();
Upvotes: 1