Marlon Bernardes
Marlon Bernardes

Reputation: 13853

How to startup Jetty Embedded as part of a Jenkins build

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

Answers (2)

Marlon Bernardes
Marlon Bernardes

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

Joakim Erdfelt
Joakim Erdfelt

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.

  • Build up the Server (using junit's @BeforeClass for example)
  • Add the Handlers
  • server.start();
  • execute your tests
  • server.stop();

Upvotes: 1

Related Questions