Embedded Jetty server cannot see web pages in context root

I am using jetty v9.2.10.v20150310 with java version "1.8.0_45" in a Linux box with kernel 3.18.9.

The problem is that if I set the context path to non root; those. / embed, I can access my webpage on my embedded jetty server. However, if I set the context path to root; that is, "/" I cannot access the page. Interestingly, this issue does not occur when I interact with the servlet via curl.

Here is the code:

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

final String servletWebDir = "/";
servletHandler.setContextPath( servletWebDir );

final customServlet iass = new customServlet();

final ServletHolder servletHolder = new ServletHolder( iass );
servletHolder.setInitOrder(0);
servletHandler.addServlet( servletHolder, "/customServlet" );

final ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setDirectoriesListed(false);
resourceHandler.setResourceBase(".");

final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ servletHandler, resourceHandler } );

server.setHandler( handlers );

      

If I change servletWebDir from "/" to "/ embed" everything works as it should. If not, I get a 404.

I can successfully communicate with the servlet via curl commands. a:

curl http: // host: 8080 / customServlet? command = exp

If I try to use http: // host: 8080 / customServlet in Firefox or chrome with servletWebDir set to "/" I get 404. Note that this code works fine in jetty v8.1.16.v20140903 mode.

What am I doing wrong? What am I missing in Jetty v9.x?

Updated code to use setBaseResource and discard ResourceHandler:

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
final String servletWebDir = "/";
final String theBaseResourceDir = "/aa/bb/cc";
Resource theBaseResource = null;
try{
    theBaseResource = Resource.newResource( theBaseResourceDir );
}
catch( MalformedURLException e ){
    System.err.println( "setup failed on newResource with the exception " + e.toString() );
    System.exit(0);
}

servletHandler.setBaseResource( theBaseResource );
System.err.println("Class path->" + servletHandler.getClassPath() );

final customServlet iass = new customServlet();
final ServletHolder servletHolder = new ServletHolder( iass );
servletHolder.setInitOrder(0);
servletHandler.addServlet( servletHolder, "/customServlet" );
final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ servletHandler } );
server.setHandler( handlers );

      

This new code no longer serves as a static page for the web browser regardless of the value of servletWebDir. Interacting with a custom servlet via curl still works. If the above new code is correct, am I missing something? The classpath is reported as null in the error logs. What can I try next?

Joakim:

I tried the code you suggested. I really appreciate the time and effort you put into preparing the sample code. However, the code doesn't work at runtime. The error log says:

STDERR: 2015-05-09 15: 51: 32.278: WARN: / embed: main: unavailable java.lang.IllegalAccessException: class org.eclipse.jetty.server.handler.ContextHandler $ The context cannot access the customServlet class with modifiers "private" at sun.reflect.Reflection.ensureMemberAccess (Reflection.java:102)

The exception does not define the exact member to be posted. My updated code actually works and I don't need to change a whole bunch of methods from private to public.

Joakim, please explain the benefits of your solution, which, if I'm not mistaken, requires changing private methods and data members to the public of data members and methods, and therefore losing some of the benefits of encapsulation.

Updated code that fixes this issue:

server = new Server();
final ServerConnector connector = getConnector( server );
connector.setReuseAddress(false);
connector.setSoLingerTime(0);

final int port = 8080;
connector.setHost( theHostName );
connector.setPort( port );

server.addConnector(connector);

final String theRootContextDir = "/";
final ContextHandler rootContext = new ContextHandler(theRootContextDir);
final String theBaseResourceDir = ".";
rootContext.setResourceBase( theBaseResourceDir );

final ResourceHandler rhx = new ResourceHandler();
rootContext.setHandler( rhx );

/**
  * I want to replace the default jetty error handler with my
  * custom error handler. However I have not figured out how
  * to do it under jetty v9.x, yet-(May.08.2015,W.S.)
  * final ErrorHandler uiErrHandler = new userInputErrorHandler( logger );
  * rootContext.setErrorHandler( uiErrHandler );
  ***/

final ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);

final String theServletContextPath = "/";
servletHandler.setContextPath( theServletContextPath );
servletHandler.setResourceBase( "." );

final customServlet iass = new customServlet();
final ServletHolder servletHolder = new ServletHolder( iass );
final MultipartConfigElement mce = new MultipartConfigElement( fileUploadTmpDir );
servletHolder.getRegistration().setMultipartConfig( mce );
servletHolder.setInitOrder(0);
final String theServletName = "/customServlet";
servletHandler.addServlet( servletHolder, theServletName );

final HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]{ rootContext, servletHandler } );

server.setHandler( handlers );

      

+3


source to share


1 answer


You are using ServletContextHandler

, you cannot mix this with ResourceHandler

, as the inline DefaultServlet

ServletContextHandler

will serve files (or give an error response), leaving ResourceHandler

to never execute.

To fix it:

Discard ResourceHandler

(its far below DefaultServlet

).

Install servletHandler.setBaseResource(Resource)

to the root directory of your web application (where your static files are located). This can be a link to a URL, a URI, or a file system path.

Examples:



// As a file system reference
servletHandler.setBaseResource(Resource.newResource("/path/to/res"));

// or URL
servletHandler.setBaseResource(Resource.newResource("jar:file://tmp/b.jar!/webroot"));

      

The resource path must point to a directory, not a specific file.

See the previous answer on this for details .

Example:

package jetty;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.nio.file.Path;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.resource.Resource;

public class SimpleServletExample
{
    public static void main(String[] args)
    {
        try
        {
            Server server = new Server(8080);

            // Find the full path to the webroot.
            // Use the real path, with real file system case for all parts of the path
            // Otherwise we fall afoul of alias checking.
            // (esp on OSX and Windows. Unix and Linux do not have this issue)
            Path webrootPath = new File("src/test/resources/sample-files").toPath().toRealPath();

            URI webrootUri = webrootPath.toUri();

            System.err.println("webroot uri: " + webrootUri);

            Resource webroot = Resource.newResource(webrootUri);
            if (!webroot.exists())
            {
                System.err.println("Resource does not exist: " + webroot);
                System.exit(-1);
            }

            if (!webroot.isDirectory())
            {
                System.err.println("Resource is not a directory: " + webroot);
                System.exit(-1);
            }

            // Establish ServletContext for all servlets
            ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
            context.setContextPath("/");
            context.setBaseResource(webroot);
            // What file(s) should be used when client requests a directory
            context.setWelcomeFiles(new String[] { "index.html" });
            server.setHandler(context);

            // Add a servlet (technique #1)
            ServletHolder holderHello = context.addServlet(HelloServlet.class,"/hello");
            holderHello.setInitOrder(0);

            // Add default servlet last (always last) (technique #2)
            // Must be named "default", must be on path mapping "/"
            ServletHolder holderDef = new ServletHolder("default",DefaultServlet.class);
            holderDef.setInitParameter("dirAllowed","true");
            context.addServlet(holderDef,"/");

            // Start server
            server.start();
        }
        catch (MalformedURLException e)
        {
            System.err.println("Unable to establish webroot");
            e.printStackTrace(System.err);
        }
        catch (Throwable t)
        {
            t.printStackTrace(System.err);
        }
    }
}

      

+1


source







All Articles