Spring Framework 4.0 안내

스프링 프레임워크가 3.0이 출시되고 4.0으로 버전업 하기까지 4년 가까운 시간이 흘렀습니다. 스프링 프레임워크의 프로젝트 리더인 Juergen Hoeller는 그의 블로그를 통해 첫번째 마일스톤이 완성되었음을 알렸습니다.
첫번째 마일스톤의 결과물의 다운로드 링크는 아직 제공하지 않았습니다. 
스프링 4.0의 테마는 Java SE8(아마도 Open JDK 8 build 88 이후 버전을 base로 작업하고 있는듯) 과 Java EE 7의 지원과 몇가지 사용성 기능 추가로 보입니다.

Juergen는 JAVA SE 8에 대한 지원이 개발되고 있으며 JDK 8 developer preview의 출시에 맞춰 2013년 9월경에는 release candidate 출시를 예상하고있습니다. 올 9월에있을 SpringOne에서 소개할 예정입니다.

다음과 같은 Java se 8의 기능이 지원됩니다
JSR-335 Lambda expressions.
JSR-310 Date-Time value types for Spring data binding and formatting.
Support for the new 1.8 byte code format (람다 표현식 지원을 위해 필요).

다음 JEE 7 기능 지원도 포함됩니다.
JSR-343 JMS 2.0.
JSR-338 JPA 2.1.
JSR-349 Bean Validation 1.1.
JSR-236 Java EE 7 Enterprise Concurrency support.
JSR-356 Spring's WebSocket endpoint mode.


http://www.infoq.com/news/2013/06/Spring_Framework_4.0_Announced

2013/07/08 13:03 2013/07/08 13:03
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

Java EE 7 출시 이벤트 - 라이브 웹캐스트 등록

오라클이 Java EE 7 출시 준비를 마치고 오는 6월 13일 온라인 웹캐스트 이벤트를 진행한다고 합니다.
9 a.m. PT / 12 p.m. ET / 5 p.m. London or
9 p.m. PT / 12 a.m. ET (Thursday) / 2 p.m. Sydney (Thursday)
라고 하니 우리나라 시간으로는 6월 13일 목요일 오후1시입니다.

이번 온라인 이벤트에서는

  • Business Keynote (Hasan Rizvi and Cameron Purdy)
  • Technical Keynote (Linda DeMichiel)
  • Breakout Sessions on different JSRs by specification leads
  • Live Chat
  • Lots of Demos
  • Community, Partner, and Customer video testimonials
  • 들을 다룰 예정이라고 하며 온라인 사전 등록 페이지에서 자세한 내용을 확인하실 수 있습니다.
    관심있으신 개발자는 등록하시고 들어보시는것도 나쁘진 않을것 같습니다.

    저는 breakout session 에서 json, websocket 1.0 , servlet 3.1 에 눈길이 가네요.

    아래 배너 클릭 하시면 등록페이지로 이동합니다.  

    2013/05/23 14:35 2013/05/23 14:35
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    Hibernate의 generated query와 MSSQL의 nolock 힌트에 대한 고찰

    하이버네이트와 같은 OR매핑 도구를 이용하게되면 개발자가 SQL 를 작성할 필요가 없어지고 ( 물론, createSQLQuery() 메소드를 통해 native query를 작성할 수 있지만 이번글의 주제와는 조금 다른 이야기이니 제쳐두자. ) OR매퍼에서 생성된 쿼리가 실행되는데 MSSQL과 hibernate를 이용할때는 한 가지 특수한 상황에 맞딱드리게 된다.

    바로 select lock.
    MSSQL, Sybase, DB2는 여타 DBMS와는 달리 select 쿼리에도 row level lock ( 트랜젝션이 몰리면 이 lock도 에스컬레이션해서 row -> page -> table lock으로 범위가 확대 )을 거는데 일반적인 web application을 개발하는데 select lolock은 DB성능을 떨어트리는 원인이되기때문에 대게 select 쿼리에 각 테이블에 with(nolock) 힌트를 줘서 락을 걸지 않도록 처리한다.

    이제 Hibernate로 돌아와서, hibernate에 의해  generate된 쿼리에는 with(nolock) 옵션이 기본 적용이 되지 않는다.  MSSQL에서 그냥 이용해도 하이버네이트 캐시시스템의 덕으로 문제가 발생하지 않을 수도 있지만 쿼리 실행 시 부하를 줄일 수 있는 방안이 있다면 적용하지 않을 이유가 없다.

    이와 같은 내용은 검색 엔진에 hibernate mssql nolock 등의 키워드로 찾아보면 많은 결과를 확인할 수 있다. 그 중에 https://forum.hibernate.org/viewtopic.php?f=1&t=934158 의 쓰레드를 통해 확인한 방법은 다음과 같다.

    [code]
    session.connection().setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
    [/code]

    물론, MSSQL의 READ COMMITTED 격리수준 등 더 깊이있는 주제들도 있지만 내가 DB Geek도 아니고... 프로그래머 입장에서 요 정도까지만..
    2012/06/12 18:27 2012/06/12 18:27
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    잘못 알려지거나 무용지물이 된 Java 상식들

    2011/08/07 00:16

    서비 JAVA

    Java에 대해 잘못 알려지거나 java 5.0 이전의 정보로 현재의 java에서는 무용지물인 상식들이 몇가지 있는데 그런 종류의 상식에 대해 올바른 답을 전달하는 글이 있어 정리합니다.
    원문은 http://java.dzone.com/articles/incorrect-core-java-interview 입니다.
     
    Java의 인자 전달 방식은?
    이 질문은 자바 태생과 함께해온 오랜 질문 중의 하나로 제 과거 포스팅 '자바는 call by value? call by reference?' 에서도 언급했던 내용입니다. 하나의 기능에서 또다른 기능, 혹은 subroutine으로 인자를 전달하는 방식은 pass by value와 pass by reference 두 가지 방식이 존재합니다만 java 세상에서는 pass by value 만이 존재할 뿐입니다. reference의 값(reference by value)을 전달할 순 있지만 reference 자체를 전달할 순 없습니다. java reference는 Call By Sharing 으로 설명되기도 하지만 일반적으로 쓰이는 용어는 아닙니다.

    Garbage collection이란 무엇이며 어떻게 동작하는가?

    일반적으로 알려진 바로는 '어떤 변수에도 할당되지 않은 Object를 가비지콜렉터가 메모리에서 정리한다' 이죠. 맞는말이긴 합니다만 조금 더 정확히 기술하자면 Root context로 부터 더 이상 strong reference 되지 않은 Object가 가비지콜렉터의 대상이 됩니다. weak reference 혹은 soft reference Object가 그 대상인거죠.

    또한 System.gc()는 Full GC를 수행하라고 VM에게 힌트를 주는것이지  System.gc() 호출 시점에 GC가 수행되는것은 아닙니다. ( finalize 메소드의 오버라이딩을 자제해야 하는 이유. )

    Transient 와 Volatile 접근 제한자는 무엇인가?
    알려진 내용은 다음과 같죠.
    Transient 접근 제한자는 Object를 직렬화(serialize)하여 다른곳으로 전송하거나 객체를 저장할 때 Transient 제한자가 적용된 변수는 저장되지 않는다.  Volatile 접근 제한자는 해당변수를 컴파일러에게 해당 변수가 다른 프로그램에 의해 불규칙하게 변경될 여지가 있음을 알려준다.
    사실은 이렇습니다.
    transient 접근제한자는 오직 feild (클래스변수)에만 적용할 수 있으며, 지역변수에는 적용할 수 없습니다. static 변수에도 적용할수는 있지만 그 기능은 무시됩니다. trensient가 적용된 변수는 serialized 되진 않지만 writeObject(), readObject() 같은 커스텀 serialization을 통해 직렬화 할 수 있습니다.
    volatile 접근 제한자 역시 feild에만 적용할 수 있으며, compiler가 아닌 JIT 쪽에 필드값을 참조할 때 메인 메모리상의 필드값이 캐시(CPU의 L1,L2캐시)에 복사하도록(캐시를 갱신) 명시하는 역할을 합니다. 멀티쓰레드 환경에서 서로 다른 쓰레드들이 갱신되지 않은 캐시로 프로그램이 오작동 할 수 있는 부분에 적용할 수 있습니다.

    Integer 클래스와 int 의 차이점은 무엇인가?
    Integer는 java.lang 패키지에 정의된 클래스이며 int는 Java 언어 자체에 정의되어 있는 primitive 데이타 타입이다.
    딱히 틀린말은 아니지만 조금 더 정확히 표현하면 Integer는 int를 싸는(wrap) 참조 객체(reference to an object) 이고 autoboxing, unboxing이 도입된 이후의 Integer와 int의 가장 큰 차이점은 Integer는 null일 수 있는것과 == 연산자에서 Integer는 reference를 비교하거나 warpping된 값(int) 를 비교하는것 입니다. 아래 코드를 보시죠
    [code]
    Integer i1 = 1;
    Integer i2 = 1;
    // autoboxing이 적용되어 int값 비교로 true 출력.
    System.out.println(i1 == i2);

    Integer i3 = 3000;
    Integer i4 = 3000;
    // autoboxing이 적용되지 않고 reference 비교를 하기때문에 false 출력.
    System.out.println(i3 == i4);
    [/code]
    신기합니다. 두 Integer 객체 비교에 어떤 경우엔 true가, 또 어떤 경우엔 false가 됩니다.
    이 문제의 비밀은 java실행 옵션에 있는데요. SUN/Oracle JVM의 경우 integer값을 캐시하는 기본 최대값은 127입니다. 즉 127이내의 Integer를 비교하면 autoboxing이 적용된 int를 비교하게됩니다. 물론 이 옵션은
     -XX:AutoBoxCacheMax= or -Djava.lang.Integer.IntegerCache.high=2000
    과 같은 방법으로 변경할 수 있습니다.

    Thread의 상태는?
    Thread는 ready, running, dead 의 상태를 갖는다고 일반적으로 알려져 있습니다만 java 5.0으로 넘어오면서 Thread.State enum이 추가되면서
    NEW : 쓰레드가 시작되지 않은 상태
    RUNNABLE : JVM에서 쓰레드가 동작중인 상태
    BLOCKED : block되어 monitor lock을 기다리는 상태
    WAITING : 다른쓰레드가 특정한 행위를 수행할때까지 기약없이 대기하는 상태.
    TIMED_WAITING : 다른쓰레드가 특정한 행위를 수행할때까지 약속된 시간까지 대기하는 상태.
    TERMINATED : 쓰레드가 종료된 상태.
    의 6가지 상태로 구분됩니다.

    모든 클래스의 base 클래스는?
    java.lang.Object
    아마 모든 Java 입문서에 나와있는 내용일겁니다. 물론 일반적인 자바객체는 java.lang.Object를 상속하고 있습니다.
    하지만 이는 custom class에만 적용되는 이야기입니다. int.class, void.class와 같은 primitive 타입과 Object 그 자체는 super class가 없습니다.
    [code]
    Class parent = boolean.class.getSuperclass(); // returns null
    [/code]

    Java Beans란?
    java beans는 '다양한 환경에서 재사용이 가능하도록 디자인된 소프트웨어 컴포넌트이다.' 라고 설명 되기도 합니다. 하지만 Java Beans를 좀 더 구체적으로 설명하자면 '직렬화 가능하고(serializable) 인자없는 생성자를 가지며, getter ,setter 메소드를 통하여 프로퍼티에 접근 가능한 Java Object이다.'정도가 될것입니다.

    synchronized block vs. synchronized method.
    일반적으로 synchronized block이  synchronized method보다 lock을 거는 주기가 더 짧다고 알려져있습니다. 옳은 말이긴하지만 항상 그렇게 동작한다고 보증할 순 없는데요. 아래는 일반적으로 사용되고 있는 코드 예시로 synchronized block에 lock으로 this가 아닌 다른 object를 사용하고 있습니다. 이런 경우 synchronized block은 synchronized method로 lock을 걸게 됩니다. 결국 synchronized block으로 lock 영역을 줄인 의미가 없어지게 되는거죠.
    [code]
    Map<Key, Value> map = Collections.synchronizedMap(new LinkedHashMap<Key, Value>());
    // perform multiple operations in a thread safe manner
    synchronized(map) {
        Value value = map.get(key);
        if (value == null)
            map.put(key, value = new Value(key));
        return value;
    }
    [/code]

    2011/08/07 00:16 2011/08/07 00:16
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
    1. Blog Icon
      rkdgusrnrlrl

      안녕하세요 글 잘봤습니다. 제가 궁금하게 있어 질문은 남깁니다. Integer a = 10; 해서 a라는 Interger 타입의 클래스에 10라는 데이터를 담았습니다. 그리고 그 a의 주소값은 Integer b 에게 넘겨주려고 합니다. 기본적인 클래스의 방식 대로라면 Integer b = a; 이겠지만 이렇게 하면 값(10)이 넘어가 버립니다. 제가 원하는 것은 a 와 b 는 같은 주소를 공유해 a의 값에 변화가 생기면 b의 값에 변화를 주고 싶습니다. 그래서 a.hashcode(); 도 사용해봤는데 주소 값이 아닌 데이터 값이 10을 반환하더군요. a의 주소값은 얻어와 b에 그 주소값으로 설정해 줄수 있는 방법이 없을까요??

    2. Blog Icon
      서비

      rkdgusrnrlrl님 안녕하세요.
      java API를 유심히 살펴 보셨다면 java 언어가 wrapper 클래스를 님이 원하는 방식으로 사용하지 않기를 바랐다는것을 아실 수 있었을 겁니다.
      java.lang.Integer 는 public final class Integer extends Number 와 같이 정의되어 있습니다. 네.. final class 죠. 한번 생성 후 변경할 수 없는 클래스로 만들어져 있습니다. 이런 이유로 setValue() 나 setInt() 같은 메소드도 존재하지 않는것이구요. final class이기 때문애 값을 변경하려면 항상 새로운 객체를 할당할 수 밖에 없습니다.

      님과 같은 상황을 해결하려면 Integer를 멤버변수로 갖는 VO를 만들어 사용하시면 됩니다.

      public class IntegerData implements Serializable{
      private Integer i;

      public void setInteger(Integer i){
      this.i = i;
      }

      public Integer getInteger(){
      return this.i;
      }
      }

    3. 안녕하세요 transient 관련 글을 검색하다 방문했습니다. 좋은 글 잘 읽었습니다. 그런데 class에 final 키워드는 제가 알기로는 더 이상 상속을 불가능케 하는거지 생성된 인스턴스의 변경 불가와는 크게 상관이 없어 보이는데요 제가 잘못 알고 있는건가요? 관련 레퍼런스가 있다면 알려주시면 감사하겠습니다.

    4. Blog Icon
      rkdgusrnrlrl

      아 그럼 위의 방식으로 하게 되면 데이터 값 교환이 아닌 주소값 교환인 되는 건가요?? 이제 프로그래밍을 배우고 있고 지금 제가 자바 초급을 막 완료한 상태라 VO가 뭔지는 잘 모르겠니요^^;; 얼마전에 wrapper 클래스를 배우서 Integer라는 클래스가 int와 비슷한 기능을 해 관심을 갖고 있었거든요 c 에서는 포인트가 있어 int 변수의 주소 값을 가져올 수 있는 것 같은데 그런 점에서는 자바가 많이 아쉽네요ㅠㅠ 답변 감사합니다.

    5. @Saver

      맞습니다. 클래스에 final이 붙어서 Integer가 불변이 아니지요.

      값을 담고 있는 value가 final이라는 것을 보여주려고 하셨던 것 같습니다.

      private final int value;

      또한 setter가 없기 때문에 Integer의 내부의 value를 바꿀 수 없는 것이지요.

    제임스 고슬링 구글로 이적

    자바의 아버지 제임스 고슬링 아저씨가 구글로 그 자리를 옮겼다고 합니다. 뭐 썬이 오라클로 넘어가면서 자연스레 오라클 소속이 되었다가 작년에 그만두었죠(http://kldp.org/node/114063). 일년의 공백 후 구글로 입사한 거니 딱히 자리를 옮겼다고 표현하기에도 뭐하지만요. 오라클의 자바 및 오픈소스 지원정책에 불만이 있었기에 오라클을 그만둔 그의 다음 포지션을 많은 이가 궁금해 했을 겁니다. IBM 정도가 아닐까 예상했는데.. 구글로 가는군요. 구글의 비공개 직위로 간다는데 이게.. 오라클과의 특허 분쟁 방어용으로 가는건지 혹은, 자바나 또다른 언어를 위한 것인지는 아직 알려진 바는 없습니다. 그의 강연이나 이전까지 보여준 독설이나 자바 옹호 행위에서 느낀 것은 고슬링아저씨가 위대한 사람이긴 해도 성인군자 스타일은 아니란 거죠. 오라클을 엿먹이기 위해 구글과 손잡았을 가능성도 전혀 배제하진 못하겠네요. 그 정도 창의력이 있는 사람이라면 앞으로도 혁신적인 일로 인류에 공헌하면 좋겠어요.
    2011/03/29 12:26 2011/03/29 12:26
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    Unable to compile class for JSP

    2011/03/22 03:09

    서비 JAVA , ,

    java / jsp 개발 시 거의 보기 어려운 익셉션으로 대게 아래와 같은 익셉션을 출력한다.
    [code]
    org.apache.jasper.JasperException: Unable to compile class for JSP:

    An error occurred at line: 3 in the jsp file: /src/test/test.jsp
    Employee cannot be resolved to a type
    1: <%@ page language="java" import="java.util.*,com.employee.*" pageEncoding="ISO-8859-1"%>
    2: <%
    3: Employee ddd = new Employee();
    4: %>
    [/code]

    익셉션 출력물 그대로 jsp 파일을 .class 파일로 검파일 하지 못했다는 의미이다. 왜 그럴까?
    예상하건데 첫 번째 라인의 import 내용과 3번째 라인의 클래스 생성코드를 삭제하고 실행하면 페이지가 열릴 것이다.
    그럼, 이 예외상황은 import한 클래스를 찾지 못한 것인가? 그렇지 않다. import 가 잘못되었다면 NoSuchClassFound 같은 익셉션을 보게 될 것이다.

    위와 같은 오류를 만나면 아래 jsp를 적당한 이름으로 저장한 후 컨텍스트 루트, 즉 WEB-INF 디렉토리가 있는 경로에 소스를 올리고 jsp를 호출해 보자.
    [code]
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
       <html>  
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>JSP Page</title>
        </head>
        <body>
    sun.boot.class.path : <%= System.getProperty("sun.boot.class.path") %>
    sun.boot.library.path : <%= System.getProperty("sun.boot.library.path") %>
    java.library.path : <%= System.getProperty("java.library.path") %>
    java.class.path : <%= System.getProperty("java.class.path") %>
    getClassLoader() : <%= this.getClass().getClassLoader() %>
    DocumentBuilderFactory : <%= javax.xml.parsers.DocumentBuilderFactory.newInstance() %>
    /javax/xml.parsers/DocumentBuilderFactory.class : <%= this.getClass().getResource("/javax/xml.parsers/DocumentBuilderFactory.class") %>
    SAXParserFactory : <%= javax.xml.parsers.SAXParserFactory.newInstance() %>
    /javax/xml/parsers/SAXParserFactory.class : <%= this.getClass().getResource("/javax/xml/parsers/SAXParserFactory.class") %>
    TransformerFactory : <%= javax.xml.transform.TransformerFactory.newInstance() %>
    /javax/xml/transform/TransformerFactory.class : <%= this.getClass().getResource("/javax/xml/transform/TransformerFactory.class") %>
    <hr>
    Servlet : <%= application.getMajorVersion() %>.<%= application.getMinorVersion() %>
    JSP : <%= javax.servlet.jsp.JspFactory.getDefaultFactory().getEngineInfo().getSpecificationVersion() %>
    ServerInfo : <%= application.getServerInfo() %>
    RealPath : <%= application.getRealPath("/") %>
    ContextPath : <%= request.getContextPath()%>
    <hr>
    totalMemory : <%= Runtime.getRuntime().totalMemory() %>
    maxMemory : <%= Runtime.getRuntime().maxMemory() %>
    freeMemory : <%= Runtime.getRuntime().freeMemory() %>
    <hr>
        </body>
    </html>
    [/code]
    위 소스를 실행하면 몇몇 중요한 정보를 얻을 수 있는데 그중에 request.getContextPath() 값을 한번 확인해 보자.
    개발 시 의도했던 컨텍스트 루트가 아닐 가능성이 크다.
    컨텍스트 루트가 의도했던 루트와 다르다면 웹서버든.. WAS든 host 설정과 관계된 설정파일을 보면서 해당 문제를 교정하면 된다.
    원인은 컨텍스트가 다름으로 인해 import한 클래스를 클래스로더가 찾을 수 없어 발생하는 현상이다.

    한가지 팁이라면 톰켓 + 가상호스트로  구성한 웹 어플리케이션의 컨텍스트 루트가 / 라면  [CATALINA_HOME]/conf/Catalina/[HOST_NAME]/ROOT.xml 의
    Context 항목의 docBase는 "[웹어플리케이션경로]/ROOT" 와 같이 설정되어야 하고, 웹어플리케이션의 또한 [웹어플리케이션경로]/ROOT/  아래에 배포되어야  한다.

    2011/03/22 03:09 2011/03/22 03:09
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
    1. Blog Icon
      김진규

      와 진짜 정말 도움 많이됐습니다 ... 이 문제였어요 ㅠㅠ

    Java 6u21 과 이클립스

    최근에 오라클에서 Java 6 update 21 을 발표했습니다. 이번 버전에서 java.dll의 변경된 사항으로 인해 이클립스 구동에 영향을 미치게 되었다고 합니다.

    변경 사항은 JDK의 개발사 정보를 기존 "Sun Microsystems, Inc." 에서 "Oracle Corporation" 으로 수정한 것인데요 이클립스의 경우 Sun JRE 에 있는 non-standard 실행 옵션 중의 하나인 -XX:MaxPermSize 적용 가능 여부를 java.dll의 제조사 정보 문자열의 "Sun Microsystems"로 구분하고 있다고 하네요. 실제로  -XX:MaxPermSize 옵션을 지원하지 않는 몇몇 JVM에 해당 옵션을 적용하면 이클립스 구동이 실패한다고 합니다. 이클립스 런처는 Windows에서 실행되는 SUN VM인 경우 자동으로 -XX:MaxPermSize=256m 옵션을 적용한다고 하네요.

    JVM 의 Vendor 정보를 변경한 것으로 영향을 받는것은 비단 이클립스 뿐만이 아닐겁니다.
    http://www.excelsior-usa.com/blog/excelsior-jet/apps-will-stop-working-under-oracle-jre/ 에서와 같이 System.getProperty("java.vm.vendor") 값으로 무언가를 처리하는 모든 어플리케이션이 영향을 받을 수 있습니다.

    JAVA가 Oracle의 자산이 된 이상 개발사 정보를 변경하는 것을 뭐라고 할 순 없지만 기존에 개발된 어플리케이션에 미치는 영향을 생각한다면 오라클이 어떤식으로든 액션을 취하지 않으면 안될것 같습니다. Java 6u21에서 이클립스 구동이 실패한다면 당분간은 JDK를 Java 6u20으로 다운그래이드 해야할 듯 합니다.
    2010/07/30 00:53 2010/07/30 00:53
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    InputStream.read()

    제가 만든 서버에서 보낸 데이터가 xml 형식으로 바이트 스트림으로 해서 받는데 in.read로 받았더니 byte 버퍼에 태그단위로 하나씩 들어가는데다가 디버그해봤더니 in.read라는 문장은 받은 xml 태그 수만큼 반복해서 실행되고 전체 xml을 받아서 파싱하려고 Stringbuffer를 이용해서 append 하려고 했더니 이것도 안되네요..

    안녕하세요 질문자님.
    질문 내용을 제가 정확히 이해한 건진 모르겠습니다만 제가 이해한 내용은
    보내는 서버 측에서는 예를 들어, "<tag>내용</tag>" 스타일의 문자열을  byte[]로 변환하여
    outputStream.write( byte[] );
    하고 있고 클라이언트 측에서는
    [code]
    while ((readLength = inputStream.read(input, 0, input.length)) != -1) {
        stringBuffer.append(  new String( input )  );
    }
    [/code]
    과 같은 동작을 하고 있다고 생각이 됩니다.

    질문 내용 중 ' in.read라는 문장은 받은 xml 태그 수만큼 반복해서 실행되고' 라고 하신 걸로 미루어보아 데이터는 정상적으로 들어오고 있다고 판단됩니다. 받은 데이터를 가공하는데 어려움을 느끼고 계신 건 아닌가 하는 생각이 드네요.

    우선 작성하신 클라이언트 쪽이 서버에서 보내주는 xml을 다 받으면 while 문을 빠져 나오는지 확인해 보시고요. 정상적으로 while문을 빠져 나온다면 유입된 Data를 가공하는 문제가 될 거고 그렇지 않다면 서버 측의 outputStream 에 write() 하는 부분을 확인하셔서 stream을 확실히 끝내고 있는지 확인하셔야 할 것 같습니다.

    참고로 제가 작성한 소스를 첨부합니다.
    첨부한 소스는 xml 형식의 문서를 읽어들여 byte 형식으로 전송하여 수신부에서 file과 문자열로 복원하는 코드가 작성되어 있습니다. Server.java 와 Client.java 는 일반적인 자바 bolocked Socket 프로그래밍 방식을 취하고 있습니다. 실제로 확인해야 하는 부분은 ByteArrayTransporter 클래스에서 클라이언트에 Data를 전송하는 부분과 Client 클래스에서 java.nio.ByteBuffer 를 이용하여 입력 데이터를 처리하는 부분 정도가 될 거 같습니다.



    ByteArrayTransporter.java
    [code]
       byte[] byteArray = new byte[1024];
       int readLength = 0 ;
       while ( (readLength = fileInStream.read(byteArray, 0, byteArray.length) ) != -1 ){
         out.write(byteArray, 0, readLength);
       }
       out.flush();
       out.close();  //<-- 스트림 끝내기
    [/code]

    Client.java
    [code]   ByteBuffer bBuffer = ByteBuffer.allocate(102400);
       while ((readLength = bin.read(input, 0, input.length)) != -1) {   //byteBuffer에 byte[] 쓰기
          bBuffer.put(input, 0 ,readLength );
       }   //ByteBuffer 에 담긴 문자열 확인
       System.out.println( new String(bBuffer.array() , "UTF-8" ) );
    [/code]

    2010/07/20 19:54 2010/07/20 19:54
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
    1. 다른 문제로 구글링하다가 들리게 되었는데, 좋은 글 잘 읽었습니다.

      이 페이지에 어울리지 않을지는 모르나 도움을 주실 수 있을 듯하여 한 가지 질문 드리겠습니다.

      <질문> 삼성 갤럭시폰에서 파일도 존재하고 파일크기도 0이 아닌데 FileNotFoundException 에러 나타나는 문제

      구글링해도 제 힘으로 답을 구하지 못해 도움을 청합니다.

      도와주시면 정말로 감사하겠습니다.

      1. 테스트 환경 : 폰(삼성 갤럭시S3/갤럭시S5), 파일(MMS에 첨부된 .vcf 주소록파일), 안드로이드 스튜디오 2.3, 윈7(64비트)

      아래 코드의 실행 결과 : "파일 OK/2025bytes/주소록 내용을 읽을 수 없습니다."

      즉 exists 메소드로 검사하면 파일도 존재하고, length 메소드로 검사하면 파일크기도 0이 아니므로 분명 존재하는 파일입니다.

      그런데 BufferedReader/readLine으로 파일을 읽으면 FileNotFoundException 에러를 내고 파일 내용을 읽지 못합니다.

      다른 테스트 폰 엘지 G2에서는 정상으로 읽힙니다.

      // 주소록 보이기
      public void viewVcf(final String filePath) {
      File vcfFile = new File(filePath);
      if (vcfFile.exists()) {
      long lFileSize = vcfFile.length();
      tv_unique.setText("파일 OK/"+lFileSize+"bytes");
      String content = readFile(filePath);
      if (content.isEmpty())
      tv_unique.setText(tv_unique.getText().toString()+"/주소록 내용을 읽을 수 없습니다.");
      else {
      ...
      }
      }
      else {
      report10sec("주소록 파일이 없습니다.");
      }
      }

      2. 테스트 환경 : 폰(삼성 갤럭시S3/갤럭시S5), 파일(MMS에 첨부된 .mp4 동영상파일), 안드로이드 스튜디오 2.3, 윈7(64비트)

      동영상 파일의 경우도 위와 비슷합니다.

      "파일 OK/707989bytes"

      // 비디오 재생
      public void viewVideo(final String filePath) {
      File videoFile = new File(filePath);
      if (videoFile.exists()) {
      long lFileSize = videoFile.length();
      tv_unique.setText("파일 OK/"+lFileSize+"bytes");
      ...
      }
      else {
      report10sec("비디오 파일이 없습니다.");
      }
      }

      위 ... 부분의 코드에 따라서 2가지 테스트 결과입니다.

      1) startActivity(intent);

      삼성폰, 엘지폰 모두 비디오가 재생되지 않습니다.

      (엘지) java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.ActivityThread$ApplicationThread android.app.ActivityThread.getApplicationThread()' on a null object reference

      (삼성) java.lang.NullPointerException

      2) videoView.start();

      엘지폰에서는 정상으로 재생이 됩니다.

      삼성폰에서는 에러 로그는 없으나, "재생할 수 없는 동영상입니다./확인" 메시지가 뜨고 비디오가 재생되지 않습니다.

      읽어 주셔서 고맙습니다.

    2. Blog Icon
      김병희

      <답변> 존재하고 크기도 있는 파일의 FileNotFoundException = 권한 없음/[Android] http://blog.daum.net/andro_java/1121

    소수 자리 숫자들의 사칙연산

    커뮤니티에 올라온 질문 중에 소수자리 숫자에 대한 덧셈 계산의 결과가 이상하다는 내용이 있어 정리해 봅니다.
    질문에 올라온 코드는 아래와 같습니다.
    [code]
    double a = 35147.464;
    double b = 73823.828;
    double c= a+b;
    System.out.println("a+b=" + (a+b));
    System.out.println("c=" + c);

    double d = 587350.504;
    double e = 63354.488;
    double f= d+e;
    System.out.println("d+e=" + (d+e));
    System.out.println("f=" + f );
    [/code]

    실행한 결과는 아래와 같습니다.
    [code]
    a+b=108971.29199999999
    c=108971.29199999999
    d+e=650704.992
    f=650704.992
    [/code]

    왜 똑같이 소수점 세 자리 숫자를 더했는데 어떤 때는 소수점 아래 자릿수가 늘고 어떤 때는 세 자리로
    출력되었을까요?

    소수자리 숫자는 인간이 생각하는 10진수의 개념으로 접근 하면 안되기 때문인데요..
    알고있듯이 컴퓨터는 0,1 로 모든 연산을 처리하는데 int, long 같은 정수라면 0,1로 표현할 수 있지만
    float, double 같은 소수자리 수는 IEEE 754 표준에 의한 binary의 일부(fractions)로  표현하게 됩니다.
    ( http://www.math.byu.edu/~schow/work/IEEEFloatingPoint.htm 참조하시면 됩니다만 제게는 참.. 어렵네요.)
    어쨌거나 저쨌거나 결과만 놓고 보면 '소수자리 숫자는 컴퓨터는 근사값 밖에 알 수 없다.' 인데요.

    그럼, 저렇게 계산되도록 놔둬야 하느냐? 그렇지는 않습니다.
    위 같은 경우는 DecimalFormat.parse() 메소드를 이용하면 됩니다.
    맨 처음 코드를 아래와 같이 다시 작성해 볼 수 있겠지요.
    [code]
    java.text.DecimalFormat format = new java.text.DecimalFormat(".###");

    double a = 35147.464d;
    double b = 73823.828d;
    double c= a+b;
    System.out.println("a+b=" + format.parse( format.format(a+b) ) );
    System.out.println("c=" + format.parse( format.format(c) ) );

    double d = 587350.505d;
    double e = 63354.491d;
    double f= d+e;
    System.out.println("d+e=" + format.parse( format.format(d+e) ) );
    System.out.println("f=" + format.parse( format.format(f) ) );
    [/code]


    그럼 결과는 아래와 같이 원하는 대로 출력이 될 겁니다.
    [code]
    a+b=108971.292
    c=108971.292
    d+e=650704.996
    f=650704.996
    [/code]


    한가지 유의해야 할 점은 저런 방식의 처리를 정확성을 요구하는 금융이나, 계측 분야에 적용 할 때는
    계산결과의 정밀도가 충분히 받아들여질 만한 것인지를 다시 한 번 고민해야 한다는 겁니다.

    금융과 같이 double이 허용하는 것보다 큰 숫자가 필요로 할 때는 BigDecimal을 이용해야 합니다.
    ( http://www.yunsobi.com/blog/227 BigDecimal의 필요성 참조 )

    2010/05/14 19:54 2010/05/14 19:54
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    Java 6 update 18 출시 : 성능 향상과 windows 7 지원

    2010/02/04 14:56

    서비 JAVA , , ,

    새로운 hotspot, UI 어플리케이션의 시작과 구동 성능 향상, 우분투 8.04와 레드햇 엔터프라이즈 리눅스 5.3 및
    윈도우즈7 지원, 357개의 버그 픽스가 이루어진 sun java 6 update 18 가 출시되었습니다.
    JavaSE 6 Update Release Note

    엔터프라이즈 개발자가 특히 흥미를 가질만한것은 가비지 컬렉션의 성능 향상일듯합니다.
    Garbage First(G1) 가비지 컬렉터( 드디어 experimental 딱지를 뗐습니다.)가 신뢰성과 성능에서 괄목할 만한
    향상을 이루어 냈다는겁니다. 가비지 대상 수집 처리를 병렬화(Parallel Scavenger)하고 향상된 NUMA
    ( Non Uniform Memory Access ) 지원이 포함됩니다.
    NUMA 아키텍처는 메모리에 액세스하는 방식 중 하나로 프로세스들은 서로 다른 메모리 영역에 엑세스하는데
    동일하지 않은 시간을 소비하는 특징이 있습니다.

    NUMA 아키텍처..


    대부분의 현대적인 컴퓨터는 이 NUMA 아키텍처에 기반하고 있습니다. Java HotSpot VM에서는 NUMA 를 이용
    할 수 있는 시스템이라면  -XX:+UseNUMA 플래그를 통하여 병렬로 가비지 대상을 수집할 수 있습니다.
    이 옵션의 효과는 꽤나 훌륭해서 8코어 옵테론 시스템에서 측정한 SPEC JBB 2005  ( http://www.spec.org/jbb2005/index.html )
    벤치마킹에서 32비트에서 30%, 64비트에서 40%성능 향상이 있었습니다.

    데스크탑 어플리케이션과 Web Start의 업데이트 주요 항목을 보고있자면 썬은 데스크탑과 RIA 마켓도
    무시하지 않고 있음을 엿볼 수 있습니다.
    ( 개인적으로 java가 이 두 영역에서의 그다지 큰 영향력을 행사하지 못할것 같다는 생각을 하지만요..)
     - 클라이언트 서버 양쪽 VM에 새로운 java heap configuration을 적용하여 가비지 컬렉션 성능 향상.
     - 빠른 시작을 위한 클래스로딩 최적화.
     - Direct 3D를 사용할 경우 시스템에 따라 100-200ms가량 어플리케이션 시작 시간 단축.
     - JavaFX 어플리케이션의 warm start 시 15%가량 빠른 구동.
     - Web Start와 애플릿의 jar파일의 동시 다운로드
     - Java Web Start 스펙 JSR-056 을 6.0.18로 버전업하고 다수의 버그 픽스.

    이 외에도 다음과 같은 변화를 포함
     - jar 파일 생성시간 20% 단축
     - JavaDB 버전 10.5.3으로 업데이트
     - VisualVM 버전 1.2.1로 업데이트
     - StaX(Streaming API for XML) 마이너 업데이트

    이번 버전에 보안관련 버그 픽스 사항은 포함되지 않았습니만 이번 분기에 발표 할 다음번 업데이트에
    포함될것으로 예상하고있습니다.

    http://blog.sdnkorea.com/blog/504

    2010/02/04 14:56 2010/02/04 14:56
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    뜻밖에도 JDK7에 Closure가 도입됩니다.

    이전 Java 7 로드맵 업데이트와 커뮤니티의 반응. 포스팅을 통해 JDK7에서의 클로저 누락에 대한 언급을 한 적이 있는데요. 뜻밖에도 JDK7에 클로저를 포함하기로 했다는 뉴스를 접했습니다.

    Java SE의 수석 엔지니어 Mark Reinhold는 지난 자신의 의견에 반하여 JDK7에 클로저를 도입하기로 했다는군요. JDK 출시 일정은 조금 지연되어 2010년 9월께가 될 듯합니다.

    Coin 프로젝트의 수석 엔지니어인 Joseph D. Darcy는 다음 버전의 JDK7에는 BGGA의 제안과 유사한 방식의 "경량의" 클로저가 포함되며 Java 7에서 약간의 언어상 변화가 있을 것이라고 말했습니다.

    썬은 java 클로저에 회의적이었지만 자바 커뮤니티는 이미 3가지의 클로저 구현 방법을 제안했었습니다.
    2009/12/04 15:46 2009/12/04 15:46
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    JAVA Hot Deploy 도구 Jrebel ( 舊 JavaRebel )

    왜 Java Enterprise Web Application에서 hot deploy가 어려우며 문제가 되는지는 아래 아티클 참조.

    Tomcat , Weblogic Application Server, WebSphere, JBoss 같은 서블릿컨테이너나 J2EE컨테이너도
    옵션을 통해 Hot Deploy를 지원하긴 하지만 어디까지나 Context 전체를 리로딩하는 수준이다.

    그런 식으로나마 서버 Shutdown , Startup 조작을 줄여주는 게 고맙기는 하지만 클래스 Hot Deploy는 자바
    웹어플리케이션 개발자에게는 성가신 문제일  수밖에 없다.

    이런 문제를 풀기 위해 몇몇 솔루션이 있는데 최근에 사용해본 게 아래의 솔루션이다.
    JRebel (舊 JavaRebel)

    Jrebel

    JRebel의 리디플로이 가능 범위


    JRebel는 훌륭한 도구이긴 하지만, 위 링크에 설명된 몇 가지 이유로 완전한 Hot Deploy를 제공하는 것은 아니다.
    다만, 분명한 것은 개발 시 로컬 서버나, 테스트 서버의 shutdown 횟수를 줄여줄 뿐만 아니라 클래스 리로딩
    시간을 현격히 줄여주는 것으로도 JRebel을 사용할 충분한 가치가 있다고 생각한다.
     
    덧. 위에 소개한 JRebel은 Open Source나 Freeware가 아님.
         단, Open Source Software개발자와 Scala 개발자에 한해 무료로 제공하고 있음.
    2009/10/12 13:15 2009/10/12 13:15
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    JDK 7 에서 기본 제공했으면하는 메소드는?

    OpenJDK core-libs-dev 메일링 리스트에 재미있는 쓰레드가 진행되고 있습니다. ( 재미있다고 적긴 했지만 재미있기만 한 것은 아니지만요..)  What methods should go into a java.util.Objects class in JDK 7? 이란 타이틀로 진행 중인 이 쓰레드의 내용인즉, '자바 개발자가 흔히 사용하는 유틸리티 성 메소드를 구현하는 java.util.Objects 같은 클래스를 만든다면 이 Objects 클래스에서 꼭 포함 했으면 하는 메소드는 무엇인가?' 하는 내용입니다.  썬社의 Joe Darcy로부터 시작된 이 쓰레드에는 많은 회신 메일로 해당 이슈에 대한 자바 개발자의 높은 관심도를 엿볼 수 있습니다.

    Darcy는 그의 첫 번째 포스트에서 Null-safe 한 equals(arg1,arg2) 와 모든 primitive type에 대응하는 compareTo(arg1, arg2) 를 제안하고 있네요.

    Andrew John Hughes 같은 경우엔 toString(arg) 메소드에 대해 자바 리플랙션을 통하여 해당 객체의 상세를 보여주면 어떻겠냐는 것과 비슷한 방법으로 clone() 메소드도 구현해 버리자는 내용을 제안했습니다.

    이 쓰레드가 커뮤니티의 긍정적인 회신을 받고 있기만 한 것은 아닙니다. 이런 내용의 글을 접한 Stephan Oudmaijer 같은 사람은 infoQ의 해당 내용에 대한 기사에 댓글을 통해 stupid idea란 표현과 함께 그런 유틸성 메소드는 jakarta-commons에서 구현하도록 하고 제발 JDK는 그냥 내버려 뒀으면 좋겠다고 표현하고 있네요. ^^;

    여러분도 평소에 '아.. 이런 메쏘드는 기본적으로 JDK에 있었으면 좋겠는데...' 하고 생각한게 하나 둘쯤은 있을 거라 생각되는데요.. 해당 메일링 리스트에 가입하셔서 의견을 피력해 보시는것도 재미있을것 같습니다.

    2009/09/14 16:26 2009/09/14 16:26
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    Struts 2.1 + ajax 플러그인 : dojo툴킷 이용 방법 변경

    실로 오랜만에 struts 2 (정확히는 2.1.6 )를 잡았습니다.
    개발팀원이 참조 할 몇몇 코드조각들을 작성하고 있는데 어제는 ajax tag 쪽 코드를 작성했습니다.
    코드를 작성해 실행을 시켰는데 아래와 같은 몇몇 오류와 맞닥뜨립니다.

    [code]
    Template /template/ajax/head.ftl not found. - Class: freemarker.template.Configuration
    File: Configuration.java
    Method: getTemplate
    Line: 489 - freemarker/template/Configuration.java:489:-1
    [/code]

    [code]
    org.apache.jasper.JasperException: Expression parameters.parseContent is undefined on line 45, column 28 in template/ajax/head.ftl. - Class: freemarker.core.TemplateObject
    File: TemplateObject.java
    Method: assertNonNull
    [/code]

    [code]
    Expression parameters.pushId is undefined on line 24, column 6 in template/ajax/a-close.ftl.
    The problematic instruction:
    ----------
    ==> if parameters.pushId [on line 24, column 1 in template/ajax/a-close.ftl]
    [/code]

    원인은 스트럿츠 2.1 릴리즈!! Committer 인터뷰에서도 언급되었던 내용에서 기인합니다.
    기존 strtus2 에서 Dojo 툴킷을 이용한 ajax를 이용하기 위해서 <s:head theme="ajax" /> 같이
    기술하던 부분이 deprecated 되었습니다. strtus2.1에서 ajax 태그를 이용하기 위해서는
    문서 상단에 <%@ taglib prefix="sx" uri="/struts-dojo-tags" %> 와 같이 새로운 태그 라이브러리를
    지정하고 <s:head theme="ajax" /> 를 <sx:head parseContent="true"/> 로 수정,
    <s:div ... /> 부분도 <sx:div ... /> 로 바뀔 뿐만 아니라 각 태그의 속성들도 변화가 있습니다.

    스트럿츠 2.0 과 2.1의 차이점을 확인하고 싶으시거나 2.0을 2.1로 마이그레이션을
    고려하고 계신다면 Apache Strtuts 2 Wiki 의
    Troubleshooting guide migrating from Struts 2.0.x to 2.1.x
    를 참고하시면 좋을 듯합니다.
    2009/08/26 10:57 2009/08/26 10:57
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

    썬은 G1(Garbage First) Garbage Collector를 상용화할 것인가?

    Sun은 G1이라는 애칭으로 불리는 Garbage First 가비지 컬렉터를 Java Update 1.6.0.14와 함께 릴리즈 하였습니다. 하지만, 많은 개발자 커뮤니티에서 기다려온, 서버에 적합한 이 가비지 컬렉터를 현 시점에서는 비용을 지불하는 고객에 한해서만 사용할 수 있도록 하고 있습니다.

    이 Garbage First(이하 G1) 가비지 컬렉터는 update 6u14 이상에서 작동합니다.

    G1은 가비지 콜렉팅 시 시스템 pause를 줄여, 서버 측에 적합합니다. G1의 가장 큰 장점은
    compaction 성능과 예측성이 향상된 Concurrent Mark-Sweep(CMS)과 사용의 간편함입니다.

    하지만, 썬의 릴리즈노트에 의하면 이 가비지 컬렉터는 Java Platform Standard Edition for Business Program을 통하여 제공되며 이용을 위해서는 썬에 Support Contact의 허락이 필요하다고 합니다.

    많은 사람이 이는 썬의 정책 변경의 징조이며 오라클과의 합병과 무관치 않다고 생각하고 있습니다.

    Java의 제약이 시작되었다. 썬은 새로운 G1 가비지 컬렉터를 포함한 Java 1.6.0.14 JDK와 JRE를 출시하며 릴리즈 노트에 'Although G1 is available for use in this release, note that production use of G1 is only permitted where a Java support contract has been purchased.'와 같이 명시했다.  이는 이미 오라클의 입김이 작용하기 시작한 것은 아닌가.
    새롭고 멋진 기능들을 Business commercial version의 Java SE에 넣는 동안 OpenJDK는 침체의 길을 걷게 될 것이다.  

    반면, G1이 아직은 다양한 검증을 필요로 하기 때문에 위와 같은 결정을 내렸을 거란 의견도 있습니다.

    릴리즈 노트를 읽고 받은 첫 느낌은
    '현재의 코드는 제품으로써 미숙하지만, 출시를 진행합니다. G1은 기본적으로 비활성화되어 있지만, 여러분의 어플리케이션에 G1을 적용하여 테스트하고 싶을지도 모릅니다. G1을 활성화하여 생기는 문제에 대해서는 Sun Support contact를 이용하지 않는다면 어떤 공식적인 도움을 기대할 수 없습니다.'
    정도 였습니다.

    G1이 JDK/OpenJDK7 의 중요한 기능으로 선정되면서, 현재의 상용화 결정이 이후에도 계속되지는 않을까 심히 걱정이 됩니다. 오라클에 특별히 반감을 품고 있거나 하진 않지만, 썬 보다 사업 수완 좋은 오라클이라는 게 마음에 걸리는군요..

    2009/06/02 16:52 2009/06/02 16:52
    Trackback Address:이 글에는 트랙백을 보낼 수 없습니다