Alvins
Alvins

Reputation: 887

JSP compilation on Android (Jetty embedded)

I'm running Jetty on Android platform to serve static html pages and servlet. Now i've tried to add support for JSP pages but i got this exception when i ask for any jsp:

HTTP ERROR 500

Problem accessing /time.jsp. Reason:

    Server Error

Caused by:

org.apache.jasper.JasperException: PWC6033: Error in Javac compilation for JSP

PWC6199: Generated servlet error:
The type java.lang.Object cannot be resolved. It is indirectly referenced from required .class files

PWC6199: Generated servlet error:
The type java.lang.Throwable cannot be resolved. It is indirectly referenced from required .class files

PWC6199: Generated servlet error:
The type java.lang.String cannot be resolved. It is indirectly referenced from required .class files

PWC6199: Generated servlet error:
org.apache.jasper.runtime.HttpJspBase cannot be resolved to a type

PWC6199: Generated servlet error:
org.apache.jasper.runtime.JspSourceDependent cannot be resolved to a type

PWC6199: Generated servlet error:
JspFactory cannot be resolved to a type

PWC6199: Generated servlet error:
JspFactory cannot be resolved

PWC6199: Generated servlet error:
java.util.List cannot be resolved to a type

PWC6199: Generated servlet error:
Syntax error, parameterized types are only available if source level is 1.5 or greater

PWC6199: Generated servlet error:
String cannot be resolved to a type

PWC6199: Generated servlet error:
org.glassfish.jsp.api.ResourceInjector cannot be resolved to a type

PWC6199: Generated servlet error:
java.util.List cannot be resolved to a type

PWC6199: Generated servlet error:
Syntax error, parameterized types are only available if source level is 1.5 or greater

PWC6199: Generated servlet error:
String cannot be resolved to a type

PWC6199: Generated servlet error:
_jspx_dependants cannot be resolved to a variable

PWC6199: Generated servlet error:
HttpServletRequest cannot be resolved to a type

PWC6199: Generated servlet error:
HttpServletResponse cannot be resolved to a type

PWC6199: Generated servlet error:
java.io.IOException cannot be resolved to a type

PWC6199: Generated servlet error:
ServletException cannot be resolved to a type

PWC6199: Generated servlet error:
PageContext cannot be resolved to a type

PWC6199: Generated servlet error:
HttpSession cannot be resolved to a type

PWC6199: Generated servlet error:
ServletContext cannot be resolved to a type

PWC6199: Generated servlet error:
ServletConfig cannot be resolved to a type

PWC6199: Generated servlet error:
JspWriter cannot be resolved to a type

PWC6199: Generated servlet error:
Object cannot be resolved to a type

PWC6199: Generated servlet error:
JspWriter cannot be resolved to a type

PWC6199: Generated servlet error:
PageContext cannot be resolved to a type

PWC6199: Generated servlet error:
_jspxFactory cannot be resolved

PWC6199: Generated servlet error:
_jspx_resourceInjector cannot be resolved to a variable

PWC6199: Generated servlet error:
org.glassfish.jsp.api.ResourceInjector cannot be resolved to a type

PWC6197: An error occurred at line: 3 in the jsp file: /time.jsp
PWC6199: Generated servlet error:
java.util.Date cannot be resolved to a type

PWC6199: Generated servlet error:
Throwable cannot be resolved to a type

PWC6199: Generated servlet error:
SkipPageException cannot be resolved to a type

PWC6199: Generated servlet error:
ServletException cannot be resolved to a type

PWC6199: Generated servlet error:
_jspxFactory cannot be resolved


    at org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:129)
    at org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:299)
    at org.apache.jasper.compiler.Compiler.generateClass(Compiler.java:392)
    at org.apache.jasper.compiler.Compiler.compile(Compiler.java:453)
    at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:625)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:492)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:378)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:457)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1075)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:384)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1009)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
    at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:52)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
    at org.eclipse.jetty.server.Server.handle(Server.java:370)
    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
    at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:949)
    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1011)
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:644)
    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:668)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
    at java.lang.Thread.run(Thread.java:856)

Powered by Jetty://

Here is my configuration code from main activity:

public void startServer()
{
        server = new Server(8080);

        System.setProperty("org.apache.jasper.compiler.disablejsr199", "true");

      // Create a resource handler for static content.
        ResourceHandler staticResourceHandler = new ResourceHandler();
        staticResourceHandler.setResourceBase(Environment.getExternalStorageDirectory().getAbsolutePath() + "/web/static/");
        staticResourceHandler.setDirectoriesListed(false);

        // Create context handler for static resource handler.
        ContextHandler staticContextHandler = new ContextHandler();
        staticContextHandler.setContextPath("/static");
        staticContextHandler.setHandler(staticResourceHandler);

        // Create WebAppContext for JSP files.
        WebAppContext webAppContext = new WebAppContext();
        webAppContext.setContextPath("/");
        webAppContext.setResourceBase(Environment.getExternalStorageDirectory().getAbsolutePath() + "/web/");
        webAppContext.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", "false");

        // Create servlet context handler for main servlet.
        ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
        servletContextHandler.setContextPath("/servlet");
        servletContextHandler.setResourceBase(Environment.getExternalStorageDirectory().getAbsolutePath() + "/web/servlet/");

        terminalServlet = new TerminalServlet(this);
        networkServlet = new NetworkDrawerServlet(this);
        servletContextHandler.setClassLoader(Thread.currentThread().getContextClassLoader());
        servletContextHandler.addServlet(new ServletHolder(terminalServlet),"/terminal");
        servletContextHandler.addServlet(new ServletHolder(networkServlet),"/topology");
        //servletContextHandler.addServlet(new ServletHolder(new DefaultServlet()), "/*");

        // Create a handler list to store our static, jsp and servlet context handlers.
        HandlerList handlers = new HandlerList();
        handlers.setHandlers(new org.eclipse.jetty.server.Handler[] { staticContextHandler, webAppContext, servletContextHandler });

        // Add the handlers to the server and start jetty.
        server.setHandler(handlers);
    try {
        server.start();
    } catch (Exception e) {
    }
}

I place the webserver files (static content and jsp file) under "/web/" directory in extarnal storage (and it works for static content, i've setted read and write privilege in manifest file).

I think it's a general confgiuration problem under Android, because the same code compiled and executed on desktop works fine.

Upvotes: 3

Views: 1974

Answers (2)

Joakim Erdfelt
Joakim Erdfelt

Reputation: 49462

JSP is not possible on Android.

Or to be more accurate, compiling JSP on an Android device is not possible.

The existing JspServlet implementations will attempt to compile *.java source into a directory as *.class files, the standard javac isn't present, so you would think you can lean on the JDT implementation written by Eclipse to do this, but even this will not work for some basic reasons.

  1. The basic class library isn't present in the standard places that the JDT compiler looks for. This is why you see all the "cannot resolve" errors.
  2. Compiling to *.class files is pointless on android, as the actual Android device itself does not understand *.class files. It is not Java, but rather Dalvik, which happens to be compatible (at the development / build time) to Java.
  3. Android's Dalvik VM expects dexified bytecode, the JDT compiler cannot produce that.
  4. I know of no on-device dexify tool, library, or utility that could do this last step for you. If one does exist, you would need to fork and modify the JSP implementation to include this extra step.

If you want to develop in JSP and have a webapp on android, this is what you need to do:

  1. Remove the JspServlet from your web.xml or webdefault.xml. You can't use it on Android anyway.
  2. Pre-compile your JSP's on your development machine.
  3. Update your WEB-INF/web.xml to include the compiled JSP references. Look at the various JSPC tooling out there, they all support this concept (either as a XML fragment suitable for inclusion, or by direct modification of your existing WEB-INF/web.xml.
  4. Dexify the post-compiled WAR file using the techniques outlined at the i-jetty project.

This will allow you to develop with JSPs, and use them on Android, but not as the raw *.jsp file itself, but rather the compiled *.class files (which are then dexified into the Android bytecode format).

Upvotes: 4

Related Questions