1. 현상

개발 환경 혹은 타 WAS 에서 잘 사용되던 JSP 를 Tomcat 에 배포하여 처리하려는데 "Page directive: illegal to have multiple occurrences of contentType with different values" 이 발생할 수 있다.

그리고 예를 들어, (old: text/html;charset=euc-kr, new: text/html;charset=EUC-KR) 가 따라올 것이다.

이런 경우 해당 JSP 에 contentType 이 중복 선언되어 있을 것이다. 혹은 JSP 내에 다른 JSP 가 include 되어 있고 두 JSP 에 각각 contentType 이 선언되어 있을 것이다. 그리고 가장 중요한 것은, 그 두 개 이상의 contentType 이 다르다는 것이다.

  • old: text/html;charset=euc-kr
  • new: text/html;charset=EUC-KR

와 같이 대소문자 차이, 혹은 공백 차이, 아니면 아예 charset 의 차이 등등 분명히 차이가 있을 것이다.


2. 원인

왜 그럴까?

Tomcat 7.0.57 소스 기준으로 org.apache.jasper.compiler 패키지의 Validator.java 를 보자.

        private static final JspUtil.ValidAttribute[] pageDirectiveAttrs = {
            new JspUtil.ValidAttribute("language"),
            new JspUtil.ValidAttribute("extends"),
            new JspUtil.ValidAttribute("import"),
            new JspUtil.ValidAttribute("session"),
            new JspUtil.ValidAttribute("buffer"),
            new JspUtil.ValidAttribute("autoFlush"),
            new JspUtil.ValidAttribute("isThreadSafe"),
            new JspUtil.ValidAttribute("info"),
            new JspUtil.ValidAttribute("errorPage"),
            new JspUtil.ValidAttribute("isErrorPage"),
            new JspUtil.ValidAttribute("contentType"),
            new JspUtil.ValidAttribute("pageEncoding"),
            new JspUtil.ValidAttribute("isELIgnored"),
            new JspUtil.ValidAttribute("deferredSyntaxAllowedAsLiteral"),
            new JspUtil.ValidAttribute("trimDirectiveWhitespaces")
        };
 
        public void visit(Node.PageDirective n) throws JasperException {
 
            JspUtil.checkAttributes("Page directive", n, pageDirectiveAttrs,
                    err);
 
            // JSP.2.10.1
            Attributes attrs = n.getAttributes();
            for (int i = 0; attrs != null &amp;&amp; i < attrs.getLength(); i++) {
                String attr = attrs.getQName(i);
                String value = attrs.getValue(i);
 
                if ("language".equals(attr)) {
                  ......
                } else if ("contentType".equals(attr)) {
                    if (pageInfo.getContentType() == null) {
                        pageInfo.setContentType(value);
                    } else if (!pageInfo.getContentType().equals(value)) {
                        err.jspError(n, "jsp.error.page.conflict.contenttype",
                                pageInfo.getContentType(), value);
                    }
                }

관련 참고.

< JspUtil.java >

    public static void checkAttributes(String typeOfTag, Node n,
            ValidAttribute[] validAttributes, ErrorDispatcher err)
            throws JasperException { ... }
 
    public static class ValidAttribute {
        String name;
 
        boolean mandatory;
 
        public ValidAttribute(String name, boolean mandatory) {
            this.name = name;
            this.mandatory = mandatory;
        }
 
        public ValidAttribute(String name) {
            this(name, false);
        }
    }

 

한참 후에 업데이트. 인터파크 쇼핑하다가 반가운 오류를 발견하여 공유한다.

org.apache.jasper.JasperException: /dsearch/include/common.jsp (line: 1, column: 2) Page directive: illegal to have multiple occurrences of contentType with different values (old: text/html; charset=euc-kr, new: text/html;charset=euc-kr)

text/html; 뒤에 공백때문에..