'Language/JAVA'에 해당되는 글 57건

  1. 2013.09.17 Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.
  2. 2013.09.03 JAXB: Marshalling and Unmarshalling CDATA block using EclipseLink MOXy
  3. 2013.08.29 .getClass() 와 .class의 차이점
  4. 2013.08.29 Log4J 사용 가이드
  5. 2013.08.29 log4j
  6. 2013.08.28 jUnit 으로 Private Method 테스트 만들기
  7. 2013.08.26 Ant - tutorial
  8. 2013.08.26 ANT Build
  9. 2013.08.21 정규식 날짜, 시간
  10. 2013.08.09 Java 인자 전달 방식: Call-by-{Value | Reference}?

Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.

Language/JAVA 2013. 9. 17. 13:07

유닉스에서 자바 이미지 객체를 사용하려 할때 다음과 같은 에러가 발생한다.

 

Exception in thread "main" java.lang.InternalError: Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.

 

이것은 일종의 JDK의 버그이다. 원인은 자바가 BufferedImage 를 생성하고 실제로 Graphics 객체를 얻어오기 위해 getGraphics나 createGraphics 메소드를 부를때, 실제로 display하거나 mouse, keyboard 자원을 하나도 쓰지 않을 것임에도 불구하고 내부적으로 AWT Toolkit이 그것들에 대한 자원을 얻어오게 되어있었기 때문이다. 

Sun에서는 이걸 버그로 취급하며 해결 방법은 2가지가 있다. 

 

1. JRE 1.3 이하 일경우 www.x.org 에서 다운로드 받을 수 있는 Xvfb 라는 것을 사용하는 방법이다. 이것은 X-server 에뮬레이터이다.

 

참고

1.1. 가상 xwindow실행하기

1.1.1 리눅스 

리눅스의 경우 XFree86-Xvfb-4.1.0-3.i386.rpm 을 설치해야 합니다. 
XFree86-Xvfb-4.1.0-3.i386.rpm 패키지는 아래의 패키지가 최소한 설치되어 있어야 합니다. 
XFree86-4.1.0-3.i386.rpm 
Mesa-3.4.2-7.i386.rpm 
Xaw3d-1.5-10.i386.rpm 

설치과정중에 에러가 발생하면 아래 커맨드를 이용하여 의존성을 검사하면 됩니다. 
rpm -ivh --nodeps ./Mesa-3.4.2-7.i386.rpm 
rpm -ivh ./XFree86-4.1.0-3.i386.rpm 
rpm -ivh ./Xaw3d-1.5-10.i386.rpm 
rpm -ivh ./XFree86-Xvfb-4.1.0-3.i386.rpm 

Xvfb는 100dpi 및 75dpi용 폰트도 설치되어 있어야 합니다. 
폰트와 관련하여 간단하게 작업하려면 아래와 같이 하세요 
wget http://www.psoft.net/downloads/X11.tgz 
tar xfz ./X11.tgz -C /usr/X11R6/lib/ 

이제 모든 설치가 완료되면 아래 커맨드로 Xvfb를 활성화 시킵니다. 
/usr/X11R6/bin/Xvfb ':0' -screen 0 100x100x8 & 

이제 서버가 시작할 때 마다 이 기능을 활성화 시키려면 
/etc/rc.d/rc.local에 추가하면 됩니다.

 

1.2.1  Solaris :

다운로드 : X11R6_bin.tar.gz

1.2.2 설치 : 
% su - 
# mkdir /usr/X11R6 
# cp X11R6_bin.tar.gz /usr/X11R6 
# cd /usr/X11R6 
# gunzip X11R6_bin.tar.gz 
# tar xvf X11R6_bin.tar 
# rm X11R6_bin.tar


1.2.3. 자동실행 
실행 스크립트 : xvfb.server 다운로드 
자동 실행 설정 스크립트 : install.xvfb다운로드 
xvfb.server에서 RUN_AS_USER=tomcat 을 적절히 수정 후 install.xvf 만 실행하면 끄~읕

참조 : 
http://www.x.org/ 
http://developers.sun.com/solaris/articles/solaris_graphics.html#3 
http://www.idevelopment.info/data/Unix/General_UNIX/GENERAL_XvfbforSolaris.shtml 
http://chartworks.com/support/server/XvfbonUnix.html 
 

 

2. JRE 1.4 이상에서  Headless AWT Toolkit을 이용해서 이 문제를 해결한다. 파일을 실행할때 간단히 -Djava.awt.headless=true 옵션을 주는것만으로 가능하다.
 

[참고]

java 1.4 버전 이상에서는 자바 자체에서 처리 가능하게 할수 있습니다.

리눅스에서 굳이 x-window나 xvf 깔기 귀찮다고 아니면 할줄 모르시는 분들은 간단하게 이문제를 해결하는 방법이 있습니다.

<!-- 
Note: If true, the system property, java.awt.headless, will be set to true. 
This should be used with JDK 1.4+ on servers without graphics cards and 
monitors. Otherwise, the property is not set. 
--> 
<!-- <headless-server>true</headless-server> -->

/WEB-INF/flex/flex-config.xml에서 이부분의 주석을 제거 해주시면 됩니다.

<headless-server>true</headless-server>

 

그리고 자바 구동시에(톰켓이나 레진) JVM 파라메터를 적는 부분이 있을 것입니다.

레진 같은 경우 걍 뒤에 자바 파라메터 적으면 작동됩니다.

resin start -Djava.awt.headless=true

 

즉 flex-config에서 headless-server 수정하고 jsp 엔진 구동시에 파라 메터 Djava.awt.headless=true 를 넣어주면 에러없이 잘 해결된다.

 

톰캣에서 이용할때는 catalina.sh 파일에
CATALINA_OPTS=-Djava.awt.headless=true를 추가하고 재구동하면 된다.



출처 - http://blog.naver.com/PostView.nhn?blogId=galahad76&logNo=20042609592

:

JAXB: Marshalling and Unmarshalling CDATA block using EclipseLink MOXy

Language/JAVA 2013. 9. 3. 13:46


eclipselink.jar

JAXB: Marshalling and Unmarshalling CDATA block using EclipseLink MOXy

11 November 2012 By Nithya Vasudevan 1,575 views 9 Comments
Rating: 0.0/5 (0 votes cast)

Project Description

  • In the example provided here, we saw how to marshal and unmarshal CDATA block using JAXB RI by creating custom adapter class.
  • In this JAXB example we will see how to marshal and unmarshal CDATA block using MOXy implementation which is available as part of Eclipselink project.
  • When using MOXy JAXB implementation there is no need to write custom adapter. Just an annotation (provided by MOXy) is sufficient to handle CDATA.

Environment Used:

  • JDK 6 (Java SE 6) or later.
  • Eclipse Indigo IDE for Java EE Developers.
  • EclipseLink 2.3.2 (Download EclipseLink from here and extract the zip file). We need this for MOXy which is an implementation of JAXB API.

New project in Eclipse

Create a new Java project in Eclipse IDE and name it as JAXBCDataMoxyImpl.

Add JAR file

  • You need to add eclipselink.jar file located in “eclipselink/jlib” in your project Build Path.
  • Right click on project -> Properties -> Java Build Path from left pane -> Libraries from right pane -> Add External JARs…

Create Bean class

Create a new Class “Book.java” in the package “com.theopentutorials.jaxb.to” and copy the following code.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.theopentutorials.jaxb.to;
 
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlCDATA;
 
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "book")
public class Book {
 
    private String name;
    private String author;
    private String publisher;
    private String isbn;
 
    @XmlCDATA
    private String description;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getAuthor() {
        return author;
    }
 
    public void setAuthor(String author) {
        this.author = author;
    }
 
    public String getPublisher() {
        return publisher;
    }
 
    public void setPublisher(String publisher) {
        this.publisher = publisher;
    }
 
    public String getIsbn() {
        return isbn;
    }
 
    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }
 
    public String getDescription() {
        return description;
    }
 
    public void setDescription(String description) {
        this.description = description;
    }
 
    @Override
    public String toString() {
        return "Book [name=" + name + ", author=" + author + ", publisher="
                + publisher + ", isbn=" + isbn + ", description=" + description
                + "]";
    }
}

This is a simple bean class containing JAXB annotations whose object is marshalled andunmarshalled. The ‘description’ property is annotated with @XmlCDATA which is provided by MOXy and vendor specific.

jaxb.properties file

To use MOXy as your JAXB implementation you need to add a jaxb.properties file in the bean package.
Create a new file “jaxb.properties” in the package “com.theopentutorials.jaxb.to” and copy the following entry.

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Create JAXB Handler (Helper class)

Create a new Class “JAXBXMLHandler.java” in the package “com.theopentutorials.jaxb.xml” and copy the following code.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.theopentutorials.jaxb.xml;
 
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
 
import com.theopentutorials.jaxb.to.Book;
 
public class JAXBXMLHandler {
 
    public static Book unmarshal(File importFile) throws JAXBException {
        Book book = new Book();
        JAXBContext context;
 
        context = JAXBContext.newInstance(Book.class);
        Unmarshaller um = context.createUnmarshaller();
        book = (Book) um.unmarshal(importFile);
        return book;
    }
 
    public static void marshal(Book book, Class[] classes,
            Map<String, Map<String, StreamSource>> properties, File selectedFile)
            throws IOException, JAXBException {
        JAXBContext context;
        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new FileWriter(selectedFile));
            context = JAXBContext.newInstance(classes, properties);
            Marshaller m = context.createMarshaller();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            m.marshal(book, writer);
        } finally {
            try {
                writer.close();
            } catch (IOException io) {/* ignore */
            }
        }
    }
}
  • This is a helper class which has methods to perform marshalling and unmarshalling. These methods are called from client code (in this case, main() method).
  • By default, the marshaller implementation of the JAXB RI tries to escape characters.
  • We use an overloaded JAXBContext.newInstance(Class) to configure ‘properties’ for this instantiation of JAXBContext. The interpretation of properties is implementation specific.

MOXy binding file

MOXy JAXB implementation allows you to enable a element to use CDATA. You could use MOXy’s binding file to indicate that the book’s ‘description’ property should use CDATA. 
Create a XML file in your project and name it as “oxm.xml” and copy the following code.

01
02
03
04
05
06
07
08
09
10
<?xml version="1.0" encoding="UTF-8"?>
   <java-types>
      <java-type name="com.theopentutorials.jaxb.to.Book">
         <java-attributes>
            <xml-element java-attribute="description" cdata="true"/>
         </java-attributes>
      </java-type>
   </java-types>
</xml-bindings>

Create Java Application client (main())

Create a new Class “JAXBCDataDemo.java” in the package “com.theopentutorials.jaxb.main” and copy the following code.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.theopentutorials.jaxb.main;
 
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.JAXBException;
import javax.xml.transform.stream.StreamSource;
import com.theopentutorials.jaxb.to.Book;
import com.theopentutorials.jaxb.xml.JAXBXMLHandler;
 
public class JAXBCDataDemo {
    public static void main(String[] args) {
 
        Book book = new Book();
        book.setAuthor("Kathy Sierra");
        book.setName("SCJP");
        book.setPublisher("Tata McGraw Hill");
        book.setIsbn("856-545456736");
 
        String desc = "<p>With hundreds of practice questions and hands-on exercises, "
                + "<b>SCJP Sun Certified Programmer for Java 6 Study Guide</b>" +
                "covers what you need to know"
                + "--and shows you how to prepare--" +
                "for this challenging exam. </p>";
        book.setDescription(desc);
 
        Map<String, StreamSource> oxm = new HashMap<String, StreamSource>(1);
        oxm.put("com.theopentutorials.jaxb.to", new StreamSource("oxm.xml"));
 
        Map<String, Map<String, StreamSource>> properties =
                new HashMap<String, Map<String, StreamSource>>();
        properties.put("eclipselink-oxm-xml", oxm);
 
        Class[] classes = { Book.class };
 
        try {
            //Marshalling: Writing Java object to XML file
            JAXBXMLHandler.marshal(book, classes, properties, new File("book.xml"));
 
            //Unmarshalling: Converting XML content to Java objects
            Book book2 = JAXBXMLHandler.unmarshal(new File("book.xml"));
            System.out.println("Unmarshal: " + book2);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }
}
  • This class creates book object with ‘description’ property containing HTML tags and calls marshal method from JAXBXMLHandler helper class passing book object and the file to write the object.
  • We call unmarshal method passing the marshalled file name which returns a book object.
  • Finally, printing the book object (which calls toString() from Book class).

Output

Run the JAXBCDataDemo.java.

Book [name=SCJP, author=Kathy Sierra, publisher=Tata McGraw Hill, isbn=856-545456736, description=
<p>With hundreds of practice questions and hands-on exercises, <b>SCJP Sun Certified Programmer for Java 6 Study Guide</b> covers what you need to know--and shows you how to prepare--for this challenging exam. </p>]

Refresh your project in Project Explorer (press F5 on your project) to see the generated XML file.

01
02
03
04
05
06
07
08
09
10
11
12
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<book>
    <name>SCJP</name>
    <author>Kathy Sierra</author>
    <publisher>Tata McGraw Hill</publisher>
    <isbn>856-545456736</isbn>
    <description><![CDATA[<p>With hundreds of practice questions
        and hands-on exercises, <b>SCJP Sun Certified Programmer
        for Java 6 Study Guide</b> covers what you need to know--
        and shows you how to prepare --for this challenging exam. </p>]]>
    </description>
</book>

Folder Structure

The complete folder structure of this example is shown below.


:

.getClass() 와 .class의 차이점

Language/JAVA 2013. 8. 29. 14:58

두 방법에 의해서 반환되는 Class 인스턴스는 시점에 따라서 달라지는데

.class는 compile time에 결정되고
.getClass()는 rumtime에 결정된다.

간단한 예제 프로그램으로 차이점을 확인할 수 있다.

public class ClassExample {
    public ClassExample()
    {
        printClass();
    }
    final public void printClass()
    {
        System.out.println("ClasExample.class : " + ClassExample.class);
        System.out.println("Sub_ClassExmaple.class : " + Sub_ClassExample.class);
        System.out.println("this.getClass() : " + this.getClass());
    }
   
    public static void main(String[] args) {
        System.out.println("new ClassExample()");
        new ClassExample();
       
        System.out.println("\nnew Sub_ClassExample()");
        new Sub_ClassExample();
    }
}

public class Sub_ClassExample extends ClassExample {
}
----------- output ---------------------------
new ClassExample()
ClasExample.class : class test.ClassExample
Sub_ClassExmaple.class : class test2.Sub_ClassExample
this.getClass() : class test.ClassExample

new Sub_ClassExample()
ClasExample.class : class test.ClassExample
Sub_ClassExmaple.class : class test2.Sub_ClassExample
this.getClass() : class test2.Sub_ClassExample


출처 - http://javafreak.tistory.com/52

:

Log4J 사용 가이드

Language/JAVA 2013. 8. 29. 14:41

1. Log4J란 ?

자바 프로그램 작성 시 로그를 남기기 위해서 사용되는 Logging Framework

URL : http://logging.apache.org/log4j/docs/

 

2. Log4J 설치하기( URL : http://logging.apache.org/log4j/docs/download.html )

2.1. 해당 파일 다운 받기

2.1.1. 기본파일

- log4j-1.2.11.jar  : Log4J를 사용하기 위해서 필요한 Jar 파일

  (http://logging.apache.org/log4j/docs/download.html )

2.1.2. 확장파일 DataBase 로그파일을 남기기 위한 파일 )

jdbcappender.jar : JDBCAppender를 사용하기 위한 Jar 파일

ojdbc14.zip      : Oracle 드라이버 Jar 파일 ( 해당 DBMS에 대한 드라이버파일 )

 

2.2. log4j Configuration 파일 설정하기

2.2.1. Root Logger 설정

log4j.rootLogger=INFO, console, filelog ,dblog

 


- 첫번째는 Log Level을 설정하고 뒤에는 Appender를 설정한다.

- Appender는 상위에 표현되어 있는 것 같이 console(화면출력), filelog(파일), dblog(데이터베이스)로 설정할 수 있으며 Appender에 대한 상세설정은 추후 표기한다. - console, filelogdblog 등의 명칭은 아래에 설정된 명칭을 사용한다.

- Log Level DEBUG, INFO, WARN, ERROR, FATAL  구성되며위와 같이 INFO로 설되어 있으면 INFO이하인 DEBUG를 제외한 모든 로그가 기록된다.

log4j.appender.console=org.apache.log4j.ConsoleAppender

log4j.appender.console.layout=org.apache.log4j.PatternLayout

log4j.appender.console.layout.ConversionPattern=%-5p,%d{yyyy/MM/dd HH:mm:ss.SSS},%-5X{APP}, %-8X{TSC}, %m %n

 2.2.2. console Appender 설정

 

- 첫번째 라인 : console에 대한 클래스 정의

- 두번째 라인 : 로그를 나타내기 위한 Layout 클래스 정의

세번째 라인 : Layout에 대한 ConversionPattern을 정의

-          

 2.2.3. filelog Appender 설정

log4j.appender.filelog=org.apache.log4j.DailyRollingFileAppender

log4j.appender.filelog.Append=true

log4j.appender.filelog.DatePattern='.'yyyy-MM-dd-HH

log4j.appender.filelog.File=./log/app.csv

log4j.appender.filelog.layout=org.apache.log4j.PatternLayout

log4j.appender.filelog.layout.ConversionPattern=%-5p,%d{yyyy/MM/dd HH:mm:ss.SSS},%-5X{APP}, %-8X{TSC}, %m %n

 

- 첫번째 라인 : filelog에 대한 클래스 정의

- 두번째 라인 : 파일에 대한 Append 여부

- 세번째 라인 : 파일을 Backup하기 위한 DatePattern을 정의

- 네번째 라인 : 로그파일명을 정의

- 다섯째 라인 : 로그를 나타내기 위한 Layout 클래스 정의

- 여섯째 라인 :  Layout에 대한 ConversionPattern을 정의

 

2.2.4. dblog Appender 설정

CREATE TABLE APP_LOG

(

  SYSTEMNAME  VARCHAR2(100 BYTE),

  LOGDATE     TIMESTAMP            DEFAULT SYSDATE,

  LOGLEVEL    VARCHAR2(100 BYTE),

  MDC1        VARCHAR2(100 BYTE),

  MDC2        VARCHAR2(100 BYTE),

  MESSAGE     VARCHAR2(4000 BYTE),

  TROWABLE    VARCHAR2(4000 BYTE)

)


-          DB로그를 작성하기 위해서는 위와 같이 DB Table을 만들어야 한다.

 

 1 Line:log4j.appender.dblog=org.apache.log4j.jdbcplus.JDBCAppender

 2 Line:log4j.appender.dblog.url=jdbc:oracle:thin:@168.219.10.149:1521:MCSDB

 3 Line:log4j.appender.dblog.dbclass=oracle.jdbc.driver.OracleDriver

 4 Line:log4j.appender.dblog.username=sds

 5 Line:log4j.appender.dblog.password=sdsdb

 6 Line:log4j.appender.dblog.sql=INSERT INTO APP_LOG( SYSTEMNAME, LOGDATE, LOGLEVEL, MDC1,MDC2, MESSAGE, TROWABLE ) values ('MCSMGR',TIMESTAMP '@TIMESTAMP@','@PRIO@','@MDC:APP@','@MDC:TSC@','@MSG@','@THROWABLE@')

 7 Line:log4j.appender.dblog.layout=org.apache.log4j.PatternLayout

 8 Line:log4j.appender.dblog.layout.ConversionPattern=%m

 9 Line:log4j.appender.dblog.buffer=1

10 Line:log4j.appender.dblog.commit=true

11 Line:log4j.appender.dblog.quoteReplace=true

12 Line:log4j.appender.dblog.throwableMaxChars=3000

 

- Line : dblog에 대한 클래스 정의

- Line : DB url 정의

- Line : DB 드라이버 클래스 정의

- Line : DB User 정의

- Line : DB Password 정의

- Line : INSERT SQL문 정의

- Line : 로그를 나타내기 위한 Layout 클래스 정의

- Line : Layout에 대한 ConversionPattern을 정의

- Line : DB Update하기 전까지 SQL문의 Buffer 개수. 1이면 바로 Update 

- 10 Line : commit 여부

- 11 Line : single quotes (') 2 single quotes ('')로 변경 여부

- 12 Line : throwable/exception stack trace의 최대 문자 개수 정의

 

 

 2.3. Logging Class 작성하기

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

import org.apache.log4j.MDC;

import org.apache.log4j.PropertyConfigurator;

 

public class Trace

{

        private static Logger McsLogger = Logger.getRootLogger();

        

        public static void log( Level level, String app, String tsc, String message  )

        {

                 log(level,app,tsc,message, null );

        }       

        public static void log( Level level, String app, String tsc, String message,  Throwable t  )

        {

                 if( tsc == null )      tsc = "";

                 if( app == null )      app = "";

                 

                 MDC.put("APP",app);

                 MDC.put("TSC", tsc );

                 McsLogger.log( level, message, t );

                 MDC.remove("APP");

                 MDC.remove("TSC");

        }

        

        public static void main(String args[])

        {

                 String Path = System.getProperty( "user.dir" );

                 

                 PropertyConfigurator.configureAndWatch( Path +"/config/log4j.properties", 1000);

                 

                 System.out.println("URL:"+ Path +"/config/log4j.properties" );

                 

                 Trace.log( Level.INFO, "APP1","TQFRP01","Message01");

                 Trace.log( Level.WARN, "APP2","TQFRP05","Message02");

                 Trace.log( Level.FATAL, "APP3","TQFRP01","Message03", new Exception("Deaded!!"));

                 

                 

                 System.out.println("TEST COMPLETED !!");

        }

}

 

- 위와 같이 시스템별로 로그클랙스를 작성한다.


3. Log4J 적용 예제

3.1. 폴더구조

 

bin    : class 파일

config : log4j.properties

lib     : jdbcappender.jar, log4j-1.2.11.jar, ojdbc14.zip

log    : 로그파일app.cvs )

src    : 소스파일Trace.java )

3.2. 실행하기

run.bat  실행


참조-PatternLayout

아래 Conversion Pattern 실제로 Test 사용하시길 바랍니다.

Conversion

Character

Effect

c

클래스 명

 

 ) %c{2} : "a.b.c "b.c".

C

클래스 명

 

) %C{1} : org.apache.xyz.SomeClass → SomeClass

d

날짜 형식

 

 ) %d{dd MMM yyyy HH:mm:ss,SSS} , %d{HH:mm:ss,SSS}

F

파일 명

l

이벤트를 발생시킨 Caller의 위치정보

L

이벤트를 발생시킨 Caller의 라인번호

m

이벤트 메세지

M

이벤트를 발생시킨 Caller의 함수명

n

라입구분자

p

로그이벤트 우선순위

r

Application이 시작된 이후이벤트가 발생될 때까지 시간( milliseconds )

t

스레드의 이름을 출력

x

NDC(nested diagnostic context)의 사용하기

X

MDC (mapped diagnostic context) 사용하기

 

) %X{clientNumber} : clientNumber Key를 의미함

%

%%는 화면에 %를 출력함

 

[출처] Log4J 사용 가이드 |작성자 실바

출처 - http://blog.naver.com/gh2501/125766571

'Language > JAVA' 카테고리의 다른 글

JAXB: Marshalling and Unmarshalling CDATA block using EclipseLink MOXy  (0) 2013.09.03
.getClass() 와 .class의 차이점  (0) 2013.08.29
log4j  (0) 2013.08.29
jUnit 으로 Private Method 테스트 만들기  (0) 2013.08.28
Ant - tutorial  (0) 2013.08.26
:

log4j

Language/JAVA 2013. 8. 29. 14:40

Log는 프로그램을 하다 보면 매우 유용한 정보입니다그렇다고 무작정 로그를 남기는 것도 시스템 performance에 악영양을 미치므로 꼭 필요한 부분에 로그를 남겨두는 것이 좋습니다.

 

로그를 남기는 가장 쉬운 방법은 System.out.println("something logs....");와 같이 System.out.println을 사용하면 되지만 프로그램을 개발완료 후에는 불필요한 로그를 삭제하는 작업이 필요하겠죠만약 삭제하지 않으면 system log에 엄청난 쓰레기 로그들이 남겠죠그러나 이런 로그들이 시스템 오류가 발생했을 때는 매우 귀중한 자원이 됩니다.

 

무작정 삭제할 수도 없고 그렇다고 그대로 놓아두면 시스템 부하가 생기겠죠이러한 로그를 잘 관리할 수 있는 뭔가가 필요할 겁니다이 문제를 해결하기 위해 나온 것이 log4j 프레임웍이라고 볼 수 있습니다.

 

Log4j에서 로그는 환경파일 설정을 통해 선택적으로 남길 수 있으며로그를 남기는 물리적인 매체를 설정할 수도 있습니다. Text file로 남기거나 database로 남기거나 등등..

 

자 그럼 log4j를 한번 사용해 보도록 할까요?

 

Log4j는 다음의 사이트에서 다운로드 받을 수 있습니다http://logging.apache.org/log4j/1.2/download.html

 

apache-log4j-1.2.16.zip 파일을 다운받으시면 될 것 같네요압축을 풀명 여러 파일이 있는데 아래의 log4j-1.2.16.jar파일을 import 시키면 됩니다.


다음은 로그를 어떻게 남길지 결정하기 위해 환경설정파일을 만들어야 겠죠기본적으로 log4j의 환경파일은 log4j.properties입니다또한 기본적인 위치는 WEB-INF\classes directory에 위치시키시면 됩니다우선 저는 src 디렉토리에 위치 시켰습니다그럼 log4j.properties의 내용을 확인해 볼까요?

 

log4j.rootCategory=DEBUG, console, filelog

 

log4j.appender.console=org.apache.log4j.ConsoleAppender

log4j.appender.console.layout=org.apache.log4j.PatternLayout

log4j.appender.console.layout.ConversionPattern=%-5p,%d{yyyy/MM/ddHH:mm:ss.SSS},%-5X{APP}, %-8X{TSC}, %m %n

 

log4j.appender.filelog=org.apache.log4j.DailyRollingFileAppender

log4j.appender.filelog.Append=true

log4j.appender.filelog.DatePattern='.'yyyy-MM-dd-HH

log4j.appender.filelog.File=./log/application.log

log4j.appender.filelog.layout=org.apache.log4j.PatternLayout

log4j.appender.filelog.layout.ConversionPattern=%-5p,%d{yyyy/MM/ddHH:mm:ss.SSS},%-5X{APP}, %-8X{TSC}, %m %n

 

 

두가지 방법만 일단 알아보겠습니다.  콘솔로 남기는 방법과 파일로 남기는 방법입니다.

 

Log4j 5가지의 로그 레벨이 있습니다. DEBUG, INFO, WARN, ERROR, FATAL 개발자는 로그를 남길 때 이 5가지의 범주로 로그를 남기시면 됩니다이는 추후에 알아보기로 하고 환경설정을 하나씩 확인해 보겠습니다.

 

log4j.rootCategory=DEBUG, console, filelog

로그를 남기는 레벨을 지정하고 로그 출력방향을 설정합니다위 설정은 DEBUG레벨로 로그를 출력하고 콘솔과 파일로그로 남긴다는 의미입니다. Console, filelog의 이름은 개발자가 마음대로 수정할 수 있습니다.

 console의 환경설정을 볼까요로그출력방향을 콘솔로 설정하고 로그 패턴을 설정하고 있습니다.

자세한 사항은 다음의 사이트에서 http://blog.naver.com/gh2501/125766571를 참조하시기 바랍니다.

잘 정리되어 있어요 ^^;

 

log4j.appender.console=org.apache.log4j.ConsoleAppender

log4j.appender.console.layout=org.apache.log4j.PatternLayout

log4j.appender.console.layout.ConversionPattern=%-5p,%d{yyyy/MM/dd HH:mm:ss.SSS},%-5X{APP}, %-8X{TSC},%m %n

 

파일로 로그를 출력합니다.

 

log4j.appender.filelog=org.apache.log4j.DailyRollingFileAppender

log4j.appender.filelog.Append=true

log4j.appender.filelog.DatePattern='.'yyyy-MM-dd-HH

log4j.appender.filelog.File=./log/application.log

log4j.appender.filelog.layout=org.apache.log4j.PatternLayout

log4j.appender.filelog.layout.ConversionPattern=%-5p,%d{yyyy/MM/dd HH:mm:ss.SSS},%-5X{APP}, %-8X{TSC},%m %n

 

자 그러면 이제 로그를 남기도록 설정을 해보도록 하겠습니다기존에 테스트하던 소스를 활용해 보겠습니다.

 

package org.power.test;

 

import org.apache.log4j.Logger;

import org.power.dao.BbsDAO;

import org.power.dao.BbsMybatisDAOImpl;

import org.power.vo.BbsVO;

 

import junit.framework.TestCase;

 

public class BbsMybatisDAOImplTest extends TestCase {

 

             private BbsDAO bbsdao;

             public Logger logger;

            

             protected void setUp() throws Exception {

                           super.setUp();

                          

                           bbsdao = new BbsMybatisDAOImpl();

                           logger = Logger.getLogger(this.getClass());

                          

             }

 

             public void testSelect() {

                          

                           BbsVO vo = new BbsVO();                            

                          

                           try {

                                        vo = bbsdao.select(1500);

                                       

logger.debug(vo.toString());

                    logger.info(vo.toString());

                    logger.warn(vo.toString());

                    logger.error(vo.toString());

                    logger.fatal(vo.toString());

                   

                            } catch (Exception e) {                           

                         e.printStackTrace();                 

                            }          

             }

 

 

위의 테스트 코드를 Debug레벨로 로그를 남기고 실행해 보며 다음과 같이 로그가 표시됩니다.

위를 보면 debug, info, warn, error, fatal의 모든 로그가 표시됩니다특히 재미있는 것은 ibatis의 로그도 표시되고 있습니다, ibatislog4j를 사용하고 있다는 의미겠죠?

 

그럼 레벨을 warn로 해보면 어떻게 될까요? log4j.properties에서 다음의 속성을 바꾸어 보겠습니다.

log4j.rootCategory=WARN, console, filelog


WARN 레벨 이상의 로그만 표시되고 있습니다.

 

자 개발시에 필요한 DEBUG정보들은 DEBUG로 레벨로 로그를 남기고 실제 운영시에는 로그레벨을 ERROR 레벨로 설정하면 로그가 쌓이는데 소모되는 시스템부하를 줄일 수가 있겠죠또한 문제가 발생시에는 로그레벨을 DEBUG로 설정하여 로그를 확인하면 오류를 쉽게 컨트롤 할 수 있을 것이라 봅니다.

 

다만, log4j도 문제가 있습니다실제적으로 로그만 출력을 하지 않을 뿐 로그를 만드는 작업즉 logger.debug(vo.toString()); 와 같은 코드가 실제적으로 시스템 리소스를 소비하기 때문입니다. String 작업은 java에서 가장 많은 리소스를 차지한다고 합니다이런 부하를 해결하기 위해 또 다른 log 관련 프레임웍의 사용이 대두 된다고합니다


출처 - http://blog.naver.com/byebird?Redirect=Log&logNo=20140995455

'Language > JAVA' 카테고리의 다른 글

.getClass() 와 .class의 차이점  (0) 2013.08.29
Log4J 사용 가이드  (0) 2013.08.29
jUnit 으로 Private Method 테스트 만들기  (0) 2013.08.28
Ant - tutorial  (0) 2013.08.26
ANT Build  (0) 2013.08.26
:

jUnit 으로 Private Method 테스트 만들기

Language/JAVA 2013. 8. 28. 17:22

TDD 프로젝트에 join 한지 두달이 넘어갑니다.
이제 Spring Framwork 에서 JUnit 테스트 만드는 일은 제법 익숙해 졌어요.

오늘은 Private 메소드에 대한 JUnit 테스트 만드는 방법을 정리해 두어야 겠습니다.

우선 Method 메소드를 만들어서 테스트할 private 메소드를 담을 겁니다.


Method m = singlePaymentController.getClass().getDeclaredMethod("method name",input parameter -class-);

singlePaymentController 는 테스트할 클래스 이름인데요.


미리 인스턴스를 생성해 놓은 변수 입니다. (SinglePaymentController singlePaymentController = new SinglePaymentController(); 이렇게요.

 

그 클래스에서 getClass()를 안의 getDeclaredMethod() 를 불러 냅니다.
private 메소드를 외부에서 접근할 때는 이 getDeclaredMethod()를 사용하고 private field 에 접근할 때는 getDeclaredField() 나 getDeclaredFields를 사용합니다.


이 밖에서getDeclaredConstructor(), getDeclaredClass() 등 여러가지가 있습니다. 필요할 때 사용하면 됩니다.

 

getDeclaredMethod() 안에 들어가는 인자들은 해당 메소드 이름이 string으로 들어가고 그 다음엔 그 메소드의 input parameter 들을 열거하면 됩니다.

 

그러면 테스트 하고 싶은 private 메소드를 Method 객체 안에 담을 수가 있습니다.

m.setAccessible(true);

 

이제 위 코드 처럼 해당 private 메소드를 접근할 수 있도록 합니다.
이제 외부에서 그 private 메소드에 접근 할 수 있습니다.

 

이제 해당 private method 를 실행시키면 됩니다.


invoke 메소드를 사용하는데요.


그 private method를 담은 Method 객체를 invoke 해 주면 됩니다.
m.invoke() 이렇게요.

 

여기서 invoke 안에는 그 private 메소드가 들어있는 class와 private method 에 전달 될 input parameter 를 넣어 주면 됩니다.

 

private 메소드가 들어있는 클래스는 아까 사용했던 singlePaymentController 가 되겠네요.
그리고 그 private method의 input parameter는 새로 생성해서 테스트 데이터를 넣어 주셔야 됩니다.

 

input parameter 에 필요한 값들 넣기

m.invoke(클래스 이름, input parameter)

 

assert 하기

이렇게해서 해당 private method 안에서 처리되어야 할 값들을 assert 문에 넣어서 예상값과 실제 처리된 값을 비교하면 되겠죠.

 

만약 그 private 메소드가 return 값이 있다면 invoke 해서 return 되는 값을 받아서 그 값을 가지고 assert 하면 됩니다.


완성된 소스는 아래와 같습니다.
 
 
 

public class jUnitPrivateTest

 

{

@Test

public void testJUnitPrivate(){

privatemethod jPrivate = new privatemethod();

Method m;

try

{

m = jPrivate.getClass().getDeclaredMethod("jUnitPrivate",String.class,String.class);

m.setAccessible(true);

String result =null;

String a = "Korea";

String b = "Seoul";

result = (String) m.invoke(jPrivate,a,b);

assertEquals("Korea : Seoul",result);

}

catch (Exception e)

{

// TODO Auto-generated catch block

e.printStackTrace();

}

}

/**

@throws java.lang.Exception

*/

@BeforeClass

public static void setUpBeforeClass() throws Exception

{

}

/**

@throws java.lang.Exception

*/

@AfterClass

public static void tearDownAfterClass() throws Exception

{

}

/**

@throws java.lang.Exception

*/

@Before

public void setUp() throws Exception

{

}

/**

@throws java.lang.Exception

*/

@After

public void tearDown() throws Exception

{

}

}

 

출처 - http://coronasdk.tistory.com/658


'Language > JAVA' 카테고리의 다른 글

Log4J 사용 가이드  (0) 2013.08.29
log4j  (0) 2013.08.29
Ant - tutorial  (0) 2013.08.26
ANT Build  (0) 2013.08.26
정규식 날짜, 시간  (0) 2013.08.21
:

Ant - tutorial

Language/JAVA 2013. 8. 26. 14:29

Apache Ant - tutorial

Lars Vogel

Version 2.5

09.04.2013

Revision History
Revision 0.130.11.2008Lars
Vogel
Created
Revision 0.2 - 2.512.01.2009 - 09.04.2013Lars
Vogel
bugfixes and enhancements

Apache Ant Tutorial

This tutorial describes the usage of Ant as a build tool to compile Java code, pack this code into an executable jar and how to create Javadoc. The usage of Ant is demonstrated within Eclipse and from the command line. This tutorial is based on Apache Ant 1.8.x.


1. Build tools

build tool is used to automate repetitive tasks. This can be for example compiling source code, running software tests and creating files and documentation for the software deployment.

Build tools typically run without a graphical user interface (headless) directly from the command line.

Popular build tools in the Java space are Apache AntMaven and Gradle.

2. Apache Ant Overview

2.1. What is Apache Ant?

Apache Ant (Ant) is a general purpose build tool. Ant is an abbreviation for Another Neat Tool.

Ant is primarily used for building and deploying Java projects but can be used for every possible repetitive tasks, e.g. generating documentation.

2.2. Configuring Apache Ant

A Java build process typically includes:

  • the compilation of the Java source code into Java bytecode
  • creation of the .jar file for the distribution of the code
  • creation of the Javadoc documentation

Ant uses an xml file for its configuration. The default file name is build.xmlAnt builds are based on three blocks: tasks,targets and extension points .

task is a unit of work which should be performed and are small, atomic steps, for example compile source code or create Javadoc. Tasks can be grouped into targets.

target can be directly invoked via AntTargets can specify their dependencies. Ant will automatically execute dependent targets.

For example if target A depends on B, than Ant will first perform B and then A.

In your build.xml file you can specify the default targetAnt will execute this target, if no explicit target is specified.

3. Installation

3.1. Prerequisites

Ant requires the installation of the Java Development Kit (JDK).

3.2. Installation of Java

Java might already be installed on your machine. You can test this by opening a console (if you are using Windows: Win+R, enter cmd and press Enter) and by typing in the following command:

java -version 

If Java is correctly installed, you should see some information about your Java installation. If the command line returns the information that the program could not be found, you have to install Java. The central website for installing Java is the following URL:

http://java.com 

If you have problems installing Java on your system, search via Google for How to install JDK on YOUR_OS . This should result in helpful links. Replace YOUR_OS with your operating system, e.g. Windows, Ubuntu, Mac OS X, etc.

3.3. Linux

On Ubuntu or Debian use the apt-get install ant command to install Apache Ant. For other distributions please check the documentation of your vendor.

3.4. Windows

Download Apache Ant from http://ant.apache.org/.

Extract the zip file into a directory structure of your choice. Set the ANT_HOME environment variable to this location and include the ANT_HOME/bin directory in your path.

Make sure that also the JAVA_HOME environment variable is set to the JDK. This is required for running Ant.

Check your installation by opening a command line and typing ant -version into the commend line. The system should find the command ant and show the version number of your installed Ant version.

4. Tutorial: Using Apache Ant

4.1. Using Ant for Java development

The following describes how you compile Java classes, create an executable JAR file and create Javadoc for your project with Apache Ant. The following example assumes that your are using the Eclipse IDE to manage your Java project and your Ant build.

4.2. Create Java project

Create a Java project called de.vogella.build.ant.first in Eclipses. Create a package called math and the following class.

package math;

public class MyMath {
  public int multi(int number1, int number2) {
    return number1 * number2;
  }
} 

Create the test package and the following class.

package test;

import math.MyMath;

public class Main {
  public static void main(String[] args) {
    MyMath math = new MyMath();
    System.out.println("Result is: " + math.multi(5, 10));
  }
} 

4.3. Create build.xml

Create a new File through the File → New → File menu and create the build.xml file. Implement the following code to this file.

<?xml version="1.0"?>
<project name="Ant-Test" default="main" basedir=".">
  <!-- Sets variables which can later be used. -->
  <!-- The value of a property is accessed via ${} -->
  <property name="src.dir" location="src" />
  <property name="build.dir" location="bin" />
  <property name="dist.dir" location="dist" />
  <property name="docs.dir" location="docs" />

  <!-- Deletes the existing build, docs and dist directory-->
  <target name="clean">
    <delete dir="${build.dir}" />
    <delete dir="${docs.dir}" />
    <delete dir="${dist.dir}" />
  </target>

  <!-- Creates the  build, docs and dist directory-->
  <target name="makedir">
    <mkdir dir="${build.dir}" />
    <mkdir dir="${docs.dir}" />
    <mkdir dir="${dist.dir}" />
  </target>

  <!-- Compiles the java code (including the usage of library for JUnit -->
  <target name="compile" depends="clean, makedir">
    <javac srcdir="${src.dir}" destdir="${build.dir}">
    </javac>

  </target>

  <!-- Creates Javadoc -->
  <target name="docs" depends="compile">
    <javadoc packagenames="src" sourcepath="${src.dir}" destdir="${docs.dir}">
      <!-- Define which files / directory should get included, we include all -->
       <fileset dir="${src.dir}">
                <include name="**" />
           </fileset>
    </javadoc>
  </target>

  <!--Creates the deployable jar file  -->
  <target name="jar" depends="compile">
    <jar destfile="${dist.dir}\de.vogella.build.test.ant.jar" basedir="${build.dir}">
      <manifest>
        <attribute name="Main-Class" value="test.Main" />
      </manifest>
    </jar>
  </target>

  <target name="main" depends="compile, jar, docs">
    <description>Main target</description>
  </target>

</project> 

The code is documented, you should be able to determine the purpose of the different ant tasks via the documentation in the coding.

4.4. Run your Ant build from Eclipse

Run the build.xml file as an Ant Build in Eclipse.

After this process your data structure should look like this:

4.5. Run your Ant build from the command line

Open a command line and switch to your project directory. Type in the following commands.

# run the build
ant -f build.xml

# build.xml is default you can also use 
ant 

The build should finish successfully and generate the build artifacts.

5. Apache Ant classpath

5.1. Setting the Ant classpath

Ant allows to create classpath containers and use them in tasks. The following build.xml from a project calledde.vogella.build.ant.classpath demonstrates this.

<?xml version="1.0"?>
<project name="Ant-Test" default="Main" basedir=".">
  <!-- Sets variables which can later be used. -->
  <!-- The value of a property is accessed via ${} -->
  <property name="src.dir" location="src" />
  <property name="lib.dir" location="lib" />
  <property name="build.dir" location="bin" />

  <!--
    Create a classpath container which can be later used in the ant task
  -->
  <path id="build.classpath">
    <fileset dir="${lib.dir}">
      <include name="**/*.jar" />
    </fileset>
  </path>

  <!-- Deletes the existing build directory-->
  <target name="clean">
    <delete dir="${build.dir}" />
  </target>

  <!-- Creates the  build  directory-->
  <target name="makedir">
    <mkdir dir="${build.dir}" />
  </target>

  <!-- Compiles the java code -->
  <target name="compile" depends="clean, makedir">
    <javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="build.classpath" />
  </target>



  <target name="Main" depends="compile">
    <description>Main target</description>
  </target>

</project> 

5.2. Print

You can use the following statements to write the full classpath to the console. You can use this to easily verify if the classpath is correct.

<!-- Write the classpath to the console. Helpful for debugging -->
<!-- Create one line per classpath element-->
<pathconvert pathsep="${line.separator}" property="echo.classpath" refid="junit.class.path">
</pathconvert>
<!-- Write the result to the console -->
<echo message="The following classpath is associated with junit.class.path " />
<echo message="${echo.classpath}" /> 

6. Running JUnit Tests via Ant

Ant allows to run JUnit tests. Ant defines junit task. You only need to include the junit.jar and the compiled classes into the classpath for Ant and then you can run JUnit tests. See JUnit Tutorial for an introduction into JUnit.

The following is a JUnit test for the previous example.

package test;

import math.MyMath;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class MyMathTest {
  @Test
  public void testMulti() {
    MyMath math = new MyMath();
    assertEquals(50, math.multi(5, 10));
  }
} 

You can run this JUnit unit test via the following build.xml. This example assumes that the JUnit jar "junit.jar" is in folder "lib".

<?xml version="1.0"?>
<project name="Ant-Test" default="main" basedir=".">
  <!-- Sets variables which can later be used. -->
  <!-- The value of a property is accessed via ${} -->
  <property name="src.dir" location="src" />
  
  <property name="build.dir" location="bin" />

  <!-- Variables used for JUnit testin -->
  <property name="test.dir" location="src" />
  <property name="test.report.dir" location="testreport" />

  <!-- Define the classpath which includes the junit.jar and the classes after compiling-->
  <path id="junit.class.path">
    <pathelement location="lib/junit.jar" />
    <pathelement location="${build.dir}" />
  </path>


  <!-- Deletes the existing build, docs and dist directory-->
  <target name="clean">
    <delete dir="${build.dir}" />
    <delete dir="${test.report.dir}" />
  </target>

  <!-- Creates the  build, docs and dist directory-->
  <target name="makedir">
    <mkdir dir="${build.dir}" />
    <mkdir dir="${test.report.dir}" />
  </target>

  <!-- Compiles the java code (including the usage of library for JUnit -->
  <target name="compile" depends="clean, makedir">
    <javac srcdir="${src.dir}" destdir="${build.dir}">
      <classpath refid="junit.class.path" />
    </javac>

  </target>

  <!-- Run the JUnit Tests -->
  <!-- Output is XML, could also be plain-->
  <target name="junit" depends="compile">
    <junit printsummary="on" fork="true" haltonfailure="yes">
      <classpath refid="junit.class.path" />
      <formatter type="xml" />
      <batchtest todir="${test.report.dir}">
        <fileset dir="${src.dir}">
          <include name="**/*Test*.java" />
        </fileset>
      </batchtest>
    </junit>
  </target>

  <target name="main" depends="compile, junit">
    <description>Main target</description>
  </target>

</project> 

7. Useful Ant tasks

7.1. fail

Ant provides the fail task which allows to fail the build if a condition is not met. For example the following task would check for the existing of a file and if this file is present the build would fail.

<fail message="PDF file was not created.">
   <condition>
      <not>
          <available file="${pdf.dir}/path/book.pdf" />
      </not>
    </condition>
</fail> 

Or you can check for the number of files generated.

<fail message="Files are missing.">
    <condition>
        <not>
            <resourcecount count="2">
                <fileset id="fs" dir="." includes="one.txt,two.txt"/>
            </resourcecount>
        </not>
    </condition>
</fail> 

8. Eclipse Ant Editor

Eclipse has an ant editor which make the editing of ant file very easy by providing syntax checking of the build file. Eclipse has also a ant view. In this view you execute ant files via double-clicking on the target.

Tip

By default Eclipse uses the ant version which ships with Eclipse. Via the preference Ant -> Runtime -> Ant Home you can configure the version of Ant Eclipse should be using.

9. Ant tips

9.1. Converting Paths

Apache Ant allows to convert relative paths to absolute paths. The following example demonstrates that.

<!-- Location of a configuration -->
<property name="my.config" value="../my-config.xml"/>
<makeurl file="${my.config}" property="my.config.url"/> 

This property can later be used for example as a parameter.

<param name="highlight.xslthl.config" expression="${my.config.url}"/> 

9.2. Regular expressions

Ant can be used to replace text based on regular expressions. The following Ant Target replaces tabs with double spaces.

<target name="regular-expressions">
  <!-- Replace tabs with two spaces -->
  <replaceregexp flags="gs">
    <regexp pattern="(\t)" />
    <substitution expression="  " />
    <fileset dir="${outputtmp.dir}/">
      <include name="**/*" />
    </fileset>
  </replaceregexp>
</target> 

10. Thank you

Please help me to support this article:

Flattr this
 

11. Questions and Discussion

If you find errors in this tutorial please notify me (see the top of the page). Please note that due to the high volume of feedback I receive, I cannot answer questions to your implementation. Ensure you have read the vogella FAQ, I also don't answer questions answered in the FAQ.

12. Links and Literature

12.1. Source Code

http://www.vogella.com/code/codejava.html Source Code of Examples

12.2. General

http://ant.apache.org/ Apache Ant Homepage http://subclipse.tigris.org/svnant.html Subversion Ant Task


'Language > JAVA' 카테고리의 다른 글

log4j  (0) 2013.08.29
jUnit 으로 Private Method 테스트 만들기  (0) 2013.08.28
ANT Build  (0) 2013.08.26
정규식 날짜, 시간  (0) 2013.08.21
Java 인자 전달 방식: Call-by-{Value | Reference}?  (0) 2013.08.09
:

ANT Build

Language/JAVA 2013. 8. 26. 14:28

우선 ant 를 다운로드 받는다. 물론 eclipse 를 사용하면 기본적으로 탑재가 되어있지만, 때에 따라서는 eclipse 같은 IDE 툴을 사용하지 못할 수 도 있기 때문에 일단 배재시키고 이야기해 보자.


압 축을 풀어보면 뭔가 잡다한 파일들이 많이 보인다. 우선 $ANT_HOME/bin 을 환경변수의 PATH 에 잡고 커맨드 창에서 ant 라고 쳐 보면 아래와 같은 메시지가 나올 것이다. 그러면 일단 설치는 성공~ (환경변수를 잡기 싫으면 ant 실행시 경로포함하여 실행하세요)


Buildfile: build.xml does not exist!

Build failed


메시지를 살펴보면 build.xml 파일이 존재하지 않는다고 한다. ant 는 기본적으로 build.xml 이라는 이름을 가진 파일에 설정을 하고 되어있다.


그럼 여기서 목표를 잡아보면 ant 를 이용하여 컴파일을 해보자.


우선, 커맨드 창에서 java 컴파일을 했던 방법을 떠 올려보자. 그동안 IDE 툴에 너무 익숙해져 있어서 다소 생소하게 느껴지지만 기억을 다듬어 보면 아래와 같은 형태로 컴파일을 한다.


javac -cp 필요한라이브러리 xxx.java 


그럼 ant의 설정파일인 build.xml 의 구조를 간단히 살펴보자.


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

<project name="agilejava" default="build" basedir=".">

</project>


가 장 기본이 되는 형태이다. default 값이 build 로 설정되었다는 의미는 ant 만 실행시에 build 라는 타겟을 찾아서 실행하라는 의미이고 basedir 의 값이 '.'  build.xml  과 같은  레벨을 기준으로 상대경로를 잡는다는 의미이다.


다음으로 아래와 같은 property 들을 정의할 수 있다. 코딩으로 따지자면 선언해 놓은 상수(?) 정도라고 할 수 있겠다.

자주 사용하는 것들을 미리 등록해 놓으면 편하게 쓸 수 있다. value 대신에 location 을 사용해도 무방하다.


    <property name="project.name" value="AntTask"/>

    <property name="PROJECT" value="D:/workspace/${project.name}" />

    <property name="build.dir" value="${PROJECT}/build"/>

    <property name="dist.dir" value="${PROJECT}/dist"/>

    <property name="src.dir" value="${PROJECT}/src"/>



    필요한 라이브러리들의 클래스 패스를 잡는다.

    스프링으로 따지자면 ref 속성으로 쓰기위한 하나의 bean 을 등록한다고나 할까?


    <path id="project.classpath">

        <fileset dir="${PROJECT}/web/WEB-INF/lib" includes="**/*.jar" />

    </path>


   

    우리가 이번글에서 목표로 하는 컴파일이다. target 속성에 depends 라는 녀석이 보이고 init 이라는 값을 가지고 있다.

    build 타겟을 실행할 때  init  타겟을 먼저 수행하라는 의미이다.  init 내용은  더 밑에서 살펴보고  build 를 좀 더  봐보자.

    javac 라는 녀석이 보인다.  컴파일을  수행하라는 이야기다.

    src ==> 소스 디렉토리,   destdir ==>  컴파일 된  클래스 파일이 들어갈 디렉토리 includes 는 컴파일 할 대상(여기서는 모든경로의 모든 java 파일을 설정). 나머지 옵션은 에러추적용 이므로 패스~

    위에서 설정한 라이브러리 패스를 사용하여 컴파일을 한다.


    <target name="build" depends="init">

        <javac srcdir="${src.dir}" destdir="${build.dir}" includes="**/*.java" debug="true" failonerror="true">

            <classpath refid="project.classpath" />

        </javac>

    </target>


    init 타겟은 별 내용이 없다. 시작시와 끝날시에 메시지 보여주고 컴파일 시에 필요한 디렉토리를 생성시킨다.

    <target name="init">

        <echo message="init... start" />

        <mkdir dir="${build.dir}"/>

        <mkdir dir="${dist.dir}"/>

        <echo message="init... end" />

    </target>


이제 실행을 해 보면 아래와 같은 형태의 메시지를 볼 수 있다.

>ant build


Buildfile: build.xml


init:

     [echo] init... start

     [echo] init... end


build:

    [javac] Compiling 1 source file to D:\workspace\AntTask\build


BUILD SUCCESSFUL

Total time: 4 seconds

빌드가 이루어지면 컴파일이 된 것을 확인할 수 있다.


 


간단한 타겟 몇 가지를 살펴보겠습니다.


* 디렉토리, 파일 지우기


    <target name="clean">

        <echo message="Cleaning ${build.dir}" />

        <delete dir="${build.dir}" />

    </target>


위의 내용만 봐도 뭐 하는 녀석인지 바로보인다. 빌드를 시켰던 디렉토리를 깨끗하게 지우는 타겟이다.

기존의 내용이 남아있다면 나중에 괜한 고생을 하게 될지도 모른다. 특히, 프로젝트가 커졌을 경우 소스코드와 빌드내용이 동기화가 되지 않을 가능성이 높다.

이클립스의 clean 기능과 일맥상통한다. (해당 프로젝트의 빌드를 모두 지워버린다.)


* 파일 복사하기


다음으로 파일복사에 대해 간단히 살펴보자.

빌드된 파일을 특정한 디렉토리로 복사를 한다.

예를 들면 소스 컴파일이 성공을 했을경우 WAS 에 해당 클래스를 복사해 넣는것이다.


    <target name="deploy" depends="build">

        <copy todir="${deploy.dir}" overwrite="true">

            <fileset dir="${build.dir}" >

               <include name="**/*.class" /> 

            </fileset>

        </copy>

    </target>


눈에 띄는 옵션은 depends="build" 와 overwrite="true" 이다.

이 또한, 이름이 직관적이라 바로 알 수 있다. deploy 를 하기전에 먼저 build 를 하고 동일한 파일이 존재할 경우 덮어써라~ 이다.


* jar 파일 만들기

빌드가 이루어진 클래스 파일을 그냥 사용할 수도 있지만, 배포를 위해서 jar 파일로 묶어서 사용할 수도 있다.

라이브러리를 배포할 경우 많이 사용하게된다.


    <target name="deployjar" depends="build">

        <echo message="create jar file : ${dist.dir}/${deploy.name}.jar" />

        <jar jarfile="${dist.dir}/${deploy.name}.jar" update="true">

            <fileset dir="${build.dir}">

                <include name="**/*.*"/>

            </fileset>

        </jar>

    </target>


역시나 jar 를 만드는 것이니 jar 부분이 눈에 들어온다. 빌드가 된 파일셋을 이용하여 지정한 이름으로 jar 파일을 생성시킬 수 있다.


* 여러 target 한꺼번에 실행하기

말 그대로 이다. 지금까지는 한번에 하나의 타겟을 실행했었고, 해당 target 에서 depends 를 걸었었다.

여러 타겟 실행하는 것도 위의 예제들에 이미 힌트가 나와있다.

depends 에 여러 타겟을 컴마(,)를 구분자로 넣어놓으면 순차적으로 실행이 된다. (너무 당연한 이야기인가?? ^^)


    <target name="all" depends="clean, cleanjar, init, deployjar" >

        <echo message="execute all task.... " />

    </target>


예제를 간단하게 만들면서 본이 아니게 중간에 echo 를 계속 사용하게 되었다.

해당 메시지를 보여주면 특정 타겟을 실행할 때 메시지를 보여줄 수 있어서 나름 쓸만한 것 같다.

이외에도 ftp 를 이용하여 파일을 전송한다던지, 특정 WAS 를 기동시킨다던지 하는 것들도 만들 수 있다.

또한, 테스트 케이스를 만들고 실행해 볼 수 있습니다.



출처 - http://blog.naver.com/arbong3/130033841414

:

정규식 날짜, 시간

Language/JAVA 2013. 8. 21. 16:53

YYYYMMDDHH24MISS


(19[7-9][0-9]|20\d{2})-(0[0-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])

:

Java 인자 전달 방식: Call-by-{Value | Reference}?

Language/JAVA 2013. 8. 9. 17:03

Java 인자 전달 방식: Call-by-{Value | Reference}?


[이미지 출처 - Google]
C++를 마지막으로 사용해본지 거의 6년이 다 되어가는 지금 Java를 다루면서 잊고 있었던 "Parameter passing in Java: call-by-value vs call-by-reference?"란 주제가 기본을 일깨워 주는 좋은 양식이 되겠다 싶어 내용을 정리해 보려고 합니다.

이 주제는 지금까지 다양한 커뮤니티상에서 오랫동안 논의 되었고, 그로 인해 잘 정리된 문서와 사이트를 어렵지 않게 찾을 수 있어 최대한 많은 참조를 토대로 작성하고자 합니다.

Java 개발자로서 두 매커니즘의 차이에 혼돈을 일으키는 이유는 아마도 
  • 서로 다른 인자전달 매커니즘을 가지는 언어를 두루 사용해 본 경험이 없거나,
    • 이 경우는 왜 이 문제가 그토록 많이 논의되었는지 잘 이해하지 못함
  • 경험이 있다 하더라도 정확한 이해없이 흘려버린 경우
등이 있지않나 생각됩니다.(고슬링 옹이 직접 시원하게 말해줬음 좋겠구만 @^^@)

0. 사전지식(Parameter, Argument, Syntax/Semantics, Reference)

메서드나 함수의 인자 전달을 설명 할 때 항상 등장하는 단어가 parameter와 argument입니다. 두 단어 모두 인자를 표현하는 단어지만 구분해서 쓰자면 formal-parameter(형식인자)와 actual-parameter(실인자)로 이해하는 것이 적당합니다. 다음 코드에서 parameter와 argument의 차이를 간단히 보도록 하겠습니다.
public class WhatIsParameter {
    //int형 변수 something은 formal-parameter
    public static void doSomething(int something) {
        System.out.println("something is " + something);
    }
    public static void main(String[] args) {
        int ten = 10;
        doSomething(ten); //ten의 값 10은 actual-parameter
        System.exit(0);
    }
}
Syntax와 semantics는 여기서 간단히 다룰 주제는 아니지만 이해를 돕기위한 것이니 아래 코드 정도만 두 용어로 이해해 봅니다. 
//Case1.
int primitiveIntVar = 1024;
//Case2.
String whoAreYou = "It's me! Uncle Bob";
두 문장은 모두 올바른 Java 문법으로 작성되었습니다. Syntax는 말 그대로 언어의 구문규칙을 의미합니다. 그럼 semantics는 뭘까요? 그대로 해석하면 "의미"인데 누구한테 가치가 있는 "의미"일까요? 언어의 semantics는 컴파일러가 구문(syntax)을 분석한 뒤 해석하여 실제로 동작에 사용되는 명령어를 생산해 내는데 사용되는 지침(모델)입니다.

Case1과 Case2의 syntax는 거의 비슷하지만 semantics는 완전히 다릅니다. Case1은 "정수형 변수 primitiveIntVar에 정수 1024를 저장"하는 명령어를 생성해 내라는 의미라면, Case2는 "문자열 객체 It's me! Uncle Bob을 생성하고, String 타입의 변수 whoAreYou에 생성된 객체의 레퍼런스를 저장"하는 명령어를 만들어 내시오라는 의미를 가지고 있습니다. 

여기서 한 가지 기억해야 할 점은, primitiveIntVar 변수의 값이 1024인 반면, whoAreYou 참조변수의 값은 "It's me! Uncle Bob"이 아닌 이 객체를 참조 할 수 있는 포인터(pointers) 값 즉, 레퍼런스란 사실입니다.(다음은 Java(SE7) Language Spec.의 4.3.1 Object 파트의 일부 내용입니다.)

"...... The reference values(often just references) are pointers to these objects, and a special null reference, which refers to no object. ......"

요약하면, 메서드의 인자로 값을 전달하는 Java 언어의 매커니즘이 call-by-value semantic인가 call-by-reference semantic인가를 알아보는 것이 본 포스트의 목적입니다.(아..서론이 너무 길었나 ㅠㅠ)

1. 인자전달 방식


call-by-value와 call-by-reference semantic의 정의를 알아보기 위해 Wikipedia를 방문했습니다.(두 semantics의 정의안에 "오해의 소지"와 "정답의 근거"가 있다고 판단되기에 짚고 넘어갑니다.)
Call-by-value
In call-by-value, the argument expression is evaluated, and the resulting value is bound to the corresponding variable in the function (frequently by copying the value into a new memory region). If the function or procedure is able to assign values to its parameters, only its local copy is assigned — that is, anything passed into a function call is unchanged in the caller's scope when the function returns.
위 내용에 따르면, call-by-value 매커니즘은 함수로 인자를 전달할 때 전달 될 argument expression의 결과(actual-parameter)를 대응되는 함수의 변수(formal-parameter)로 복사하며, 복사된 값은 함수내에서 지역적으로 사용되는 local value라는 특징을 가지고 있습니다. 그리고 caller는 인자값을 복사 방식으로 넘겨 주었으므로, callee 내에서 어떤 작업을 하더라도 caller는 영향을 받지 않습니다. Call-by-value의 대표적인 예제 코드가 C언어에서 포인터를 설명할 때 등장하는 swap 함수입니다.
void swap(int first, int second) {
    int tmp = first;
    first = second;
    second = tmp;
}
int main(int argc, char** argv) {
    int x = 10, y = 20;
    swap(x, y);
    printf("x = %d, y = %d\n", x, y);
    return 0;
}
x = 10, y = 20

위 코드에서 main 함수가 swap 함수를 호출할 때 swap 함수가 필요로 하는 x와 y의 값을 먼저 계산하고 그 값(10과 20)을 swap 함수로 복사해서 넘겨줍니다. swap 함수는 함수가 실행 될 때 스택에 first, second, tmp 세 임시 저장공간을 만들었다가 전달 받은 10과 20을 각각 first와 second에 저장한 후 함수내 코드를 실행합니다. swap 함수는 종료할 때 임시로 생성했던 모든 공간을 삭제하므로 first, second, tmp로 작업했던 내용은 모두 사라지게 되고, main 함수의 x와 y는 그대로 10과 20을 유지하고 있습니다. 요약하면 first와 second 그리고 x와 y는 아무런 관련이 없는 독립적인 변수들입니다.

그럼 call-by-reference에 대한 정의를 살펴보도록 합시다. 
Call-by-reference
In call-by-reference evaluation(also referred to as pass-by-reference), a function receives an implicit reference to a variable used as argument, rather than a copy of its value. This typically means that the function can modify (i.e. assign to) the variable used as argument—something that will be seen by its caller.
Call-by-reference는 인자로 사용될 변수의 묵시적인 레퍼런스를 함수로 전달하며, 그것이 변수의 값은 아니다라고 되있습니다. 이해를 돕기 위해 이전 swap 함수의 예를 다시 보면, 만약 call-by-reference로 swap 함수에 뭔가를 전달한다면 x와 y가 가지고 있는 값(10, 20)이 아닌 x, y 변수자체에 대한 레퍼런스를 전달해야 합니다. C언어는 포인터로 call-by-reference를 구현할 수 있습니다.
void swap(int* first, int* second) {
    int tmp = *first;
    *first = *second;
    *second = tmp;
}
int main(int argc, char** argv) {
    int x = 10, y = 20;
    swap(&x, &y);
    printf("x = %d, y = %d\n", x, y);
    return 0;
}
x = 20, y = 10
위 코드에서는 x와 y가 가진 값을 swap 함수로 전달 한 것이 아닌, x와 y 자체의 레퍼런스(주소 값)를 전달했습니다. 마지막으로 다음 C코드를 통해 두 내용을 정리해 봅시다. 아래 코드에서 (1)(2)(3)은 각각 call-by-value/call-by-reference일까요?
void modify(int p, int* q, int* r) {
    p = 27;  //(1)
    *q = 27; //(2)
    *r = 27; //(3)
}
해답은 (1)의 경우, call-by-value이고, (2)(3)은 함수를 호출한 caller가 어떤 값을 actual-parameter로 넘겨주었는지 확인해 보아야 알 수 있습니다. 만약 caller가 다음과 같다면 
int main(int argc, char** argv) {
    int a = 1;
    int b = 1;
    int x = 1;
    int* c = &x;
    modify(a, &b, c);   // a is passed by value, b is passed by reference by creating a pointer,
                        // c is a pointer passed by value
    return 0;
}
b는 call-by-reference로 전달된 것이고, c는 call-by-value로 전달된 것입니다. 단 c의 경우 c 자체의 레퍼런스가 아닌 c가 저장하고 있는 값(x에 대한 레퍼런스 값)을 넘겨준 경우입니다. 결과적으로 함수호출 후 caller에서 변경되는 변수는 b와 x 두 개입니다. 

2. 오해의 소지


Java의 경우를 살펴봅시다. 우선 Java의 메서드 인자전달 방식이 무엇인가를 판단하기 위해 두 매커니즘의 가장 큰 특징을 위주로 검증해 보겠습니다. Call-by-value의 특징은 
  • Actual-parameter 의 값을 복사하여 전달하므로 caller는 callee의 작업(?)에 영향을 받지 않는다!!!
입니다. 조금 느슨하게 적은 감이 팍 오지만 다음 코드로 위 내용을 살펴봅시다. 테스트용으로 사용할 Person 클래스입니다.
public class Person {
    private String mName;
    
    public Person(String name) { 
        mName = name; 
    }
    public void setName(String name) { 
        mName = name; 
    }
    @Override
    public String toString() {
        return "Person " + mName;
    }
}
다음은 Person 객체를 넘겨받아 새로운 Person 객체로 변경하는 메서드 호출 코드입니다.
public class CallyByXXXTest {
    public static void assignNewPerson(Person p) {
        p = new Person("Bob");
    }
    public static void main(String[] args) {
        Person sam = new Person("Sam");
        assignNewPerson(sam);
        System.out.println(sam);
        System.exit(0);
    }
}
Person sam
sam 객체를 생성한 후 assignNewPerson 메서드로 전달하고 메서드 종료 후 sam 객체가 bob 객체로 변경되었는지 확인해 봤습니다. 결과는 아무런 변화가 없습니다. 그럼 call-by-value semantic일까요? 다음 코드를 봅시다. 
    public static void changePersonName(Person p) {
        p.setName("Bob");
    }
    public static void main(String[] args) {
        Person sam = new Person("Sam");
        changePersonName(sam);
        System.out.println(sam);
        
        System.exit(0);
    }
Person bob
sam 객체의 mName 필드를 변경하는 changePersonName 메서드를 실행한 후 결과를 확인해 보니 변경사항이 발생했습니다. 오해의 소지는 여기서 그리고 용어에서 발생합니다.
  1. 특정 메서드 내에서 전달 받은 객체의 상태를 변경 할 수 있음. 
  2. 참조변수는 임의의 객체에 대한 레퍼런스를 저장하므로 메서드로 전달한 값이 레퍼런스(call-by-reference?)
1의 경우, sam 참조변수가 가리키는  [이름 속성이 "Sam"인 Person 객체]를 [이름 속성이 "Bob"인 새로운 Person 객체]로 변경한 것이 아니라, 단지 이름 속성만 변경했을 뿐입니다.

2의 경우, 전달 된 레퍼런스는 참조변수 sam 자체의 레퍼런스(주소값?)가 아닌 sam이 저장하고 있는 값(이것도 레퍼런스)입니다.
    만약 Java가 call-by-reference 매커니즘을 지원한다면 참조변수 sam 자체의 레퍼런스(주소)를 얻을 수 있는 방법이 있어야 합니다. 그러나 Java는 이 방법을 지원하지 않습니다. 따라서 "참조변수 sam에 저장된 값(다른 객체의 레퍼런스 값)"을 복사하여 formal-parameter p로 넘겨준 call-by-value 매커니즘이 합당해 보입니다.

3. Java를 왜 이렇게 설계했을까?

다음 인용문을 통해 이 질문을 정리할까 합니다.
It seems that the designers of Java wanted to make sure nobody confused their object pointers with the evil manipulable pointers of C and C++, so they decided to call them references instead. So Java books usually say that objects are stored as references, leading people to think that objects are passed by reference. They’re not, they’re passed by value, it’s just that the value [on the stack at JVM level] is a pointer.
4. 결론
  • 두 매커니즘의 정리
    • passing value of actual-parameter variable : call-by-value
    • passing reference of actual-parameter variable : call-by-reference
  • Java의 메서드 인자전달 방식은 call-by-value
    • value란? 객체에 대한 포인터 값(레퍼런스) 또는 primitive 타입의 값


: