Rectangle 27 1044

JSP is a Java view technology running on the server machine which allows you to write template text in client side languages (like HTML, CSS, JavaScript, ect.). JSP supports taglibs, which are backed by pieces of Java code that let you control the page flow or output dynamically. A well-known taglib is JSTL. JSP also supports Expression Language, which can be used to access backend data (via attributes available in the page, request, session and application scopes), mostly in combination with taglibs.

When a JSP is requested for the first time or when the web app starts up, the servlet container will compile it into a class extending HttpServlet and use it during the web app's lifetime. You can find the generated source code in the server's work directory. In for example Tomcat, it's the /work directory. On a JSP request, the servlet container will execute the compiled JSP class and send the generated output (usually just HTML/CSS/JS) through the web server over a network to the client side, which in turn displays it in the web browser.

Servlet is a Java application programming interface (API) running on the server machine, which intercepts requests made by the client and generates/sends a response. A well-known example is the HttpServlet which provides methods to hook on HTTP requests using the popular HTTP methods such as GET and POST. You can configure HttpServlets to listen to a certain HTTP URL pattern, which is configurable in web.xml, or more recently with Java EE 6, with @WebServlet annotation.

When a Servlet is first requested or during web app startup, the servlet container will create an instance of it and keep it in memory during the web app's lifetime. The same instance will be reused for every incoming request whose URL matches the servlet's URL pattern. You can access the request data by HttpServletRequest and handle the response by HttpServletResponse. Both objects are available as method arguments inside any of the overridden methods of HttpServlet, such as doGet() and doPost().

JSF is a component based MVC framework which is built on top of the Servlet API and provides components via taglibs which can be used in JSP or any other Java based view technology such as Facelets. Facelets is much more suited to JSF than JSP. It namely provides great templating capabilities such as composite components, while JSP basically only offers the <jsp:include> for templating, so that you're forced to create custom components with raw Java code (which is a bit opaque and a lot of tedious work in JSF) when you want to replace a repeated group of components with a single component. Since JSF 2.0, JSP has been deprecated as view technology in favor of Facelets.

As being a MVC (Model-View-Controller) framework, JSF provides the FacesServlet as the sole request-response Controller. It takes all the standard and tedious HTTP request/response work from your hands, such as gathering user input, validating/converting them, putting them in model objects, invoking actions and rendering the response. This way you end up with basically a JSP or Facelets (XHTML) page for View and a JavaBean class as Model. The JSF components are used to bind the view with the model (such as your ASP.NET web control does) and the FacesServlet uses the JSF component tree to do all the work.

<c:forEach>
<mytag:doesSomething/>
<jsp:attribute>

Since this is a hugely popular answer, I want to add a very important bit which is JSP tag files which allows for custom tag creation for page composition and layout without writing Java code. This feature is extremly useful and has been part of the standard for many years yet remains underutilized.

@johnny Facelets has been the preferred view technology since Java EE 6 was released in 2009 (docs.oracle.com/javaee/6/tutorial/doc/giepx.html). The minimum set of technologies to develop Java web apps isn't higher than most other languages, but there are many more options and competitors, which is confusing to newcomers. Web development in Ruby? The first choice is obvious.

java - What is the difference between JSF, Servlet and JSP? - Stack Ov...

java jsp jsf servlets java-ee
Rectangle 27 1041

JSP is a Java view technology running on the server machine which allows you to write template text in client side languages (like HTML, CSS, JavaScript, ect.). JSP supports taglibs, which are backed by pieces of Java code that let you control the page flow or output dynamically. A well-known taglib is JSTL. JSP also supports Expression Language, which can be used to access backend data (via attributes available in the page, request, session and application scopes), mostly in combination with taglibs.

When a JSP is requested for the first time or when the web app starts up, the servlet container will compile it into a class extending HttpServlet and use it during the web app's lifetime. You can find the generated source code in the server's work directory. In for example Tomcat, it's the /work directory. On a JSP request, the servlet container will execute the compiled JSP class and send the generated output (usually just HTML/CSS/JS) through the web server over a network to the client side, which in turn displays it in the web browser.

Servlet is a Java application programming interface (API) running on the server machine, which intercepts requests made by the client and generates/sends a response. A well-known example is the HttpServlet which provides methods to hook on HTTP requests using the popular HTTP methods such as GET and POST. You can configure HttpServlets to listen to a certain HTTP URL pattern, which is configurable in web.xml, or more recently with Java EE 6, with @WebServlet annotation.

When a Servlet is first requested or during web app startup, the servlet container will create an instance of it and keep it in memory during the web app's lifetime. The same instance will be reused for every incoming request whose URL matches the servlet's URL pattern. You can access the request data by HttpServletRequest and handle the response by HttpServletResponse. Both objects are available as method arguments inside any of the overridden methods of HttpServlet, such as doGet() and doPost().

JSF is a component based MVC framework which is built on top of the Servlet API and provides components via taglibs which can be used in JSP or any other Java based view technology such as Facelets. Facelets is much more suited to JSF than JSP. It namely provides great templating capabilities such as composite components, while JSP basically only offers the <jsp:include> for templating, so that you're forced to create custom components with raw Java code (which is a bit opaque and a lot of tedious work in JSF) when you want to replace a repeated group of components with a single component. Since JSF 2.0, JSP has been deprecated as view technology in favor of Facelets.

As being a MVC (Model-View-Controller) framework, JSF provides the FacesServlet as the sole request-response Controller. It takes all the standard and tedious HTTP request/response work from your hands, such as gathering user input, validating/converting them, putting them in model objects, invoking actions and rendering the response. This way you end up with basically a JSP or Facelets (XHTML) page for View and a JavaBean class as Model. The JSF components are used to bind the view with the model (such as your ASP.NET web control does) and the FacesServlet uses the JSF component tree to do all the work.

<c:forEach>
<mytag:doesSomething/>
<jsp:attribute>

Since this is a hugely popular answer, I want to add a very important bit which is JSP tag files which allows for custom tag creation for page composition and layout without writing Java code. This feature is extremly useful and has been part of the standard for many years yet remains underutilized.

@johnny Facelets has been the preferred view technology since Java EE 6 was released in 2009 (docs.oracle.com/javaee/6/tutorial/doc/giepx.html). The minimum set of technologies to develop Java web apps isn't higher than most other languages, but there are many more options and competitors, which is confusing to newcomers. Web development in Ruby? The first choice is obvious.

java - What is the difference between JSF, Servlet and JSP? - Stack Ov...

java jsp jsf servlets java-ee
Rectangle 27 16

You seem to concentrate on only the presentation and flow-control part of the scriptlets as in using if, for and switch statements and out.print() things. You seem to compare scriptlets 1:1 with JSTL. This is wrong. I was not talking about the flow control part only (which is indeed to be replaced by JSTL), but about writing raw Java code in JSP files in general. I.e. gathering request parameters, validating and converting values, interacting with database and other Java classes/methods, etc. All things you normally (indirectly) do in a Servlet or Filter.

from now on, pure java code in servlets , filters and context listener only and JSTL in JSPs.

java - JSTL vs JSP Scriptlets - Stack Overflow

java jsp jstl
Rectangle 27 16

You seem to concentrate on only the presentation and flow-control part of the scriptlets as in using if, for and switch statements and out.print() things. You seem to compare scriptlets 1:1 with JSTL. This is wrong. I was not talking about the flow control part only (which is indeed to be replaced by JSTL), but about writing raw Java code in JSP files in general. I.e. gathering request parameters, validating and converting values, interacting with database and other Java classes/methods, etc. All things you normally (indirectly) do in a Servlet or Filter.

from now on, pure java code in servlets , filters and context listener only and JSTL in JSPs.

java - JSTL vs JSP Scriptlets - Stack Overflow

java jsp jstl
Rectangle 27 76

XSS can be prevented in JSP by using JSTL <c:out> tag or fn:escapeXml() EL function when (re)displaying user-controlled input. This includes request headers, cookies, URL, body, parameters, etc, the whole request. Also the user-controlled input which is stored in a database needs to be escaped during redisplaying.

<p><c:out value="${bean.userControlledValue}"></p>
<p><input name="foo" value="${fn:escapeXml(param.foo)}"></p>

This will escape characters which may malform the rendered HTML such as <, >, ", ' and & into HTML/XML entities such as , , , and .

Note that you don't need to escape them in the Java (Servlet) code, since they are harmless over there. Some may opt to escape them during request processing (as you do in Servlet) instead of response processing (as you do in JSP), but this way you may risk that the data unnecessarily get double-escaped or that the DB-stored data becomes unportable (e.g. when exporting data to CSV, XLS, PDF, etc which doesn't require HTML-escaping at all).

If you'd like to redisplay user-controlled input as HTML wherein you would like to allow only a specific subset of HTML tags like <b>, <i>, <u>, etc, then you need to sanitize the input by a whitelist. You can use a Markdown parser like Pegdown or a HTML parser like Jsoup for this. See also I'm looking for a Java HTML encoder.

The only concern in the server side with regard to databases is SQL injection prevention. You need to make sure that you never string-concatenate user-controlled input straight in the SQL or JPQL query and that you're using parameterized queries all the way. In JDBC terms, this means that you should use PreparedStatement instead of Statement. In JPA terms, use Query.

An alternative would be to migrate from JSP/Servlet to Java EE's MVC framework JSF. It has builtin XSS prevention over all place. See also CSRF, XSS and SQL Injection attack prevention in JSF.

@chad: that's not true. It's only the case when you're string-concatenating user-controlled input straight in the SQL/HQL/JPQL query like so "SELECT ... WHERE SOMEVAL = " + someval instead of using parameterized queries as you've shown. No one ORM can safeguard against this kind of developer mistakes.

@BalusC - Doh! I had that reversed. Vulnerable example is: Query query = session.createQuery("SELECT * FROM TABLE WHERE SOMEVAL = " + someval); Using the binding syntax ":" in Hibernate (like my example above) prevents SQL injection. Deleting comment to prevent someone using my bad example.

I think you DO have to validate in the server aswell. All the validation can be bypassed by altering the HTTP parameters. And sometimes, the data that you persist can be consumed by other applications in an enterprise app. Sometimes you dont have access to the views of the other applications so you need to sanitze the input before persisting in the database.

@Guido: you're not understanding the problem.

java - XSS prevention in JSP/Servlet web application - Stack Overflow

java security jsp servlets xss
Rectangle 27 76

XSS can be prevented in JSP by using JSTL <c:out> tag or fn:escapeXml() EL function when (re)displaying user-controlled input. This includes request headers, cookies, URL, body, parameters, etc, the whole request. Also the user-controlled input which is stored in a database needs to be escaped during redisplaying.

<p><c:out value="${bean.userControlledValue}"></p>
<p><input name="foo" value="${fn:escapeXml(param.foo)}"></p>

This will escape characters which may malform the rendered HTML such as <, >, ", ' and & into HTML/XML entities such as , , , and .

Note that you don't need to escape them in the Java (Servlet) code, since they are harmless over there. Some may opt to escape them during request processing (as you do in Servlet) instead of response processing (as you do in JSP), but this way you may risk that the data unnecessarily get double-escaped or that the DB-stored data becomes unportable (e.g. when exporting data to CSV, XLS, PDF, etc which doesn't require HTML-escaping at all).

If you'd like to redisplay user-controlled input as HTML wherein you would like to allow only a specific subset of HTML tags like <b>, <i>, <u>, etc, then you need to sanitize the input by a whitelist. You can use a Markdown parser like Pegdown or a HTML parser like Jsoup for this. See also I'm looking for a Java HTML encoder.

The only concern in the server side with regard to databases is SQL injection prevention. You need to make sure that you never string-concatenate user-controlled input straight in the SQL or JPQL query and that you're using parameterized queries all the way. In JDBC terms, this means that you should use PreparedStatement instead of Statement. In JPA terms, use Query.

An alternative would be to migrate from JSP/Servlet to Java EE's MVC framework JSF. It has builtin XSS prevention over all place. See also CSRF, XSS and SQL Injection attack prevention in JSF.

@chad: that's not true. It's only the case when you're string-concatenating user-controlled input straight in the SQL/HQL/JPQL query like so "SELECT ... WHERE SOMEVAL = " + someval instead of using parameterized queries as you've shown. No one ORM can safeguard against this kind of developer mistakes.

@BalusC - Doh! I had that reversed. Vulnerable example is: Query query = session.createQuery("SELECT * FROM TABLE WHERE SOMEVAL = " + someval); Using the binding syntax ":" in Hibernate (like my example above) prevents SQL injection. Deleting comment to prevent someone using my bad example.

I think you DO have to validate in the server aswell. All the validation can be bypassed by altering the HTTP parameters. And sometimes, the data that you persist can be consumed by other applications in an enterprise app. Sometimes you dont have access to the views of the other applications so you need to sanitze the input before persisting in the database.

@Guido: you're not understanding the problem.

java - XSS prevention in JSP/Servlet web application - Stack Overflow

java security jsp servlets xss
Rectangle 27 78

XSS can be prevented in JSP by using JSTL <c:out> tag or fn:escapeXml() EL function when (re)displaying user-controlled input. This includes request parameters, headers, cookies, URL, body, etc. Anything which you extract from the request object. Also the user-controlled input from previous requests which is stored in a database needs to be escaped during redisplaying.

<p><c:out value="${bean.userControlledValue}"></p>
<p><input name="foo" value="${fn:escapeXml(param.foo)}"></p>

This will escape characters which may malform the rendered HTML such as <, >, ", ' and & into HTML/XML entities such as , , , and .

Note that you don't need to escape them in the Java (Servlet) code, since they are harmless over there. Some may opt to escape them during request processing (as you do in Servlet or Filter) instead of response processing (as you do in JSP), but this way you may risk that the data unnecessarily get double-escaped (e.g. & becomes amp; instead of and ultimately the enduser would see being presented), or that the DB-stored data becomes unportable (e.g. when exporting data to JSON, CSV, XLS, PDF, etc which doesn't require HTML-escaping at all). You'll also lose social control because you don't know anymore what the user has actually filled in. You'd as being a site admin really like to know which users/IPs are trying to perform XSS, so that you can easily track them and take actions accordingly. Escaping during request processing should only and only be used as latest resort when you really need to fix a train wreck of a badly developed legacy web application in the shortest time as possible. Still, you should ultimately rewrite your JSP files to become XSS-safe.

If you'd like to redisplay user-controlled input as HTML wherein you would like to allow only a specific subset of HTML tags like <b>, <i>, <u>, etc, then you need to sanitize the input by a whitelist. You can use a HTML parser like Jsoup for this. But, much better is to introduce a human friendly markup language such as Markdown (also used here on Stack Overflow). Then you can use a Markdown parser like CommonMark for this. It has also builtin HTML sanitizing capabilities. See also I'm looking for a Java HTML encoder.

The only concern in the server side with regard to databases is SQL injection prevention. You need to make sure that you never string-concatenate user-controlled input straight in the SQL or JPQL query and that you're using parameterized queries all the way. In JDBC terms, this means that you should use PreparedStatement instead of Statement. In JPA terms, use Query.

An alternative would be to migrate from JSP/Servlet to Java EE's MVC framework JSF. It has builtin XSS (and CSRF!) prevention over all place. See also CSRF, XSS and SQL Injection attack prevention in JSF.

@chad: that's not true. It's only the case when you're string-concatenating user-controlled input straight in the SQL/HQL/JPQL query like so "SELECT ... WHERE SOMEVAL = " + someval instead of using parameterized queries as you've shown. No one ORM can safeguard against this kind of developer mistakes.

@BalusC - Doh! I had that reversed. Vulnerable example is: Query query = session.createQuery("SELECT * FROM TABLE WHERE SOMEVAL = " + someval); Using the binding syntax ":" in Hibernate (like my example above) prevents SQL injection. Deleting comment to prevent someone using my bad example.

I think you DO have to validate in the server aswell. All the validation can be bypassed by altering the HTTP parameters. And sometimes, the data that you persist can be consumed by other applications in an enterprise app. Sometimes you dont have access to the views of the other applications so you need to sanitze the input before persisting in the database.

@Guido: you're not understanding the problem.

java - XSS prevention in JSP/Servlet web application - Stack Overflow

java security jsp servlets xss
Rectangle 27 78

XSS can be prevented in JSP by using JSTL <c:out> tag or fn:escapeXml() EL function when (re)displaying user-controlled input. This includes request parameters, headers, cookies, URL, body, etc. Anything which you extract from the request object. Also the user-controlled input from previous requests which is stored in a database needs to be escaped during redisplaying.

<p><c:out value="${bean.userControlledValue}"></p>
<p><input name="foo" value="${fn:escapeXml(param.foo)}"></p>

This will escape characters which may malform the rendered HTML such as <, >, ", ' and & into HTML/XML entities such as , , , and .

Note that you don't need to escape them in the Java (Servlet) code, since they are harmless over there. Some may opt to escape them during request processing (as you do in Servlet or Filter) instead of response processing (as you do in JSP), but this way you may risk that the data unnecessarily get double-escaped (e.g. & becomes amp; instead of and ultimately the enduser would see being presented), or that the DB-stored data becomes unportable (e.g. when exporting data to JSON, CSV, XLS, PDF, etc which doesn't require HTML-escaping at all). You'll also lose social control because you don't know anymore what the user has actually filled in. You'd as being a site admin really like to know which users/IPs are trying to perform XSS, so that you can easily track them and take actions accordingly. Escaping during request processing should only and only be used as latest resort when you really need to fix a train wreck of a badly developed legacy web application in the shortest time as possible. Still, you should ultimately rewrite your JSP files to become XSS-safe.

If you'd like to redisplay user-controlled input as HTML wherein you would like to allow only a specific subset of HTML tags like <b>, <i>, <u>, etc, then you need to sanitize the input by a whitelist. You can use a HTML parser like Jsoup for this. But, much better is to introduce a human friendly markup language such as Markdown (also used here on Stack Overflow). Then you can use a Markdown parser like CommonMark for this. It has also builtin HTML sanitizing capabilities. See also I'm looking for a Java HTML encoder.

The only concern in the server side with regard to databases is SQL injection prevention. You need to make sure that you never string-concatenate user-controlled input straight in the SQL or JPQL query and that you're using parameterized queries all the way. In JDBC terms, this means that you should use PreparedStatement instead of Statement. In JPA terms, use Query.

An alternative would be to migrate from JSP/Servlet to Java EE's MVC framework JSF. It has builtin XSS (and CSRF!) prevention over all place. See also CSRF, XSS and SQL Injection attack prevention in JSF.

@chad: that's not true. It's only the case when you're string-concatenating user-controlled input straight in the SQL/HQL/JPQL query like so "SELECT ... WHERE SOMEVAL = " + someval instead of using parameterized queries as you've shown. No one ORM can safeguard against this kind of developer mistakes.

@BalusC - Doh! I had that reversed. Vulnerable example is: Query query = session.createQuery("SELECT * FROM TABLE WHERE SOMEVAL = " + someval); Using the binding syntax ":" in Hibernate (like my example above) prevents SQL injection. Deleting comment to prevent someone using my bad example.

I think you DO have to validate in the server aswell. All the validation can be bypassed by altering the HTTP parameters. And sometimes, the data that you persist can be consumed by other applications in an enterprise app. Sometimes you dont have access to the views of the other applications so you need to sanitze the input before persisting in the database.

@Guido: you're not understanding the problem.

java - XSS prevention in JSP/Servlet web application - Stack Overflow

java security jsp servlets xss
Rectangle 27 78

XSS can be prevented in JSP by using JSTL <c:out> tag or fn:escapeXml() EL function when (re)displaying user-controlled input. This includes request parameters, headers, cookies, URL, body, etc. Anything which you extract from the request object. Also the user-controlled input from previous requests which is stored in a database needs to be escaped during redisplaying.

<p><c:out value="${bean.userControlledValue}"></p>
<p><input name="foo" value="${fn:escapeXml(param.foo)}"></p>

This will escape characters which may malform the rendered HTML such as <, >, ", ' and & into HTML/XML entities such as , , , and .

Note that you don't need to escape them in the Java (Servlet) code, since they are harmless over there. Some may opt to escape them during request processing (as you do in Servlet or Filter) instead of response processing (as you do in JSP), but this way you may risk that the data unnecessarily get double-escaped (e.g. & becomes amp; instead of and ultimately the enduser would see being presented), or that the DB-stored data becomes unportable (e.g. when exporting data to JSON, CSV, XLS, PDF, etc which doesn't require HTML-escaping at all). You'll also lose social control because you don't know anymore what the user has actually filled in. You'd as being a site admin really like to know which users/IPs are trying to perform XSS, so that you can easily track them and take actions accordingly. Escaping during request processing should only and only be used as latest resort when you really need to fix a train wreck of a badly developed legacy web application in the shortest time as possible. Still, you should ultimately rewrite your JSP files to become XSS-safe.

If you'd like to redisplay user-controlled input as HTML wherein you would like to allow only a specific subset of HTML tags like <b>, <i>, <u>, etc, then you need to sanitize the input by a whitelist. You can use a HTML parser like Jsoup for this. But, much better is to introduce a human friendly markup language such as Markdown (also used here on Stack Overflow). Then you can use a Markdown parser like CommonMark for this. It has also builtin HTML sanitizing capabilities. See also I'm looking for a Java HTML encoder.

The only concern in the server side with regard to databases is SQL injection prevention. You need to make sure that you never string-concatenate user-controlled input straight in the SQL or JPQL query and that you're using parameterized queries all the way. In JDBC terms, this means that you should use PreparedStatement instead of Statement. In JPA terms, use Query.

An alternative would be to migrate from JSP/Servlet to Java EE's MVC framework JSF. It has builtin XSS (and CSRF!) prevention over all place. See also CSRF, XSS and SQL Injection attack prevention in JSF.

@chad: that's not true. It's only the case when you're string-concatenating user-controlled input straight in the SQL/HQL/JPQL query like so "SELECT ... WHERE SOMEVAL = " + someval instead of using parameterized queries as you've shown. No one ORM can safeguard against this kind of developer mistakes.

@BalusC - Doh! I had that reversed. Vulnerable example is: Query query = session.createQuery("SELECT * FROM TABLE WHERE SOMEVAL = " + someval); Using the binding syntax ":" in Hibernate (like my example above) prevents SQL injection. Deleting comment to prevent someone using my bad example.

I think you DO have to validate in the server aswell. All the validation can be bypassed by altering the HTTP parameters. And sometimes, the data that you persist can be consumed by other applications in an enterprise app. Sometimes you dont have access to the views of the other applications so you need to sanitze the input before persisting in the database.

@Guido: you're not understanding the problem.

java - XSS prevention in JSP/Servlet web application - Stack Overflow

java security jsp servlets xss
Rectangle 27 47

Submit form to a servlet during the onchange event of the 1st dropdown (you can use Javascript for this), let the servlet get the selected item of the 1st dropdown as request parameter, let it obtain the associated values of the 2nd dropdown from the database as a Map<String, String>, let it store them in the request scope. Finally let JSP/JSTL display the values in the 2nd dropdown. You can use JSTL (just drop jstl-1.2.jar in /WEB-INF/lib) c:forEach tag for this. You can prepopulate the 1st list in the doGet() method of the Servlet associated with the JSP page.

<select name="dd1" onchange="submit()">
    <c:forEach items="${dd1options}" var="option">
        <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd2" onchange="submit()">
    <c:if test="${empty dd2options}">
        <option>Please select parent</option>
    </c:if>
    <c:forEach items="${dd2options}" var="option">
        <option value="${option.key}" ${param.dd2 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd3">
    <c:if test="${empty dd3options}">
        <option>Please select parent</option>
    </c:if>
    <c:forEach items="${dd3options}" var="option">
        <option value="${option.key}" ${param.dd3 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>

Once caveat is however that this will submit the entire form and cause a "flash of content" which may be bad for User Experience. You'll also need to retain the other fields in the same form based on the request parameters. You'll also need to determine in the servlet whether the request is to update a dropdown (child dropdown value is null) or to submit the actual form.

Print all possible values of the 2nd and 3rd dropdown out as a Javascript object and make use of a Javascript function to fill the 2nd dropdown based on the selected item of the 1st dropdown during the onchange event of the 1st dropdown. No form submit and no server cycle is needed here.

<script>
    var dd2options = ${dd2optionsAsJSObject};
    var dd3options = ${dd3optionsAsJSObject};
    function dd1change(dd1) {
        // Fill dd2 options based on selected dd1 value.
        var selected = dd1.options[dd1.selectedIndex].value;
        ...
    }
    function dd2change(dd2) {
        // Fill dd3 options based on selected dd2 value.
        var selected = dd2.options[dd2.selectedIndex].value;
        ...
    }
</script>

<select name="dd1" onchange="dd1change(this)">
    <c:forEach items="${dd1options}" var="option">
        <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd2" onchange="dd2change(this)">
    <option>Please select parent</option>
</select>
<select name="dd3">
    <option>Please select parent</option>
</select>

One caveat is however that this may become unnecessarily lengthy and expensive when you have a lot of items. Imagine that you have 3 steps of each 100 possible items, that would mean 100 * 100 * 100 = 1,000,000 items in JS objects. The HTML page would grow over 1MB in length.

  • Make use of XMLHttpRequest in Javascript to fire an asynchronous request to a servlet during the onchange event of the 1st dropdown, let the servlet get the selected item of the 1st dropdown as request parameter, let it obtain the associated values of the 2nd dropdown from the database, return it back as XML or JSON string. Finally let Javascript display the values in the 2nd dropdown through the HTML DOM tree (the Ajax way, as suggested before). The best way for this would be using jQuery. <%@ page pageEncoding="UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html lang="en"> <head> <title>SO question 2263996</title> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script> $(document).ready(function() { $('#dd1').change(function() { fillOptions('dd2', this); }); $('#dd2').change(function() { fillOptions('dd3', this); }); }); function fillOptions(ddId, callingElement) { var dd = $('#' + ddId); $.getJSON('json/options?dd=' + ddId + '&val=' + $(callingElement).val(), function(opts) { $('>option', dd).remove(); // Clean old options first. if (opts) { $.each(opts, function(key, value) { dd.append($('<option/>').val(key).text(value)); }); } else { dd.append($('<option/>').text("Please select parent")); } }); } </script> </head> <body> <form> <select id="dd1" name="dd1"> <c:forEach items="${dd1}" var="option"> <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option> </c:forEach> </select> <select id="dd2" name="dd2"> <option>Please select parent</option> </select> <select id="dd3" name="dd3"> <option>Please select parent</option> </select> </form> </body> </html> ..where the Servlet behind /json/options can look like this: protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String dd = request.getParameter("dd"); // ID of child DD to fill options for. String val = request.getParameter("val"); // Value of parent DD to find associated child DD options for. Map<String, String> options = optionDAO.find(dd, val); String json = new Gson().toJson(options); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(json); } Here, Gson is Google Gson which eases converting fullworthy Java objects to JSON and vice versa. See also How to use Servlets and Ajax?

Awesome code BalusC. If u dont mind, I want to ask a couple questions on your last method. In your function fillOption(), the line $.getJSON, it look like you send a GET request to the servlet, but where do you specify the url of the servlet. In addition, does the result that send back from the servlet get store in 'opts'. So is 'opts' like and JSON object? Can u explain this line: $('>option', dd).remove(); a bit more?

@Harry Pham: $.getJSON is documented here: api.jquery.com/jQuery.getJSON The URL is just /json/options. Also see the text (don't only look at code). You can just choose whatever URL you want. The opts is indeed JSON string as returned by servlet. Also see the JSON link to learn more about it. If you know Javabeans good, then JSON should look familiar enough. The $('>option', dd).remove() removes all previous options from the dropdown, otherwise it would only be appended, appended, etc.. By the way, if you like answers, just upvote it. I see that you almost never voted.

I see it now, the first parameter of getJSON is the url. I am a complete idiot. About the vote thing, so sorry. I did not even realize that. I will look back at my old post and update the vote. Thank you very much. If I have more question, I will come back and ask u.

So I successfully pre-populate the first combo box with some values from the db. However 1 weird thing happpen: When I select on one of the value from dd1, $('#dd1').change(fillOptions('dd2')); never got invoked again. Inside fillOptions, I put an alert box. I only see the alert box, when I first load the page, but it wont pop out when I select anything in the first combo box. Any idea why?

@BalusC: Your JQuery example won't work, as your "this" inside the fillOptions function will point to the Window object. "this" will only point to an HTMLSelectElement inside the function you passed to the .change function. I had to pass "this" to the fillOptions ("fillOptions('dd2', this)") in order to retrieve the value at the other side ("function fillOptions(ddId, callingElement)" and then "$(callingElement).val()").

Populating cascading dropdown lists in JSP/Servlet - Stack Overflow

jsp servlets drop-down-menu cascading
Rectangle 27 47

Submit form to a servlet during the onchange event of the 1st dropdown (you can use Javascript for this), let the servlet get the selected item of the 1st dropdown as request parameter, let it obtain the associated values of the 2nd dropdown from the database as a Map<String, String>, let it store them in the request scope. Finally let JSP/JSTL display the values in the 2nd dropdown. You can use JSTL (just drop jstl-1.2.jar in /WEB-INF/lib) c:forEach tag for this. You can prepopulate the 1st list in the doGet() method of the Servlet associated with the JSP page.

<select name="dd1" onchange="submit()">
    <c:forEach items="${dd1options}" var="option">
        <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd2" onchange="submit()">
    <c:if test="${empty dd2options}">
        <option>Please select parent</option>
    </c:if>
    <c:forEach items="${dd2options}" var="option">
        <option value="${option.key}" ${param.dd2 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd3">
    <c:if test="${empty dd3options}">
        <option>Please select parent</option>
    </c:if>
    <c:forEach items="${dd3options}" var="option">
        <option value="${option.key}" ${param.dd3 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>

Once caveat is however that this will submit the entire form and cause a "flash of content" which may be bad for User Experience. You'll also need to retain the other fields in the same form based on the request parameters. You'll also need to determine in the servlet whether the request is to update a dropdown (child dropdown value is null) or to submit the actual form.

Print all possible values of the 2nd and 3rd dropdown out as a Javascript object and make use of a Javascript function to fill the 2nd dropdown based on the selected item of the 1st dropdown during the onchange event of the 1st dropdown. No form submit and no server cycle is needed here.

<script>
    var dd2options = ${dd2optionsAsJSObject};
    var dd3options = ${dd3optionsAsJSObject};
    function dd1change(dd1) {
        // Fill dd2 options based on selected dd1 value.
        var selected = dd1.options[dd1.selectedIndex].value;
        ...
    }
    function dd2change(dd2) {
        // Fill dd3 options based on selected dd2 value.
        var selected = dd2.options[dd2.selectedIndex].value;
        ...
    }
</script>

<select name="dd1" onchange="dd1change(this)">
    <c:forEach items="${dd1options}" var="option">
        <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd2" onchange="dd2change(this)">
    <option>Please select parent</option>
</select>
<select name="dd3">
    <option>Please select parent</option>
</select>

One caveat is however that this may become unnecessarily lengthy and expensive when you have a lot of items. Imagine that you have 3 steps of each 100 possible items, that would mean 100 * 100 * 100 = 1,000,000 items in JS objects. The HTML page would grow over 1MB in length.

  • Make use of XMLHttpRequest in Javascript to fire an asynchronous request to a servlet during the onchange event of the 1st dropdown, let the servlet get the selected item of the 1st dropdown as request parameter, let it obtain the associated values of the 2nd dropdown from the database, return it back as XML or JSON string. Finally let Javascript display the values in the 2nd dropdown through the HTML DOM tree (the Ajax way, as suggested before). The best way for this would be using jQuery. <%@ page pageEncoding="UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html lang="en"> <head> <title>SO question 2263996</title> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script> $(document).ready(function() { $('#dd1').change(function() { fillOptions('dd2', this); }); $('#dd2').change(function() { fillOptions('dd3', this); }); }); function fillOptions(ddId, callingElement) { var dd = $('#' + ddId); $.getJSON('json/options?dd=' + ddId + '&val=' + $(callingElement).val(), function(opts) { $('>option', dd).remove(); // Clean old options first. if (opts) { $.each(opts, function(key, value) { dd.append($('<option/>').val(key).text(value)); }); } else { dd.append($('<option/>').text("Please select parent")); } }); } </script> </head> <body> <form> <select id="dd1" name="dd1"> <c:forEach items="${dd1}" var="option"> <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option> </c:forEach> </select> <select id="dd2" name="dd2"> <option>Please select parent</option> </select> <select id="dd3" name="dd3"> <option>Please select parent</option> </select> </form> </body> </html> ..where the Servlet behind /json/options can look like this: protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String dd = request.getParameter("dd"); // ID of child DD to fill options for. String val = request.getParameter("val"); // Value of parent DD to find associated child DD options for. Map<String, String> options = optionDAO.find(dd, val); String json = new Gson().toJson(options); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(json); } Here, Gson is Google Gson which eases converting fullworthy Java objects to JSON and vice versa. See also How to use Servlets and Ajax?

Awesome code BalusC. If u dont mind, I want to ask a couple questions on your last method. In your function fillOption(), the line $.getJSON, it look like you send a GET request to the servlet, but where do you specify the url of the servlet. In addition, does the result that send back from the servlet get store in 'opts'. So is 'opts' like and JSON object? Can u explain this line: $('>option', dd).remove(); a bit more?

@Harry Pham: $.getJSON is documented here: api.jquery.com/jQuery.getJSON The URL is just /json/options. Also see the text (don't only look at code). You can just choose whatever URL you want. The opts is indeed JSON string as returned by servlet. Also see the JSON link to learn more about it. If you know Javabeans good, then JSON should look familiar enough. The $('>option', dd).remove() removes all previous options from the dropdown, otherwise it would only be appended, appended, etc.. By the way, if you like answers, just upvote it. I see that you almost never voted.

I see it now, the first parameter of getJSON is the url. I am a complete idiot. About the vote thing, so sorry. I did not even realize that. I will look back at my old post and update the vote. Thank you very much. If I have more question, I will come back and ask u.

So I successfully pre-populate the first combo box with some values from the db. However 1 weird thing happpen: When I select on one of the value from dd1, $('#dd1').change(fillOptions('dd2')); never got invoked again. Inside fillOptions, I put an alert box. I only see the alert box, when I first load the page, but it wont pop out when I select anything in the first combo box. Any idea why?

@BalusC: Your JQuery example won't work, as your "this" inside the fillOptions function will point to the Window object. "this" will only point to an HTMLSelectElement inside the function you passed to the .change function. I had to pass "this" to the fillOptions ("fillOptions('dd2', this)") in order to retrieve the value at the other side ("function fillOptions(ddId, callingElement)" and then "$(callingElement).val()").

Populating cascading dropdown lists in JSP/Servlet - Stack Overflow

jsp servlets drop-down-menu cascading
Rectangle 27 47

Submit form to a servlet during the onchange event of the 1st dropdown (you can use Javascript for this), let the servlet get the selected item of the 1st dropdown as request parameter, let it obtain the associated values of the 2nd dropdown from the database as a Map<String, String>, let it store them in the request scope. Finally let JSP/JSTL display the values in the 2nd dropdown. You can use JSTL (just drop jstl-1.2.jar in /WEB-INF/lib) c:forEach tag for this. You can prepopulate the 1st list in the doGet() method of the Servlet associated with the JSP page.

<select name="dd1" onchange="submit()">
    <c:forEach items="${dd1options}" var="option">
        <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd2" onchange="submit()">
    <c:if test="${empty dd2options}">
        <option>Please select parent</option>
    </c:if>
    <c:forEach items="${dd2options}" var="option">
        <option value="${option.key}" ${param.dd2 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd3">
    <c:if test="${empty dd3options}">
        <option>Please select parent</option>
    </c:if>
    <c:forEach items="${dd3options}" var="option">
        <option value="${option.key}" ${param.dd3 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>

Once caveat is however that this will submit the entire form and cause a "flash of content" which may be bad for User Experience. You'll also need to retain the other fields in the same form based on the request parameters. You'll also need to determine in the servlet whether the request is to update a dropdown (child dropdown value is null) or to submit the actual form.

Print all possible values of the 2nd and 3rd dropdown out as a Javascript object and make use of a Javascript function to fill the 2nd dropdown based on the selected item of the 1st dropdown during the onchange event of the 1st dropdown. No form submit and no server cycle is needed here.

<script>
    var dd2options = ${dd2optionsAsJSObject};
    var dd3options = ${dd3optionsAsJSObject};
    function dd1change(dd1) {
        // Fill dd2 options based on selected dd1 value.
        var selected = dd1.options[dd1.selectedIndex].value;
        ...
    }
    function dd2change(dd2) {
        // Fill dd3 options based on selected dd2 value.
        var selected = dd2.options[dd2.selectedIndex].value;
        ...
    }
</script>

<select name="dd1" onchange="dd1change(this)">
    <c:forEach items="${dd1options}" var="option">
        <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option>
    </c:forEach>
</select>
<select name="dd2" onchange="dd2change(this)">
    <option>Please select parent</option>
</select>
<select name="dd3">
    <option>Please select parent</option>
</select>

One caveat is however that this may become unnecessarily lengthy and expensive when you have a lot of items. Imagine that you have 3 steps of each 100 possible items, that would mean 100 * 100 * 100 = 1,000,000 items in JS objects. The HTML page would grow over 1MB in length.

  • Make use of XMLHttpRequest in Javascript to fire an asynchronous request to a servlet during the onchange event of the 1st dropdown, let the servlet get the selected item of the 1st dropdown as request parameter, let it obtain the associated values of the 2nd dropdown from the database, return it back as XML or JSON string. Finally let Javascript display the values in the 2nd dropdown through the HTML DOM tree (the Ajax way, as suggested before). The best way for this would be using jQuery. <%@ page pageEncoding="UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html> <html lang="en"> <head> <title>SO question 2263996</title> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script> $(document).ready(function() { $('#dd1').change(function() { fillOptions('dd2', this); }); $('#dd2').change(function() { fillOptions('dd3', this); }); }); function fillOptions(ddId, callingElement) { var dd = $('#' + ddId); $.getJSON('json/options?dd=' + ddId + '&val=' + $(callingElement).val(), function(opts) { $('>option', dd).remove(); // Clean old options first. if (opts) { $.each(opts, function(key, value) { dd.append($('<option/>').val(key).text(value)); }); } else { dd.append($('<option/>').text("Please select parent")); } }); } </script> </head> <body> <form> <select id="dd1" name="dd1"> <c:forEach items="${dd1}" var="option"> <option value="${option.key}" ${param.dd1 == option.key ? 'selected' : ''}>${option.value}</option> </c:forEach> </select> <select id="dd2" name="dd2"> <option>Please select parent</option> </select> <select id="dd3" name="dd3"> <option>Please select parent</option> </select> </form> </body> </html> ..where the Servlet behind /json/options can look like this: protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String dd = request.getParameter("dd"); // ID of child DD to fill options for. String val = request.getParameter("val"); // Value of parent DD to find associated child DD options for. Map<String, String> options = optionDAO.find(dd, val); String json = new Gson().toJson(options); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(json); } Here, Gson is Google Gson which eases converting fullworthy Java objects to JSON and vice versa. See also How to use Servlets and Ajax?

Awesome code BalusC. If u dont mind, I want to ask a couple questions on your last method. In your function fillOption(), the line $.getJSON, it look like you send a GET request to the servlet, but where do you specify the url of the servlet. In addition, does the result that send back from the servlet get store in 'opts'. So is 'opts' like and JSON object? Can u explain this line: $('>option', dd).remove(); a bit more?

@Harry Pham: $.getJSON is documented here: api.jquery.com/jQuery.getJSON The URL is just /json/options. Also see the text (don't only look at code). You can just choose whatever URL you want. The opts is indeed JSON string as returned by servlet. Also see the JSON link to learn more about it. If you know Javabeans good, then JSON should look familiar enough. The $('>option', dd).remove() removes all previous options from the dropdown, otherwise it would only be appended, appended, etc.. By the way, if you like answers, just upvote it. I see that you almost never voted.

I see it now, the first parameter of getJSON is the url. I am a complete idiot. About the vote thing, so sorry. I did not even realize that. I will look back at my old post and update the vote. Thank you very much. If I have more question, I will come back and ask u.

So I successfully pre-populate the first combo box with some values from the db. However 1 weird thing happpen: When I select on one of the value from dd1, $('#dd1').change(fillOptions('dd2')); never got invoked again. Inside fillOptions, I put an alert box. I only see the alert box, when I first load the page, but it wont pop out when I select anything in the first combo box. Any idea why?

@BalusC: Your JQuery example won't work, as your "this" inside the fillOptions function will point to the Window object. "this" will only point to an HTMLSelectElement inside the function you passed to the .change function. I had to pass "this" to the fillOptions ("fillOptions('dd2', this)") in order to retrieve the value at the other side ("function fillOptions(ddId, callingElement)" and then "$(callingElement).val()").

Populating cascading dropdown lists in JSP/Servlet - Stack Overflow

jsp servlets drop-down-menu cascading
Rectangle 27 2

JSPs under WEB-INF cannot be directly accessed. This is generally a Good Thing. A redirect tells the browser to request a different URL, so sending a redirect to a JSP tells the browser to directly request that JSP.

To server a JSP inside of WEB-INF, RequestDispatcher#forward() to it from a servlet.

java - Redirect the request to JSP in servlet giving error? - Stack Ov...

java tomcat servlets
Rectangle 27 2

JS runs at the client machine. Java runs at the server machine. The only communication tool between those is HTTP. Java/JSP can generate/produce a HTML page and send it from server to client as a HTTP response, thus it can easily (pre)set Javascript variables by simply generating them as-is in the JSP template. But the other way round really requires a HTTP request from the client to the server. You can invoke HTTP requests synchronously by clicking a link or submitting a form, either manually or with little help of Javascript like link.click() or form.submit(). You can also invoke HTTP requests asynchronously with help of Ajaxical powers.

Long story short: let JS set it as a (hidden) input value / request parameter and send it to the server side by submitting the form with the (hidden) input value, or by invoking a link with the request parameter, or by firing an ajax request with a query string.

To learn more about the wall between Java/JSP and Javascript, you may find this article useful as well: Java/JSP/JSF and JavaScript.

Hope this clears a lot of things up and opens a new world for you.

Assigning values from JavaScript to Java variable - Stack Overflow

java javascript jsp jstl
Rectangle 27 8

Variables in scriptlets cannot be seen in JSTL because Expression Language, the stuff between ${} used in JSTL, will look for attributes in page, request, session or application. You have to at least store the variable from scriptlet in one of these scopes, then use it.

<%
    boolean a = true;
    request.setAttribute("a", a);
%>

<c:if test="${a}">
    <c:out value="a was found and it's true." />
</c:if>

As a recommendation, stop using scriptlets. Move the business logic in your JSP to controller and the view logic into EL, JSTL and other tags like <display>. More info: How to avoid Java code in JSP files?

What is the difference between using request.setAttribute and pageCotnext.setAttribute ? I want to my temp variables to be as short lived as possible, and only available during the rendering of that single jsp file.

jsp - How to pass java variables from scriptlets to c:when expression ...

java jsp jstl scriptlet
Rectangle 27 8

Variables in scriptlets cannot be seen in JSTL because Expression Language, the stuff between ${} used in JSTL, will look for attributes in page, request, session or application. You have to at least store the variable from scriptlet in one of these scopes, then use it.

<%
    boolean a = true;
    request.setAttribute("a", a);
%>

<c:if test="${a}">
    <c:out value="a was found and it's true." />
</c:if>

As a recommendation, stop using scriptlets. Move the business logic in your JSP to controller and the view logic into EL, JSTL and other tags like <display>. More info: How to avoid Java code in JSP files?

What is the difference between using request.setAttribute and pageCotnext.setAttribute ? I want to my temp variables to be as short lived as possible, and only available during the rendering of that single jsp file.

jsp - How to pass java variables from scriptlets to c:when expression ...

java jsp jstl scriptlet
Rectangle 27 8

Variables in scriptlets cannot be seen in JSTL because Expression Language, the stuff between ${} used in JSTL, will look for attributes in page, request, session or application. You have to at least store the variable from scriptlet in one of these scopes, then use it.

<%
    boolean a = true;
    request.setAttribute("a", a);
%>

<c:if test="${a}">
    <c:out value="a was found and it's true." />
</c:if>

As a recommendation, stop using scriptlets. Move the business logic in your JSP to controller and the view logic into EL, JSTL and other tags like <display>. More info: How to avoid Java code in JSP files?

What is the difference between using request.setAttribute and pageCotnext.setAttribute ? I want to my temp variables to be as short lived as possible, and only available during the rendering of that single jsp file.

jsp - How to pass java variables from scriptlets to c:when expression ...

java jsp jstl scriptlet
Rectangle 27 31

1) Using <c:url> tag from JSTL

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:

There are several solutions to your problem, here are some of them:

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:

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.

Here we have retrieved the context path from the request object. And to access the request object we have used the pageContext implicit object.

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.

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>

As suggested by user @gavenkoa you can also use scriptlets like this:

<%= request.getContextPath() %>

I personally prefer ether 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.

@VishalAnand You are welcome!

You forget about scriplets solution: <%=request.getContextPath()%> )) stackoverflow.com/a/33356037/173149 Alternatively it is possible to write custom JSTL lib with own DSL/sugar.

Well yes, you can use scriptlets in this case although generally using scriptlets in JSP is discouraged. I just offered some of the most common available approaches, I'll mention your suggestion too, thanks.

java - Adding external resources (CSS/JavaScript/images etc) in JSP - ...

java css jsp jstl el
Rectangle 27 31

1) Using <c:url> tag from JSTL

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:

There are several solutions to your problem, here are some of them:

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:

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.

Here we have retrieved the context path from the request object. And to access the request object we have used the pageContext implicit object.

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.

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>

As suggested by user @gavenkoa you can also use scriptlets like this:

<%= request.getContextPath() %>

I personally prefer ether 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.

@VishalAnand You are welcome!

You forget about scriplets solution: <%=request.getContextPath()%> )) stackoverflow.com/a/33356037/173149 Alternatively it is possible to write custom JSTL lib with own DSL/sugar.

Well yes, you can use scriptlets in this case although generally using scriptlets in JSP is discouraged. I just offered some of the most common available approaches, I'll mention your suggestion too, thanks.

java - Adding external resources (CSS/JavaScript/images etc) in JSP - ...

java css jsp jstl el
Rectangle 27 16

Your concrete problem is most likely caused because your JSF command link/button is actually sending an ajax request which in turn expects a special XML response. If you're sending a redirect as response to an ajax request, then it would just re-send the ajax request to that URL. This in turn fails without feedback because the redirect URL returns a whole HTML page instead of a special XML response. You should actually be returning a special XML response wherein the JSF ajax engine is been instructed to change the current window.location.

But you've actually bigger problems: using the wrong tool for the job. You should use a servlet filter for the job, not a homegrown servlet and for sure not one which supplants the FacesServlet who is the responsible for all the JSF works.

Assuming that you're performing the login in a request/view scoped JSF backing bean as follows (if you're using container managed authentication, see also 2nd example of Performing user authentication in Java EE / JSF using j_security_check):

externalContext.getSessionMap().put("user", user);

Then this kickoff example of a filter should do:

@WebFilter("/*") // Or @WebFilter(servletNames={"facesServlet"})
public class AuthorizationFilter implements Filter {

    private static final String AJAX_REDIRECT_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
        + "<partial-response><redirect url=\"%s\"></redirect></partial-response>";

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {    
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        HttpSession session = request.getSession(false);
        String loginURL = request.getContextPath() + "/login.xhtml";

        boolean loggedIn = (session != null) && (session.getAttribute("user") != null);
        boolean loginRequest = request.getRequestURI().equals(loginURL);
        boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER + "/");
        boolean ajaxRequest = "partial/ajax".equals(request.getHeader("Faces-Request"));

        if (loggedIn || loginRequest || resourceRequest)) {
            if (!resourceRequest) { // Prevent browser from caching restricted resources. See also https://stackoverflow.com/q/4194207/157882
                response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
                response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
                response.setDateHeader("Expires", 0); // Proxies.
            }

            chain.doFilter(request, response); // So, just continue request.
        }
        else if (ajaxRequest) {
            response.setContentType("text/xml");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().printf(AJAX_REDIRECT_XML, loginURL); // So, return special XML response instructing JSF ajax to send a redirect.
        }
        else {
            response.sendRedirect(loginURL); // So, just perform standard synchronous redirect.
        }
    }

    // ...
}

OK, I've implemented it via Filter. However, I still don't understand the else if("partial/ajax"...) part. Could you explain in more detail or provide some links?

A JSF ajax request requires a special XML response. A HTTP 302 response is not interpreted as a window redirect by JSF ajax engine, but as a redirect to a new XML response. However if that redirect actually returns a HTML page, it fails with "no feedback". You need to return a special XML response which tells JSF ajax engine to send a redirect on the given URL. You can recognize JSF ajax requests by checking the mentioned response header value. In JSF side, this is normally "under the covers" handled by ExternalContext#redirect(). But outside JSF context, you have to deal with it manually.

request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER);
css
<h:outputStylesheet>

They are not. :-) Will re-write, thanks a lot.

java - Authorization redirect on session expiration does not work on s...

java jsf redirect jsf-2 authorization