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 ...
Related
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.
I'm working on a project that uses an old, custom-built CMS to run a website that is quite heavy in JavaScript. Throughout a given template (.jsp), they're using Java conditionals to set up inline JavaScript variables and functions. They're also making external JavaScript and CSS requests all over the place. This has led to some very poor performance, as you can imagine.
I'm trying to organize things so that most of the JavaScript is in external files, being called before the closing body tag. One of the tricky parts of this is externalizing inline JavaScript when they're using Java to create variables. As far as i know, I can't drop bits of Java into a .js file.
The solution I've come up with is to create an object into which Java can print some variable values, and then pass them on to the external JS files. For example:
var foo = new Object;
foo.bar = <s:property value="bar" escape="false"/>;
Then in the external file:
(function(){
console.log(foo.bar);
}());
From a conceptual standpoint, does this seem like a valid solution? It seems to work fine, but I'm wondering if there's a specific reason that I shouldn't do it this way. Please excuse my wording if I'm not using the proper terms.
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.
I'm trying to build (or find an existing one I can use) a web filter that will compress a JavaScript file at runtime. I've tried building one based on YUICompressor, but I'm getting weird errors out of it when I try and pass a String based source into it instead of an actual file.
Now I'm expecting to get bombarded with responses like 'Real time compression/minification is a bad idea' but there is a reason I'm not wanting to do it at build time.
I've got a JavaScript web application that lazy loads it's JavaScript. It will only load what it actually needs. The JavaScript files can specify dependencies and I already have a filter that will concatenate the requested files and any dependencies not already loaded into a single response. This means that there is a large number of different combinations in the JavaScript that will be sent to the user which makes trying to build all the bundles at build time impractical.
So to restate. Ideally I'm looking for an existing real time javascript filter I can just plug into my app.
If one doesn't exist I'm looking for tips on what I can use as building blocks. YUICompressor hasn't quite got me there and GoogleClosure seems to only be a web API.
Cheers,
Peter
Take a look at The JavaScript Minifier from Douglas Crockford. The source is here: JSMin.java. It's not a filter and only contains the code to minify. We've made it into a filter where we combine and minify JavaScript on the fly as well. It works well, especially if you have browsers and a CDN cache results.
Update: I left out that we cache them on the server too. They're only regenerated if any of the assets required to make the combined and minified output have changed. Basically instead of "compiling" them at build time, we handle each combination once at runtime.
I already have a filter that will
concatenate the requested files and
any dependencies not already loaded
into a single response
Sooo.. Why not just minify those prior to loading/concatenating them?
(And yes, compression on the fly is horribly expensive and definitely not worth doing for every .js file served up)
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)