Reputation: 4118
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:
Start.class.getProtectionDomain().getCodeSource()
resolves to null
.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).
Upvotes: 8
Views: 4507
Reputation: 1269
I believe, I faced a similar problem a couple months ago, I used Jetty v9.4.12.v20180830.
Here is my solution:
If you have the following generated JAR structure:
app.jar
+----- com /
| +--- ( classes ... )
|
+----- config /
| |
| +--- display.properties
|
+----- webapp /
|
+--- index.html
Then the following code will refer to the correct folder:
ServletContextHandler webappContext = new ServletContextHandler(ServletContextHandler.SESSIONS);
URL webRootLocation = YourJettyStarterClass.class.getResource("/webapp/index.html");
URI webRootUri = URI.create(webRootLocation.toURI().toASCIIString().replaceFirst("/index.html$", "/"));
webappContext.setContextPath("/");
webappContext.setBaseResource(Resource.newResource(webRootUri));
webappContext.setWelcomeFiles(new String[] { "index.html" });
The important part:
URL webRootLocation = YourJettyStarterClass.class.getResource("/webapp/index.html");
Upvotes: 0
Reputation: 782
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
Upvotes: 1