Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Starting up embedded jetty server for a JAR file

What I am trying to do, is to build an executable JAR file which will contain my project. I have included its dependencies right next to it, also in JAR files, so my directory listing looks something like this:

~/Projects/Java/web-app/out:

web-app.jar

dependency1.jar

dependency2.jar

dependency3.jar

I know and am sure that my problem does not arise from dependencies, as my application functions properly, right up to the moment I start up Jetty embedded.

The code I use to start Jetty is like this:

public class ServerExecutionGoal implements ExecutionGoal {    

    private final static Logger logger = Logger.getLogger(ServerExecutionGoal.class);    

    private WebAppContext getWebAppContext() throws IOException {    
        WebAppContext context = new WebAppContext();    
        System.out.println("context = " + context);    
        context.setResourceBase(new PathMatchingResourcePatternResolver().getResource("classpath:/webapp").getURL().toExternalForm());    
        context.setContextPath("/");    
        context.setLogger(new StdErrLog());    
        return context;    
    }    

    @Override    
    public void execute(Map<String, Object> stringObjectMap) throws ExecutionTargetFailureException {    
        logger.info("Instantiating target server ...");    
        final Server server = new Server(8089);    
        final ContextHandlerCollection handlerCollection = new ContextHandlerCollection();    
        try {    
            handlerCollection.setHandlers(new Handler[]{new RequestLogHandler(), getWebAppContext()});    
        } catch (IOException e) {    
            throw new ExecutionTargetFailureException("Could not create web application context", e);    
        }    
        server.setHandler(handlerCollection);    
        try {    
            logger.info("Starting server on port 8089 ...");    
            server.start();    
            server.join();    
            logger.info("Server started. Waiting for requests.");    
        } catch (Exception e) {    
            throw new ExecutionTargetFailureException("Failed to properly start the web server", e);    
        }    
    }    

    public static void main(String[] args) throws ExecutionTargetFailureException {    
        new ServerExecutionGoal().execute(null);    
    }    

}    

I can validate that the "webapp" folder gets relocated correctly inside my JAR to /webapp, and that when running the code through my IDE (IntelliJ IDEA 11) context.setResourceBase(new PathMatchingResourcePatternResolver().getResource("classpath:/webapp").getURL().toExternalForm()) maps validly to the resource in question. Also, I can show that it resolves to something like:

jar:file:~/Projects/Java/web-app/out/web-app.jar!/webapp

and is accessible (I read it).

However, when I start my application's main method, and Jetty starts, on http://localhost:8089 I get the following:

HTTP ERROR: 503

Problem accessing /. Reason:

Service Unavailable

Powered by Jetty://

Where am I going wrong?

I know that by setting "resourceBase" to "." the address "http://localhost:8089" will act as an interface to the location "~/Projects/Java/web-app/out/" where I can see a listing of all the JAR files, including the "web-app.jar", upon clicking on which I am offered to download it.

I have seen the following questions, and the answers do not apply:

  1. Embedded jetty application not working from jar: I get NullPointerException since Start.class.getProtectionDomain().getCodeSource() resolves to null.
  2. Embedded Jetty WebAppContext FilePermission issue: which not only isn't answered, but the situation clearly does not apply, as I do not have permission issues (the fact that I can get a file listing should prove that).
  3. embedding jetty server problems: also unanswered, also not applicable as I don't have any dependency problems (as pointed out previously in my comments above).

I think that I should somehow enable Jetty to access the /webapp folder, which is located under my src/main/resources/ directory and is bundled into my web application. Should I be forsaking a bundled web application and deploy the exploded context path to somewhere accessible by Jetty instead (this is not desirable at all as it poses a multitude of issues for me and my clients).

like image 869
Milad Naseri Avatar asked Oct 01 '12 11:10

Milad Naseri


1 Answers

I'm not sure, if the WebAppContext of Jetty can be used with PathMatchingResourcePatternResolver!

In one of my projects I solved this problem by writing my own javax.servlet.Filter, which loads the requested resources by Class#getResourceAsStream. Class#getResourceAsStream reads resources from inside a jars as well as inside a resource path (e.g. maven).

Hope this tip is helpful for you, cheers Thilo

like image 93
Thilo Schwarz Avatar answered Nov 07 '22 03:11

Thilo Schwarz