I need programmaticaly render JSP page.
What's the functional requirement after all? You're clearly looking for a solution in the wrong direction. What is it, the problem/requirement for which you think that this is the solution? We may come up with better suggestions.
Do you for example need just its output? If so, then java.net.URLConnection
may suffice.
Edit: you edited your question:
I want to change source JSP before compilation in some way (merge two JSP together to be precise), so I need a way to compile JSP result from InputStream (or Reader) using JSP compiller directly.
OK, that's a bit more clear. But what for do you need this? What does those JSPs actually represent? What is the final result supposed to be used for?
Do you for example just want to include the one JSP in the other? E.g. including a head.jsp
in a main.jsp
? If so, then <jsp:include>
may suffice. Or is it more worse, do they contain raw Java code with some specific code which you wanted to reuse? If so, then you should use plain Java classes and if necessary taglibs for this.
Edit 2: as you commented:
But now we need a way to use these JSP pages (which are store is in memory by the way) as layouts for all JSP pages that user request
Just store the JSP files on the disk file system inside the webapp's webcontent (the ServletContext#getRealPath()
may come into rescue here) and forward the request to your own main JSP file which includes the two JSP files using for example:
<jsp:include page="${page1}" />
<jsp:include page="${page2}" />
Edit 3: I created an SSCCE to prove its working.
package mypackage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
File root = new File(getServletContext().getRealPath("/"));
String main = "<jsp:include page=\"${page1}\" /><jsp:include page=\"${page2}\" />";
write(main, new File(root, "main.jsp"));
String page1 = "<p>We are in ${data1}";
write(page1, new File(root, "page1.jsp"));
request.setAttribute("page1", "page1.jsp");
request.setAttribute("data1", "first jsp");
String page2 = "<p>We are in ${data2}";
write(page2, new File(root, "page2.jsp"));
request.setAttribute("page2", "page2.jsp");
request.setAttribute("data2", "second jsp");
request.getRequestDispatcher("main.jsp").forward(request, response);
}
private static void write(String content, File file) throws IOException {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
writer.write(content);
} finally {
if (writer != null) try { writer.close(); } catch (IOException ignore) {}
}
}
}
Execute it at http://localhost:8080/playground/test (or whatever host/contextname you're using) and you'll see
We are in first jsp
We are in second jsp
To make it more efficient I would cache every resource and make use of File#exists()
to check if the particular page is already saved on disk.