'JSTL'에 해당되는 글 17

  1. 2011.11.24 [EP] JSTL(Apache Taglibs 1.0) 사용하기 1
  2. 2010.05.17 Unable to find a value for "PROPERTY" in object of class "CLASS" using operator "."
  3. 2010.04.13 허무함. 뭐가 잘못된 걸까?
  4. 2010.02.20 [미완] 공통 JSP 파일 및 JSTL 설정하기
  5. 2010.01.10 [해석] Developing a Spring Framework MVC application step-by-step Chapter 2. Developing and Configuring the Views and the Controller
  6. 2009.08.12 java.lang.NumberFormatException: For input string: ""
  7. 2009.08.09 JSTL - core
  8. 2009.07.26 Eclipse, WTP, Derby로 웹 애플리케이션 구현하기
  9. 2009.07.26 Java EE 5 스펙에서 JSTL 구현
  10. 2009.07.19 JSP 2.0 EXPRESSION LANGUAGE
  11. 2009.07.19 JSTL Quick Reference
  12. 2009.06.11 JSTL 비교 연산자
  13. 2009.05.06 JSTL - fmt
  14. 2009.04.08 NetBeans - Introduction to the JavaServer Faces Framework
  15. 2009.03.01 유지보수 - 소스
  16. 2009.02.24 JSTL 제약사항 - 상수
  17. 2008.12.26 시스템 정보 조회용 JSP

[EP] JSTL(Apache Taglibs 1.0) 사용하기 1

- 환경
ServerInfo : SAP J2EE Engine/7.00
Servlet : 2.3
JSP : 1.2
web.xml 을 수정할 수 없음.

- JSTL (Apache Taglibs 1.0 구현체)을 사용하려고 함.
Tomcat 4, 5에서는 예제(standard-examples.war)가 잘 동작함.

- jstl.jar, standard.jar를 PORTAL-INF/lib/에 넣는다.

test.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
com.sapportals.portal.prt.servlets_jsp.server.jsp.ParseException:  Error in parsing taglib 'http://java.sun.com/jstl/core' tag in web.xml or .tld file of the taglib library.
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.syntax.JspTaglibDirective.verifyAttributes(JspTaglibDirective.java:189)
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.syntax.JspDirective.parse0(JspDirective.java:162)
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.syntax.JspDirective.parse(JspDirective.java:117)
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.syntax.ElementCollection.parse(ElementCollection.java:86)
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.syntax.ParserImpl.parse(ParserImpl.java:595)
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.JSPParser.parse(JSPParser.java:2170)
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.JSPCompiler.compile(JSPCompiler.java:81)
        ...

tld 파일을 여기저기 넣어 보고 uri를 바꿔봐도 안됨.
(JSPCompiler를 디컴파일해서 uri를 어떻게 찾는지 보려고 했는데 어디에 있는지 찾지를 못했다.)

- htmlb를 사용하는 글을 보고 tld를 설정함.

portalapp.xml PORTAL-INF/taglib/에 c.tld를 넣는다.

test.jsp taglib 선언은 되는데 실제 사용할 때 에러가 발생한다.
com.sapportals.portal.prt.servlets_jsp.server.jsp.ParseException: java.lang.NullPointerException
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.TagBeginGenerator.init(TagBeginGenerator.java:148)
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.syntax.xmlsyntax.CustomJspTag.action(CustomJspTag.java:114)
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.syntax.ElementCollection.action(ElementCollection.java:47)
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.JSPParser.parse(JSPParser.java:2170)
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.JSPCompiler.compile(JSPCompiler.java:81)
        at com.sapportals.portal.prt.servlets_jsp.server.jsp.JSPCompiler.run(JSPCompiler.java:140)
        at com.sapportals.portal.prt.core.broker.JSPComponentItem.compileJSP(JSPComponentItem.java:291)
        ...

- SAP NetWeaver 04, 7.1이 JSP 1.2를 지원하지 않는다고 함.
javax.servlet.jsp.JspFactory.getDefaultFactory().getEngineInfo().getSpecificationVersion()의 리턴값은 1.2인데...

- 커스텀 태그라이브러리를 작성해 보니 JSP 1.1 형식으로는 가능
Taglibs의 c.tld를 1.1형식으로 변경하면 가능할 거 같다.

Unable to find a value for "PROPERTY" in object of class "CLASS" using operator "."

javax.servlet.jsp.el.ELException: Unable to find a value for "PROPERTY" in object of class "CLASS" using operator "."

자바 빈 명명 규칙에 어긋나서 발생하는 에러임.

 멤버  getter  사용  비고
 S_PAR_POINT  getS_PAR_POINT()  ${data.s_PAR_POINT}  ${data.S_PAR_POINT}는 안됨.
 PAR_POINT  getPAR_POINT()  ${data.PAR_POINT}  
       

[todo] 자바 빈 명명 규칙을 정리할 필요있음. 어디에 있더라...

허무함. 뭐가 잘못된 걸까?

화면에서 데이터를뿌려주는데 아무리해도 OK가 나오지 않는다.
개발자가 1시간동안 헤맷다고 한다.

[미완] 공통 JSP 파일 및 JSTL 설정하기

include.jsp

JSTL을 사용하기 위해서는 jstl.jar, standard.jar를 WEB-INF/lib/에 넣는다.

[todo] tld파일 관련한 uri를 web.xml 에 설정하는 것도 확인해서 정리해 둘것.

[todo] 이미지 경로, context path 상수도 추가할 것.
웹서버와 연동하는 경우도 고려해서 정리하자.
정적 파일의 위치를 상수로 처리하는게 제일 나은 듯.

[해석] Developing a Spring Framework MVC application step-by-step Chapter 2. Developing and Configuring the Views and the Controller

http://web.archive.org/web/20161120010625/http://docs.spring.io/docs/Spring-MVC-step-by-step/part2.html

Chapter&nbsp;2.&nbsp;Developing and Configuring the Views and the Controller.pdf


2장. 뷰와 컨트롤러 개발

[todo] 이 부분 빠졌음.

2.1. JSTL과 JSP 헤더 파일 작성

JSTL 관련 라이브러리인 jstl.jar, standard.jar를 WEB-INF/lib/에 복사한다.

앞으로 작성할 모든 JSP에 포함될 헤더파일을 작성한다.
헤더파일을 include해서 모든 JSP 파일에 동일한 구문을 간단하게 넣을수 있다.
모든 JSP 파일을 WEB-INF/jsp/에 넣는다.
URL을 통해서 직접 접근하지 못하고 컨트롤러를 통해서만 뷰에 접근 가능하도록 한다.
이 방법은 어떤 어플리케이션 서버에서는 작동하지 않을지도 모르는데 이 경우 jsp/를 위로 올린다.

우선 모든 JSP에 포함될 헤더파일을 만든다.
'springapp/war/WEB-INF/jsp/include.jsp':

헤더파일을 사용하도록 index.jsp를 수정하면 JSTL을 사용할 수 있으므로 Front Controller로 리다이렉트하는 <c:redirect/> 태그를 사용한다.
이것은 index.jsp에 대한 모든 요청을 어플리케이션 프레임워크로 통하도록 수정한다.
'springapp/war/index.jsp':

hello.jsp를 WEB-INF/jsp/로 옮기고 index.jsp와 동일한 directive를 추가한다.
model에서 가져와서 뷰에 전달된 현재 일자와 시간을 JSTL <c:out/> 태그를 사용하여 출력한다.
'springapp/war/WEB-INF/jsp/hello.jsp':

2.2. Controller 개선

Controller에서 JSP의 위치를 수정하기 전에 단위테스트부터 수정한다.
뷰에 대한 경로를 WEB-INF/jsp/hello.jsp로 수정해야 하고 모델에 now라는 키로 객체를 전달해야 한다.
'springapp/tests/HelloControllerTests.java':

이 상태에서 테스트를 실행하면 당연히 실패한다.
뷰에 대한 경로를 WEB-INF/jsp/hello.jsp로 수정하고 모델에 현재 일자와 시간에 대한 값을 now라는 문자열 키로 담는다.
'springapp/src/springapp/web/HelloController.java'
:

Controller는 springapp-servlet.xml에 이미 설정되어 있기 때문에 수정한 코드를 빌드하고 배포하는데 문제없다.
브라우저에 http://localhost:8080/springapp/를 치면 index.jsp를 호출하고 hello.htm으로 전달된다. 이것은 DispatcherServlet에 의해서 처리된뒤, 페이지 컨트롤러에서 모델에 날짜와 시간을 담고 hello.jsp에서 사용된다.

2.3. Controller에서 View 분리하기

현재 컨트롤러는 뷰에 대한 전체 경로를 명시하고 있는데 이것은 컨트롤러와 뷰 사이에 불필요한 종속성을 만들고 있다.
뷰에 대해 논리적인 이름을 매핑하면 컨트롤러를 수정하지 않고 뷰를 교체할수 있다
ResourceBundleViewResolver나 SimpleUrlHandlerMapping을 사용하면 프로퍼티파일에 이러한 매핑을 설정할수 있다
InternalResourceViewResolver에서는 뷰에 대한 매핑을 접두어, 접미어를 이용해서 간단하게 설정할수 있다
여기서는 두번째 방법으로 구현한다
springapp-servlet.xml에 viewResolver 엔트리를 추가한다.
JstlView를 설정하면 국제화를 지원하는 메세지 리소스 번들를 JSTL과 같이 사용할수 있다.
'springapp/war/WEB-INF/springapp-servlet.xml':

컨트롤러에서 뷰 이름을 수정하고 HelloControllerTests를 실행하면 실패할 것이다.
'springapp/test/springapp/web/HelloControllerTests.java':

컨트롤러에서 사용한 뷰이름에서 접두어와 접미어를 제거하면 컨트롤러는  hello라는  논리적인 이름으로 뷰를 참조하게 된다
이제는 테스트를 통과하게 되고 컴파일해서 배포해서 어플리케이션이 동작하는지 확인한다

2.4. 요약
 
2장에서 작성한 것을 살펴보면
우리가 사용할 JSP페이지에서 사용할 태그 라이브러리 디렉티브를 담고 있는 Include.jsp 헤더 파일을 작성했다.

여기에서 변경한 것은
컨트롤러가 뷰를 참조할때 하드코딩된 이름이 아닌 논리적인 이름으로 참조하도록 HelloControllerTests를 수정하였고
HelloController는 springapp-servlet.xml에 정의된 InternalResourceViewResolver를 사용한 논리적인 이름을 참조한다.

아래는 이런 작업을 한뒤의 프로젝트 디렉토리 구조 스크린샷이다.




java.lang.NumberFormatException: For input string: ""

숫자를 출력할 때 이런 에러가 종종 발생한다.
근본적으로는 데이터베이스에 이런 데이터가 들어가지 못하게 해야 한다.

JSTL 사용시 이런 값이 있는 경우

숫자포맷을 사용한다면 다음과 같이 사용

아니면 태그 라이브러리를 하나 만들어

- 2010-02-27 추가
레거시에서 데이터를 전달해주는데 EMPTY 문자열이 넘어와야 하는데 길이가 1인 경우도 있다.
<c:when test="${empty item.state}"> //" "인 경우 empty는 false를 반환한다.
<c:when test="${empty fn:trim(item.state)}"> //trim 처리를 한다.

JSTL - core


Eclipse, WTP, Derby로 웹 애플리케이션 구현하기

http://www.ibm.com/developerworks/kr/library/dm-0509cline/
  1. Import LowFareAir.war
  2. Import derbyclient.jar, jstl.jar, standard.jar
  3. Import /data/airlinesDB/
  4. Import /devlib/derby.jar, derbynet.jar, derbyrun.jar
  5. build.xml : Derby를 서버로 구동시키는 Ant 스크립트, derby.properties
  6. web.xml 수정 : 데이터베이스 경로, 사용자/암호
  7. com.ibm.sample.DerbyDatabase.java 수정 : 데이터베이스 경로, 사용자/암호
  8. Data Source Explorer에 Derby 설정
  9. Tomcat 시작
- web.xml

Java EE 5 스펙에서 JSTL 구현

- Geronimo의 배신: GlassFish JSTL 1.2와 Apache Geronimo 2.0 통합 패키지 사용하기 (한글)

- JSF와 JSP 1.2
JSF 1.0에서는 JSTL의 EL과 비슷하게 동작하는 고유의 EL을 갖고 있으며, 이 때까지는 JSF EL과 JSTL EL은 호환성이 없었다.

- 통합 표현식 언어(Unified expression language)
자바 EE 5에서는 JSTL과 JSF의 EL이 합쳐져 JSTL과 JSF를 혼합해 쓰는 것이 가능해졌다.

- 자바 EE 5의 일부로서 EL
J2EE 1.4 스펙까지는 JSTL 구현이 필수 사항이 아니었지만 자바 EE 5 스펙에서는 JSTL 구현이 필수 사항이다.

- 제로니모와 글래스피시 JSTL
아파치 제로니모 개발자들은 자바 EE 5 구현체인 제로니모 2.0을 만들 때, JSTL 구현체를 포함해야만 했다.
통합 표현식 언어는 JSTL 구현체의 주요 요구사항이었지만, 많은 JSTL 구현체는 JSF와 함께 동작할 수 없어서 기존 구현체 중에서 선택할 수 없었다.
다행히도 제로니모 팀은 직접 JSTL과 통합 표현식 언어 구현체를 만드는 대신 썬의 글래스피시를 활용할 수 있었다.
글래스피시는 자바 EE 5 스펙을 위한 썬의 참조 구현체다.

JSP 2.0 EXPRESSION LANGUAGE

http://blog.sdnkorea.com/blog/272

- "." 와 [] 연산자 비교
${header["host"]} localhost:8080
${header.host} localhost:8080

${header["user-agent"]} Mozilla/5.0 (Macintosh;...)
${header.user-agent} 0 //마이너스 연산을 한다.

- []에 EL변수 사용가능
<c:set var="headerName" value="host"/>
${header[headerName]}

- 디폴트 값 정의하기
<c:out value="${colors[1024]}" default="transparent"/>

${colors[1024] == null ? "transparent" : colors[1024]}

- forEach구문에서 Map 사용하기
JSTL태그 forEach를 이용할 때, 반복 변수(iteration)는 java.util.Map.Entry 타입이다.
Map에 들어있는 데이터에 접근하려면 Entry#key 와 Entry#value를 사용하면 된다.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%
    java.util.Map map = new java.util.HashMap();
    map.put("a", "1");
    map.put("b", "2");
    map.put("c", "3");
    map.put("4", "d");
    pageContext.setAttribute("map", map);
%>
<c:forEach var="data" items="${map}">
${data.key}=${data.value}<br>
</c:forEach>
<hr>
${map["4"]}<br>
${map.4}<br> //EXCEPTION
<hr>
<c:forEach var="hdr" items="${header}">
${hdr.key}=${hdr.value}<br>
</c:forEach>
<hr>
<c:forEach var="cookieVal" items="${cookie}">
${cookieVal}<br>
</c:forEach>

JSTL Quick Reference


JSTL 기능이 간략하게 잘 정리되어 있다.

XML Tag Library, JSTL Configuration 를 다시 한번 살펴볼 것.
[todo]
<%@ taglib prefix="x" uri="http://java.sun.com/jstl/xml" %>

<%-- Create the XML --%>
<x:parse var="doc">
<users>
    <user id="997">
        <first-name>George</first-name>
        <last-name>Burdell</last-name>
    </user>
    <user id="998">
        <first-name>Joseph</first-name>
        <last-name>Blough</last-name>
    </user>
</users>
</x:parse>
<%-- Define a variable holding user ID --%>
<c:set var="userId" value="${user.id}" scope="page"/>
<%-- Find the user with matching ID --%>
<x:set var="user" select="$doc//users/user[@id=$pageScope:userId]"/>
<%-- Say Hi to the user --%>
Hi <x:out select="$user/first-name"/> !
java.lang.NoClassDefFoundError: org/apache/xpath/XPathException
    java.lang.ClassLoader.defineClass1(Native Method)
    java.lang.ClassLoader.defineClass(ClassLoader.java:620)
    java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)

[todo] 예전에 datasource 를 jndi 로 되어 있는 것만 되는줄 알았는데...음 confguration 으로 두면 좋은 점이 뭘까?

JSTL 비교 연산자

- 테스트환경 1
잘모름

- 테스트환경 2
Apache Tomcat/5.5.9
standard-taglib 1.1.2

  ${test} ${empty test} ${test == null} ${test == 'null'} ${test == ''} ${test == ' '}[각주:1] ${test == '0'} ${test == 0}
 [각주:2] "" true true false false false false false
pageContext.setAttribute("test", null); "" true true false false false false false
pageContext.setAttribute("test", ""); "" true false false true false false true
pageContext.setAttribute("test", " "); " " false false false false true false Exception[각주:3]
pageContext.setAttribute("test", new Integer(0)); 0 false false[각주:4]
Exception[각주:5]
Exception[각주:6] true Exception[각주:7] true true
pageContext.setAttribute("test", "0"); 0 false false false false false true true

- empty 연산자는 test 가 없는 경우 참이다.
- Map, List, 배열이 비어 있는 경우에도 참이다.

[todo] 다른 구현체에서도 해볼 것.(resin, glassfish...구현체 확인해 둘것)
  1. 테스트환경 2에서 추가 [본문으로]
  2. 테스트환경 2에서 추가 [본문으로]
  3. An exception occured trying to convert String " " to type "java.lang.Long" [본문으로]
  4. 테스트환경 1 [본문으로]
  5. 테스트환경 2, An exception occured trying to convert String "null" to type "java.lang.Long" [본문으로]
  6. An exception occured trying to convert String "null" to type "java.lang.Long" [본문으로]
  7. An exception occured trying to convert String " " to type "java.lang.Long" [본문으로]

JSTL - fmt



<fmt:formatNumber  value="12345" pattern=".#"/> //12345.0
<fmt:formatNumber  value="12345" pattern=".0"/> //12345.0

<fmt:formatNumber  value="12345.6789" type="number" pattern="#.#####"/> //12,345.6789
<fmt:formatNumber  value="12345.67890" type="number" pattern="#.#####"/> //12,345.6789
<fmt:formatNumber  value="12345.67890" type="number" pattern="#.00000"/> //12,345.67890

NetBeans - Introduction to the JavaServer Faces Framework

- http://www.netbeans.org/kb/61/web/jastrologer-intro.html
NetBeans 에서 JSF 따라하기









- 이미지출처는 http://www.netbeans.org


유지보수 - 소스

- 아주 긴 클래스에서 개발자가 소스를 수정하다가 현재 작업중인 부분과 전혀 상관없는 아래 코드를 잘못 수정했다.
이런 실수를 방지할 수 있는 방법은 없을까?
- 아래와 같은 JSTL 이 지금까지 에러 안나고 있었음
이전 환경 : Tomcat 5.0 이나 Resin 3.0.25
Tomcat 6.0.18 에서 에러 발생

JSTL 제약사항 - 상수

간단하지만 편리한 기능때문에 JSP에서 JSTL 사용을 적극 권장하고 있다.
그러나 JSTL은 Java Bean에만 접근이 가능하고, 인자없는 getter만 사용가능하다.
상수를 참조할수도 없다.
Constants.TYPE_ADMIN 이라는 상수가 있는데 참조할 수가 없다.
그래서 하드코딩을 해야 한다.

- 그래서 isAdmin()을 추가한다.
- JSTL 구문에서 상수를 직접 사용할수 있도록 하자.

- 설계시점에 고려를 해서 뷰레이어가 단순해지도록 해야 한다.
뷰레이어에 Java코드를 사용하거나 상수를 사용하지 않는 것이 좋다.

시스템 정보 조회용 JSP

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.