steveliles/jetty-embedded-spring-mvc-noxml

Won't load WebApplicationInitializer from fat jar

Closed this issue · 5 comments

I am stumped and have not been able to figure out how to make this project run directly from the fat jar. Maven builds it just fine but if I try and start using: java -jar jetty-noxml-1.0-SNAPSHOT.jar it will not find the WebAppInitializer.

If I unzip the jar unzip ../jetty-noxml-1.0-SNAPSHOT.jar and do this it works just fine: "java -cp . com.sjl.Main"

Is there some way to make it run from the "fat" jar?

Here is the console output for the failure case:

[target (master)]$ java -jar jetty-noxml-1.0-SNAPSHOT.jar
2013-04-10 11:36:54.174:INFO:oejs.Server:jetty-8.y.z-SNAPSHOT
Null identity service, trying login service: null
Finding identity service: null
2013-04-10 11:36:54.294:INFO:/:No Spring WebApplicationInitializer types detected on classpath
2013-04-10 11:36:54.294:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,jar:file:/Users/name/working/jettyDemo/original/jetty-embedded-spring-mvc-noxml/target/jetty-noxml-1.0-SNAPSHOT.jar!/META-INF/webapp}
2013-04-10 11:36:54.299:INFO:oejs.NCSARequestLog:Opened /Users/name/working/jettyDemo/original/jetty-embedded-spring-mvc-noxml/target/var/logs/$s/2013_04_10.request.log
2013-04-10 11:36:54.324:INFO:oejs.AbstractConnector:Started SelectChannelConnector@localhost:8000
^C2013-04-10 11:36:59.067:INFO:oejsh.ContextHandler:stopped o.e.j.w.WebAppContext{/,jar:file:/Users/name/working/jettyDemo/original/jetty-embedded-spring-mvc-noxml/target/jetty-noxml-1.0-SNAPSHOT.jar!/META-INF/webapp}
2013-04-10 11:36:59.118:INFO:oejut.ShutdownThread:shutdown already commenced

This is the console output in the success case:

[temp (master)]$ java -cp . com.sjl.Main
2013-04-10 11:40:28.076:INFO:oejs.Server:jetty-8.y.z-SNAPSHOT
Null identity service, trying login service: null
Finding identity service: null
2013-04-10 11:40:29.391:INFO:/:Spring WebApplicationInitializers detected on classpath: [com.sjl.config.WebAppInitializer@3ff2cea2]
2013-04-10 11:40:29.520:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/name/working/jettyDemo/original/jetty-embedded-spring-mvc-noxml/target/temp/META-INF/webapp/}
2013-04-10 11:40:29.520:INFO:/:Initializing Spring root WebApplicationContext
Apr 10, 2013 11:40:29 AM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization started
Apr 10, 2013 11:40:29 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing Root WebApplicationContext: startup date [Wed Apr 10 11:40:29 CDT 2013]; root of context hierarchy
Apr 10, 2013 11:40:29 AM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
INFO: JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
Apr 10, 2013 11:40:29 AM org.springframework.web.context.support.AnnotationConfigWebApplicationContext loadBeanDefinitions
INFO: Registering annotated classes: [class com.sjl.config.ApplicationModule]
Apr 10, 2013 11:40:29 AM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@6b9fe451: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,applicationModule,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy
Apr 10, 2013 11:40:29 AM org.springframework.web.context.ContextLoader initWebApplicationContext
INFO: Root WebApplicationContext: initialization completed in 217 ms
2013-04-10 11:40:29.743:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/name/working/jettyDemo/original/jetty-embedded-spring-mvc-noxml/target/temp/META-INF/webapp/}
2013-04-10 11:40:29.751:INFO:/:Initializing Spring FrameworkServlet 'dispatcher'
Apr 10, 2013 11:40:29 AM org.springframework.web.servlet.FrameworkServlet initServletBean
INFO: FrameworkServlet 'dispatcher': initialization started
Apr 10, 2013 11:40:29 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing WebApplicationContext for namespace 'dispatcher-servlet': startup date [Wed Apr 10 11:40:29 CDT 2013]; parent: Root WebApplicationContext
Apr 10, 2013 11:40:29 AM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
INFO: JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
Apr 10, 2013 11:40:29 AM org.springframework.web.context.support.AnnotationConfigWebApplicationContext loadBeanDefinitions
INFO: Registering annotated classes: [class com.sjl.config.WebModule]
Apr 10, 2013 11:40:29 AM org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider registerDefaultFilters
INFO: JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning
Apr 10, 2013 11:40:29 AM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@62803d5: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,webModule,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0,applicationModule,home,delegatingWebMvcConfiguration,requestMappingHandlerMapping,viewControllerHandlerMapping,beanNameHandlerMapping,resourceHandlerMapping,defaultServletHandlerMapping,requestMappingHandlerAdapter,mvcConversionService,mvcValidator,httpRequestHandlerAdapter,simpleControllerHandlerAdapter,handlerExceptionResolver,viewResolver]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@6b9fe451
Apr 10, 2013 11:40:30 AM org.springframework.web.servlet.handler.AbstractHandlerMethodMapping registerHandlerMethod
INFO: Mapped "{[/],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView com.sjl.web.Home.home()
Apr 10, 2013 11:40:30 AM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Root mapping to handler of type [class org.springframework.web.servlet.mvc.ParameterizableViewController]
Apr 10, 2013 11:40:30 AM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/s/] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
Apr 10, 2013 11:40:30 AM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/WEB-INF/view/
] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
Apr 10, 2013 11:40:30 AM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/i/] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
Apr 10, 2013 11:40:30 AM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/c/
] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
Apr 10, 2013 11:40:30 AM org.springframework.web.servlet.handler.AbstractUrlHandlerMapping registerHandler
INFO: Mapped URL path [/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
Apr 10, 2013 11:40:30 AM org.springframework.web.servlet.FrameworkServlet initServletBean
INFO: FrameworkServlet 'dispatcher': initialization completed in 628 ms
2013-04-10 11:40:30.382:INFO:oejs.NCSARequestLog:Opened /Users/name/working/jettyDemo/original/jetty-embedded-spring-mvc-noxml/target/temp/var/logs/$s/2013_04_10.request.log
2013-04-10 11:40:30.410:INFO:oejs.AbstractConnector:Started SelectChannelConnector@localhost:8000
^C2013-04-10 11:41:11.743:INFO:/:Destroying Spring FrameworkServlet 'dispatcher'
2013-04-10 11:41:11.745:INFO:/:Closing Spring root WebApplicationContext
2013-04-10 11:41:11.746:INFO:oejsh.ContextHandler:stopped o.e.j.w.WebAppContext{/,file:/Users/name/working/jettyDemo/original/jetty-embedded-spring-mvc-noxml/target/temp/META-INF/webapp/}
2013-04-10 11:41:11.797:INFO:oejut.ShutdownThread:shutdown already commenced

Fixed - the AnnotationParser was ignoring jar URI's, so it ignored the shaded jar.

Steve,

Thank you for the fix and also thanks for this great piece of code that is perfect for a starting point of a project.

do you have an example using jetty 9. It is really annoying 9 version...

@aehtiopicus a friend and ex-colleague of mine mailed me this some time ago, but I never got around to updating the github project:

public void parseContainerPath (final WebAppContext context, final AnnotationParser parser) throws Exception
        {
            //always parse for discoverable annotations as well as class hierarchy and servletcontainerinitializer related annotations
            final Set<AnnotationParser.Handler> handlers = new HashSet<AnnotationParser.Handler>();
            handlers.addAll(_discoverableAnnotationHandlers);
            handlers.addAll(_containerInitializerAnnotationHandlers);
            if (_classInheritanceHandler != null)
                handlers.add(_classInheritanceHandler);

            _containerPathStats = new CounterStatistic();

            List<Resource> _resources = new ArrayList<Resource>();
            _resources.addAll(context.getMetaData().getContainerResources());
            _resources.addAll(getSelfResources(getClass().getClassLoader()));

            for (Resource r : _resources)
            {
                //queue it up for scanning if using multithreaded mode
                if (_parserTasks != null)
                {
                    ParserTask task = new ParserTask(parser, handlers, r, _containerClassNameResolver);
                    _parserTasks.add(task);  
                    _containerPathStats.increment();
                }
            } 
        }

        private List<Resource> getSelfResources(ClassLoader aLoader) throws IOException
        {
            URL _url = aLoader.getResource("com/aub/library/servlets");

            Resource _r = new CustomResource(Resource.newResource(_url));

            return Arrays.asList(_r);
        }

And since they decided not to allow us have sub implementations of jarfileresource, i did the following:

public class CustomResource extends Resource 
{
private Resource delegate;

public CustomResource(Resource aDelegate)
{
    delegate = aDelegate;
}

@Override
public boolean isContainedIn(Resource r) throws MalformedURLException
{
    return delegate.isContainedIn(r);
}

@Override
public void close()
{
    delegate.close();
}

@Override
public boolean exists()
{
    return delegate.exists();
}

@Override
public boolean isDirectory() {
    return delegate.isDirectory();
}

@Override
public long lastModified() {
    return delegate.lastModified();
}

@Override
public long length() {
    return delegate.length();
}

@Override
public URL getURL() {
    return delegate.getURL();
}

@Override
public File getFile() throws IOException {
    if(delegate.getClass().getSimpleName().equalsIgnoreCase("JarFileResource"))
        return new File(getName());

    return delegate.getFile();
}

@Override
public String getName() {
    return delegate.getName();
}

@Override
public InputStream getInputStream() throws IOException
{
    return delegate.getInputStream();
}

@Override
public ReadableByteChannel getReadableByteChannel() throws IOException
{
    return delegate.getReadableByteChannel();
}

@Override
public boolean delete() throws SecurityException {
    return delegate.delete();
}

@Override
public boolean renameTo(Resource dest) throws SecurityException {
    return delegate.renameTo(dest);
}

@Override
public String[] list() {
    return delegate.list();
}

@Override
public Resource addPath(String path) throws IOException,
        MalformedURLException {
    return new CustomResource(delegate.addPath(path));
}

@steveliles Hi Thanks for the reply. I am having a really bad time trying to make it work with version 9. So I will keep on 8 although it is deprecated. The issue is that Spring doesn't boot at all and no messages are thrown to console but I got 503 or in the best case 404. If I get it running I will post it back.