Java Mail 첨부파일 처리

옛날 sun의 메일 관련 기술 문서인데 썬이 사라지면서 함께 사라졌던 문서. 우연히 인터넷에서 찾게되어 기록용으로 남겨둠.

ADVANCED HTML EMAIL

The April 26, 2004 Tech Tip titled Using the JavaMail API to Send HTML Email, showed how to use the JavaMail API to send HTML email that is also readable by text browsers. But the email from that tip was text only -- it didn't include images. In the following tip, you'll see how to use the JavaMail API to send HTML email that contains embedded images.

 

Email Image Links Considered Harmful

You might sometimes receive HTML email that includes images. Sometimes the message's HTML code links to the image on the sender's server using an <img> tag, and a src attribute that identifies the image's URL, like this:

   <img src="http://originating_server/images/image.jpg" />

The browser accesses these images just as if it were displaying an image in a Web page. Unfortunately, unscrupulous spammers have used this mechanism as a sneaky way to record who visits their site. They do this by including a unique id in the image src URL, and then saving the ID along with your email address. Such an image URL might look like this:

   <img src="http://evilspammer.com/images/x.jpg?userid=12" />

When you visit the site, the server looks up your email address by the ID, and singles you out for special treatment. Unknowingly, you've just told a spammer that you're considering their product, so they may choose to market to you more aggressively. Worse, you've told them that your email address is "live", so it can be sold at a higher price to yet other spammers.

To protect your privacy, many Web-based (and other) email clients don't display images in HTML emails. While blocking image URLs in emails protects your privacy as a user, it can complicate your life as an application developer. Fortunately, you have another option: embedded images.

 

Embedding Images in HTML Emails

An alternative to placing absolute URLs to images in your HTML is to include the images as attachments to the email. You then use relative URLs to those images in your HTML code. The email format for attachments is defined by MIME (Multipurpose Internet Email Extensions), the standard protocol specifications for Internet email.

MIME has a mechanism that can be used to send an email containing HTML, plus attachments that contain the images the HTML references. A specification called RFC 2387 defines the MIME content type "multipart/related". A message in multipart/related format contains a collection of objects that are meant to be used together. For the purposes of this tip, that means an HTML file and the images it uses.

Each attachment in a multipart/related message has a unique identifier called its content-id. The content-id is defined by the application that sends the email, and is assigned when the message is constructed. The HTML can reference the image in an attachment by using the protocol prefix cid: plus the content-id of the attachment. For example, if an attachment has content-idimage.part.1@x.org, then an HTML file in the same message could use the image inline with the following tag:

  <img src="cid:image.part.1@x.org" />

A mail reading program (either a standalone program, or a web-based email interface) would render the tag above using the image with the given content-id.

 

Providing a Text Alternative

As described in the April 2004 tip, you can use a multipart/alternative content type to include alternative versions of the same object. In doing this, you allow the receiving program (the mail reader) to choose the most appropriate content type. The "most appropriate" content type may be defined by the capabilities of the mail reader or by user preferences.

The sample code that accompanies this tip includes both a text version of the transmitted file and an HTML version with embedded images. The content-type of the message itself ismultipart/alternative. The message's first body part is the text alternative. The second body part is the HTML alternative. Images are included in the second part (the HTML) by defining the second part's content-type as multipart/related. The first related body part is the HTML code (text/html), and subsequent body parts are attachments containing any images (image/jpg) used by the first (HTML) related body part.

Here is a diagram of the multipart message sent by the sample code.

사용자 삽입 이미지

 

JavaMail Sample Code

The class that sends the email, HtmlEmailer.java, uses the JavaMail API to send an email with the structure defined above. The program takes a single argument: the name of a properties file that configures the program's behavior. The first section of the code loads the properties file and uses its values to create and initialize a new MimeMessage.

       Properties props = new Properties();
       props.load(new FileInputStream(propfile));
        
       Session session = Session.getInstance(props, null);
       MimeMessage msg = new MimeMessage(session);
  
       InternetAddress from =
          new InternetAddress((String)props.get
            ("ttjun2004.from"));
    
       InternetAddress to =
          new InternetAddress((String)props.get
            ("ttjun2004.to"));
    
       msg.setFrom(from);
       msg.addRecipient(Message.RecipientType.TO, to);
       msg.setSubject((String)props.get("ttjun2004.subject"));

The next section of the code creates the multipart/alternative section of the message by constructing a MimeMultipart object. It also creates the first alternative body part from the text file name supplied in the props file.

       // Create a "related" Multipart message
       Multipart mp = new MimeMultipart("alternative");

       // Read text file, load it into a BodyPart, 
       // and add it to the message.
       String textfile = (String)props.get("ttjun2004.txtfile");
       BodyPart alt_bp1 = getFileBodyPart(textfile);
       mp.addBodyPart(alt_bp1);

Method getFileBodyPart is simply a convenience method for creating body parts to use as file attachments:

   public BodyPart getFileBodyPart(String filename)
      throws javax.mail.MessagingException {
         BodyPart bp = new MimeBodyPart();
         bp.setDataHandler(new DataHandler
            (new FileDataSource(filename)));
         return bp;
   }

The DataHandler loads the file. The JavaMail classes identify and correctly set the file's Content-type header.

Returning to the class's sendmail method, the next several lines of code create amultipart/related Multipart container, and load it with its first body part: the HTML file contents.

     // Include an HTML version with images. The HTML file
     // is a Multipart of type "related". Inside it are
     // two BodyParts: the HTML file and an image
     String htmlfile = (String)props.get("ttjun2004.htmlfile");
     Multipart html_mp = new MimeMultipart("related");

     // Get the HTML file
     BodyPart rel_bph = getFileBodyPart(htmlfile);
     html_mp.addBodyPart(rel_bph);

The next task is to get the image file. The simple example program allows only a single image file, but more files would be easy to add. The properties file contains the name of the image file to attach, and also defines the content-id. The content-id must match the content-id used by the HTML file. The HTML file can use the same content-id multiple times, but the content-id should be globally unique: no two content-ids should ever be the same.

The code below creates a new MimeBodyPart for the image, and loads it with a FileDataSourcethat acquires the image file contents. The code then initializes several of the image properties. It then adds the image as the second related part of the HTML alternative.

     // Get the image file
     String imagefile = (String)props.get("ttjun2004.imagefile");
     String cid = (String)props.get("ttjun2004.cid");
     MimeBodyPart rel_bpi = new MimeBodyPart();
     FileDataSource ifds = new FileDataSource(imagefile);

     // Initialize and add the image file to the html body part
     rel_bpi.setFileName(ifds.getName());
     rel_bpi.setText("Image 1");
     rel_bpi.setDataHandler(new DataHandler(ifds));
     rel_bpi.setHeader("Content-ID", "<" + cid + ">");
     rel_bpi.setDisposition("inline");
     html_mp.addBodyPart(rel_bpi);

Two of the initializations above merit special attention. First, if the Content-ID header is not set, the image will not be identifiable by the HTML file. In this case, the image will not appear. By convention, the Content-ID is enclosed in angle-brackets. Also, a MIME message's content-id must be URL-encoded (using the same encoding as an HTTP GET query string). Second, the call tosetDisposition("inline") configures the image to appear inline in the HTML, rather than separately at the bottom of the message. This is necessary because some mail readers show images inline only when explicitly told to do so.

The final few lines of the sendmail method create a new MimeBodyPart to wrap theMimeMultipart that forms the second alternative in the message. This code adds the second alternative to the main message body, adds the main message body to the Message object, and then uses the JavaMail Transport class to send the message.

     // Create the second BodyPart of the multipart/alternative,
     // set its content to the html multipart, and add the
     // second bodypart to the main multipart.
     BodyPart alt_bp2 = new MimeBodyPart();
     alt_bp2.setContent(html_mp);
     mp.addBodyPart(alt_bp2);

     // Set the content for the message and transmit
     msg.setContent(mp);
     Transport.send(msg);

The default content (text file, html file, and image) simulates a newsletter that provides a "Space Image of the Day". In this case, the "Space Image of the Day" is a picture of the planet Saturn, accompanied by some text describing the picture. Experiment with this class by defining your own HTML content, and linking and attaching images. Don't forget to change the parameters in the properties file to reflect your changes.

 

2015/09/10 15:22 2015/09/10 15:22
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

.properties 파일

Java에서 설정값 저장용으로 널리 쓰이는 .properties 파일은 다음과 같은 특징이 있다.

포맷
키,밸류 쌍으로 문자열을 작성하게 되며 허용하는 형식은 다음과 같다.
key=value
key = value
key:value
key value


공백없이 첫 문자가 number sign( # ), exclamation mark ( ! ) 로 시작하는 라인은 코맨트로 처리한다.
키에 공백을 포함하려면 escape character로 역슬래시 ( \ )를 사용한다.
다음에 몇가지 예를 참조.
# 이 라인은 코맨트 처리되어 프로퍼티 파일 처리에 아무런 영향을 미치지 않음.
! 과 같이 느낌표로도 코맨트 라인임을 표기할 수 있음.

site = https\:/ /www.yunsobi.com
language = ko

# 역 슬래시로 계속해서 읽어들임을 표시.
message = Hello \
             World\!
# key에 공백문자를 표시하기 위해서도 역슬래스를 사용한다.
key\ with \ space = key is "key with space"

# 유니코드
tab : \u0009
.properties 파일의 인코딩은 latin-1으로 알려진 ISO-8859-1 로 저장 한다. latin-1 으로 표현할 수 없는 문자인 경우 Unicode escape character를 사용하여 표기하여야 한다.
2015/03/03 10:40 2015/03/03 10:40
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

ConcurrentHashMap , Collections.synchronizedMap(Map) 어떤걸 써야 하는거?

멀티쓰레드 환경하에서 적절히 사용할 수 있는 Map계열 자료형으로 ConcurrentHashMap , Collections.synchronizedMap(Map) 이 있는데 어떤걸 사용하는게 더 효과적인지 확인해 봤다.

https://ria101.wordpress.com/2011/12/12/concurrenthashmap-avoid-a-common-misuse/ 과 http://stackoverflow.com/questions/1291836/concurrenthashmap-vs-synchronized-hashmap(새 창으로 열기) 의 글을 통해 Collections.synchronizedMap(Map) 과 ConcurrentHashMap은 lock 메카니즘이 다름을 알 수 있었다.

다음은 대표적인 map 계열 클래스의 차이점을 표로 정리.
속성 HahsMap Hashtable ConcurrentHashMap
Null value/key 허용 허용 비허용
thread safe 아님 안전
lock 메카니즘 없음 전체 lock portion of map
iterator fail-fast fail-safe
2015/02/04 17:41 2015/02/04 17:41
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

Java 자동화, 매크로 도구들

Java Robot : JDK에 기본으로 포함되어있는 API.

Tasklist - http://technet.microsoft.com/en-us/library/bb491010.aspx
프로세스 정보를 출력하는 콘솔 명령어

NirCmd - http://www.nirsoft.net/utils/nircmd.html
콘솔명령도구

Open CV for JAVA - http://opencv.org/
Imgproc.matchTemplate(img1, img2, img3, Imgproc.TM_CCOEFF_NORMED); 와 같은 방식으로 이미지 비교 및 위치 검색 수행.
특정버튼을 미리 캡쳐해 놨다가 자동으로 클릭하는 기능같은 기능 개발시 유용.

JNativeHook - https://github.com/kwhat/jnativehook
자바 글로벌 후커

2015/01/16 11:14 2015/01/16 11:14
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

뭐..? 러시아가 시간대를 바꾼다고?

윈도우 업데이트는 대게 어떤 항목이 업데이트 되는지 자세히 확인하지 않고 업데이트를 진행하는게 평소 패턴이었는데 오늘은 어째서인지 (정말 아무런 이유도 없이..) 업데이트 상세정보를 확인해 봤다.
사용자 삽입 이미지
그래서 열린 페이지가...
http://support.microsoft.com/kb/2970228 야 랑
http://support.microsoft.com/kb/2998527 야 인데...

사용자 삽입 이미지

응!? 뭐? 러시아 시간대가 바뀐다고라고? 
러시아 관련된 일을 하지 않으니까 별 상관이 없을수도 있지만... 지구상에 러시아와 관련있거나 글로벌 시스템으로 구성된 수많은 컴퓨팅 자원들의 시간 계산이 적절하게 대응해야 한다는 걸 생각하면 쉬운일이 아닌뎅?

그래서 "러시아 시간대 변경" 으로 관련 기사를 뒤져봤더니...
헐.. 2009년부터 논의되고 있었넹.. http://www.ohmynews.com/nws_web/view/at_pg.aspx?CNTN_CD=A0001276772(새 창으로 열기)
그리고 러시아 시간대 변경 역사에 대한 간략한 기사도 찾을 수 있었다. http://russiafocus.co.kr/society/2014/04/15/44319.html(새 창으로 열기)

그래 대강의 상황은 파악했음.
윈도우즈는 업데이트로 대응했고... 그럼 유닉스, 리눅스 계열이나 내 밥벌이 언어인 Java쪽 대응은 어떻게 되는지 궁금해 질 수 밖에...
Java는 오라클에서 Timezone Update Tool이 배포되고 있고... http://www.oracle.com/technetwork/java/javase/tzupdater-readme-136440.html(새 창으로 열기)
Novell NetWare 계열의 대응도 확인 했다. https://www.novell.com/communities/coolsolutions/how-implement-lastest-time-zone-changes-russia-netware/
Linux 계열은 timezone 데이타 파일을 업데이트 방법을 제시하고 있다. http://unix.stackexchange.com/questions/25139/russian-timezone-is-not-up-to-date(새 창으로 열기)


러시아가 지금까지 11개의 서로 다른 시간대를 가지고 있었다는것도 놀라웠고 그걸 4개의 표준시로 통합해버린 패기도 놀랍다.
오후 2시에 밤을 맞이하는 시간대 사람들에게 묵념...
2014/09/24 18:59 2014/09/24 18:59
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

Java SE 8 의 새로운 기능.

2014/06/30 21:34

서비 JAVA

Java 8 의 closure, lambda, Nashorn 등 굵직한 변화에 묻혀 잘 화자되진 않지만 몇 가지 유용한 기능을 살펴보면
  1. Stamped Lock
    멀티 쓰레드 코드는 오랜 기간 (지금도 여전히) 서버 개발자의 골칫거리 중에 하나이다. 오랜 시간 Java Core에는 공유된 자원에 대해 최소한의 잠금시간을 위한 여러 라이브러리들이 추가되어 왔다. 대표적인 ReadWriteLock는 읽기와 쓰기를 위한 lock을 분리하여 잠금시간을  최소화할 수 있도록 지원( 동기화 클래스 - ReadWriteLock 인터페이스의 ReentrantReadWriteLock(새 창으로 열기) ) 하고 있다. 이게 이론상으로는 나이스한 아이디어 이긴한데 실제로 이 ReadWriteLock은 너무 느리다(새 창으로 열기)는 문제가 있다.
    이 문제를 해결하기 위해 Java 8에서는 StampedLock(새 창으로 열기) 이라는 새로운 ReadWrite lock을 소개하고 있다. 좋은 소식은 이 StampedLock은 정말 빠르다는거고 나쁜소식은 코드를 작성하는게 좀 더 복잡하다는거다. 이 lock은 reentrant 하지 않으며, 이는 곧 deadlocking에서 자유로움을 의미한다.
    StampedLock lock = new StampedLock();
    //빠른 non-blocking lock 획득
    long stamp = lock.tryOptimisticRead();   
    // 원하는 동작 작성.
    work();
    if (lock.validate(stamp)) {
    //work() 작업 성공. 다른 writer thread 와 경합 없었음.
    } else { // 다른 쓰레드의 write 작업으로 경합이 있다면 read lock으로 재시도.
    //스탬프를 변경하는동안 다른 스레드는 쓰기 잠금을 획득해야함.    
    //기존의 무거운 read lock으로 변경.
    //전통적인 blocking lock 획득
    stamp = lock.readLock(); 
    try {
    //다시 한번 시도
    work();
    } finally {
    //lock 해제
    lock.unlock(stamp);
    }
    }
    

    StampedLock과 기존의 ReadWriteLock , synchronized 과의 성능 비교 아티클(새 창으로 열기)도 있으니 참고.

  2. Concurrent Adder
    가장 기본적인 동시성 패턴은 읽기 / 쓰기에 대한 숫자 카운터이다. 이걸 처리하는데는 많은 방법이 있지만 Java 8에서 제공하는것 만큼 효율적이거나 우아하진 못했다. 지금까지는 sun.misc.Unsafe class를 활용한 CPU의 CAS( Compare and Swap ) 인스트럭션에 직접 counter를 설정하는 Atomics를 이용하는것이었다. 이 방식의 문제는 경합에의해 CAS에 실패하는 경우 AtomicInteger를 증가하면서 CAS에 성공할때까지 루프 상태가 되는데 이 부분이 성능의 발목을 잡고 있었다.
    Java8의 Concurrent Adder 계열의 클래스는 read / write에 함께 사용하는 편리한 방법을 제공한다. 엄청 간단해서 LongAdder 객체를 만들고 add() 나 intValue() 같은 메소드를 호출하기만 하면된다. 

    기존 Atomics와 Adder의 차이점은 경합에의한 CAS 실패 시 Adder는 CPU를 spin하는 대신 증분값(delta)를 해당 쓰레드를 위해 할당된 internal cell object에 기록한다. 그런 다음 intValue() 결과에 다른 보류중인 cell에 기록해둔 delta를 더한다. 이것으로 CAS를 시도하거나 다른 쓰레드를 block하는 횟수를 줄일 수 있게된다.

  3. Parallel Sorting
    conccurent Adder의 고속화에 힘입어 Java 8에서는 소팅을 고속화 할 수 있는 간결한 벙법을 제공한다. 사용방법도 상당히 단순하다.
    //기존방식 
    Array.sort(arrayToSort);
    //새로운 방식
    Array.parallelSort(arrayToSort);
    


  4. new Date API
    Java 8 에서는 완전히 새로운 date-time(새 창으로 열기) API를 제공한다. 사용하기 편하고 정확도가 높은 joda time API가 Java core library에 포함 되었다.지금까지의 Date 관련 API는 대부분 deprecated 된다. 새로운 API는 기능적이면서도 우아하지만 아쉽게도 기존 api를 사용하는 방대한 코드는 여전히 남아있고 빠른시간에 새로운 api로 교체되지는 못할것이다.

    기존 api (java.util.Date java.sql.Date 등)와 신규 api의 갭을 메우기위해 기존 Date 객체를 Instant로 변경하기 위한 toInstant() 메소드와 ㅑInstant를 Date 로 변경하기 위한 from(Instant instant) static 메소드를 추가하였다. 이는 특히 새로운 API보다는 기존 API로 작업하는것을 선호하는 개발자에게 효과적일 수 있다.

  5. OS Process Control
    JNI를 통한 OS 프로세스 호출이 필요악일 지라도 자바 코드 내에서 OS 프로세스를 실행한 경우 실행중인 프로세스를 제어하기 어려웠다. 이를 개선하기위해 Process class에 다음 세개의 메소드를 추가하였다.
    - destroyFprcibly() : 기존 destroy() 보다 더 높은 프로세스 종료율을 제공.
    - isAlive() : java code를 통해 실행한 프로세스가 살아있는지 확인.
    - waitFor() : 새로 오버로드한 waitFor() 메소드를 통해 프로세스 종료를 얼마나  기다릴지 정할수 있음.

    프로세스가 끝나지 않은 경우 끝내고 다음 코드로 진행.
     if (process.wait(MY_TIMEOUT, TimeUnit.MILLISECONDS)){ 
    //success! 
    } else {
    process.destroyForcibly();
    } 

    코드가 완료되기 전 어떤 프로세스도 남겨두지 않으려 할 경우, 느리지만 확실하게 OS에서 사라지게하기.
     for (Process p : processes) { if (p.isAlive()) { p.destroyForcibly(); } } 


  6. Overflow 대응 숫자 연산
    숫자 연산에서의 overflow는 가끔 끔찍한 버그를 만든다. 특히 int 값을 증가하는 count 값을 이용하는 시스템에서 특히 그런데, 개발계나 스테이징에서는 발견하지 못하고 오랜기간 운영하는 production 모드에서 발생하면 그야말로 재앙이다.

    이런 상황에 도움이 되고자 Java 8에는 부호에 민감한 계산에서 overflow발생 시 ArithmeticException을 던지는 새로운 exact 메소드(새 창으로 열기)가 추가되었다.
    //overflow 시 ArithmeticException 발생
    int multi = Math.multiplyExact( bigA, bigB ); 

    이 새로운 메소드의 한가지 단점이라면 overflow가 발생할 코드의 위치를 찾는것은 개발자의 몫이란거다.

  7. Secure Random Generator
    Java는 근 몇년 간 보안 허점과 분투하고 있다. JVM과 Framework에 걸친 광범위한 보안조치가 취해지고 있다.  낮은 수준의 난수로 암호화 키를 생성하거나, 민감한 정보를 해시하는 경우도 해킹에 취약한 시스템을 만든다.

    오랜기간동안 Random Number Generator algorithm은 개발자 영역으로 남겨져 있었고. 구현체가 특정 하드웨어 / OS / JVM에 의존하는 경우, 원하는 알고리즘을 사용하지 못할 수 있었다. 문제는 이런 경우 응용 프로그램은 공격의 더 취약한 Generator를 기본값으로하는 경향이 있었다.

    Java 8에는 JVM 보안 공급자/알고리듬을 선택하기를 원하는 개발자를 위해 SecureRandom.getInstanceStrong() 를 새로이 추가하였다. 이 메소드는 hardware / OS / JVM에 대한 완전한 통제권이 없는 상황에서 ( cloud , PaaS 등.. ) 개발 할 때 적절한 솔루션이 될 수 있다.

  8. Optional 참조
    NullPointer는 말하자면 문지방에 찧은 발가락 같다. 실제로 저명한 언어 디자이너 / 석학 중 일부는 null reference를 고안한 건 엄청남 실수라고 말하는 사람도 있다. 나는 개인적으로 null reference 가 있는게 더 자연스럽다고 생각하는 쪽이긴 하지만... 여하튼 null pointer 관련 에러는 성가신 존재임에는 틀림없다. Java 8 에서는 이런 Null pointer 처리를 도와줄 Optional<T>(새 창으로 열기) 템플릿이 도입되었다.

    Scala와 Haskell에서 빌려온 이 템플릿은, 템플릿에 전달하거나 함수에의해 반환 된 참조가 null이 될 수있는 경우를 명시적으로 언급하는 것이 가능해졌다. 이렇게 함으로써 코드 작성 시 document 도움 없이도 런타임에 특정 참조가 null인 경우가 있을지 없을지 guess game 하는 정력 낭비를 줄여준다.
    Optional<User> tryFindUser(int userID) { }
    //혹은
    void processUser(User user, Optional<Cart> shoppingCart) { }
    
    또한, Optional 템플릿은 null 이외의 값을 사용할 수 있는지 확인하기 위해, isPresent() 람다에서는 ifPresent() 메소드를 제공한다.
2014/06/30 21:34 2014/06/30 21:34
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

lambda 와 closure 의 차이점 ?

Java SE 8에 도입되기 전부터 관심을 받던 람다식과 closure. 이 둘의 차이는 뭘까?

한마디로 lambda는 이름이 없는 익명 함수( anonymous function ) 를 가르키며,
closure는 하나 이상의 엮인(bound) 변수가 있는 환경에서 실행( or 평가)되는 함수 정도로 이해할 수 있겠다.

자유변수(메소드 파라메터도 아니고 코드 내부에도 저장되지 않는 변수)의 값을 포함하는 코드 블록의 기술용어가 클로저 closure이다.누군가 자신이 사용하는 언어에 클로저가 있다고 흐뭇해한다면, 자바에도 클로저가 있으니 안심해도 좋다. 자바에서는 람다 표현식이 클로저다. 사실 이너 클래스가 클로저로 존재해왔다. 다만, 자바8에서는 매력적인 문법으로 클로저를 제공한다.
- 가장 빨리 만나는 자바8 (길벗) 에서.


두 의미에 대한 깊은 논의는 다음 링크에서 확인 할 수 있음.
http://stackoverflow.com/questions/220658/what-is-the-difference-between-a-closure-and-a-lambda(새 창으로 열기)
http://www.langdev.org/posts/38

그럼, Clojure 는?
http://clojure.org/(새 창으로 열기) 에서 정의하고 있는것과 같이 JVM(Java Virtual Macine) , CLR(Common Language Runtime), JavaScript 엔진에서의 동작을 목표하는 dynamic programing language. 단어를 처음 접했을 때 정의를 찾아보지 않고, Kroisse님이 알려주기전까지 두 단어가 혼용되어 쓰이고 있다고 적당해 생각해 버렸던게 부끄럽넹...

2014/06/25 15:13 2014/06/25 15:13
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
  1. Clojure는 프로그래밍 언어 이름이고, 말씀하시는 개념은 closure입니다.

  2. Blog Icon
    서비

    Kroisse님. 고맙습니다.
    영미권 검색 시에 Clojure, closure 모두 검색되어서 혼용해서 사용하는 줄 알았습니다. 알려주신 내용으로 좀 더 명확하게 공부하도록 하겠습니다.

java se 8 에서 람다식 사용하기 - 기초

java 8 에 람다 표현식이 도입되면서 closure를 사용하지 않고도 함수형 언어 비슷한 코드를 작성하는게 가능해졌다. 람다 표현식은 이름이 없는 익명 함수를 의미한다.
람다 표현식에 관심을 둬야하는 몇가지 이유는 다음과 같다.
  • OOP 언어인 Java에서 함수형 코드를 작성할 수 있게 해준다.
  • 람다 표현식을 이용함으로써 간결하고 명확한 코드로 그 의도를 표현할 수 있다.
  • Collection filtering, Iteration , Extraction 등에서 놀라운 코드 생산성을 보인다.


아주 아주 기본적인 람다 표현식에 대해 익혀보자.
Syntax

(argument) -> (body)

0개 이상의 인자를 실행하고자 하는 함수 body 로 전달한다는 의미이며, 이는 람다 표현식의 일반적인 구문이다.
예를 들면 다음과 같이 표현된다.
(int a, int b) -> a*b 
(Person p) -> { return p.getAge();}


다음 코드는 swing 에서 자주 보이는 이벤트 핸들러를 람다로 변경하는 코드이다.
btnOk.setOnAction( newEventHandler() {
 @Override
 public voidhandle(ActionEvent e) { //버튼 action에 처리할 코드를 여기에 작성
 }
});

위 코드를 람다 표현식으로 변경하면 다음과 같다.
btnOk.setOnAction( e -> { //버튼 action에 처리할 코드를 여기에 작성 
});


표현식의 또 다른 예로 익명 클래스는 다음과 같이 작성할 수 있다.
new Thread(
() -> System.out.println("This is a seperate thread")
).start();


마지막으로 collection을 다루는 예제만 더 보고 끝내자.
ArrayList arrayList= new ArrayList<>(); 
for(int i=1; i<=100; i++) 
arrayList.add(i); 

//일반적인 for-loop 문 
for(Integer i: arrayList)
{ System.out.println(i); 
} 

//lambda식으로 표현한 for-loop문 
arrayList.forEach( i -> {System.out.println(i);});


이상으로 람다 표현식이 어떻게 코드 수를 줄이고 Java와 함수형 언어 사이의 갭을 매워주는지에 대해 간략히 알아보았다.

2014/06/25 14:32 2014/06/25 14:32
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

근래 JAVA 쪽에는 어떤 일들이 있나?

문득 문득 현재 JAVA의 위상이나 JAVA 다음은 무엇일까 등을 생각해 보는데요...  그에 대한 힌트를 얻을 수 있는 발표 자료가 있어 공유합니다. Zeroturnaround 社에서 2,164 명의 개발자 설문 결과를 정리/배포한 자료입니다.
현재 java 진영의 트렌드에 초점이 맞춰져있고 국내 상황과도 다소 차이가 있을 수 있지만 개발 현장의 광범위하고 객관적인 자료 정도로 생각하고 훑어보시면 되겠습니다.

레포트 원문은 http://zeroturnaround.com/rebellabs/java-tools-and-technologies-landscape-for-2014/(새 창으로 열기) 입니다.

아래 쪽에 첨부한 pdf 내용 중 저에게는 다음 항목들이 눈길을 끌었습니다.

  • 16페이지의 The next JVM language to learn : 역시 scala의 기세는 대단하군.. Clojure가 Groovy를 제칠 수 있을까..? 그렇다면 그 시점은?
  • 18페이지의 IDE used most open : 아.. 제가 애용하는 넷빈즈의 참담한 점유율.. 상용인 Intellij IDEA 보다 낮다니.. 너 이자식 힘내라!
  • 21페이지의 Build tool used most open : Maven이 대세인건 부정할 수 없는 현실. Ant야 기존 레거시 시스템 덕으로 2위인거고... Gradle이 현재의 메이븐의 위상을 갖추는건 언제쯤일까..
  • 31페이지의 ORM framework in use : MyBatis 사용율이 의외로 낮네.. 국내는 전자정부 표준 프레임워크 영향으로 사용율이 높은건가...
  • 43페이지의 VCS technologes used : Git은 이미 대세구나... 국내 기업체도 2-3년 내에 SVN에서 Git으로 넘어가지 않을까...


레포트의 말미에는 2015년도 예상 우선 순위도 게시되어 있습니다.

java-tools-and-technologies-2014.pdf

JAVA TOOLS AND TECHNOLOGIES LANDSCAPE FOR 2014






2014/06/09 16:04 2014/06/09 16:04
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

2014년 java 진영 웹 프레임워크

2014년 기준으로 java 진영에서 웹개발에 사용하고 있는 프레임워크 동향을 JRebel 제품으로 유명한 Zeroturnaround 社에서 레포팅했습니다. 역시나 SpringMVC가 가장 널리 활용되고 있으며 JSF , Vaadin 이 그 뒤를 잇고 있습니다. 발표 자료가 자료니 만큼 국내와는 사정이 다르게 JSF 사용율이 굉장히 높네요..

2014년 웹프레임워크 동향

출처 : https://twitter.com/RebelLabs/status/469176327007117312/photo/1





2014/06/09 15:41 2014/06/09 15:41
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

Spring3 에서 Spring4 - servlet 3.0 으로 웹어플리케이션 마이그레이션하기

기존 Spring3 기반으로 개발한 웹어플리케이션을 Servlet 3.0 , Spring 4 버전으로 마이그레이션 하는 순서는 다음과 같다.
Spring 4의 변경 신기능 소개.(새 창으로 열기)

1. 메이븐 형식의 프로젝트라면 POM 파일에 서블릿 3.0 스펙의 API를 사용할 수 있도록 servlet-api.jar dependancy를 업데이트
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope> <!-- 런타임시에는 서블릿 컨테이너에의해 제공되므로 provided로 설정 -->
</dependency>


2. web.xml namespaces,xsd files 과 version 업데이트
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">


3. Spring Framework 의 라이브러리 jar 들을 버전 4로 업데이트

4. 스프링 Context 설정 파일의 스키마 로케이션 정보 업데이트. 다음과 유사하게 xsi:schemaLocation 의 스키마 버전 정보를 4.0으로 변경.
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:aop="http://www.springframework.org/schema/aop" 
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:task="http://www.springframework.org/schema/task"
  xmlns:util="http://www.springframework.org/schema/util" 
  xmlns:cache="http://www.springframework.org/schema/cache"
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd 
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
    http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">


5. Jackson 라이브러리 업데이트. 버전 1.x 의 jackson 라이브러리를 사용하고 있었다면 2점대로 변경. 이는 스프링 라이브러리에 의해 사용된다.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.0</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.3.0</version>
</dependency>


6. view resolver 쪽에 jackson 매핑이 1.x 대응이라면 2.x 대응으로 변경.
1.x jackson mapper 설정이 다음과 같다면..
 <bean id="jsonMapper" class="com.fasterxml.jackson.databind.ObjectMapper" />
<bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="objectMapper" ref="jsonMapper" />
</bean> 

다음과 같이 MappingJackson2JsonView 로 변경 필요.
<!-- Spring3 이상, jackson 라이브러리 2 이상일 때는 MappingJackson2JsonView 로 설정. -->
<bean id="jsonMapper" class="com.fasterxml.jackson.databind.ObjectMapper" />
<bean id="jsonView" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
<property name="objectMapper" ref="jsonMapper" />
</bean>
2014/05/28 10:14 2014/05/28 10:14
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

VisualVm으로 원격 JVM 프로파일링


1. jstatd.all.policy 파일 작성
[java_home]/bin 디렉토리에 아래 내용의 jstatd.all.policy 파일을 작성한다.
grant codebase "file:${java.home}/../lib/tools.jar" {
   permission java.security.AllPermission;
};


2. 2020 포트로 rmi 통신 준비.
rmiregistry 2020&

3. jstatd 구동
jstatd -J-Djava.security.policy=all.policy -p 2020&

4. VisualVM 실행 하여 Add Remote Host 로 원격지 정보 등록
2014/03/26 12:48 2014/03/26 12:48
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

구글 JAVA 코딩 스타일 가이드

원문 : http://www.infoq.com/news/2014/02/google-java-coding-standards

구글은 최근에 자바 코딩 표준을 퍼블리싱했습니다.
http://google-styleguide.googlecode.com/svn/trunk/javaguide.html(새 창으로 열기) 에서 확인할 수 있으며

특징으로는
  • 모든 소스파일은 UTF-8 인코딩으로 저장.
  • import 구분에 와일드 카드(*)를 사용하지 않기.
  • 오버로드는 순차적으로 기술하기.
  • 내용이 비어 있거나 한줄 짜리 코드라도 중괄호 사용하기.
  • 들여 쓰기에 2개의 화이트스페이스 사용하기.
  • 열은 80 또는 100 자까지 가능.
  • C 스타일 배열 선언 하지 않기.
  • switch 문에 default 문을 누락하지 않기.
  • 제한자는 Java 언어 사양에서 권장하는 순서로 작성하기.
  • 상수의 표기는 CONSTANT_CASE 형식이며 모든 상수는 static final 로 설정함.
  • 그렇다고해서 모든static final 이 상수를 의미하지는 않음.

들여쓰기를 공백문자 2개로 정의한게 조금 특이하네요.
2014/02/13 13:16 2014/02/13 13:16
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다

Thread throw Exception 핸들링하기

java thread에서 Exception을 던져 쓰레드를 생성/실행한 곳에서 익셉션을 받아 처리하기위해서는 Thread.UncaughtExceptionHandler 를 이용해야한다.

다음과 같이 말이다.

//테스트용 쓰레드 생성.
Thread t = new Thread(
  new Runnable{
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            System.out.println("Interrupted.");
        }
        System.out.println("익셉션 발생 시킴 ...");
        throw new RuntimeException();
    }

  }
);
//Thread에 UncaughtExceptionHandler 를 설정.
t.setUncaughtExceptionHandler(
  new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread th, Throwable ex) {
        //쓰레드에서 던진 예외는 이곳으로 오게됨.
        System.out.println("Uncaught exception: " + ex);
    }
  }
);
t.start();


쓰레드와 익셉션 핸들링관련 도식은 다음과 같다.


Thread와 Exception

이미지 : http://book.javanb.com/java-threads-3rd/jthreads3-CHP-13-SECT-5.html




출처 : http://www.javamex.com/tutorials/exceptions/exceptions_uncaught_handler.shtml



2013/09/24 00:31 2013/09/24 00:31
Trackback Address:이 글에는 트랙백을 보낼 수 없습니다