JAVA & Open Framework2013. 5. 27. 09:35

ftp 연결하는 소스들은 많은데에 비해 sftp에 대한 소스들은 많이 부족한듯 싶다.

여기서 잠깐. sftp가 그럼 뭐냐?! 궁금한사람은 직접 정보의 바다에서 헤엄쳐보시길~!

일단. 이 포스트에서 사용한 코드를 사용하기 위해서는 특별한 jar 파일이 필요하다.

http://www.jcraft.com/jsch/ 이 곳에 들어가서 jsch-0.1.42.jar 를 받아두자.

그리고 이클립스에서 jar 파일을 가져와 셋팅~! 자...그럼 이제 준비가 끝났다.

아래에는 간단하게 sftp에 연결하고, 파일의 업로드, 다운로드를 하는 코드이다.

다른 블로그에 있는 소스를 참고해서 만드느라고 했는데 제대로 된 것인지 글쎄;;(실행은 잘 된다.)

이상한 점 첫 째는 public void disconnection() 의 메소드의 내용이 정확한 것인지 모르겠고

둘 째는 main 메소드를 실행하면 프로그램이 실행은 문제 없이 되지만 종료가 되지 않는 점이다.

(그런데 사이트에서 받은 예제 소스에서도 System.exit(0);을 사용하여 종료시킨다.)

왜그러지??ㅡㅅㅡ; 답을 아시는 분이 있음 나도좀 알려줘요~ㅋㄷ

[ 소스 코드 보기 ]

package util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

/**
 * 서버와 연결하여 파일을 업로드하고, 다운로드한다.
 *
 * @author haneulnoon
 * @since 2009-09-10
 *
 */
public class SFTPUtil{
    private Session session = null;

    private Channel channel = null;

    private ChannelSftp channelSftp = null;

    /**
     * 서버와 연결에 필요한 값들을 가져와 초기화 시킴
     *
     * @param host
     *            서버 주소
     * @param userName
     *            접속에 사용될 아이디
     * @param password
     *            비밀번호
     * @param port
     *            포트번호
     */
    public void init(String host, String userName, String password, int port) {
        JSch jsch = new JSch();
        try {
            session = jsch.getSession(userName, host, port);
            session.setPassword(password);

            java.util.Properties config = new java.util.Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();

            channel = session.openChannel("sftp");
            channel.connect();
        } catch (JSchException e) {
            e.printStackTrace();
        }

        channelSftp = (ChannelSftp) channel;

    }

    /**
     * 하나의 파일을 업로드 한다.
     *
     * @param dir
     *            저장시킬 주소(서버)
     * @param file
     *            저장할 파일
     */
    public void upload(String dir, File file) {

        FileInputStream in = null;
        try {
            in = new FileInputStream(file);
            channelSftp.cd(dir);
            channelSftp.put(in, file.getName());
        } catch (SftpException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 하나의 파일을 다운로드 한다.
     *
     * @param dir
     *            저장할 경로(서버)
     * @param downloadFileName
     *            다운로드할 파일
     * @param path
     *            저장될 공간
     */
    public void download(String dir, String downloadFileName, String path) {
        InputStream in = null;
        FileOutputStream out = null;
        try {
            channelSftp.cd(dir);
            in = channelSftp.get(downloadFileName);
        } catch (SftpException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            out = new FileOutputStream(new File(path));
            int i;

            while ((i = in.read()) != -1) {
                out.write(i);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                out.close();
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    /**
     * 서버와의 연결을 끊는다.
     */
    public void disconnection() {
        channelSftp.quit();

    }
}


[ 사용 예제 보기 ]

public static void main(String args[]) {

        String host = "sftp주소";
        int port = 포트번호;
        String userName = "아이디";
        String password = "비밀번호";
        String dir = "/폴더명/"; //접근할 폴더가 위치할 경로
        String file = "f:\\test.txt(업로드시킬 파일)";

        UsingFTP util = new SFTPUtil();
        util.init(host, userName, password, port);
        util.upload(dir, new File(file));

String fileName="다운로드 받을 파일명"; //ex. "test.txt"
String saveDir="저장할 위치"//ex. "f:\\test3.txt"

        util.download(dir, fileName, saveDir);

        util.disconnection();
        System.exit(0);
    }

 

출처 : http://haneulnoon.tistory.com/55

Posted by 아로나
JAVA & Open Framework2013. 5. 10. 10:39

Spring 3.0부터는 Quartz가 없이도 실행 스케쥴 설정이 가능합니다. 설정과 테스트 방법을 정리했습니다.

 

@Schedule 를 써서 크론 표현식 설정

  실행을 하고 싶은 메소드를 @Component, @Schedule annotaion을 통해 지정을 합니다.


@Component
public class BaseballScheduledJobLauncher extends JobLaunchSupport {

.....

    @Scheduled(cron="45 * * * * MON-FRI")
    public void baseballJob() {
        JobParameters params = createTimeParameter();
        run("baseballJob", params);
    }

   
    @Scheduled(cron="45 10 5 * * MON-FRI")
    public void baseballExportJob() {
        JobParameters params = createTimeParameter();
        run("baseballExportJob", params);
    }

}


 java 파일에 설정된 Annotation을 인식하기 위해서 Application context의 xml파일에 component-scan과 annotation으로 schedule을 설정하겠다는 선언을 추가합니다.  그리고 schedule을 실행할 thread pool의 크기도 지정합니다.


    <context:component-scan base-package="edu.batch.baseball.schedule"/>
    <task:scheduler id="myScheduler" pool-size="10"/>
    <task:annotation-driven scheduler="myScheduler"/>


 'task'와 'component'의 namespace가 xml에 추가되어 있어야 합니다.

테스트 코드

 테스트 코드를 단순하게 만들기 위해서 크론표현식을 추출하고 검사하는 코드는 SpringCronE-pressionTestUtils클래스로 분리했습니다.

 

package edu.batch.baseball.schedule;

import static edu.batch.support.launch.SpringCronE-pressionTestUtils.*;

import java.util.Arrays;
import java.util.List;

import org.junit.Test;

import edu.batch.baseball.schedule.BaseballScheduledJobLauncher;

public class BaseballScheduledJobLauncherTest {

    private static final String DATE_PATTERN = "yyyy/MM/dd hh:mm:ss";

    @Test
    public void testBaseballJobSchedule() {
        String initialTime = "2010/09/01 09:00:00";
        List<String> expectedTimeList = Arrays.asList(
                "2010/09/01 09:00:45",
                "2010/09/01 09:01:45",
                "2010/09/01 09:02:45");
        String cronE-pression = getCronE-pressionOfMethod(BaseballScheduledJobLauncher.class, "baseballJob");
        assertSchedule(cronE-pression, initialTime, expectedTimeList,DATE_PATTERN);
    }
}


 

 SpringCronE-pressionTestUtils

첨부파일 : SpringCronE-pressionTestUtils.java

 

package edu.batch.support.launch;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import java.lang.reflect.Method;
import java.text.ParseException;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.SimpleTriggerContext;

public class SpringCronE-pressionTestUtils {

 public static String getCronE-pressionOfMethod(Class<?> targetClass,
   String methodName)  {
  Method scheduledMethod;
  try {
   scheduledMethod = targetClass.getDeclaredMethod(methodName,
     new Class[] {});
  } catch (SecurityException e) {
   throw new IllegalArgumentException("cannot access the method : " + methodName, e);
  } catch (NoSuchMethodException e) {
   throw new IllegalArgumentException(e);
  }
  Scheduled scheduleInfo = scheduledMethod.getAnnotation(Scheduled.class);
  String cronE-pression = scheduleInfo.cron();
  return cronE-pression;
 }

 

public static void assertSchedule(String cronE-pression, String initialTime,
   List<String> expectedTimeList, String datePattern) {
  CronTrigger trigger = new CronTrigger(cronE-pression);
  Date startTime;
  try {
   startTime = DateUtils.parseDate(initialTime,
     new String[] { datePattern });
  } catch (ParseException e) {
   throw new IllegalArgumentException("wrong date format", e);
  }
  SimpleTriggerContext context = new SimpleTriggerContext();
  context.update(startTime, startTime, startTime);

  for (String exptectedTime : expectedTimeList) {
   Date nextExecutionTime = trigger.nextExecutionTime(context);
   String actualTime = DateFormatUtils.format(nextExecutionTime,
     datePattern);
   assertThat("executed on expected time", actualTime,
     is(exptectedTime));
   context.update(nextExecutionTime, nextExecutionTime,
     nextExecutionTime);
  }
 }

}

 

 

출처 : http://blog.benelog.net/2802946

Posted by 아로나
JAVA & Open Framework2013. 5. 9. 18:54

org.mybatis.spring.SqlSessionTemplate

- selectOne

  • 쿼리의 결과가 없으면 null을 반환한다. 또한, 쿼리의 결과로 레코드가 하나만 나와야 한다.
  • DB에 하나의 레코드만 있는 경우 사용. 그렇지 않으면 org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException 이 발생한다.

- selectList

  • 쿼리의 결과를 List<E>로 반환한다. 결과가 없으면, 빈 List를 반환한다.
  • selectList()가 null을 반환하지는 않는다.

 

출처 : http://deepblue28.tistory.com/entry/mybatis-selectOne-vs-selectList

Posted by 아로나
JAVA & Open Framework2013. 3. 1. 11:48

자바의 어노테이션(Annotation)


Java5부터 새로 도입된 어노테이션(Annotation) 기능에 대해서 알아보기로 하겠다.

즉 여러분이 자바5 이후의 버젼을 설치하였다면 이 기능을 사용하는데 아무런 문제가 없을 것이다.

필자가 처음에 받으라고 올린 자바 설치 프로그램은 자바6이므로 당근 어노테이션 사용가능하다.^^

잠시 들어가기 전에 Java5는 뭔지 아리쏭해하는 이들이 있을지도 모르겠다. 특히 오래전에 자바를

공부하다가 다시 공부하는 이들은 자바5는 뭐고 자바6는 뭔지 이게 완전히 다른건지 궁금해 하는

이들을 위해 필자가 잠시 정리를 하고 본 단원을 진행하겠다.

 

새로 자바를 공부하는 이들은 자바6가 요즘 나온 프로그램이구나라고 생각하면서 쓰겠지만 오래전에

 자바를 공부한 이들은 아마 버젼 1.2 아니면 1.3 그래도 최근이었으면 1.4 정도까지 하다가

그 뒤부터 잠시 손을 뗀 이들이 보통 혼란스러워한다. 자바가 새로운 기능과 문제점을 보완하고

업데이트해 오면서 줄곧 1.xx 형태로 해왔는데 메이저급 업데이트를 함에도 불구하고 거의 제품에

차이가 없다고 생각하는 이들이 많아 확연히 다르다는 것을 강조하기 위해 버젼을 Java5(=1.5)

그리고 우리가 지금 쓰고 있는 Java6(=1.6)로 표기하고 있다고 알고 있으면 된다. 한마디로 엄청

달라진것 같이 느껴지니 그런 의미에서는 확실히 성공한듯 하다.ㅎㅎ

 

자 이제 본격적으로 어노테이션에 대해서 설명해 보겠다. 우리말로 해석하자면 주석이라는 뜻인데

이게 사실 우리가 여태까지 설명을 쓸때 주석(//)을 썼지만 이런 주석이랑 같은 의미로 생각하면

내용을 파악하기 힘들다. 그래서 영어 그대로 어노테이션이라고 표기하니 어노테이션에 무슨 기능이

있는지 여러분이 이번 시간을 통해 알아놓고 필요할때 써먹을수 있으면 그걸로 족하니 안심하기

바란다. 언제나 그렇듯 어노테이션에 대해서 정말 모르겠다하는 이들은 오늘 강좌를 들으면 고작

이런거였어?라는 말이 나오도록 만들어 줄것이니 본 강좌에 집중하기 바란다.^^

 

어노테이션에서 여러분이 쓸수 있는 기능이 다양하지만 그중에서도 @Deprecated@Override가 아주 유용하게 써먹을수 있는 어노테이션이므로 본 단원에서는 이 두가지에 대해서 배워보기로 하겠다. 일단 어노테이션을 쓰려면 자바코드로 어떻게 써야하는지 알아보자.

 

@어노테이션명

위와 같이 AT으로 불리는 골뱅이 마크를 쓰고 싶은 어노테이션 이름앞에다가 붙이면 작동한다.

어노테이션은 자바 프로그램에 영향을 주는 것이 아니라 컴파일할때 개발자에게 주석같이 설명처럼

알려주는 형태를 말한다. 어노테이션은 클래스나 필드 혹은 메소드 앞에 붙여서 사용하며 끝에

세미콜론(;)은 붙이지 않는다. 예제를 보면서 필자의 설명을 들으면 저절로 이해가 될것이니 감이

오지 않는 이들은 아래 예제를 보면서 따라오기 바란다.^^

 

 

 

 


강이의 자바강좌
클래스 A의 one 메소드

 

위의 예제를 실행하면 위와 같은 결과가 나온다. 예제가 간단하니 이해못할 이들은 없을 것이라 본다.

첫번째로 @Deprecated 어노테이션에 대해서 설명하겠다. one( )이라는 메소드 앞에 붙였으니 one( )

메소드를 Deprecated로 어노테이션 처리하라는 뜻이다. deprecated는 사전적 의미로 비난하다

반대하다라는 뜻이 있지만 프로그래밍 용어로는 사용을 피해달라 사용을 자제해달라는 의미로

쓰인다. 영어만 해석했는데도 이해가 팍팍되고 있으리라 생각한다.ㅎㅎ

즉 기존에 있는 one( ) 메소드를 쓰지말고 필요하면 다른걸로 만들어서 써달라는 뜻으로 해석하면

된다. 위의 예제는 컴파일이 되어 실행이 가능하지만 컴파일시 이런 메세지를 준다.

 

Note: C:\Test63.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

 

이 메세지는 @Deprecated라는 어노테이션을 써서 컴파일시 이렇게 알려주는 것이다.

그럼 이런 기능은 언제 쓰라고 만든 것일까? 이해하기 쉽도록 필자가 예를 들어보겠다.

여러분이 프로그램을 만들었는데 지금은 이 기능을 지원하지만 다음 버젼업된 프로그램에서는

이런 기능을 없애려 한다던지 다음부터는 더 향상된 다른 기능으로 대체하려고 계획하고 있는데

기존에 지원하던 기능을 계속해서 쓴다면 나중에 여러분이 계획했던 프로그램을 만들때 많은 비용과 시간에 차질이 생길수 밖에 없을 것이다. 이런 것을 방지하고자 만든 기능이다.

 

그럼 다음으로 클래스 B에서 @Override라는 어노테이션을 two( ) 메소드 앞에 썼는데 이건 무엇을

의미하는 것일까? 일단 override라는 뜻은 기억하는가? 자바에서 상속시 오버라이드는 리턴타입이니

매개변수니 메소드명이니 이런거 모두 같고 내용이 다른 것을 말한다고 이미 예전 강좌에서 배웠는데

기억하나 모르겠다.ㅎㅎ

 

위의 예제에서는 @Override를 썼지만 two( ) 메소드의 오버라이드를 정확히 구현하였으니 문제가

없어 컴파일시 아무런 에러도 나지 않고 프로그램이 실행된다. 하지만 여러분이 void two( ) 메소드

대신에 void twp( ) 메소드로 이름을 잘못 썼다던지 void two(int a) 메소드로 매개변수를 넣었다던지

하면 컴파일시 에러가 난다. 직접 이런 식으로 고쳐서 실행해 보기 바란다. 에러가 나서 실행이 되지

않을 것이다.

정말 대단하지 않은가? 만약 two( ) 메소드앞에 @Override 어노테이션이 없었다면 철자가 틀리든

매개변수가 있든 상관하지 않고 에러없이 실행된다. 상속받았다고 해서 오버라이드만 하라는 법은

없으니까 말이다. twp( )라고 썼으면 자바는 메소드를 새롭게 인식해서 실행할 것이고 two(int a)도

자바의 다형성 중에 하나인 오버로딩한 형태로 인식하므로 전혀 문제될것이 없다. 이런 기능이

굳이 필요할까? 라고 반문하는 이가 있을지 모르겠다.

 

지금은 예제가 짧아서 별것 아닌듯이 느낄지 모르겠으나 프로그램이 좀 복잡하고 길면 오버라이드

하려고 계획하고 프로그램을 짰어도 오타가 있을시 이를 찾아내는데 상당히 애를 먹게된다.

컴파일하고 실행하는데는 아무런 문제가 없을테니까 말이다. 다만 여러분이 생각한데로 똑같이

프로그램을 만들지 못한 것이니 프로그램 안에 버그(?)가 도사리고 있는게 문제가 될것이다.ㅎㅎ

 

사실 그리 난해한 내용은 아니므로 정확한 의미만 파악한다면 어노테이션을 자유자재로 여러분이

만드는 프로그램에서 써먹을수 있을 것이다. 특히 어노테이션의 @Override 기능은 오버라이드할때

될수 있으면 쓰는 습관을 갖기 바란다. 여러분이 본의아니게 조그마한 실수를 해도 자바 컴파일러가

알아서 여러분을 구원(?)해 줄테니까 말이다.^^

 

 

출처 : http://alecture.blogspot.kr/2011/06/annotation.html

Posted by 아로나
JAVA & Open Framework2013. 2. 20. 01:03

Tomcat 에러 페이지 web.xml에 설정하기

 

web.xml에 에러 코드 유형별로 에러 페이지 설정 방법

<web-app>
<error-page>
<error-code>404</error-code>
<location>/404error.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500error.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/exception_error.jsp</location>
</error-page>
</web-app>

100 : Continue
101 : Switching protocols
200 : OK, 에러없이 전송 성공
201 : Created, POST 명령 실행 및 성공
202 : Accepted, 서버가 클라이언트 명령을 받음
203 : Non-authoritative information, 서버가 클라이언트 요구 중 일부 만 전송
204 : No content, 클라언트 요구을 처리했으나 전송할 데이터가 없음
205 : Reset content
206 : Partial content
300 : Multiple choices, 최근에 옮겨진 데이터를 요청
301 : Moved permanently, 요구한 데이터를 변경된 임시 URL에서 찾았음
302 : Moved temporarily, 요구한 데이터가 변경된 URL에 있음을 명시
303 : See other, 요구한 데이터를 변경하지 않았기 때문에 문제가 있음
304 : Not modified
305 : Use proxy
400 : Bad request, 클라이언트의 잘못된 요청으로 처리할 수 없음
401 : Unauthorized, 클라이언트의 인증 실패
402 : Payment required, 예약됨
403 : Forbidden, 접근이 거부된 문서를 요청함
404 : Not found, 문서를 찾을 수 없음

405 : Method not allowed, 리소스를 허용안함
406 : Not acceptable, 허용할 수 없음
407 : Proxy authentication required, 프록시 인증 필요
408 : Request timeout, 요청시간이 지남
409 : Conflict
410 : Gone, 영구적으로 사용할 수 없음
411 : Length required
412 : Precondition failed, 전체조건 실패
413 : Request entity too large,
414 : Request-URI too long, URL이 너무 김
415 : Unsupported media type
500 : Internal server error, 내부서버 오류(잘못된 스크립트 실행시)
501 : Not implemented, 클라이언트에서 서버가 수행할 수 없는 행동을 요구함
502 : Bad gateway, 서버의 과부하 상태
503 : Service unavailable, 외부 서비스가 죽었거나 현재 멈춤 상태
504 : Gateway timeout
505 : HTTP version not supported

ex)

<error-page>
<error-code>401</error-code>
<location>/WEB-INF/error/errorPage.jsp</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/WEB-INF/
error/errorPage.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/
error/errorPage.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/WEB-INF/
error/errorPage.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/WEB-INF/
error/errorPage.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/WEB-INF/
error/errorPage.jsp</location>
</error-page>

체크사항

: 에러를 출력하는 페이지가 적어도 512kbyte 이상의 내용을 담고 있어야 적용된다.!!! 꼭 확인하기 바람!!! 페이지가 정상 출력되지 않습니다.


출처 : http://blog.daum.net/evasuri/15998861

Posted by 아로나
JAVA & Open Framework2013. 2. 14. 00:13

저번시간에

springsource를 다운받아서 설치하고

톰켓을 설정하고 프로젝트를 생성하는데까지 진도를 나갔었습니다.

오늘은 저번에 생성한 프로젝트를 실행해보도록 하겠습니다.

그에 앞서

저번시간에 언급했던 .m2.zip 파일을 기억하시죠?

제가 드린다고 약속했었는데 이놈이 뭔지를 알아야 겠죠?

아시는 분은 아시겠지만 이놈이 바로 그유명한 마분 Maven이라고 하는 놈이었습니다.

이놈이 뭐하는 놈이냐 간단하게 설명하면

보통 자바에서 필요한 라이브러리를 다운받아서 lib 폴더에 넣죠?

근데 이 마분이란 놈은 다운받을 필요없이 pom.xml이라는 파일에 그 라이브러리를 써넣기만 하면

자동으로 마분 서버에 요청을 해서 라이브러리를 서버 혹은 내 로컬 개발 PC로 다운로드를 받습니다.

그 경로가 바로 첫시간에 말했던

c:\Document and Setting\{윈도우 계정명}\.m2

라는 폴더입니다. 보통 말하는 내문서죠.

이놈이 있어서 참 편리한것이 이 라이브러리를 쓰는놈인지 안쓰는놈인지 따로 관리할 필요가 없이

자동으로 쓰는놈은 보관하고 아닌놈은 삭제해준다는 겁니다.

아주 간단하게 설명한 거구요.

마분의 뛰어난 능력을 더 알고 싶으신 분은 일단 다른곳에서 검색해서 보시구요. 저는 간단하게 넘어가겠습니다.

마분이 정말 그런일을 하는지 의심할 분들을 위해서 간단하게 테스트를 해볼까합니다.

먼저 스프링소스툴을 여시고 저번에 생성한 프로젝트를 펼치면 아래 보시는 바와 같이 pom.xml 이라는 파일을 열고

열려진 파일에서 제일 오른쪽에 pom.xml 탭을 클릭하여 소스를 봅니다.


왼쪽 Package Explorer 에 Maven Dependencies 을 열고

오른쪽 pom.xml 소스를 보면 120번째줄에 dependency로 시작되는 녀석이 있습니다. junit이란 놈이군요.

이놈의 실제 jar파일이 왼쪽에 보이죠? junit-4.7.jar 파일이라고...

그렇다면 pom.xml파일에서 junit의 dependency부분을 삭제해 보게습니다.


삭제를 했더니? 왼쪽에 jar파일이 사라진것을 볼수 있습니다.

다시 집어 넣으면? 다시 생기겠죠?

이 처럼 마분 Maven 이란 놈은 일일이 사이트를 찾아다니며 라이브러리를 다운 받을 필요없이

자동으로 라이브러리를 관리해주는 고마운 녀석입니다.

하지만 이놈이 그렇게 완벽한 녀석이 아닙니다.

하다보면 느끼겠지만 이 마분 디펜던시 서버가 안정적이지가 못해서

다운을 받아도 오류가 많이 발생을 하고 다운이 제대로 안된다던지 이런 부분이 있습니다.

그래서 저번에 제가 .m2.zip 파일을 따로 드린다고 한겁니다. 제가 필요한 라이브러리들을 모두 넣어놨기 때문입니다.

자동으로 다운로드 받는 기능은 안쓰더라도 일단 라이브러리를 관래해주는것만으로 만족하면서 마분 Maven 이란 놈을 쓰시기 바랍니다.

.m2.zip파일은 첨부하겠습니다. (모두 18개 파일로 다음 강의에 이어서 올리겠습니다. 30MB제한.)

내문서에 .m2 폴더에 덮어쓰시면 되겠습니다.

출처 : http://blog.naver.com/jazz1234k/40121366551

Posted by 아로나
JAVA & Open Framework2013. 2. 14. 00:11

maven 설치

-- 메이븐 설치

1. 메이븐 다운로드
http://maven.apache.org/download.html 이동
현제 3.0.3 버전이 최신임
apache-maven-3.0.3-bin.zip 다운 - http://ftp.daum.net/apache//maven/binaries/apache-maven-3.0.3-bin.zip


2.원하는 디렉터리에 압축을 풀기 및 설정파일 변경
설치된 Maven의 경로로 이동하여 conf 폴더 아래 settiongs.xml 파일을 열고,
아래 localRepository 경로를 새롭게 지정합니다
예)<localRepository>C:\maven\repository</localRepository>


3. 환경변수 등록
MAVEN_HOME=C:\maven\apache-maven-3.0.3
path=%MAVEN_HOME%\bin


4. cmd프롬프트에서 mvn --version
Apache Maven 3.0.3 (r1075438; 2011-03-01 02:31:09+0900)
Maven home: C:\maven\apache-maven-3.0.3\bin\..
Java version: 1.6.0_17, vendor: Sun Microsystems Inc.
Java home: C:\Program Files\Java\jdk1.6.0_17\jre
Default locale: ko_KR, platform encoding: MS949
OS name: "windows xp", version: "5.1", arch: "x86", family: "windows"



-- m2eclipse 플러그인을 이용한 이클립스(갈릴레오) 연동

이클립스 상단메뉴의 Help>Install New Softwares...를 선택

1.Add 버튼을 눌러 m2eclipse url 입력하고 설치 진행한다.
http://m2eclipse.sonatype.org/sites/m2e

설치후 재시작


2.m2eclipse Extras 플러그인을 설치한다.
http://m2eclipse.sonatype.org/sites/m2e-extras

인스톨 항목이나오면 "Maven Integration for Eclipse Extras"와
"Maven Integration for Eclipse WTP를 선택하고 설치하면 됩니다.

설치후 재시작

3. 이클립스 메이븐 설정
Preferences - Maven - User Settings
C:\maven\apache-maven-3.0.3\conf\settings.xml

출처 : http://blog.naver.com/PostView.nhn?blogId=seban21&logNo=70110678014

Posted by 아로나
JAVA & Open Framework2013. 2. 14. 00:09

Maven 은 간단하게 말하자면 Project Management Framework 라고 할 수 있다...

POM(Project Management Object)이란 녀석을 이용하여 빌드에서부터 시작해서 의존성 관리 및 배포까지 모든 것을 관리할 수 있다..

Maven을 이용하면 Coherence, Reusability, Agility, Maintainability 등을 제공한다고 한다...

아직 잘 모르면서 그냥 쓰고 있기 때문에 저런 장점을 제공하는지는 잘 모르겠다... -_-;;

대체 Maven이 어떤 철학을 가지고 있길래 저런 것들을 제공하는지 한 번 알아보자...


1. Convention Over Configuration

관념이 설정보다 우선한다는 말인데 이게 대체 무슨 말인가...

Ruby on Rails 에서 유명하게 된 말이라고 하는데 간단하게 말하자면 디폴트로 뭔가 정해 놓고 그건 신경쓰지 말고 쓰자는 말이다..

물론 설정을 통해 자신이 원하는대로 변경할 수 있지만 신경 쓸 필요 없는 걸 구지 신경쓰지 말잔 말이다..

Maven 에서는 다음과 같은 3가지를 제공하면서 위의 철학을 실현하고 있다..


Standard Directory Layout

말 그대로 디렉토리 구조를 미리 정해 놓은 것이다. 소스파일, 설정파일, 빌드파일, 도큐먼트 등의 위치를 정해놓고 그대로 쓰자는 얘기다.


Separation Of Concerns

하나의 프로젝트에서는 하나의 결과물을 가지도록 하는 것이다. 이를 통해 재사용성을 증가시킬 수 있다. 이는 바로 다음에 살펴볼 빌드 로직을 재사용하는 것에서 쉽게 확인할 수 있다.


Standard Naming Conventions

디렉토리와 결과물의 이름 규칙도 정해져 있다. 예를 들어 commons-loggin-1.2.jar 란 파일이 있다고 하면 commons logging의 버전 1.2를 사용한다는 것을 쉽게 알 수 있다. 자바의 get/set 메소드도 하나의 예라고 할 수 있다.


2. Reuse of Build Logic


Maven에서는 빌드를 위해 필요한 로직을 플러그인이란 이름의 모듈로 구현해 놓았다. 이런 플러그인에는 컴파일, 테스트, 패키징, 문서화등등 수 많은 플러그인들이 존재한다. 여기서 아주 중요한 사실은 Maven은 이와 같은 플러그인들의 실행 결과를 모아서 최종 결과를 낸다는 것이다. 이런 플러그인들을 Maven의 설정 파일인 POM(Project Object Model)에 설정하게 되고 Build Life Cycle에 따라 플러그인들이 순서대로 실행되어 최종 결과물을 출력하게 된다.


3. Declarative Execution


위에서 잠깐 알아보았듯이 Maven에서는 POM(Project Object Model)에 모든 설정을 하게 된다. 그러면 POM이 무엇이고 잠깐 살펴본 Build Life Cycle이 무엇인지 알아보도록 하자.


POM(Project Object Model)


Maven에서는 하나의 프로젝트에 하나의 POM을 가진다. POM은 XML 형태로 구성되어 있고 아래는 아주 간단한 예제이다.


<project>

<modelVersion>4.0.0</modelVersion>

<groupId>com.mycompany.app</groupId>

<artifactId>my-app</artifactId>

<packaging>jar</packaging>

<version>1.0-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>3.8.1</version>

<scope>test</scope>

</dependency>

</dependencies>

</project>


위의 15줄에 불과한 POM을 사용하면 컴파일, 테스트 및 문서화까지도 가능하다. 어떻게 이런 일이 가능할까... 왜냐하면 Maven은 묵시적으로 Super POM을 사용하기 때문이다. 자바의 Object 클래스와 같은 역할을 한다고 보면 된다. 그렇다면 각각의 속성에 대해 간단하게 알아보도록 하자.


<project> - pom.xml 파일의 ROOT. 무조건 이 속성으로 시작해야 한다.

<modelVersion> - 현재 POM이 사용하고 있는 버전을 나타낸다. 이 버전은 자기 마음대로 정해주면 되는데 적당히 잘 해주도록 하자.

<groupId> - 프로젝트를 만든 조직이나 그룹의 유일한 식별자이다. 보통 자바 패키지 만드는 형식으로 지정해주면 된다. 물론 안 그렇게 해도 된다.

<artifactId> - 프로젝트에서 생성하는 결과물의 이름에 사용되는 속성이다. Maven에서는 <artifactId>-<version>.<extension> 같은 형식의 파일 이름으로 패키징 해준다. 위의 예제는 my-app-1.0-SNAPSHOT.jar 와 같은 형태로 만들어지게 된다.

<packaging> - 패키징 할 파일 형식을 지정한다. (JAR, WAR, EAR 등등) 뿐만 아니라 빌드 프로세스의 부분으로 사용하기 위한 특정 Life Cycle을 나타내기도 한다. 그냥 Build Life Cycle을 커스터마이징 할 때 사용된다고 알아두면 된다고 한다. -_-;;

<version> - 프로젝트의 버전을 표시한다. 위에 SNAPSHOT이라고 붙은 것은 개발 상태일 때 붙인다고 한다.

<name> - 프로젝트의 이름

<url> - 프로젝트 사이트

<description> - 프로젝트 설명


다른 자세한 내용은 http://maven.apache.org/maven-model/maven.html 여기에 가면 확인할 수 있다. 일단 이정도 까지만 살펴보고 나머지는 뒤에 나올 것 같으니 일단 넘어가도록 하자...


Build Life Cycle


그렇다면 계속 말이 나오던 Build Life Cycle에 대해서 알아보자.

일반적으로 소프트웨어 프로젝트는 컴파일, 테스트, 패키징, 인스톨과 같은 전형적인 단계를 갖는다.

Maven에서는 이러한 단계들을 Build Life Cycle이라고 부른다.

Maven의 Build Life Cycle은 크게 compile, test, package, install 등과 같은 goal 들로 구성된다.

특정한 goal 을 실행할 때 하위 레벨에 실행해야 할 goal 들이 있다면 하위 레벨의 goal 들이 먼저 실행된다.

예를 들어 클래스들을 컴파일하기 위해 compile goal 을 실행하게 되면 하위 레벨의 goal 들인 validate, initialize, generate-sources, process-sources, generate-resources 를 실행한 후에 complie goal 을 수행하게 된다.

이처럼 Build Life Cycle은 많은 단계들로 구성되어 있고 또한 이를 확장할 수도 있다.

Build Life Cycle의 하나의 단계는 하나의 플러그인으로 만들어지고 해당 플러그인은 해당 goal 을 실행하게 된다.

(실제로 compile goal은 compiler 플러그인이 담당하고 있고 test goal은 surefire 플러그인이 담당한다.)


4. Coherent Organization of Dependencies


이번에는 Maven에서 의존성 관리를 어떻게 해주는지 살펴보도록 하자. 아까 살펴본 POM 예제를 다시 살펴보도록 하자.


<project>

<modelVersion>4.0.0</modelVersion>

<groupId>com.mycompany.app</groupId>

<artifactId>my-app</artifactId>

<packaging>jar</packaging>

<version>1.0-SNAPSHOT</version>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>3.8.1</version>

<scope>test</scope>

</dependency>

</dependencies>

</project>


딱 보면 알 수 있듯이 junit 란 녀석에게 의존성을 갖는 것을 알 수 있다.

의존성이란 Repository 에 존재하는 특정 라이브러리 파일에 대한 참조를 말한다.

Maven에서는 이런 의존성을 해결하기 위해 어떤 라이브러리 파일을 어떤 Repository를 살펴봐야 하는지 정보가 필요하다.

이런 것들은 groupId, artifactId, version 속성을 사용해서 식별하게 된다.

라이브러리가 물리적으로 어디에 존재하는지 또한 파일을 다운로드 받을 필요도 없다.

그저 위에서 처럼 설정만 하면 junit (groupId) 에서 제공하는 junit (artifactId) 의 3.8.1 (version) 에 의존성이 있다고 명시만 하면 된다..

그렇게 하면 Maven에서 이용 가능한 모든 Remote Repository를 뒤져서 사용자의 Local Repository로 복사해준다.

Maven에는 방금 살펴본대로 2가지 Repository가 존재한다.

Remove Repository는 말 그대로 해당 라이브러리를 다운로드 받을 수 있는 곳을 말한다.

Local Repository는 Maven을 처음 설치하고 실행하게 되면 모든 의존성이 있는 라이브러리를 모아 놓는 곳이다.

기본적으로 사용자의 홈 디렉토리에 ~/.m2/repository 요런 식으로 생성되게 된다.

위의 의존성을 해결하게 되면 사용자 홈 디렉토리에 다음과 같은 형식으로 해당 라이브러리 파일이 저장되게 된다.


repository

└ groupId

└ artifactId

└ version

├ artifactId-version.jar

├ artifactId-version.jar.sha1

├ artifactId-version.pom

└ artifactId-version.pom.sha1


만약 groupId가 org.apache.maven 이라면 자바의 패키지 생성과 같은 방식으로 org - apache- maven 디렉토리가 생성되고 그 아래에 나머지 구조대로 생성되게 된다.

Maven은 이처럼 의존성을 해결할 때 먼저 Local Repository에 /repository/groupId/artifactId/version/artifactId-version.jar 파일이 존재하는지 확인한다.

만약 존재하지 않는다면 Remote Repository에서 다운로드 받아 Local Repository의 해당 위치에 복사하게 된다.

Maven은 Remote Repository로 http://www.ibiblio.org/maven2 를 기본으로 사용한다.

또한 Maven은 여러 개의 Remote Repository를 가질 수 있는데 POM에 정의된 순서대로 찾아가게 된다.

이렇게 Local Repository를 사용하면 여러 개의 프로젝트에서 같은 파일을 사용해도 하나의 파일만 존재하면 된다.

또한 버전별로 관리할 수 있으므로 쓸데 없는 라이브러리를 프로젝트에 추가하지 않을 수 있게 된다.


휴.. 이렇게 대충 Maven이 어떤 것이고 어떤 구조를 가지고 있으며 무슨 생각으로 이렇게 만들었는지 살펴보았다...

다음번에는 실제로 Maven을 사용해보도록 하자!!

 

출처 : http://nadostar.egloos.com/176414

Posted by 아로나
JAVA & Open Framework2013. 2. 12. 15:46

이클립스에서 웹개발을 위한 tomcat의 시작, 종료를 할 수 있고 이클립스 console에서 log를 볼 수 있는 Tomcat Plugin을 설치해보겠습니다.

Tomcat을 사용하는것은 크게 3가지로 나눌 수 있습니다

1. Tomcat 직접 시작

2. 이클립스의 Run Server기능을 이용하여 Tomcat 시작

3. Tomcat Plugin으로 Tomcat 시작

위의 세가지 방식중 이 포스팅에서는 3번을 알아 볼 것이며, 이런 저런 방법으로 일해보면서 Tomcat Plugin인을 이용한 방법이 가장 편했다고 생각합니다.

1번은 log를 보기가 힘들고, 2번은 이런저런 알수없는 오류들을 겪었습니다.


------------설치------------

1. http://www.eclipsetotale.com/tomcatPlugin.html#A3 접속

2. tomcatPluginV33.zip 를 다운로드 (2012년 4월2일 기준 최신버전은 3.3)

(Tomcat Plugin 3.3버전에서는 이클립스 3.6까지만 지원한다고 나와있지만 이클립스 3.7.2버전에서도 정상 작동을 확인 했습니다.)

3. 압축풀면 com.sysdeo.eclipse.tomcat_3.3.0 라는 폴더가 나오는데 이것을 이클립스의 plugins폴더 안에 복사합니다, Tomcat Plugin은 별도의 install없이 이클립스 내부에 플러그인 폴더를 복사하는것으로 설치가 됩니다.

4. 이클립스를 재시작하면 아래와같이 Tomcat 이미지가 생기고, 좌로부터 시작, 종료, 재시작 입니다.


5. 이클립스의 window -> preferences -> Tomcat 항목에서 Tomcat version은 6을 선택하고, Tomcat home은 톰캣이 있는 디렉터리를 지정하는데 bin, conf, work와 같은 폴더가있는 바로 상위 폴더를 지정해야 합니다.


 

6. 이제 Tomcat startup 아이콘을 클릭하면 console창에 로그들이 지나가고 정보: Server startup in ~~~ ms 로그가 나오면 정상.

'JAVA & Open Framework' 카테고리의 다른 글

[펌] Maven 설치하기  (0) 2013.02.14
[펌] Maven 이란 무엇인가.  (0) 2013.02.14
[펌] 이클립스 SVN 플러그인 설치  (0) 2013.02.12
[펌] 자바에서 URL 호출하기2  (0) 2013.01.30
[펌]Java에서 URL 호출하기1  (0) 2013.01.23
Posted by 아로나
JAVA & Open Framework2013. 2. 12. 15:43

예전에는 이클립스의 플러그인을 설치하기위해서 plugins, features 폴더에 파일을 직접 복사하거나

이클립스 메뉴의 Help -> install new Software를 이용해서 update site를 수동입력하여 update받아야 했지만

이클립스 3.6부터는 Help메뉴에 Eclipse Marketplace가 생겨서 마치 안드로이드 앱 다운받는것처럼 쉽게 단어 검색으로 이클립스 플러그인을 다운 받을 수 있게 되었습니다.

Eclipse Marketplace 사용법 및 SVN Plugin 검색과 설치를 포스팅 설명하겠습니다.

포스팅에 사용된 이클립스는 3.7.2 버전(Eclipse IDE for Java EE Developers)입니다.


참고사항 - 아래의 3,4번 과정에서 오랜시간이 걸릴 수 있습니다, 매번 그런것은 아니겠지만 필자의 경우 1시간 가량 소모되었습니다.


1. 이클립스 메뉴의 Help -> Eclipse Marketplace클릭하고 나오는 팝업에서 Find에 svn입력후 Go버튼 클릭


2. 검색후 나오는 화면에서 Subversive - SVN Team Provider 의 Install 클릭


3. SVN Plugin 다운


4. SVN Plugin 설치


5. 이클립스 재시작


 


6. 마지막으로 svn connector를 설치해야하는데

이클립스 재시작후 자동으로 뜨는 팝업에서 아래와같은 항목 체크후 진행 (Install Connectors팝업이 뜨지않는다면 다시한번 이클립스 재시작, 시간이 지나면서 버전업이 될 수 있는데 모든버전을 다 체크해도 된다.)


 


출처 : http://kdarkdev.tistory.com/36

Posted by 아로나