Hi,

Thanks for the tip. But I don't want the jar-with-dependencies, it doesn't play 
well with spring for instance. (It overwrites META-INF and such).

I think I solved the issue by implementing my own resource class that is 
returned from the DefaultServlet.getResource(). It works in my case, but I 
can't really see if there are any side-effects I don't know about (yet). So if 
any of the commiters can check that would be great.

The resource:

public class JarInJarResource extends URLResource {

  private static final String JAR_FILE_PROTOCOL = "jar:file:/";
  private ByteArrayOutputStream resourceOutput = new ByteArrayOutputStream();
  private long lastModified;

  public JarInJarResource(Resource resource) {
    super(resource.getURL(), null);
  }

  @Override
  public boolean exists() {
    int firstIndexOfJarSeparator = this._urlString.indexOf("!/");
    int lastIndexOfJarSeparator = this._urlString.lastIndexOf("!/");
    try {
      JarFile mainJar = getMainJar(firstIndexOfJarSeparator);
      JarEntry jarInJar = getJarInJarAsJarEntry(firstIndexOfJarSeparator, 
lastIndexOfJarSeparator, mainJar);
      JarInputStream jarInJarStream = getJarInJarAsJarInputStream(mainJar, 
jarInJar);
      JarEntry jarEntry = null;
      while ((jarEntry = jarInJarStream.getNextJarEntry()) != null) {
        String fileNameRequested = 
this._urlString.substring(lastIndexOfJarSeparator + 2);
        if (jarEntry.getName().equals(fileNameRequested)) {
          IOUtils.copy(jarInJarStream, resourceOutput);
          lastModified = jarInJar.getTime();
          return true;
        }
      }
    } catch (IOException e) {
      Log.debug(Log.EXCEPTION, e);
    }
    return false;
  }

  private JarInputStream getJarInJarAsJarInputStream(JarFile jarFile, JarEntry 
entry) throws IOException {
    InputStream jarInJarInputStream = jarFile.getInputStream(entry);
    return new JarInputStream(jarInJarInputStream);
  }

  private JarFile getMainJar(int firstIndexOfJarSeparator) throws IOException {
    String firstJar = this._urlString.substring(0, 
firstIndexOfJarSeparator).replaceAll(JAR_FILE_PROTOCOL, "");
    return new JarFile(firstJar);
  }

  private JarEntry getJarInJarAsJarEntry(int firstIndexOfJarSeparator, int 
lastIndexOfJarSeparator, JarFile jarFile) {
    String secondJar = this._urlString.substring(firstIndexOfJarSeparator + 2, 
lastIndexOfJarSeparator);
    return jarFile.getJarEntry(secondJar);
  }

  @Override
  public synchronized InputStream getInputStream() throws IOException {
    return new ByteArrayInputStream(resourceOutput.toByteArray());
  }

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

The Extension on DefaultServlet:

public class OneJarSupportingDefaultServlet extends DefaultServlet {
  private static final long serialVersionUID = 1L;

  @Override
  public Resource getResource(String pathInContext) {
    Resource resource = super.getResource(pathInContext);
    if(resource instanceof JarResource) {
      return new JarInJarResource(resource);
    }
    return resource;
  }
}


-- Lars 

On Apr 23, 2011, at 12:46 PM, Ondrej Zizka wrote:

> Instead of one-jar, try the assembly plugin with it's `jar-with-dependencies` 
> built-in descriptorRef:
> http://ondra.zizka.cz/stranky/programovani/java/maven/maven-create-distribution-package.texy
> 
> Ondra
> 
> 
> 
> On Fri, 2011-04-22 at 09:29 +0200, Lars Vonk wrote:
>> Hi,
>> 
>> 
>> I am trying to create an application using embedded Jetty (version 
>> 7.4.0.v20110414) and want to package it using the onejar maven plugin 
>> (http://code.google.com/p/onejar-maven-plugin/).
>> 
>> 
>> Here is the code where I start jetty:
>> 
>> 
>>     Server server = new Server(8180);
>>     ServletContextHandler context = new 
>> ServletContextHandler(ServletContextHandler.SESSIONS);
>>     context.setContextPath("/");
>>     context.setWelcomeFiles(new String[]{"index.html"});
>> 
>> 
>>     ServletHolder servletHolder = new ServletHolder(new DefaultServlet());
>>     URL resource = getClass().getResource("/web/");
>>     String resourceBase = resource.toURI().toString();
>>     servletHolder.setInitParameter("resourceBase", resourceBase);
>>     context.addServlet(servletHolder, "/");
>> 
>> 
>>     server.setHandler(context);
>>     server.start();
>> 
>> 
>> 
>> 
>> When I do java -jar onejar.jar and go to http://localhost:8180/index.html I 
>> get a 404.
>> 
>> 
>> 
>> 
>> My onejar.jar looks like this:
>> 
>> 
>> onejar.jar
>> main/myapp.jar
>> main/myapp.jar/web/index.html
>> 
>> 
>> 
>> 
>> (Rest omitted for readability).
>> 
>> 
>> 
>> 
>> I debugged through the application and noticed it throws (and ignores) an 
>> exception in the org.eclipse.jetty.util.resource.JarFileResource class in 
>> the method exists() in this piece of code:
>> 
>> 
>> try
>>                 {
>>                     JarURLConnection c=(JarURLConnection)((new 
>> URL(_jarUrl)).openConnection());
>>                     c.setUseCaches(getUseCaches());
>>                     jarFile=c.getJarFile();
>>                 }
>>                 catch(Exception e)
>>                 {
>>                        Log.ignore(e);
>>                 }
>> 
>> 
>> The _jarUrl contains: 
>> jar:file:/target/onejar.jar!/main/myapp.jar!/web/index.html and throws a 
>> ZipException when doing c.getJarFile(): java.util.zip.ZipException: error in 
>> opening zip file.
>> 
>> 
>> 
>> 
>> Does anyone has experience in using embedded jetty with the mentioned onejar 
>> plugin? What I'd like to do is do java -jar myjar.jar where myjar contains 
>> everything that is needed, no additional files and such.
>> 
>> 
>> Extra information:
>> 
>> 
>> I also created a unit test for this asfollows:
>> 
>> 
>> @Test
>>   public void defaultServlet() throws Exception {
>>     final Server server = new Server(8181);
>>     ServletContextHandler context = new 
>> ServletContextHandler(ServletContextHandler.SESSIONS);
>>     context.setContextPath("/");
>>     context.setWelcomeFiles(new String[]{"index.html"});
>>     DefaultServlet defaultServlet = new DefaultServlet();
>>     ServletHolder servlet = new ServletHolder(defaultServlet);
>>     servlet.setInitParameter("resourceBase", 
>> "jar:file:/target/onejar.jar!/main/myapp.jar!/web/");
>>     context.addServlet(servlet, "/");
>>     server.setHandler(context);
>>     server.start();
>>     Resource resource = defaultServlet.getResource("/index.html");
>>     assertNotNull(resource);
>>     server.stop();
>>   }
>> 
>> 
>> This tests succeeds, meaning resource is not null. Does a real request use 
>> something else to find the resources that the getResource method on the 
>> servlet?
>> 
>> 
>> Thanks in advance,
>> 
>> 
>> Lars 
>> 
>> 
>> _______________________________________________
>> jetty-users mailing list
>> [email protected]
>> https://dev.eclipse.org/mailman/listinfo/jetty-users
> 
> _______________________________________________
> jetty-users mailing list
> [email protected]
> https://dev.eclipse.org/mailman/listinfo/jetty-users

_______________________________________________
jetty-users mailing list
[email protected]
https://dev.eclipse.org/mailman/listinfo/jetty-users

Reply via email to