java.net.SocketException: Connection reset 발생시 처리 방법

Published on: 2013. 11. 14. 14:13 by louis.dev
commons-net을 이용하여  ftp로 업로드 하는 중
java.net.SocketException: Connection reset
에러가 발생하면서 업로드에 실패했다. 자세히 로그를 살펴보니 FTP에 로그인까지 잘되었지만 파일업로드만 진행되지 않는 문제였다. 그래서 찾아보니 위 문제는 windows machine에서 java 7을 사용할때 발생되는 버그로 아래와 같이 해결할수 있다.
  1. 시작 -> cmd을 실행한다.
  2. 콘솔창에 netsh advfirewall set global StatefulFTP disable 을 입력한다.
이렇게 하면 간단하게 해결할 수 있다.

[Spring Framework] @RequestParam을 사용하여 List형 데이터 받을때 주의점

Published on: 2013. 11. 14. 14:11 by louis.dev
html페이지로부터 전달되는 파라미터를 받아올때 @RequestParam 어노테이션을 사용해서 httpServletRequest 를 사용하지 않고도 데이터를 전달 받을 수 있다. 만약 페이지에서 name 속성을 동일하게 주어지면 @RequestParam을 이용해서 List형태로 받는것도 가능하다.
<form action="/submit" method="get">
	name=value1 <input type="text" name="value1" />
	name=value1 <input type="text" name="value1" />
	<input type="submit" value="submit" />
</form>
이렇게 textbox를 동일한 이름으로 submit을 하게 되면 파라미터는
value1=1111&value1=2222
처럼 동일한 파라미터 명을 가지게 되고 이 값을 스프링의 Controller에서 List형태로 받으려면
@RequestMapping("/submit")
public String submit(@RequestParam(value="value1", required=true) List<String> values) {
	System.out.println(values.size());  //2가 나오는것을 볼수 있다.
	return null;
}
처럼 사용할수 있다. 그런데 @RequestParam은 ,(comma)형태로 데이터를 보내게되도 ,(comma)를 구분자로하여 데이터를 쪼개서 List형태로 데이터를 변환한다.
//전달된 파라미터가 value1=111,222,333,444 형태라면
@RequestMapping("/submit")
public String submit(@RequestParam(value="value1", required=true) List<String> values) {
	for(String value : values) {
		System.out.println(value);    
	}
	//출력결과는 
	//111
	//222
	//333
	//444
	return null;
}
만약 html 뷰 페이지에서 다음과 같이 추가 버튼을 눌러 동적으로 입력 폼을 추가 하게되게끔 개발을 했다고 하면
<form action="/submit" method="get">
	name=value1 <input type="text" name="value1"/><button type="button" onclick="textbox추가 로직">추가</button>
	<input type="submit" value="submit" />
</form>
Controller에서는 몇개의 textbox가 추가가 될지 모르니 위와같이 @RequestParam을 이용해서 List형태로 받게 될것이다. 이때 textbox가 1개이고(추가버튼을 누르지 않고) 입력된 데이터가 ,(comma)로 구분되는 문자가 들어오게 된다면 우리는 의도했던것과는 다르게 사이즈가 1개이상인(콤마갯수 + 1개) List를 돌려받게 될것이다. 위와같은 문제가 발생될 소지가 있다면 어쩔수 없이 httpServletRequest의 getParameterValues 메소드를 사용하여 직접 받을 수 밖에 없으니 comma에 주의해서 @RequestParam 어노테이션을 사용하자.

[Maven] Dependency Scope의 종류

Published on: 2013. 11. 14. 14:10 by louis.dev
maven은 dependency 엘리먼트 하위의 scope 엘리먼트를 통해 포함하려는 라이브러리의 범위를 지정할 수 있다. Maven 3에서는 다음의 여섯가지 옵션을 지원하고 있다.
  • compile : 기본 scope이다. 만약 dependency에 아무것도 입력하지 않았다면 기본적으로 입력되는 scope이다. 이 옵션은 프로젝트의 모든 classpath에 추가된다(테스트 중이건 런타임 중이건 상관없이).
  • provided : 이 옵션은 compile과 매우 비슷하지만, 실행시 의존관계를 제공하는 JDK나 Web Container(tomcat 같은)에 대해서 적용된다.  예를 들어 Java Enterprise Edition Web application을 개발할때 Servlet API나 Java EE API들은 "provided" scope로 지정해야한다. 왜냐하면 Servlet API같은 경우는 Servlet Container 자체에서 지원해 주기 때문에(Tomcat 같은 경우는 ${tomcat home directory}/lib 디렉토리에 있는 Servlet 라이브러리를 사용) 컴파일시 또는 테스트시에는 필요하지만 실행시에는 필요하지 않기 때문이다.
  • runtime : 컴파일 시에는 필요하지 않지만 실행시에 사용되는 경우 사용한다. 이 옵션은 런타임, 테스트 시 classpath에 추가 되지만, 컴파일시에는 추가 되지 않는다.
  • test : 일반적인 경우에는 필요하지 않고 테스트시에만 필요한 경우 사용한다.
  • system : 해당 jar를 포함해야 한다고 명시적으로 입력 하는 것을 제외하고는 provided와 유사하다. 선언된 artifact들은 항상 사용가능하지만 Maven의 central repository에서 찾아서 가져오는 것은 아니다.
  • import : Maven 2.0.9 이상의 버전에서 지원하는 scope로서, 이 scope는 <dependencyManagement> 섹션에서 pom의 의존관계에 대해 사용된다. 지정된 pom이 해당 pom의 <dependencyManagement> 영역에 있는 의존관계로 대체됨을 뜻한다.
자세한 예제는 메이븐 공식 홈페이지 에서 확인할 수 있다.

[Maven] package org.junit does not exists 에러 발생시

Published on: 2013. 11. 14. 14:09 by louis.dev
오늘 우연히 Maven을 통해 packaging을 진행을 하다가 이런 에러를 발생시키면서 packaging이 진행되지 않았다.
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.3.1:compile (default-compile) on project ${프로젝트명}: Compilation failure: Compilation failure:
[ERROR] ${에러 소스파일 경로}\${파일명}.java:[10,38] package org.junit.runners.Parameterized does not exist
[ERROR] ${에러 소스파일 경로}\${파일명}.java:[10,38] package org.junit.runners.Parameterized does not exist
[ERROR]
[ERROR] ${에러 소스파일 경로}\${파일명}.java:[10,38] package org.junit.runners.Parameterized does not exist
[ERROR]
[ERROR] ${에러 소스파일 경로}\${파일명}.java:[10,38] package org.junit.runners.Parameterized does not exist
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn <goals> -rf :Infinite
에러내용을 읽어보니 org.junit.runers.Parameterized라는 패키지가 존재하지 않는다는 문제였다. 아마  검색을 통하여 이 포스트를 찾았다면 에러가 발생된 패키지 명은 달라도 모두 junit에서 발생한 문제일 것이다. 이문제는 컴파일 단계에서 junit 라이브러리가 포함이 되지 않아 발생하는 문제로 Maven의 버그가 아니라 pom파일의 dependency 설정때문에 발생한다.
<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>4.8.1</version>
	<scope>test</scope>
</dependency>
위와같이 pom파일의 dependency 설정을통해 junit 라이브러리를 추가하게 되는데 이때 해당라이브러리의 사용범위를 지정할수있도록 Maven은 scope라는 엘리먼트를 지원해 주고 있다. 이때 scope를 test로 선언하게 되면 해당라이브러리는 테스트 중에만 사용을 하고 실제 packaging 중에는 포함이 되지 않는다. 이렇게 사용범위를 지정함으로서 불필요한 라이브러리 포함을 줄여 어플리케이션의 사이즈를 줄일수 있도록 만들게 되었다. 따라서 위와 같은 빌드 실패는 어플리케이션이 빌드되고 배포 되어질때 junit 라이브러리는 scope 설정때문에 패키징에서 제외되었음으로 org.junit.runers.Parameterized 패키지가 존재하지 않아 발생되는 문제이다. 필자의 경우에는 실제 org.junit.runers.Parameterized 패키지를 사용한 것이 아니라 mybatis의 @Param 어노테이션을 사용하려고 이클립스에서 지원하는 code assist 기능을 사용하여 입력하였고 그때 잘못 입력하여 java파일 상단에 import org.junit.runners.Parameterized.Parameters; 가 포함되었기 때문에 위와 같은 문제가 발생했다. 만약 각자의 코트에서 junit class를 런타임시에도 필요하다면(그럴일은 거의 없겠지만) scope 엘리먼트를 제거하면 되고, 그렇지 않으면 불필요한 import 문을 제거해 주면 깔끔하게 해결된다. 다른 dependency scope를 확인하고 싶다면 여기를 통해 확인하자.

[Mybatis] 프로시져(procedure) 실행하기

Published on: 2013. 11. 14. 14:09 by louis.dev
ibatis 시절에는 procedure라는 테그가 있어서 해당 테그를 이용해 프로시져를 수행했다면 myBatis에서는 일반 쿼리문 처럼 insert, update, select 문을 통하여 프로시져를 수행할수 있다. insert, update, select 중 어떠한 테그를 사용해도 프로시저를 호출할수 있다. 대신 statementType="CALLABLE" 이라는 속성을 추가해 줘야 프로시져로 인식하여 프로시져를 수행한다.
<update id="execureProcedure" statementType="CALLABLE">
	{
		call procedure_name(#{id}, #{name})
	}
</update>