Po DW
Po DW

Reputation: 103

Embedded Jetty Error The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved

I'm using Embedded Jetty server to run my tests and Maven for build. Following is the code used to start Jetty before tests.

System.out.println("Initializing Jetty Server...");
jettyServer = new Server(0);

WebAppContext webapp = new WebAppContext("src/main/webapp", "/testApp");
jettyServer.addHandler(webapp);

jettyServer.start();
int actualPort = jettyServer.getConnectors()[0].getLocalPort();
String baseUrl = "http://localhost:" + actualPort + "/testApp";

All the tests passes if I run it with 'Run as Junit Test'. No problems here.

But if I run it as Maven Test or Maven Install The tests fails withe following cause

Caused by: com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException: 500 /WEB-INF/pages/test1.jsp(3,62) PWC6188: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application

I have the JSTL dependancy added in POM.xml. Please help to resolve this..

Upvotes: 0

Views: 996

Answers (2)

ericminio
ericminio

Reputation: 116

In the following repo: https://github.com/ericminio/learning-jetty

You can find:

  1. The JstlTest that demoes Jetty serving jsp containing a c:forEach tag
  2. The pom needed to remove the error message about resolving http://java.sun.com/jsp/jstl/core

Hope it helps

Upvotes: 1

Joakim Erdfelt
Joakim Erdfelt

Reputation: 49515

You didn't initialize and setup the environment in a way that is suitable for JSP use.

It requires a bunch of extra work.

You'll need to manipulate classloaders, setup some initializers, declare the javac implementation behavior, and even declare the jsp servlet handling. (missing any one of these and you'll be subject to the environment that you executed under, which is different in your 3 examples)

For a complete example maven project see https://github.com/jetty-project/embedded-jetty-jsp

public class Main
{
    // Resource path pointing to where the WEBROOT is
    private static final String WEBROOT_INDEX = "/webroot/";

    public static void main(String[] args) throws Exception
    {
        int port = 8080;
        LoggingUtil.config();
        Log.setLog(new JavaUtilLog());

        Main main = new Main(port);
        main.start();
        main.waitForInterrupt();
    }

    private static final Logger LOG = Logger.getLogger(Main.class.getName());

    private int port;
    private Server server;
    private URI serverURI;

    public Main(int port)
    {
        this.port = port;
    }

    public URI getServerURI()
    {
        return serverURI;
    }

    public void start() throws Exception
    {
        server = new Server();
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(port);
        server.addConnector(connector);

        URL indexUri = this.getClass().getResource(WEBROOT_INDEX);
        if (indexUri == null)
        {
            throw new FileNotFoundException("Unable to find resource " + WEBROOT_INDEX);
        }

        // Points to wherever /webroot/ (the resource) is
        URI baseUri = indexUri.toURI();

        // Establish Scratch directory for the servlet context (used by JSP compilation)
        File tempDir = new File(System.getProperty("java.io.tmpdir"));
        File scratchDir = new File(tempDir.toString(),"embedded-jetty-jsp");

        if (!scratchDir.exists())
        {
            if (!scratchDir.mkdirs())
            {
                throw new IOException("Unable to create scratch directory: " + scratchDir);
            }
        }

        // Set JSP to use Standard JavaC always
        System.setProperty("org.apache.jasper.compiler.disablejsr199","false");


        // Setup the basic application "context" for this application at "/"
        // This is also known as the handler tree (in jetty speak)
        WebAppContext context = new WebAppContext();
        context.setContextPath("/");
        context.setAttribute("javax.servlet.context.tempdir",scratchDir);
        context.setResourceBase(baseUri.toASCIIString());
        context.setAttribute(InstanceManager.class.getName(), new SimpleInstanceManager());
        server.setHandler(context);

        // Add Application Servlets
        context.addServlet(DateServlet.class,"/date/");

        //Ensure the jsp engine is initialized correctly
        JettyJasperInitializer sci = new JettyJasperInitializer();
        ServletContainerInitializersStarter sciStarter = new ServletContainerInitializersStarter(context);
        ContainerInitializer initializer = new ContainerInitializer(sci, null);
        List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
        initializers.add(initializer);

        context.setAttribute("org.eclipse.jetty.containerInitializers", initializers);
        context.addBean(sciStarter, true);



        // Set Classloader of Context to be sane (needed for JSTL)
        // JSP requires a non-System classloader, this simply wraps the
        // embedded System classloader in a way that makes it suitable
        // for JSP to use
        ClassLoader jspClassLoader = new URLClassLoader(new URL[0], this.getClass().getClassLoader());
        context.setClassLoader(jspClassLoader);

        // Add JSP Servlet (must be named "jsp")
        ServletHolder holderJsp = new ServletHolder("jsp",JspServlet.class);
        holderJsp.setInitOrder(0);
        holderJsp.setInitParameter("logVerbosityLevel","DEBUG");
        holderJsp.setInitParameter("fork","false");
        holderJsp.setInitParameter("xpoweredBy","false");
        holderJsp.setInitParameter("compilerTargetVM","1.7");
        holderJsp.setInitParameter("compilerSourceVM","1.7");
        holderJsp.setInitParameter("keepgenerated","true");
        context.addServlet(holderJsp,"*.jsp");
        //context.addServlet(holderJsp,"*.jspf");
        //context.addServlet(holderJsp,"*.jspx");

        // Add Example of mapping jsp to path spec
        ServletHolder holderAltMapping = new ServletHolder("foo.jsp", JspServlet.class);
        holderAltMapping.setForcedPath("/test/foo/foo.jsp");
        context.addServlet(holderAltMapping,"/test/foo/");

        // Add Default Servlet (must be named "default")
        ServletHolder holderDefault = new ServletHolder("default",DefaultServlet.class);
        LOG.info("Base URI: " + baseUri);
        holderDefault.setInitParameter("resourceBase",baseUri.toASCIIString());
        holderDefault.setInitParameter("dirAllowed","true");
        context.addServlet(holderDefault,"/");

        // Start Server
        server.start();

        // Show server state
        if (LOG.isLoggable(Level.FINE))
        {
            LOG.fine(server.dump());
        }

        // Establish the Server URI
        String scheme = "http";
        for (ConnectionFactory connectFactory : connector.getConnectionFactories())
        {
            if (connectFactory.getProtocol().equals("SSL-http"))
            {
                scheme = "https";
            }
        }
        String host = connector.getHost();
        if (host == null)
        {
            host = "localhost";
        }
        int port = connector.getLocalPort();
        serverURI = new URI(String.format("%s://%s:%d/",scheme,host,port));
        LOG.info("Server URI: " + serverURI);
    }

    public void stop() throws Exception
    {
        server.stop();
    }

    /**
     * Cause server to keep running until it receives a Interrupt.
     * <p>
     * Interrupt Signal, or SIGINT (Unix Signal), is typically seen as a result of a kill -TERM {pid} or Ctrl+C
     */
    public void waitForInterrupt() throws InterruptedException
    {
        server.join();
    }
}

Upvotes: 1

Related Questions