Is it possible to use JSP/JSTL to generate dynamic css/javascript files?
What you want to do is assign the *.css servlet mapping to the JSPServlet.
In most containers, you will see a mapping like this (this is from Glassfish, in it's default-web.xml):
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
Here, it is declaring the JSP servlet, and mapping "*.jsp" to it. So, in this case, the JSP servlet reference name is, simply 'jsp'.
So you would want to add:
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
When you do that, "suddenly" ALL of your CSS files are, effectively, JSPs, so you can do with them whatever you want.
The detail is I don't know if 'jsp' is the same for ALL containers, so your web.xml MAY NOT be portable.
But that's the gist of what you want to do. If you don't want ALL CSS to be JSPs, you could put the files in their own directory, and map that to the JSP servlet. Then ANYTHING you put in there would be a JSP (css, js, etc.)
i'm dynamically generating css and js using jsp/jstl/spring. How to place this result in link tag at head section. not in script tag in head section
I achieved this.
I created a new route /resource/css|js , I use internal resource view resolver - (folder).
My link url is moething like /resource/css/qtn/page1.css.
In controller /resources/{type}/{page}.css.
Here i get type and page values and used this in my dynamic jsp page to achieve my result.
For security i checked the url is it comes from my own page or not.
Hint :
While using internal resource view resolver it will throw error when you pass page values directly to resource url because sometimes page url will be /page1/block1 so our controller throws error.
To solve this i passed page values as /resource/css/qtn/page1.css?sub=${page}.
In controller we can easily cath this sub value and send to our dynamic jsp as model.
how to use dynamic css in jsp file base on param value
You can append the request attribute's value to the class
attribute in the JSP :
<td class="td-type<%=type%>">
As a side note, the use of scriptlets (java code in JSP's) is strongly discouraged. Use JSTL and EL instead. In this question you'll find out Why and how to avoid Java Code in JSP files.
<td class="td-type${type}">
Or, if you wanted to implement an if-else like construct, for instance :
<c:choose>
<c:when test="${type eq "2"}">
<c:set var="varclass" value="td-type2"/>
</c:when>
<c:otherwise>
<c:set var="varclass" value="td-type1"/>
</c:otherwise>
</c:choose>
<td class="${varClass}">
Adding external resources (CSS/JavaScript/images etc) in JSP
The reason that you get the 404 File Not Found
error, is that your path to CSS given as a value to the href
attribute is missing context path.
An HTTP request URL contains the following parts:
http://[host]:[port][request-path]?[query-string]
The request path is further composed of the following elements:
Context path: A concatenation of a forward slash (/) with the context
root of the servlet's web application. Example:http://host[:port]/context-root[/url-pattern]
Servlet path: The path section that corresponds to the component
alias that activated this request. This path starts with a forward
slash (/).Path info: The part of the request path that is not part of the
context path or the servlet path.
Read more here.
Solutions
There are several solutions to your problem, here are some of them:
1) Using <c:url>
tag from JSTL
In my Java web applications I usually used <c:url>
tag from JSTL when defining the path to CSS/JavaScript/image and other static resources. By doing so you can be sure that those resources are referenced always relative to the application context (context path).
If you say, that your CSS is located inside WebContent folder, then this should work:
<link type="text/css" rel="stylesheet" href="<c:url value="/globalCSS.css" />" />
The reason why it works is explained in the "JavaServer Pages™ Standard Tag Library" version 1.2 specification chapter 7.5 (emphasis mine):
7.5 <c:url>
Builds a URL with the proper rewriting rules applied.
...
The URL must be either an absolute URL
starting with a scheme (e.g. "http:// server/context/page.jsp") or a
relative URL as defined by JSP 1.2 in JSP.2.2.1 "Relative URL
Specification". As a consequence, an implementation must prepend the
context path to a URL that starts with a slash (e.g. "/page2.jsp") so
that such URLs can be properly interpreted by a client browser.
NOTE
Don't forget to use Taglib directive in your JSP to be able to reference JSTL tags. Also see an example JSP page here.
2) Using JSP Expression Language and implicit objects
An alternative solution is using Expression Language (EL) to add application context:
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/globalCSS.css" />
Here we have retrieved the context path from the request object. And to access the request object we have used the pageContext implicit object.
3) Using <c:set>
tag from JSTL
DISCLAIMER
The idea of this solution was taken from here.
To make accessing the context path more compact than in the solution №2, you can first use the JSTL <c:set>
tag, that sets the value of an EL variable or the property of an EL variable in any of the JSP scopes (page, request, session, or application) for later access.
<c:set var="root" value="${pageContext.request.contextPath}"/>
...
<link type="text/css" rel="stylesheet" href="${root}/globalCSS.css" />
IMPORTANT NOTE
By default, in order to set the variable in such manner, the JSP that contains this set tag must be accessed at least once (including in case of setting the value in the application scope using scope attribute, like <c:set var="foo" value="bar" scope="application" />
), before using this new variable. For instance, you can have several JSP files where you need this variable. So you must ether a) both set the new variable holding context path in the application scope AND access this JSP first, before using this variable in other JSP files, or b) set this context path holding variable in EVERY JSP file, where you need to access to it.
4) Using ServletContextListener
The more effective way to make accessing the context path more compact is to set a variable that will hold the context path and store it in the application scope using a Listener. This solution is similar to solution №3, but the benefit is that now the variable holding context path is set right at the start of the web application and is available application wide, no need for additional steps.
We need a class that implements ServletContextListener interface. Here is an example of such class:
package com.example.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class AppContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent event) {
ServletContext sc = event.getServletContext();
sc.setAttribute("ctx", sc.getContextPath());
}
@Override
public void contextDestroyed(ServletContextEvent event) {}
}
Now in a JSP we can access this global variable using EL:
<link type="text/css" rel="stylesheet" href="${ctx}/globalCSS.css" />
NOTE
@WebListener annotation is available since Servlet version 3.0. If you use a servlet container or application server that supports older Servlet specifications, remove the @WebServlet annotation and instead configure the listener in the deployment descriptor (web.xml). Here is an example of web.xml file for the container that supports maximum Servlet version 2.5 (other configurations are omitted for the sake of brevity):
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
...
<listener>
<listener-class>com.example.listener.AppContextListener</listener-class>
</listener>
...
</webapp>
5) Using scriptlets
As suggested by user @gavenkoa you can also use scriptlets like this:
<%= request.getContextPath() %>
For such a small thing it is probably OK, just note that generally the use of scriptlets in JSP is discouraged.
Conclusion
I personally prefer either the first solution (used it in my previous projects most of the time) or the second, as they are most clear, intuitive and unambiguous (IMHO). But you choose whatever suits you most.
Other thoughts
You can deploy your web app as the default application (i.e. in the default root context), so it can be accessed without specifying context path. For more info read the "Update" section here.
Using scriptlets inside a .CSS file?
The .jsp
files are compiled by the container, so you have to write the you css class in .jsp
file make sure the response content type is text/css
and add the JSP file to your html like below.
<link rel="stylesheet" href="filename.jsp">
How to dynamically import javascript and css files
Sort of, yes.
boolean condition = evaluateItSomehow();
request.setAttribute("condition", condition);
request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);
Then in page.jsp
using JSTL c:if
:
<head>
<c:if test="${condition}">
<link rel="stylesheet" type="text/css" href="style.css">
<script type="text/javascript" src="script.js"></script>
</c:if>
...
</head>
Update: since you seem to have more than one files for this, you can even make it more flexible by just setting the desired filename suffix (or prefix, or even the entire name, what you like):
String suffix = evaluateItSomehow();
request.setAttribute("suffix", suffix);
request.getRequestDispatcher("/WEB-INF/page.jsp").forward(request, response);
and
<head>
<link rel="stylesheet" type="text/css" href="style_${suffix}.css">
<script type="text/javascript" src="script_${suffix}.js"></script>
...
</head>
If you set suffix
to for example "foo"
, this will load style_foo.css
and script_foo.js
. I think this gives enough new insights.
Better way to set LI width in JSP / JSTL
You can simply do it like this :
<li style="width:${number}%;">hello</li>
The usage of c:out
is useful to escape XML, for example if number
content is :
<ul></ul>
the output will be
<ul></ul>
More info :
- JSTL c:out
Related Topics
Jersey Rest Web Service with Activemq Middleware Integration
How to Send Put, Delete Http Request in Httpurlconnection
Javafx - What Is This Weird Container That Holds Context Menu
Universal Way to Write to External Sd Card on Android
Error Launching Android Studio: Failed to Create Jvm: Error Code-6
How to Sort Alphabetically While Ignoring Case Sensitive
Change Icons of Checked and Unchecked for Checkbox for Android
Classnotfoundexception: Didn't Find Class "Com.Google.Android.Gms.Ads.Adview"
Create a Bitmap/Drawable from File Path
How to Read Firestore Sub-Collection and Pass It to Firestorerecycleroptions
How to Access a Folder Inside of a Resource Folder from Inside My Jar File
How to Get the Selected Index of a Radiogroup in Android
How to Give Images Rounded Corners in Android
Change Listview Background - Strange Behaviour
Android Simpledateformat, How to Use It
How to Prevent Gson from Expressing Integers as Floats
Android Unable to Instantiate Activity: Didn't Find Class on Path