So I found yet a better answer based off the one from ericacm above. The only reason that it's better is that you can still use <load-on-startup> for the servlets in the web.xml file.
When embedding the Jetty server, you need to create a WebAppContext. The super-class ContextHandler lets you set an array of EventListener which includes ServletContextListener.
So the solution is extend ContextLoader and implement both Spring's ApplicationContextAware and the ServletContextListener interface. The loader lets you return the parent context set by the contextaware interface, and the listener provides you the ServletContext via contextInitialized().
You can then initialize this before any of the Jetty components, and get access to the fully populated ServletContext as the Jetty server is loading, which gets called before any of the web app's themselves are initialized.
Listener implementation:
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.web.context.ContextLoader;
public final class EmbeddedJettySpringContextLoaderListener
extends ContextLoader
implements ApplicationContextAware,
ServletContextListener
{
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
/**
* Returns the parent application context as set by the
* {@link ApplicationContextAware} interface.
*
* @return The initial ApplicationContext that loads the Jetty server.
*/
@Override
protected ApplicationContext loadParentContext(ServletContext servletContext) {
return this.applicationContext;
}
@Override
public void contextInitialized(ServletContextEvent sce) {
super.initWebApplicationContext(sce.getServletContext());
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
//not needed
}
}
Jetty config for WebAppContext (eventually referenced by the server):
<!-- Loads this application context as the parent of the web application context. -->
<bean id="parentContextLoaderListener" class="com.citi.matrix.server.restapi.EmbeddedJettySpringContextLoaderListener" />
<bean id="restApiWebAppContext" class="org.mortbay.jetty.webapp.WebAppContext">
<property name="displayName" value="RestApi" />
<property name="contextPath" value="/" />
<!-- the value for war, must be a relative path to the root of the application, and does not use the classpath. -->
<property name="war" value="${WEBAPPS_HOME}/rest-api" />
<property name="eventListeners">
<ref local="parentContextLoaderListener" />
</property>
<property name="configurationClasses">
<list>
<value>org.mortbay.jetty.webapp.WebInfConfiguration</value>
<value>org.mortbay.jetty.webapp.WebXmlConfiguration</value>
<value>org.mortbay.jetty.webapp.JettyWebXmlConfiguration</value>
</list>
</property>
<property name="logUrlOnStart" value="true" />
</bean>