Execute JSP directly from Java - java

I need to execute a JSP. But I need to directly from Java, without using Tomcat or any other servlet container. Compiling JSPs would be a good thing too, but not necessary. I think maybe org.apache.jasper package is good for doing this, but I can't find any good example or tutorial online.
I need something as:
Class compiledJSP = compileJSP(new File("helloWorld.jsp"));
String html = executeJSP(compiledJSP, httpServletRequest, httpServletResponse, ...);
html --> "Hello World, John!"
Thanks!

If you need to capture JSP's output as string it's reasonably straightforward (although far from ideal from the design point of view) from within Servlet Container:
1. Extend javax.servlet.HttpServletResponseWrapper and override getWriter() / getOutputStream() methods to provide your own buffered versions (e.g. StringWriter)
2. Invoke "include()" method of RequestDisparcher, wrapping original response in your own.
3. Grab buffer's content.
Now if you need to do the same thing outside Servlet Container, you really need to ask yourself "why?". Perhaps you should be using a template engine (FreeMarker / Velocity / StringTemplate / etc...) instead of JSPs? If your JSPs are well-formed XML files and are not using any java code inserts it may be reasonably trivial to convert them to FreeMarker templates (FreeMarker supports custom JSP tag libraries) which would greatly simplify your task.
Nevertheless, if it's an absolute hard requirement your most straightforward options are:
1. Run an external Servlet Container and let it handle JSP interpretation. Your program would submit HTTP requests to it and capture the output.
2. Same as above, but you can run embedded Servlet Container (e.g. Jetty).
If your JSPs are available at build-time you can precompile them via Jasper as suggested in other answers.
I would strongly advice against trying to implement your own servlet container - you'll be walking into a world of hurt.

You will need a container. A JSP is an abstraction on Servlet. Servlets have a dependency on a life cycle provided by a container.You need a container to provide the life cycle.

This is possible without a servlet container. There are two steps to it.
The first is to generate the source code. If you look at the source code of the jspc ant task it is possible to do it directly in code. Or you could just invoke the ant task.
The code that is generated is just a Servlet and it is possible to invoke the methods on a servlet outside of a container:
Just instantiate it and then call doGet(request, response). I'm not sure exactly what you need this for but your life will be made easier using spring mock objects for the http request and response.
This will populate the Response object. you can then get the output with:
res.getContentAsString();
See an example here:
http://ytreyvus.blogspot.com/2007/03/private-void-cloneplaneffectrelationshi.html

Try MockRunner to execute it. You'll need to compile the JSP first, though. I'm using Maven 2 for this (and the JSP Compiler plugin)

Related

Would testing my Java Servlet be neccessary?

I just wanted to ask if it is necessary to test the java servlet that calls another java method (in another file I might add) to do the bulk of the work.
Like for instance, my java servlet currently only is being used to get parameters and displaying the results of the method that was called in html format. So I am only planning on testing my main java file that does all the work!
I am not very familiar with testing so if there would be specific ways to test this simple Java servlet, please let me know!
Testing your Java Servlet or for that case, any Java code is very necessary. The way we always tend to write any code is called the HAPPY PATH, which sometimes overlooks possible scenarios that might break your service. It is always a best practice to code via the TDD way (test driven).
You can Unit Test your Servlet alone, if it does perform the main logic as a single unit.
You can perform Integration testing if your Servlet along with other Java code performs the logic as a whole.
There is this question on SO which covers almost all the details on how to perform this and also the various choices to choose from to perform them.
Hope this helps!
Like for instance, my java servlet currently only is being used to get
parameters and displaying the result of the method is has called in
html format. So I am only planning on testing my main java file that
does all the work!
Ideally, you should Why so?
If something messy happens and servlet broke befoe calling the Main business logic
Testing how parameters are fetched so you can be sure which kind of parameters my Servlet can handle (I personally don't like junk values to be passed to my business logic).

Interact with JSP compiler

I have some text templates stored in a database. We need to use a templating engine to process these texts. We first thought of Velocity / Freemaker / Thymeleaf to process these texts. However, I thought (but could be wrong) that one could interact with the application server JSP compiler. I'd prefer to use JSP compiler rather than importing a new bunch of jars.
Thanks
AFAIK they are different concepts and work differently so they won't directly interact :
JSP is processed by a JSP compiler to generate java code for a servlet that is compiled (at run-time) in a .class file. It is later used by the servlet container as any other servlet. You can include any java code in a JSP with scriptlets (even if it now considered as bad practice)
template engines (Velocity / Freemaker / Thymeleaf) take a template and only allow to replace variable place holders with values at run time to produce text. Of course, they also allow tests and loops, but no java source nor class object is ever generated. In a web application they use one single servlet that takes the template and the replacement values and generate the text that will be sent in the response.
But of course as JSP can contain arbitrary java code, you could call a template engine from a JSP, but I really cannot imagine a proper use case.
Edit per comment:
You could try to use JSP as a template engine, but my advice is : don't do that ! You would need :
create a stub implementing ServletResponse where the getOutputStream() and the getWriter() methods end in a String.
force the ServletContainer to generate the java source and the class file - or manage to do that at compile time (I don't know how exactly how to do that, but I'm pretty sure it can be done)
at run time include the generated servlet with the response stub to generate the output String.
But beware, even if you succeed, it will lead to hardly maintainable code heavily coupled to a servlet container or using special steps (JSP -> java) at build time. As already said : don't do that.
I've just come to JSP compilation to string or in memory bytearray with Tomcat/Websphere, looks like your question is a duplicate of that one ...

Read a JSP file and produce HTML - not with a web server

If I wanted to read a jsp like:
File f = new File("my.jsp");
and then I want it to produce the expected HTML as say a String (byte[], OutputStream, whatever), How would I do that?
I assume there is some transformer or something. Can anyone point me in the right direction?
A JSP File is translated and compiled as a Servlet class, so it not directly generate a html File, the reason is a JSP as a Servlet could generate dynamic html depending of the parameters in the request, in the tomcat server it use the Jasper 2 JSP Engine to implement the JavaServer Pages 2.1 specification that process the JSP, so you can check it but I don't recommend you do that.
Maybe what your really want is a template mechanism, for example you have a text file similar to the jsp with similar sintax to the EL that can access some objects, so you can use the template engine and bound your object with the text and produce your html. If it works for you, you can use Apache Velocity - HTML example or FreeMaker - HTML example.
Jasper is the JSP compiler used by Tomcat, it takes the JSP pages themselves, parses them, and generates Java code (in the form of a servlet, or at least it used to be) which writes the JSP's output to the servlet response. That Java code would then be compiled and executed against the containers implementation of the Servlet API.
Jasper is a standalone library, so in theory you could instantiate its classes inside your own harness, point it at a JSP, generate the servlet code, then compile and execute it. However you'd need to pass in your own mock implementations of the Servlet API interfaces, as it's these that will be called to determine request parameters (HttpServletRequest), and to write the response (HttpServletResponse). You'd need to provide a version of HttpServletResponse that will buffer up the output for you to grab later.
From the Tomcat 6 API, this bits your want are in the org.apache.jasper package.
Taking a look at at it you'd probably want to create a JspCompilationContext which points to your JSP, call createCompiler(), and take it from there.
As far as mocking out the Servlet API goes, you might get what you need from the stub implemetations provided by the Spring Framework for testing purposes
Velocity and FreeMarker are both excellent for this, and much easier for basic templating.
However, it can be done.
I have an example explained here: Tomcat JSP/JSTL without HTTP
It's obviously easier from within a web app (as all of the jars will be there), but it can be done outside, you'll just need to identify and the appropriate jars to your program.

Convert Java Servlet to Standalone Java Application

I have a legacy Java servlet that is currently running in a Tomcat container. I want to run it outside the container, as a standalone Java application. The primary intention in doing so is because the new role in which this application will be deployed, involves only computation, and no servicing of requests.
How should I go about modifying the servlet code? Will pulling out the servlet's init() code into the main() method of a new class help?
Extract the functionality you want from the servlet to other classes, so that the servlet is only the web interface to the functionality.
Those other classes should ideally not use anything in javax.servlet.*.
Then create a separate class with a main method that uses those other classes, in an appropriate way.
I would transform the servlet class into a main class, as you mentioned. The main method of the new class will create an instance of main class, execute init method to initialise if (potentially using the arguments received from the command line). Then invoke the service method inside a try/catch/finally block and invoke the destroy method of the servlet inside the finally block. Of course, your new service method will be invoked without parameters and will not contain any references to the servlet api.
yes.
The servlet implements the interface to interact with the Tomcat servlet container. If there are no settings read from the servlet context (path names, configuration paramters) you can extract the logic into a main class.
You will need to make sure you do not rely on the request/response scheme in your services. Usually if only one process runs code is much easier to write than in concurrent scenarios. But one cannot be sure there will be no such effect (for example caches that are now request based will not be emptied in standalone).
also remove any servlet api dependencies in your code. It will not work and is no longer required.
good luck!
You have to do that carefully. It may happen that some filters are doing necessary work not seen within the servlet
Assuming your case is rather simple and a GET or POST just triggers the code, it should be easy to convert into a classical java application.
Just call the former init part and the code from doGet or doPost respectly.
You need to figure out a couple of things first, the functionality in the servlet will probably react to some of the url's parameters.
first figure out what the computational part is and what parameters it expects,
once you understand that, figuring out what to put in your standalone application will be trivial.
another approach is to embed Jetty in your main application and let that run your servlet,
this will leave your servlet code untouched reducing the risk of introducing bugs

JSP recompilation needed?

I just want the general idea about what will happen in the following situation, without getting into the technical details.
The main advantage of JSP is that we have separate presentation (static HTML) and dynamic application logic. So we can make changes into either of them without affecting the other. Now suppose, we have a precompiled JSP into either a servlet or bytecode, and we want to make a change in the presentation part, would we then have to recompile the whole stuff, even though we did not make any change in the application logic?
Thanks everyone for the answer, but all the answers that I get do point to the fact that whether automatically or manually, the JSP does need to be recompiled into the servlet, which is then converted into the corresponding byctecode. In short a completely new file would be created I suppose.
As long as it is JSP, you dont need to compile/convert. The application server automatically translates your JSP into corresponding servlet, a Java file (on the first hit to the JSP), and then compiles it to class file. Whenever you update the JSP file and when the server receives request for that resource (JSP) it checks the last updated time and does the above job if required.
Yes and no. JSP's are ultimately compiled into servlets, but the servlet container will usually recompile the JSP for you if it has changed, which is a fairly quick operation.
No. If you change the JSP, generally speaking the servlet/jsp container will 'see' the jsp changed and will recompile it.
That being said, i'm not clear on your deployment model. if you're 'precompiling' the asps and adding those to your .war then you might be out of luck.

Categories

Resources