2009-09-30

톰켓 6.0 + JSTL

톰켓 6.0에서 JSTL 1.2를 사용하는 방법이다.

우선 JSTL 라이브러리를 여기에서 다운로드한 후에, WEB-INF/lib 디렉토리에 복사한다.

  • jstl-api-1.2.jar
  • jstl-impl-1.2.jar

그리고 JSTL을 사용하는 JSP 앞쪽에 다음 내용을 추가한다.

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

* sql, xml, fmt 태그 등도 비슷한 방법으로 사용한다.


그런데 JSP가 임의의 클래스를 상속하는 경우에는 c:forEach 태그가 정상적으로 동작하지 않을 수 있다. 이를 해결하려면 JSP 상위 클래스에서 ServletConfig를 올바르게 처리해야 한다.

package com.dimdol.web;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.HttpJspPage;

public abstract class BasePage implements HttpJspPage {

  private ServletConfig config;

  public ServletConfig getServletConfig() {
    return config;
  }

  public String getServletInfo() {
    return config.getServletName();
  }

  public void init(ServletConfig config) throws ServletException {
    this.config = config;
    jspInit();
  }

  public void jspInit() {
    _jspInit();
  }

  public void _jspInit() {
    // Implemented by Web Container
  }

  public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    _jspService(httpRequest, httpResponse);
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response) throws ServletException,
      IOException {
    // Implemented by Web Container
  }

  public void destroy() {
    jspDestroy();
  }

  public void jspDestroy() {
    // Implemented by Web Container
  }

}



2009-09-25

JSP 태그 라이브러리

JSP 태그 라이브러리에 대한 생각들이다.


JSTL은 좋지만 지양하고 싶다. JSTL을 5년 이상 사용했는데 지금 생각하면 사용하지 않는 것이 좋은 것 같다. 그냥 자바 구분을 이용하는게 더 효과적인것 같다. EL 정도만 사용하면 될 듯...


SimpleTag를 사용하면 Body에 JSP를 사용할 수 없다.ㅠㅠ


속성에서 <%=%> 사용이 혼란스럽다.

<attribute>
  <name>name</name>
  <required>false</required>
  <rtexprvalue>true</rtexprvalue>
</attribute>

다음은 가능하다.

name="<%= customer.getName() %>"

다음도 가능하다.

name="${customer.name}"

그러나 다음은 불가능하다.

name="Customer_<%= customer.getName() %>"



2009-09-24

Prototype 라이브러리

Prototype 라이브러리 사용과 관련한 주의사항이다.


AJAX를 이용해서 화면 특정 영역을 업데이트하는 경우가 있다.

new Ajax.Updater("update_area", "/update.html");

이 때 화면에 포함된 자바 스크립트를 수행하려면 다음과 같이 한다.

new Ajax.Updater("update_area", "/update.html", {evalScripts: true});


그런데 이 경우 IE 6.0에서는 자바 스크립트를 주석처리하면 안된다.

아래 같이 하면 자바 스크립트가 실행되지 않는다.

<script type="text/javascript"><!--

--></script>

아래 같이 해야 자바 스크립트가 실행된다.

<script type="text/javascript">

</script>


또한 함수를 선언할 때는 다음과 같이 해야 한다.

<script type="text/javascript">
  processRequest = function() {
    ...
  }
</script>

이 때 다음과 같이 var를 붙여서도 안된다.

  var processRequest = function() {
   ...
  }

2009-09-16

자바 - Reflection으로 static 필드 정보 java.util.Map에 담기

자바에서 Reflection을 이용해서 특정 클래스의 static 필드 정보를 java.util.Map에 담는 방법이다.


다음은 java.sql.Types 클래스에 포함된 int 유형의 데이터베이스 칼럼 타입 정보를 처리하는 예제이다.

Map<String, Integer> typeMapping = new HashMap<String, Integer>();

Field[] fields = java.sql.Types.class.getDeclaredFields();
for (Field field : fields) {
  if (Modifier.isStatic(field.getModifiers()) && field.getType() == int.class) {
    typeMapping.put(field.getName(), (Integer) field.get(null));
  }
}


2009-09-14

톰켓 6.0 + JPA

톰켓 6.0에서 JPA를 사용하는 방법이다.

우선 톰켓 6.0 깨끗하게 하기를 참고하여 톰켓을 설치하고, 톰켓 6.0 데이터소스 설정를 참고하여 아파치 더비를 데이터소스로 설정한다.


JPA 구현부로는 오라클이 제공하는 TopLink Essentials을 다운로드한다.

다운로드한 glassfish-persistence-installer-v2-b41.jar 파일이 있는 디렉토리로 이동하여 다음 명령어를 실행한다. 자바가 사용할 수 있어야 한다.

java -jar glassfish-persistence-installer-v2-b41.jar


아래 화면에서 스크롤을 맨 아래까지 내린 다음에 Accept 버튼을 누른다.



압축이 풀리면서 디렉토리가 생기는데 다음 2 파일을 webapps/ROOT/WEB-INF/lib 디렉토리에 복사한다.

  • toplink-essentials.jar
  • toplink-essentials-agent.jar

그리고 webapps/ROOT/WEB-INF/classes/META-INF/persistence.xml 파일을 작성하고 다음 내용을 기술한다.

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
  <persistence-unit name="ExampleUnit" transaction-type="JTA">
    <provider>oracle.toplink.essentials.PersistenceProvider</provider>
    <jta-data-source>java:comp/env/jdbc/Base</jta-data-source>
    <class>com.dimdol.example.model.Document</class>
    <class>com.dimdol.example.model.User</class>
    <class>com.dimdol.example.model.Element</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
      <!--
      <property name="toplink.ddl-generation" value="create-tables" />
      -->
      <property name="toplink.session.customizer" value="com.dimdol.example.util.ToplinkSessionCustomizer" />
    </properties>
  </persistence-unit>
</persistence>

  • persistence-unit 태그 name 속성에 모델 그룹을 지칭하는 적절한 이름(ExampleUnit)을 설정한다.
  • provider 태그에 JPA 구현 클래스 이름(oracle.toplink.essentials.PersistenceProvider)을 설정한다.
  • jta-data-source 태그에 데이터소스 JNDI 이름(java:comp/env/jdbc/Base)을 설정한다.
  • class 태그로 모델 클래스들을 설정한다.

property 태그로 toplink.session.customizer 이름에 다음 클래스를 설정한다. 이렇게 해야 하는 정확한 이유는 알수 없지만 이렇게 하지 않으면 정상적으로 동작하지 않는다.

package com.dimdol.example.util;

import oracle.toplink.essentials.jndi.JNDIConnector;
import oracle.toplink.essentials.sessions.Session;
import oracle.toplink.essentials.tools.sessionconfiguration.SessionCustomizer;

public class ToplinkSessionCustomizer implements SessionCustomizer {

    public void customize(Session session) throws Exception {
        JNDIConnector connector = (JNDIConnector) session.getLogin().getConnector();
        connector.setLookupType(JNDIConnector.STRING_LOOKUP);
    }

}


아파치 더비 - 테이블 스페이스 정리

아파치 더비를 사용할 때 테이블 스페이스를 정리하는 방법이다. 이를 Reorganization이라고 한다.


테이블 스페이스와 관려한 정보를 포함한 테이블 목록은 다음 SQL로 조회한다.

  SELECT TABLENAME,
         (SELECT SUM(NUMALLOCATEDPAGES * PAGESIZE)
            FROM new org.apache.derby.diag.SpaceTable('DB', T.TABLENAME) X),
         (SELECT SUM(ESTIMSPACESAVING)
            FROM new org.apache.derby.diag.SpaceTable('DB', T.TABLENAME) X)
    FROM SYS.SYSTABLES T
ORDER BY TABLENAME

SELECT 절 두번째 칼럼은 해당 테이블이 사용하고 있는 테이블 스페이스 크기를 의미하고, 세번째 칼럼은 테이블 스페이스 정리를 통해서 확보할 수 있는 크기를 의미한다.


실제 테이블 스페이스 정리는 Stored Procedure로 처리한다.

CALL SYSCS_UTIL.SYSCS_COMPRESS_TABLE('DB', ?, 1)

바인딩 파라미터에 테이블 이름을 사용한다.

이를 수행하는 자바 코드는 다음과 같다.

String tableName = ...
if (tableName != null) {
  Connection con = null;
  CallableStatement cstat = null;
  try {
    con = getConnection();
    cstat = con.prepareCall("CALL SYSCS_UTIL.SYSCS_COMPRESS_TABLE('DB', ?, 1)");
    cstat.setString(1, tableName);
    cstat.execute();
  } catch (SQLException e) {
    throw new RuntimeException(e);
  } finally {
    closeResource(con, cstat);
  }
}


* DB 대신에 데이터베이스 이름을 사용한다.

톰켓 6.0 JSESSIONID 충돌

동일 도메인이나 IP에 포트 번호를 달리해서 여러 개의 자바 애플리케이션 서버를 운영하면 세션 유지를 위해 사용하는 JSESSIONID 쿠키가 충돌한다.

예를 들어 한 사용자가 동일 브라우저에서 이 애플리케이션들을 동시에 사용하면 계속해서 세션이 상실되는 현상이 발생한다.


웹로직같은 경우에는 JSESSIONID 대신에 다른 이름을 사용하도록 변경할 수 있지만 톰켓 5.5에서는 이를 지원하지 않았다. 문제 해결을 위해서 구글링하다가 톰켓 개발자가 쓴 글을 보고 톰켓 코드를 수정해서 사용한 적이 있다.


그런데 톰켓 6.0.20 버전에서는 그 내용이 그대로 반영되어서 코드 수정없이 JSESSIONID 대신에 다른 이름을 사용할 수 있다. (정확하게 톰켓 6.0 어떤 버전부터인지는 모르겠다)


다음 자바 시스템 환경 변수로 JSESSIONID를 수정한다.

-Dorg.apache.catalina.SESSION_COOKIE_NAME=JSESSIONID
-Dorg.apache.catalina.SESSION_PARAMETER_NAME=jsessionid
-Dorg.apache.catalina.authenticator.Constants.SSO_SESSION_COOKIE_NAME=JSESSIONIDSSO

  • 첫번째는 JSESSIONID 쿠키 이름이다.
  • 두번째는 URL Rewriting을 할 때 사용하는 파라미터 이름으로 톰켓에서는 JSESSIONID에 대한 소문자를 사용한다.
  • 세번째는 SSO 처리와 관련된 것으로 보이는데 사용해본 적이 없어서 자세히는 모르겠다.

따라서 위의 값에 대해서 JSESSIONID 대신에 다른 걸 사용하면 세션 충돌을 방지할 수 있다.



동일 도메인에서 서로 다른 자바 애플리케이션 서버가 같은 HTTP 포트 번호를 사용할 수는 없다. 그래서 JSESSIONID + HTTP 포트 번호 조합을 사용하는 것이 가장 바람직하다.


먼저 conf/server.xml 파일을 다음과 같이 수정한다.

<?xml version="1.0" encoding="UTF-8"?>

<Server port="${http.shutdown.port}" shutdown="SHUTDOWN">

  <Service name="Catalina">

    <Connector port="${http.startup.port}" protocol="HTTP/1.1" connectionTimeout="20000"
      redirectPort="8443" URIEncoding="UTF-8"/>

    <!-- 나머지 부분 생략 -->

톰켓 설정 파일에 ${}로 설정하면 자동으로 자바 환경 변수로 치환된다.

  • http.startup.port - HTTP 시작 포트
  • http.shutdown.port - HTTP 종료를 위한 포트

윈도우에서는 bin/catalina.bat 파일 앞부분에 다음 내용을 추가한다.

if "%STARTUP_PORT%" == "" SET STARTUP_PORT=8080
if "%SHUTDOWN_PORT%" == "" SET SHUTDOWN_PORT=8005

set JAVA_OPTS=%JAVA_OPTS%
-Xmx512m
set JAVA_OPTS=%JAVA_OPTS% -Dhttp.startup.port=%STARTUP_PORT%
set JAVA_OPTS=%JAVA_OPTS% -Dhttp.shutdown.port=%SHUTDOWN_PORT%
set JAVA_OPTS=%JAVA_OPTS% -Dorg.apache.catalina.SESSION_COOKIE_NAME=JSESSIONID%STARTUP_PORT%
set JAVA_OPTS=%JAVA_OPTS% -Dorg.apache.catalina.SESSION_PARAMETER_NAME=jsessionid%STARTUP_PORT%
set JAVA_OPTS=%JAVA_OPTS% -Dorg.apache.catalina.authenticator.Constants.SSO_SESSION_COOKIE_NAME=JSESSIONIDSSO%STARTUP_PORT%


* 띄어쓰기 문제로 맨 마지막 줄이 잘려보인다.  =JSESSIONIDSSO%STARTUP_PORT%이 잘려 보이는 것이다.


유닉스/리눅스에서는 bin/catalina.sh 파일 앞부분에 다음 내용을 추가한다.

STARTUP_PORT="${STARTUP_PORT}"
SHUTDOWN_PORT="${SHUTDOWN_PORT}"

if [ "${STARTUP_PORT}" = "" ]
then
    STARTUP_PORT="7900"
fi

if [ "${SHUTDOWN_PORT}" = "" ]
then
    SHUTDOWN_PORT="7999"
fi

JAVA_OPTS="$JAVA_OPTS -Xmx512m"
JAVA_OPTS="$JAVA_OPTS -Dhttp.startup.port=${STARTUP_PORT}"
JAVA_OPTS="$JAVA_OPTS -Dhttp.shutdown.port=${SHUTDOWN_PORT}"
JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.SESSION_COOKIE_NAME=JSESSIONID${STARTUP_PORT}"
JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.SESSION_PARAMETER_NAME=jsessionid${STARTUP_PORT}"
JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.authenticator.Constants.SSO_SESSION_COOKIE_NAME=JSESSIONIDSSO${STARTUP_PORT}"

* 띄어쓰기가 없어서 맨 마지막 줄이 잘려보인다.  =JSESSIONIDSSO%STARTUP_PORT%이 잘려 보이는 것이다.


이렇게 설정하면 HTTP 포트 번호가 8080일때 JSESSIONID8080이 세션 유지를 위한 쿠키 이름으로 사용된다.

톰켓 6.0 데이터소스 설정

톰켓 6.0에 데이터소스를 설정하는 방법이다. 우선 톰켓 6.0 깨끗하게 하기를 참조한다.


conf/server.xml 파일에 데이터소스를 설정하고 JDBC 드라이버는 lib 디렉토리에 복사해야 한다.


아파치 더비

<Context ...>
  <Resource name="jdbc/Base" auth="Container"
    type="javax.sql.DataSource" maxActive="100" maxIdle="30"
    maxWait="10000" username="username" password="password"
    driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
    url="jdbc:derby:db;create=true" />
</Context>

JDBC 드라이버 : derby.jar

* 외부에서도 아파치 더비에 접근하려면 derbynet.jar 파일도 복사해야 한다.


오라클


<Context ...>
  <Resource name="jdbc/Base" auth="Container"
    type="javax.sql.DataSource" maxActive="100" maxIdle="30"
    maxWait="10000" username="username" password="password"
    driverClassName="oracle.jdbc.driver.OracleDriver"
    url="jdbc:oracle:thin:@127.0.0.1:1521:db" />
</Context>

JDBC 드라이버 : ojdbc14.jar


DB2

<Context ...>
  <Resource name="jdbc/Base" auth="Container"
   type="javax.sql.DataSource" maxActive="100" maxIdle="30"
   maxWait="10000" username="username" password="password"
   driverClassName="com.ibm.db2.jcc.DB2Driver"
   url="jdbc:db2://127.0.0.1:50000/db" />
</Context>

JDBC 드라이버 : db2jcc.jar, db2jcc_license_cu.jar


MS SQL 2005


<Context ...>
  <Resource name="jdbc/Base" auth="Container"
   type="javax.sql.DataSource" maxActive="100" maxIdle="30"
   maxWait="10000" username="username" password="password"
   driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
   url="jdbc:sqlserver://127.0.0.1:1433;databaseName=db" />
</Context>

JDBC 드라이버 : 자바 1.6을 사용하면 sqljdbc4.jar, 자바 1.5를 사용하면 sqljdbc.jar


web.xml 파일 수정

이 설정이 끝나면 web.xml 파일에 다음 내용을 추가한다.

<resource-ref>
  <description>Base DB Connection</description>
  <res-ref-name>jdbc/Base</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
  <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

* jsp-config 태그 다음에 추가한다. 일반적으로 거의 마지막에^^

톰켓 6.0 깨끗하게 하기

톰켓 6.0을 자주 사용하는데 불필요한 파일과 설정들이 많이 있다. 그래서 항상 다음과 같이 정리한다.


1. 다운로드

exe 파일이 아닌 zip이나 tar.gz 파일을 다운받은 후에 톰켓을 운영할 디렉토리에 압축을 푼다.


2. 지우기

다음 파일 혹은 디렉토리를 지운다.
  • conf/context.xml
  • conf/tomcat-users.xml
  • webapps/docs 디렉토리
  • webapps/examples 디렉토리
  • webapps/host-manager 디렉토리
  • webapps/manager 디렉토리
  • webapps/ROOT 디렉토리에서 WEB-INF/web.xml 파일을 제외한 나머지 파일을 모두 삭제한다.


3. conf/server.xml 파일 정리

취향이겠지만 난 주석을 좋아하지 않고, 애플리케이션 개발에 당장 필요하지 않은 설정은 일단 지우고 필요하면 다시 설정하는 쪽이다.

conf/server.xml 파일은 다음과 같이 정리한다.

<?xml version="1.0" encoding="UTF-8"?>

<Server port="8005" shutdown="SHUTDOWN">

  <Service name="Catalina">

    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000"
      redirectPort="8443" URIEncoding="UTF-8" />

    <Engine name="Catalina" defaultHost="localhost">
      <Host name="localhost" appBase="webapps"
            unpackWARs="true" autoDeploy="false"
            xmlValidation="false" xmlNamespaceAware="false">
        <Context docBase="${catalina.base}/webapps/ROOT" path="" reloadable="true" backgroundProcessorDelay="3">
        </Context>
      </Host>
    </Engine>

  </Service>
</Server>

  • 한글 인코딩 처리를 위해서 Connector 태그에 URIEncoding 속성을 지정했다
  • 톰켓 문서에서는 Context 설정은 별도 파일에 하는 것을 권장하지만 한두개의 애플리케이션을 배치할 때는 굳이 그럴 필요성을 느끼지 못한다. ROOT 디렉토리를 명시적으로 설정하였다. 개발시에는 Context 태그의 reloadable 속성을 true로 설정한다.


4. 로그 설정 정리

전에는 log4j를 선호했지만 지금은 자바 라이브러리를 줄이는 쪽에 가중치를 준다. 그래서 자바 표준 라이브러리에 있는 로그 모듈을 사용한다. 톰켓도 기본 설정이 그렇다.

conf/logging.properties 파일로 로그 설정을 하는데 관리 애플리케이션을 지웠기 때문에 이 파일에 그 내용을 반영해야 한다. 그렇지 않으면 무의미한 로그 파일이 만들어진다.

handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler

.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler

1catalina.org.apache.juli.FileHandler.level = FINE
1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.FileHandler.prefix = catalina.

2localhost.org.apache.juli.FileHandler.level = FINE
2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
2localhost.org.apache.juli.FileHandler.prefix = localhost.

java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler

2009-09-13

[책] 웹 이후의 세계

김국현 씨가 쓴 웹 이후의 세계를 읽었다.

SasS에 대한 관심 때문에 우연하게 서점에서 접한 이 책을 구매했다.


현실계, 이상계, 환상계라는 세계 구분은 좀 뜬금없게 느껴지고, 그 맥락 속에서 서술되는 이야기들이 별로 와닿지 않는다. 아마도 뻔한 이야기라는 느낌이거나 너무 무게를 잡았다는 인상 때문일거다.

아마도 이 책을 구매한 이유가 정보에 대한 빠른 이해를 기대하는 것이었기 때문일 게다.


그래도 정보에 대한 빠른 이해에는 큰 도움이 되었다. 이 바닥에서 일하지만 IT 트랜드에 대한 무지함 혹은 무관심이 야기한 이해 부족을 조금이나마 해소할 수 있었으니깐...

  • SasS와 클라우드의 차이를 이해했다. 난 클라우드를 SasS의 또다른 이름 정도로 치부했는데...
  • 가상화는 워낙 무지한 분야라 읽기 전이나 후나 큰 차이는 없지만... 각론으로 들어가면 이견이 많을 것 같다. 물론 무지함이 관심없음에 기인하기 때문에 각론으로 파들어갈 일은 없겠지만^^
  • 그린 IT는 MB 때문에 무조건 정이 안간다. 궁극적으로 혐오가 망가트리는 건 대상이 아니라 나 자신이라는 게 다시 증명되었다.
  • RIA는 아마도 내 업무와 관련성이 많은 분야인데 플래시나 실버라이트가 가지고 있지 못한 장점을 자바가 가지고 있다고 생각한다. 플래시나 실버라이트로 제니퍼를 구현할 수 있었을까? 닷넷과 결합한 버전업되었다는 실버라이트는 모르겠지만 플래시로는 어림도 없다. 물론 자바 FX는 나도 모른다.
  • 디지털 미디어나 모바일과 관련한 논의가 어떤 이슈를 중심으로 일어나고 있고, 어떤 문제점들이 있으며, 대안들에는 어떤 것들이 있을까를 잘 이해할 수 있었다. 핸드폰을 사용하기 시작한게 3년도 안된 나로서는 도움이 많이 되었다.
  • 제 3장 웹 주의 선언도 각론에서는 이견이 있겠지만 큰 맥락은 100% 동의한다. 하지만 나의 독서 필요성에서는 조금 벗어나 있다.


결론적으로 뜬금없어도 좋은 책이다.

2009-09-10

직각 삼각형의 각도 구하기

직각 삼각형 각도는 다음과 같이 구한다.


tan(각도 b)  = 높이(B) / 밑변(A)

각도 b = inverse tan(높이 / 밑변)

각도 a = 90 - 각도 b


자바에서는 다음과 같이 처리한다.

double angleInRadians = Math.atan(높이 / 밑변);

double degreeA = Math.toDegrees(angleInRadians);

double degreeB = 90 - degreeA;

2009-09-09

자바 HTTP POST 요청

자바(1.4 이상)로 HTTP POST 요청을 하는 방법이다.

먼저 URLConnection 객체를 생성한다.

URL url = new URL("http://example.dimdol.com/example.jsp");
URLConnection con = url.openConnection();

URLConnection 객체 setRequestProperty 메소드로 HTTP 헤더 정보를 설정한다.

con.setRequestProperty("Accept-Language",  "ko-kr,ko;q=0.8,en-us;q=0.5,en;q=0.3");

URLConnection 객체 setDoOutput 메소드로 POST 요청임을 설정한다.

con.setDoOutput(true);


요청 파라미터는 name=value 패턴으로 지정하고 두 개 이상은 &을 사용해서 연결한다.

String parameter = URLEncoder.encode("name", "UTF-8") + "=" URLEncoder.encode("dimdol", "UTF-8");

parameter += "&" + URLEncoder.encode("age", "UTF-8") + "=" URLEncoder.encode("35", "UTF-8");

HTTP 요청을 한다.

OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
wr.write(parameter);
wr.flush();  // 꼭 flush를 호출해야 한다.


응답 결과가 텍스트인 경우에는 다음과 같이 처리한다.

BufferedReader rd = null;

rd = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
String line = null;
while ((line = rd.readLine()) != null) {
  // 로직 처리
}

응답 결과가 XML인 경우에는 다음과 같이 처리한다.

DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document document = builder.parse(con.getInputStream());

// 이하 document를 이용해서 로직 처리

응답 헤더는 다음과 같이 확인할 수 있다.

String cookie = con.getHeaderField("Set-Cookie");


전체를 try/finally로 묶고 finally 절에서 OutputStreamWriter과 BufferedReader를 close한다.



2009-09-06

ALM 애플리케이션 목록

ALM(Application Lifecycle Management) 애플리케이션 목록이다.


YouTrack

IntelliJ IDEA로 유명한 JetBrains에서 만든 버그 이슈 트래커
아직은 베타 상태
키보드 단축키를 통한 빠른 사용을 장점으로 함

codeBeamer

기능적인 완성도는 모르겠지만 ALM 전체를 커버

tinyPM

Agile에 기반한 프로젝트 관리 도구

파이어폭스 3.5 느리다

파이어폭스 3.5 초기 부팅 과정이 느리다. 내 컴퓨터에서만 그런지는 모르겠지만 느리다.

느리다는 건 다른 웹 브라우저와 비교해도 파이어폭스 이전 버전하고 비교해도 그렇다.


프로그램 시작 자체도 느리지만, 즐겨 찾기 대신 Ctr + L 단축키로 URL을 직접 입력하는 내 사용 패턴이 더욱 답답하게 한다. 주소 입력 창에 URL을 입력할 때의 그 버벅임이란...

마이크로소프트 익스프레션

오늘 오후에 종각 영풍 문고에서 시간을 보내다가 두꺼움에 혹해서 크리에이티브 웹이라는 잡지를 구매했다.

서점을 지나가면서 표지를 본적이야 있겠지만 실제 내용을 보기는 처음이었다. 우리나라에 이렇게 많은 웹 에이전시 회사가 있다는 사실을 알았다.


그러다가 뒷면 광고에 나온 마이크로소프트 REMOIX09 행사 내용에 포함되어 있는 마이크로소프트 익스프레션이라는 솔루션에 눈길이 갔다.


그 중에 SketchFlow가 있었는데 일종의 와이어프레임 솔루션인 것 같다.

2009-09-02

홈페이지 메인 화면

http://www.gracesmith.co.uk





이런 디자인이 사람에게 주는 의미가 다양하겠지만 나는 좋다^^


http://vaadin.com


텍스트가 얼마나 중요한 요소인지를 보여준다.

2009-09-01

와이어프레임

구글 리더로 구독하는 Smashing Magazine에서 와이어프레임(Wireframes)과 관련한 35 Excellent Wireframing Resources을 보았다.


처음 알았는데 화면 스케치를 와이어프레임이라고 하는 것 같다. 혹은 프로토타입이라고 하거나...


파워포인트나 모델링 도구와는 달리 스케치 느낌을 살린 화면 스케치를 프로그램으로 구현할 수 있을까 생각한 적이 있는데 이를 구현한 제품(iPlotz)도 볼 수 있었다.

종이로 그린 후에 디지털 카메라나 스케너로 스캔하는 것과 이런 애플리케이션을 사용하는 것 중에서 어느 것이 더 생산적일까?



요구사항 관리 애플리케이션이 텍스트 편집기와 와이어프레임 편집기를 함께 제공하면 좋을 듯 하다. 여기디가 유스케이스 모델링 정도까지 추가해서...


와이어프레임 도구

Balsamiq Mockups

인상적임

Mockup Screens


관련 글

MockupScreens Review