I am developing an application using Java and Spring MVC. As usual, stored one JSP file in /WEB-INF/view/ folder which is working as the View for all the requests.
Normally we have this JSP hard-coded that also has some codes to process the Model (tags and EL). Things are working fine till this point.
Now instead of hard-coding the JSP, I want to populate this JSP file dynamically from the database. So the user can upload and select different templates/themes/layouts to display his pages.
Here is the code to explain what I am trying to do (I know this is not the way but for illustration purpose only).
/WEB-INF/views/index.jsp
<%# page import="com.example.domain.Template" %>
<%# page import="com.example.dao.TemplateStore" %>
<!-- Following code is supposed to return complete JSP template from the database as uploaded by the user. -->
<%= TemplateStore.getUserTemplate("userTemplate") %>
I searched web for this topic but could not find anything.
Any help on how to accomplish this would be highly appreciated.
Thanks in advance.
IMPORTANT: I have asked this question a few days ago but marked as "off-the-topic" by some members. I am yet to understand how this question is off-the-topic - https://stackoverflow.com/questions/18026092/creating-content-of-jsp-views-in-web-inf-views-dynamically-from-the-database.
If view templates are to be dynamically fetched from a database, you shouldn't think of JSP. JSPs are compiled into servlet classes and there's little support for doing that other than the standard way (static files somewhere under your webapp root).
Therefore, just consider switching the view technology (at least for the dynamic part) to some general-purpose templating library like Velocity or Freemarker. This comes with a security bonus, since there's less one can break from within such a template than from within JSP code.
You could even support multiple view technologies (perhaps anything that Spring MVC supports out-of-the-box, except for JSP) and allow your users to choose the type of template when uploading.
Then you can write a custom view resolver which would delegate to the appropriate standard resolver (Velocity, Freemarker, XSLT, whatever...) with the user-selected template.
However, if JSP is a hard requirement, I guess one ugly workaround for JSP (which should work in any servlet container) could be to fetch content from the DB and create an actual file (like WEB-INF/templates/${primarky-key}.jsp) under your exploded webapp root, then RequestDispatcher.forward() to it.
You might or might not be able to do this with JSP, but you can certainly compile Java code in memory and then call it.
http://www.java2s.com/Code/Java/JDK-6/CompilingfromMemory.htm
Of course going from JSP to Servlet would just be another step.
Related
I am migrating my java web-application project from JSP to thymeleaf.
I want temporarily to have ability to reuse some simple custom JSP tags in thymeleaf pages. It seems not a problem with custom tags defined in old fashion, as java files. I just instantiate tag, set fake PageContext, request and response, attribtes - and call doStartTag / doEndTag.
However I could not find a way how to instantiate object representing JSP 2.0 tag (i.e. defined in a ".tag" file. How can I achieve this?
Thanks in advance for any ideas!
It looks there are two ways:
Use jspc-maven-plugin to get precompiled classes from jsp and tag files - I checked that works - however latest version of this plugin is 2.0-alpha-3 and it is 4 years old now.
Access servlet-container jsp compiler (in most cases jasper) and do the same thing as in first variant, but on demand, in execution time. However, this makes application container-dependent.
(My personal opinion now is that it would better to avoid the idea at whole - all solutions looks too unreliable to use in production)
If I'm using HttpServlet's for my controllers, and I've got my models setup and in a specific package, what about the views? The last thing I want is to dump all of this HTML into my controllers. Where do I put it? What file types?
I'm new to Java :)
Update
If I should be using jsp files, wouldn't having jsp files within my "Web Pages" section make them publicly viewable? Or should they go somewhere else? How do I include them on my page and pass parameters to them?
If you are using servlets (which seems to be the case), your view should go in JSP files. If you are using JSF, you put your view in facelets, but it is not the case since you are using servlets. JSF is the most recent specification, but I bet it is better to start by JSPs and servlets - maybe following the official tutorial.
EDIT: how to dispatch a request from the servlet to a JSP? Just get a RequestDispatcher from the ServletRequest passing the JSP path as parameter:
RequestDispatcher dispatcher = request.getRequestDispatcher("/index.jsp");
If the dispatcher is different from null, just call its include() forward() method:
dispatcher.forward(request, response);`
The dispatcher can be null (for example, if the JSP does not exist) so it is a good practice to verify if a proper dispatcher was returned.
jsps or javascript if you are going for a rich internet application (RIA).
You most likely want jsps.
JSPs are for views. So they should be public. JSPs dont expose anything except for html that your output just as you would in PHP. The source does not show unless you have configured your server incorrectly.
Also you can pass objects from servlet to jsp through shared objects as they are in same vm. JSP is servlet reversed so instead of printing HTML from java you embed Java in html which saves you from writing out.print statements....
So servlets are more suited to write actions. JSP for views.
You might also look into spending some time learning JSTL too. It makes your JSPs clean and readable: http://docs.oracle.com/javaee/5/tutorial/doc/bnakc.html
Keep in mind, a user will not be able to see the code in your JSP, the web container actually compiles the JSP file much like the JVM (actually in a very similar fashion) compiles source code. If you are using something like Tomcat, you can look at a compiled JSP in the work directory of your web container. It will look surprisingly like a normal class file with a lot of out.write's in it.
I started out with an html page. Then, I renamed the file with a .jsp extension, as I will be using jsp to accomplish this particular task.
Which is: I wish to take a value from the page on a form, send it to sql to be used in a where clause, then send the data set back to the same page. Now, I could likely employ AJAX, instead of submitting a form. I would appreciate some advice, like a step-by-step procedure, for I'm bewildered about at least a couple of items. 1) Can I write the JSP code in the same page? 2) Can or should I write SQL inside the JSP code? 3) Should I Have another page set up just for JSP?
I suppose I'm looking for a "Hello World" explanation, as I've primarily worked with non-java based languages in the past.
Thank you.
1) You can write JSP (Java) code in the same file, but it is not recommended.
2) Same as 1. you can write SQL code in JSP, but you shouldnt.
3) HTMLs renamed to JSPs are perfectly valid jsp files.
I suggest that you use a MVC framework like Spring MVC to do your task. Here's a tutorial.
UPDATE: Standard JSP & servlet tutorials
http://archive.coreservlets.com/Chapter3.html
http://archive.coreservlets.com/Chapter16.html
http://archive.coreservlets.com/Chapter15.html
http://archive.coreservlets.com/Chapter3.html
For quick and dirty, you should look at using the JSTL SQL tags. They're pretty easy to use, actually, and eliminate much of the JDBC cruft if you simply embedded Java.
This page is a decent little example that covers most of the fundamentals, for SQL with JSTL.
I would like to invoke the JSP parser programmatically. That means that I want to be able, in Java, to 'run' a jsp page and get its output, without sending it back to the client (I actually want to save the output to a file). I don't want to 'forward' the request to the JSP page. I want to be able to do that on several JSP pages in a row.
What is the best way of doing this?
I have found this question, but BalusC doesn't really answer the question directly.
In case you are wondering, I need to do this is because I want to 'precompile' the JSPs for using on other platforms than a Java servlet container.
EDIT
What I need is not the .class file, but the HTML output. Indeed, that will be static once generated but I have some custom jsp tags and I want to leverage the JSP parser to expand them.
I'm not sure that I understand the point of all this.
JSPs are parsed and precompiled to .class files. They're Java servlets at that point. You need a servlet engine to execute them.
If your intent is to capture the generated HTTP response as the "precompiled" response, it would suggest that there's no dynamic content and the response is the same every time you send that particular request. If that's the case, what you've got is static HTML.
If I'm correct, this would seem to be a poor way to generate such a thing.
If your wish is to precompile JSPs to .class files, the problem is that different Java EE app servers use different JSP precompilation engines. You can't precompile JSPs using Tomcat and use them on WebLogic.
The best way to get the html output from a jsp page is to actually deploy it to a real webserver and then call the page and save the rendered output.
If you want to automate some part of this, you might want to look into using a testing tool that exercises through the real interface, such as Selenium or that emulates the browser, such as HttpUnit.
But this is doing much more than just invoking the JSP compiler.
Maybe it would be more practical to use template engines like http://freemarker.sourceforge.net/ or http://velocity.apache.org/
Freemarker even seems to support JSP Taglibs: http://freemarker.sourceforge.net/features.html
Is your JSP dynamically generated. If so then you are stepping into a potential disadvantage situation wherein your JSP will be compiled again and again, leading to performance issues.
However if you could have a single large JSP with all the rules that you need to prepare your display, you could use HttpClient to make a call to your own JSP and that would return the HTML. This would ensure that you are not app-server dependent. If you use JSP Parser you are going to be vendor dependent.
But if your JSP is being dynamically constructed then you should look at options wherein your HTML can be generated on Java side. But if it involved rule based HTML creation, you are better off creating it in Java. You can use Apache Jakarta ECS library for this.
And yes JSPs are not meant for this purpose.
I'm about to choose to way to organize my view (with spring-mvc, but that shouldn't matter much)
There are 6 options as far as I see (though they are not mutually exclusive):
Tiles
Sitemesh
Freemarker
Velocity
<jsp:include>
<%# include file="..">
Tiles and Sitemesh can be grouped; so can Freemarker and Velocity. Which one within each group to use is not a matter of this discussion, there are enough questions and discussions about it.
This is an interesting read, but can't quite convince me to use tiles.
My question is - what do these frameworks give that can't be properly done with <# include file=".."> and JSTL. Main points (some taken from the article):
Including parts of pages, like header and footer - there isn't a difference between:
<%# include file="header.jsp" %>
and
<tiles:insert page="header.jsp" />
Defining parameters in the header - like title, meta tags, etc. This is very important, especially from SEO point of view. With the templating options you can simply define a placeholder which each page should define. But so you can in jsp with JSTL, using <c:set> (in the including page) and <c:out> (in the included page)
Layout reorganization - if you want to move the breadcrumb above the menu, or the login box above another side-panel. If page inclusions (with jsp) is not well organized, you might need to change every single page in such cases. But if your layout is not overly complex, and you put the common things in header/footer, there is nothing to worry about.
Coupling between the common components and the specific content - I don't find an issue with this. If you want to reuse some fragment, move it to a page that doesn't include any header/footer, and include it wherever needed.
Efficiency - <%# include file="file.jsp" %> is more efficient than anything else, because it is compiled once. All other options are parsed/executed many times.
Complexity - all non-jsp solutions require additional xml files, additional includes, pre-processor configurations, etc. This is both a learning curve and introducing more potential points of failure. Also, it makes support and changing more tedious - you have to check a number of files/configurations in order to understand what's happening.
Placeholders - do velocity/freemarker give anything more than JSTL? In JSTL you put placeholder, and use the model (placed in request or session scope, by controllers) to fill these placeholders.
So, convince me that I should use any of the above frameworks instead of/in addition to plain JSP.
A few arguments for Velocity (I haven't used Freemarker):
Potential to re-use templates outside of a web context, such as in sending emails
Velocity's template language syntax is far simpler than JSP EL or tag libraries
Strict separation of view logic from any other sort of logic - no possible option to drop down to using scriptlet tags and doing nasty things in your templates.
Placeholders - do velocity/freemaker give anything more than JSTL? In JSTL you put placeholder, and use the model (placed in request or session scope, by controllers) to fill these placeholders.
Yes, references are really the core of VTL:
<b>Hello $username!</b>
or
#if($listFromModel.size() > 1)
You have many entries!
#end
Efficiency - <%# include file="file.jsp" %> is more efficient than anything else, because it is compiled once. All other options are parsed/executed many times.
Not so sure I agree with or understand this point. Velocity has an option to cache templates, meaning the abstract syntax tree they are parsed into will be cached rather than read from disk each time. Either way (and I don't have solid numbers for this), Velocity has always just felt fast for me.
Layout reorganization - if you want to move the breadcrumb above the menu, or the login box above another side-panel. If page inclusions (with jsp) is not well organized, you might need to change every single page in such cases. But if your layout is not overly complex, and you put the common things in header/footer, there is nothing to worry about.
The difference is, with a JSP approach, wouldn't you be re-organzing this layout in every JSP file that uses the same header/footer? Tiles and SiteMesh allow you to specify a base layout page (JSP, Velocity template, etc - both are JSP frameworks at their heart) where you can specify whatever you want and then just delegate to a "content" fragment/template for the main content. This means there would be just one file to move the header in.
The choice between jsp:include and Tiles/Sitemesh/etc is the choice between simplicity and power that developers face all the time. Sure, if you only have a few files or don't expect your layout to change very often, then just use jstl and jsp:include.
But applications have a way of growing incrementally, and it can be hard to justify the "stop new development and retrofit tiles (or some other solution) so we can fix future problems more easily", which is required if you don't use a complex solution in at the start.
If your sure your application will always remain simple, or you can set some benchmark of application complexity after which you will integrate one of the more complex solutions, then I'd recommend not using tiles/etc. Otherwise, use it from the get-go.
I'm not going to convince you to use other technologies. For all I know everyone should just stick to JSP if it works for them.
I work mainly with Spring MVC and I find JSP 2+ in combination with SiteMesh the perfect match.
SiteMesh 2/3
Provide decorators to be applied to the views mostly like inheritance works in other templating engines. Such feature is unthinkable to work without nowadays.
JSP 2+
People claiming that JSP will make it hard to avoid Java code in templates is bogus. You just shouldn't do it and with this version it's unnecessary to do so. Version 2 supports calling methods using EL which is a big advantage compared to previous versions.
With JSTL tags your code will still look like HTML so it's less awkward. Spring packs a lot of support for JSP through taglibs which is very powerful.
The taglibs are also easy to extend so customizing your own environment is a breeze.
One of the best arguments for facelets (not in your list, but I'll just mention it) opposed to using JSP is that the compilation is integrated with the interpreter instead of being delegated to the JSP compiler. This means that one of the most annoying things I had with JSF 1.1 - having to change the id-attribute on a surrounding JSF-tag when saving a change in order for the runtime engine to discover the change - went away, giving the save-in-editor, reload-in-browser cycle back, along with much better error messages.
A good view technology eliminates most and most anoying if/switch/conditional statements, simple include does not. Using a 'complex' view technology results in a 'simple' application.
You didn't provide information about specific of your applications. For example I do not use JSP just for few reasons:
It is hard to avoid using Java code in JSP templates so your break concept of pure View, and as result you will have difficulties to maintain code in several places as view and controller
JSP automatically creates JSP context which establishes a session. I may want to avoid it, however if your applications always use session it can be not a problem for you
JSP requires compilation and if target system doesn't have Java compiler, any minor tweaking will require to use other system and then redeploy
Minimal JSP engine is about 500k of bytecode plus JSTL, so it can be not suitable for embedded systems
Template engine can generate different content type of the same model, let say JSON payload, webpage, e-mail body, CSV and so on.
Non Java programmer may have difficulties to work with JSP templates, when non technical people never had difficulties to modify regular templates.
I was asking same question long time ago and ended by writing my framework (surely template engine based) which was free from all disadvantages I saw in other solutions. Needless to say it is about 100k of byte code.
I realize that this comes off as a smart ass answer, but the truth of it is, if you don't see any advantage to using templating over code in your current project, it's probably because in your current project, there isn't one.
Part of it is about scale. You might think that includes are every bit as powerful as let's say sitemesh, and that's certainly true, at least for a small number of pages (I'd say probably about 100), but if you have several thousands it starts becoming unmanageable. (So for eBay it's not necessary, for Salesforce it probably is)
Also, as has been mentioned before, freemarker and velocity are not servlet specific. you can use them for anything (mail templates, offline documentation, etc.). You do not need a Servlet container to use freemarker or velocity.
Lastly your point 5 is only partially true. It is compiled every time it is accessed if it has not been so already. This mean that whenever you change something you need to remember to delete your servlet containers "work" directory, so that it recompiles the JSP. This is unnecessary with a templating engine.
TL;DR Templaing engines were written to address some (perceived or real) shortcomings of JSP + JSTL. Whether you should use them or not depends entirely on your requirements and the scale of your project.