jsfmyfacestomahawkjsf-1.1

myfaces htmlHead is not rendered first


I have started to maintain a legacy JSF application. It uses myFaces 1.1.x and tomahawk 1.1.6. I need to print META tag X-UA-Compatible as the first element of HEAD element otherwise IE will ignore it.

<%@page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="t" uri="http://myfaces.apache.org/tomahawk"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <f:view>
    <t:documentHead>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta http-equiv="Content-type" content="text/html; charset=UTF-8">

It will generate

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
<script type="text/javascript" src="/Viewer/faces/myFacesExtensionResource/org.apache.myfaces.renderkit.html.util.MyFacesResourceLoader/15311471/navmenu.jscookmenu.HtmlJSCookMenuRenderer/JSCookMenu.js"><!--
//--></script>
<script type="text/javascript" src="/Viewer/faces/myFacesExtensionResource/org.apache.myfaces.renderkit.html.util.MyFacesResourceLoader/15311471/navmenu.jscookmenu.HtmlJSCookMenuRenderer/MyFacesHack.js"><!--
//--></script>
<script type="text/javascript"><!--
var myThemeMiniBlackBase='/Viewer/faces/myFacesExtensionResource/org.apache.myfaces.renderkit.html.util.MyFacesResourceLoader/15311471/navmenu.jscookmenu.HtmlJSCookMenuRenderer/ThemeMiniBlack/';
//--></script>
<script type="text/javascript" src="/Viewer/faces/myFacesExtensionResource/org.apache.myfaces.renderkit.html.util.MyFacesResourceLoader/15311471/navmenu.jscookmenu.HtmlJSCookMenuRenderer/ThemeMiniBlack/theme.js"><!--
//--></script>
<link rel="stylesheet" href="/Viewer/faces/myFacesExtensionResource/org.apache.myfaces.renderkit.html.util.MyFacesResourceLoader/15311471/navmenu.jscookmenu.HtmlJSCookMenuRenderer/ThemeMiniBlack/theme.css" type="text/css" />
<script type="text/javascript" src="/Viewer/faces/myFacesExtensionResource/org.apache.myfaces.renderkit.html.util.MyFacesResourceLoader/15311471/popup.HtmlPopupRenderer/JSPopup.js"><!--
//--></script>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta http-equiv="Content-type" content="text/html; charset=UTF-8">

How can I force the META tag to be the first element? I tried plain HTML HEAD element but it did not work either.

I need

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta http-equiv="Content-type" content="text/html; charset=UTF-8">

Update:

Some of these javascripts and styles are rendered because of this tag:

<t:jscookMenu theme="ThemeMiniBlack" layout="hbr" immediate="true">

The remaining javascript comes from

<t:popup closePopupOnExitingElement="true" closePopupOnExitingPopup="true"
         displayAtDistanceX="10" displayAtDistanceY="20" styleClass="popup">

The question is if I can enforce that what I put to t:documentHead has a precedence? I worry I will need to write my custom tag.


Solution

  • I would give a try to adding the meta tag yourself in a custom java filter.

    <filter>
       <filter-name>MetaTagsFilter</filter-name>
       <filter-class>com.yournamespace.MetaTagsFilter</filter-class>
    </filter>
    

    Then do a filter mapping for the JSF servlet:

    <filter-mapping>
       <filter-name>MetaTagsFilter</filter-name>
       <servlet-name>FacesServlet</servlet-name>
    </filter-mapping>
    
    <servlet-mapping>
      <servlet-name>FacesServlet</servlet-name>
      <url-pattern>*.faces</url-pattern>
    </servlet-mapping>
    

    In your filter logic, add the meta tag, after the servlet has performed the processing, kind of this:

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain filterChain) throws IOException, ServletException {
    
        HtmlResponseWrapper capturingResponseWrapper = new HtmlResponseWrapper(
                (HttpServletResponse) response);
    
        filterChain.doFilter(request, capturingResponseWrapper);
    
        if (response.getContentType() != null
                && response.getContentType().contains("text/html")) {
    
    
            // Try this https://stackoverflow.com/a/32830377/1199132
            capturingResponseWrapper.addHeader("X-UA-Compatible", "IE=edge");
    
    
            // Or this, that way you have more control over WHERE it gets written
            String content = capturingResponseWrapper.getCaptureAsString();
    
            // replace stuff here (find the <head></head> tags and add the <meta> at the very beginning)
    
            System.out.println(replacedContent);
    
            response.getWriter().write(replacedContent);
    
        }
    
    }
    

    See also: