Spring MVC classes not found

 

Eclipse Juno 에 Spring MVC 을 활성화 하는 중이다. 분명히 Templates를 통해서 프로젝트를 생성했는데 아래와 같은 Problems 이 발생하는 것이 아닌가!?

 

 

문제점

 

Description Resource Path Location Type
Class 'org.springframework.web.servlet.view.InternalResourceViewResolver' not found [config set: spring-mvc/web-context] servlet-context.xml /spring-mvc/src/main/webapp/WEB-INF/spring/appServlet line 19 Spring Beans Problem

 

 

해결방안

 

Spring Project Nature 를 비활성화 하고 다시 활성화 하였더니 해당 에러가 사라지는 것이었다. 동시에 JSTL을 못찾던 문제도 함께!

 

Package Explorer -> Project 메뉴(우클릭) -> Spring tools -> spring project nature

 

혹시나 하는 의문에 구글링을 해보았지만 명쾌한 답은 찾지못하고 동일한 상황을 겪은 stackOverflow 글을 발견했다.

 

http://stackoverflow.com/questions/9177902/spring-mvc-classes-not-found

 

 

감사합니다 :)

 

Posted by 리트모스
:

Integrating Jasypt with Spring 3.0

 

앞선 글에 이어서 JASYPT 라이브러리를 활용하는 소스를 간략이 살펴보도록 하겠다. 적용되는 관련 환경과 툴은 Spring 3.0x 에 Maven 이다.

 

 

1. Maven repository

 

아래 소스와 같이 spring 3.0x 에 맞는 라이브러리가 있다. 그리고 icu4j는 Java 5 SE 이하 버전일 경우에만 추가하고 Java 6 SE 버전 이상일 경우에는 내장된 Normalizer 패키지를 사용하므로 하단의 com.ibm.icu 라이브러리를 추가하지 않는다.

 

 

    <!-- JASYPT: Spring 3.0x Simplified Encryption -->
    <dependency>
        <groupId>org.jasypt</groupId>
        <artifactId>jasypt-spring3</artifactId>
        <version>1.9.0</version>

    </dependency>

    <!-- JASYPT: com.ibm.icu.text.Normalizer -->
    <dependency>
        <groupId>com.ibm.icu</groupId>
        <artifactId>icu4j</artifactId>
        <version>49.1</version>
    </dependency>

 

 

 

2. 원문 가이드

 

Maven Dependency Update를 마치고 자바 프로젝트에 라이브러리가 추가 되었다면 이제 Jasypt 를 사용할 준비가 되었다. 아래 Jasypt 사이트에서 상세한 가이드를 통해 쉽게 적용할 수 있다.

 

http://www.jasypt.org/spring3.html

 

 

 

3. DataSource Configuration (XML)

 

Jasypt + Spring 3.0 가이드를 살펴보면 아래와 같은 코드가 추가 되어 있는 것을 확인 할 수 있다.

일반적인 DataSource 설정이라면 propertyConfigurer와 dataSource 부분만 설정 되어 있다.

 

Jasypt를 적용하게 되면

 - 빈객체가 두개 추가 되었고

 - propertyConfigurer에서 사용되는 Class도 Jasypt에서 제공되는 Class를 활용하도록 한다.

 

 

    <bean id="environmentVariablesConfiguration"

      class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
        <property name="algorithm" value="PBEWithMD5AndDES" />
        <property name="passwordEnvName" value="APP_ENCRYPTION_PASSWORD" />
    </bean>
 
    <bean id="configurationEncryptor"

      class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
        <property name="config" ref="environmentVariablesConfiguration" />
        <property name="password" value="jasyptPass" />
    </bean>

 

    <bean id="propertyConfigurer"

class="org.jasypt.spring3.properties.EncryptablePropertyPlaceholderConfigurer">
        <constructor-arg ref="configurationEncryptor" />
        <property name="locations">
            <list>
                <value>classpath:properties/jdbc.properties</value>
            </list>
        </property>
    </bean>

 

    <!-- DataSource Configuration -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"

      destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>

        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

 

        .

        .

        .

 

    </bean>

 

 

 

4. jdbc.properties 파일값 암호화

 

PBE방식으로 암호화해서 암호화 값을 properties에 대입하도록 한다.

http://www.jasypt.org/api/jasypt/1.8/org/jasypt/encryption/pbe/StandardPBEStringEncryptor.html

 

StandardPBEStringEncryptor Class를 활용한 값 암호화

 

    StandardPBEStringEncryptor pbeEnc = new StandardPBEStringEncryptor();
    pbeEnc.setPassword("jasyptPass"); // PBE 값(XML PASSWORD설정)

 

    String url = pbeEnc.encrypt("jdbc:oracle:thin:@x.x.x.x:1521:xxxxx");
    String username = pbeEnc.encrypt("xxxxx");
    String password = pbeEnc.encrypt("xxxxx");

 

    System.out.println(url);
    System.out.println(username);
    System.out.println(password);

 

 

jdbc.properties 값대입 예시

 

    jdbc.driverClassName=core.log.jdbc.driver.OracleDriver
    jdbc.url=ENC(bga9c867hgFkE4ALozTBqBWj2C5wPxH8kDa//7Pqlm8DpGbFK6Fod)
    jdbc.username=ENC(6gaEuIet0A4zRztWpUkS5w==)
    jdbc.password=ENC(XR7FHiFzSBhGT+uIYZJO6w==) 

 

 

이때 유의할 점은 ENC를 빼고 값을 대입하면 Jasypt에서 일반 문자열로 인식을 하게 되므로 암호화한 문자열 값 앞에 ENC로 감싸도록 한다.

 

 

감사합니다 :)

Posted by 리트모스
:

Integrating jasypt with Spring's application configuration infrastructure

 

프로퍼티 파일IP주소, 아이디, 패스워드 등의 정보를 암호화하여 기입하고 JASYPT 라이브러리를 통해 암호화 값을 비교한다.

 

 

1. 적용환경

 - JDK 1.5.0_22

 - org.springframework 3.0.6.RELEASE

 - MAVEN

 

 

2. 라이브러리

 - Spring 3.0x Simplified Encryption JASYPT 1.9.0

 - icu4j 49.1 (com.ibm.icu.text.Normalizer)

 

 

JASYPT 설정을 마치고 Apache Tomcat을 통해 Spring Context를 로드하는 중에 java.text.Normalizer 패키지를 찾는 경우가 발생했다. 해당 패키지는 Normalizer (Java Platform SE 6) 이상에 포함되어 있는 패키지이다.

 

해당 패키지 말고 icu4j 라이브러리를 추가하면 된다라고 친절하게도 Exception을 떨궈준다. 1.5.x 이하의 버전 이라면 icu4j 라이브러리를 추가한다.

 

 

3. 파일첨부

jasypt-1.9.0.jar jasypt-spring3-1.9.0.jar icu4j-49.1.jar

 


4. 관련 URL

 - JASYPT : http://www.jasypt.org/

 - Spring 3.0x Simplified Encryption JASYPT : http://www.jasypt.org/spring3.html

 - Jasypt Maven Repository : http://mvnrepository.com/artifact/org.jasypt/jasypt

 - icu4j Maven Repository : http://mvnrepository.com/artifact/com.ibm.icu/icu4j

 

 

5. 라이센스

 - http://www.jasypt.org/license.html

 - The Apache Software License, Version 2.0

 - http://www.apache.org/licenses/LICENSE-2.0

 

 

Jasypt 사이트에서 가이드하고 있는 내용에는 PBEWithMD5AndDES 로 적용하도록 안내하고 있다. PBE방식과 함께 적용되는 MD5 방식이었지만, MD5가 해독이 가능하다는 얘기를 들은바 있다.

 

그래서 PBEWithSHAAnd128BitRC4 등의 PBEWithSHA* 알고리즘으로 암호화 하려고 시도 했지만 불가능했다. 이에 관련하여 상세한 정보가 있다면 댓글 바란다.

 

그리고 SHA512와는 틀리게 암호화 시 항상 다른 값을 만들어줬다. 그리고 이 항상 달리 만들어 주는 값으로도 JASYPT 라이브러리를 통해 값을 대조해볼때 알아서 인식을 했다. 깊이 들어가지는 않았지만 암호화 할때와 암호화값을 대조할때에도 특정한 조건이 형성이 되어 있을거라 예상된다.

 

 

감사합니다 :)

 

Posted by 리트모스
:

log4sql

 

콘솔에 인자값을 포함한 SQL 로그 출력

 

 

1. 관련URL

http://log4sql.sourceforge.net/index_kr.html

 

 

2. 다운로드

http://sourceforge.net/projects/log4sql/files/

 

1. 라이브러리(log4sql.jar)를 다운 받고 빌드 PATH에 추가한다.

2. jdbc 관련 설정에서 Driver Class Name을 설정한다.

 

 

3. 파일첨부

log4sql.jar log4sql.zip

 

 

다양한 라이브러리를 통해 SQL 로그를 남기지만 여러가지 불편한 사항이 많다. 특히 전달한 인자값을 쿼리와 분리시켜 SQL 로그를 남기는 것은 더더욱 불편함을 야기시킨다.

 

log4sql은 이러한 문제를 해결하여 인자값을 포함한 SQL로그를 콘솔로 보여준다. 개인적으로 느끼는 단점이라면 쿼리 가독성이 떨어져 다시 보기 좋게 변경해야 하는 것이었다. 관련 URL을 따라가면 매우 상세한 설명을 확인할 수 있을 것이다.

 

아래는 log4sql 사이트에 소개된 내용이다.

 

log4sql은 소스의 변경없이 간단한 설정변경만으로 모든 SQL의 실행로그를 보여줍니다.

 

개발을 할경우 우리는 무수히 많은 프레임웍과 도구들을 사용 합니다. View계층, Model계층 그리고 Controller또는 DataAcess계층에서 많은 도구들과 프레임웍은 현재 거의 모든 layer들에 걸쳐서 사용되고 개발되어지고 있습니다. 이런경우 개발자에게 중요한것중의 하나는 비즈니스 로직인 PL/SQL작업을 하는 것 입니다.


모든 PL/SQL작업은 SQL을 작성하고 실행한 후에 버그가 존재하가나 원하는 결과가 나오지 않을경우 수정하는 것이며 이런작업은 반복적으로 수행됩니다. 이런 경우에 우리는 jdbc또는 Connection Pooling(Apache DBCP) 또는 support 2PC (JTA,JOTM)등을 사용합니다.

 

또한 우리는 데이터 접근계층의 프레임웍으로 IBATIS나 SpringFramework을 사용할 경우 springJDBC 또는 HIBERNATE등을 사용합니다. 이런 상황에서 우리는 의문을 갖게 됩니다.

 

'내가 작성한 SQL이 정상적으로 작동한 것인가?', '내가 입력값으로 넣어준 값들이 제대로 등록된 SQL인가?' SQL을 확인하고자 개발 소스의 구석구석에 System.out.println(...)으로 확인을 할 것입니다.

 

개발이 종료된 시점에 주석으로 가려진 가독성이 떨어지는 소스는 유지보수담당자에게 머리아픈 소스가 될 것이고 운영상에 문제가 발생할 경우 해당 SQL을 다시 확인하는 복잡한 작업이 반복될 것입니다. 이런경우를 경험한 개발자라면 log4sql은 간단한 설정으로 많은 편리함을, 개발의 즐거움을 당신에게 드릴것 입니다.

 

감사합니다 :)

 

Posted by 리트모스
:

java.text.SimpleDateFormat

 

SimpleDateFormat is a concrete class for formatting and parsing dates in a locale-sensitive manner. It allows for formatting (date -> text), parsing (text -> date), and normalization.

 

참조 URL

http://docs.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html

 

사용예시

Date today = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
System.out.println(format.format(today));

 

아래는 API에 정의 되어 있는 패턴이다.

(all other characters from 'A' to 'Z' and from 'a' to 'z' are reserved)

 

Letter Date or Time Component Presentation Examples
G Era designator Text AD
y Year Year 1996; 96
M Month in year Month July; Jul; 07
w Week in year Number 27
W Week in month Number 2
D Day in year Number 189
d Day in month Number 10
F Day of week in month Number 2
E Day in week Text Tuesday; Tue
a Am/pm marker Text PM
H Hour in day (0-23) Number 0
k Hour in day (1-24) Number 24
K Hour in am/pm (0-11) Number 0
h Hour in am/pm (1-12) Number 12
m Minute in hour Number 30
s Second in minute Number 55
S Millisecond Number 978
z Time zone General time zone Pacific Standard Time; PST; GMT-08:00
Z Time zone RFC 822 time zone -0800

 

 

아래는 US 로케일 정보를 기반한 예시이다.

 

// 2001.07.04 AD at 12:08:56 PDT

new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z", Locale.US)

 

// Wed, Jul 4, '01

new SimpleDateFormat("EEE, MMM d, ''yy", Locale.US)


// 12:08 PM

new SimpleDateFormat("h:mm a", Locale.US)

 

// 12 o'clock PM, Pacific Daylight Time

new SimpleDateFormat("hh 'o''clock' a, zzzz", Locale.US)

 

// 0:08 PM, PDT

new SimpleDateFormat("K:mm a, z", Locale.US)

 

// 02001.July.04 AD 12:08 PM

new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa", Locale.US)

 

// Wed, 4 Jul 2001 12:08:56 -0700 

new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.US)

 

// 010704120856-0700 

new SimpleDateFormat("yyMMddHHmmssZ", Locale.US)

 

 

아래는 KO 로케일 정보를 기반한 예시이다.

 

// 2012년 07월 04일 수요일
new SimpleDateFormat("yyyy년 MM월 dd일 E요일");


// 2012-07-04 10:10:51 오전
new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a");

 

 

감사합니다 :)

 

Posted by 리트모스
:

java.util.Date.Date(long date)

 

long 타입으로 생성되는 Date 타입의 변수를 일수 더하거나 빼기

 

일자 감산 혹은 원하는 밀리세컨드 만큼의 값을 연산하여 문자열 타입의 날짜값을 생성하도록 한다.

문자열 포맷은 SimpleDateFormat 를 활용한다.

 

// -1일

long subTime = 1000 * 60 * 60 * 24 * -1;

 

// Returns the number of milliseconds (1970년 1월 1일, 0시 0분 0초 이후 밀리초 수 반환)

long iCurTime = new Date().getTime();

 

// 음의 수를 가산하여 String 타입 dateStr 으로 생성

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");

String dateStr = dateFormat.format(new Date(iCurTime + subTime)));

 

 

감사합니다 :)

 

Posted by 리트모스
:
잡담 : 몇년전 웹 디자이너로써 활동하던 시절이 있었습니다. 그 당시 게임을 운영하는 분이 짜달라고 했던 숫자 야구게임이라는 게 있었습니다. 기본적인 제어문도 제대로 다룰줄 몰랐던 저는 할 줄 모른다고 말씀 드리고 프로그래밍에 대한 열망이 쌓이게 된 계기이기도 하였습니다. 그 게임 운영자가 얼마전에 연락이 되어서 그때의 숫자 야구 게임에 대해서 생각이 나더군요. 그래서 한번 소스를 짜봤습니다.



최대한 API의 이용을 줄였으며, 이해하기 쉽게 소스를 짜도록 하였다.

 
import java.util.*;

public class BaseballServer {

 static int strike = 0; // 정답 변수 선언
 static int ball = 0; // 정답 변수 선언

 public static void main(String[] args) {
  int a[] = new int[3]; // 컴퓨터가 랜덤으로 값을 저장할 배열 선언
  int b[] = new int[3]; // 유저에게 입력받는 값을 저장할 배열 선언
 
  Random ra = new Random(); 
  while(a[0] == 0) { a[0] = ra.nextInt(10); }
  while(a[0] == a[1] || a[1] == 0) { a[1] = ra.nextInt(10); }
  while(a[0] == a[2] || a[1] == a[2] || a[2] == 0) { a[2] = ra.nextInt(10); }
  // 1~9까지의 랜덤 값을 a배열에 대입
  
  // System.out.println(a[0] + ", " + a[1] + ", " + a[2] + "\n");
  // 컴퓨터가 정한 값 출력
 
  Scanner s = new Scanner(System.in);
 
  while(strike < 3) { // 정답을 맞출때까지 계속 반복
 
   for(int i = 0; i < b.length; i++) { // 반복적으로 유저에게 값 입력 받기
    System.out.print(i+1 + "번째 수(1~9) : ");
    b[i] = s.nextInt();
    while (b[i] >= 10 || b[i] == 0) { // 입력된 값의 오류 체크
     System.out.println("[오류] 1~9 사이의 한자리수 입력!");
     System.out.print(i+1 + "번째 수(1~9) : ");
     b[i] = s.nextInt();
    }
    // System.out.println("입력한 수는 " + b[i] + "입니다.");
   }
  
   for(int i = 0; i < 3; i++) { // strike, ball 여부 체크
    for(int j = 0; j < 3; j++) {
     if( a[i] == b[j] ) {
      if ( i == j ) { strike += 1; } else { ball +=1; } // strike, ball 값 갱신
     }
    }
   }
  
   if (strike == 0 && ball == 0) { // 모두 틀릴 경우
    System.out.println("\n아웃!\n");
   } else if(strike == 3) { // 정답일 경우
    System.out.print("\n정답입니다!");
    System.exit(0);
   } else { // 부분 정답일 경우
    System.out.println("\n" + strike + " Strike" + ", " + ball + " Ball\n");
    strike = 0;
    ball = 0;
   }
  }
 }
}


실행 결과



Posted by 리트모스
:


Summing.java 소스예제

import java.rmi.*;

public interface Summing extends Remote {
 int sum(int max) throws RemoteException;
 int sum2(int min, int max) throws RemoteException;
}


SummingImpl.java 소스예제
import java.rmi.*;
import java.rmi.server.*;

public class SummingImpl extends UnicastRemoteObject implements Summing{
 
 public SummingImpl() throws RemoteException {
 }
 
 public int sum(int max) throws RemoteException {
  if (max <= 0) return 0;
  else return (max + sum(max-1));
 }
 
 public int sum2(int min, int max) throws RemoteException {
   return min + max;
 }
 
 public static void main(String[] args) {
  try {
   SummingImpl s = new SummingImpl();
   Naming.rebind("SumServer", s);
  } catch(Exception e) {
   System.out.print(e);
  }
 } 
}


실행된 환경에서만 환경변수를 일시적으로 설정하여 준다.

 D:\JavaNetwork>set classpath=%classpath%;.


스터브와 스켈레톤 파일을 생성한다. 자바 1.2 이후에는 스터브로 통일되었으므로 스터브 파일만 생성되는 것을 확인할 수 있다. SummingImpl_Stub.class 파일 생성확인

 
D:\JavaNetwork>rmic -d . SummingImpl


서버측에 필요한 파일(Summing.class, SummingImpl.class, SummingImpl_Stub.class)을 원하는 서버폴더를 선택하여 복사한다. 여기서 기재하는 내용은 기존 폴더를 서버로 이용한다.

서버측에서 네이밍 서버(rmiregistry)를 실행한다.

 
D:\JavaNetwork>start rmiregistry


서버측에서 RMI 서버를 실행한다.

 
D:\JavaNetwork>java SummingImpl



SummingClient.java 소스예제

import java.rmi.*;

public class SummingClient{
 public static void main(String[] args) {
  if(args.length < 2) {
   System.out.println("Specity IP & Number");
   System.exit(1);
  }
  
  try {
   String serverURL = "rmi://" + args[0] + "/SumServer";
   Summing s = (Summing) Naming.lookup(serverURL);
   System.out.println("Your Input = " + args[1] + " + " + args[2]);
   int min = Integer.parseInt(args[1]);
   int max = Integer.parseInt(args[2]);
   
   if (args[2] == null) {
    System.out.println("The sum 1 to " + max + " is " + s.sum(max));
   } else {
    System.out.println("The sum " + min + "+" + max + " is " + s.sum2(min, max)); 
   }   
  } catch(Exception e) {
   System.out.print(e);
  }
 }
}


클라이언트측에 필요한 파일(Summing.class, SummingClient.class, SummingImpl_Stub.class)을 원하는 클라이언트 폴더를 생성한 뒤 복사한다.


 
D:\JavaNetwork\Client> java SummingClient 127.0.0.1 100


참고사항 : 프롬프트에서 설정한 classpath는 프롬프트 창을 껐다 켤 경우 윈도우즈 환경변수의 원래값으로 재설정되니 classpath 설정을 확인하는 단계를 거치도록 한다.

Posted by 리트모스
:

자바에서 제공하는 자료 유형은 크게 두가지로 나눌 수 있는데 기본 자료 유형(primitive data type)과 참조 자료 유형(reference data type)으로 나눌 수 있다. 자바에서 제공되는 유형은 모두 11가지 이다.


기본 자료 유형 : byte, short, int, long, float, double, boolean, char


그림파일 다운로드 : 20090212_datatype.jpg


참조 자료 유형 : 인터페이스(interface), 클래스(class), 배열(array)

Posted by 리트모스
:

클래스
프로그램을 구성하는 단위이다. 클래스는 아래와 같은 문법 구조를 가지고 있다.

public class className {
     ...
}

클래스는 class 뒤에 클래스 이름이 오며, 중괄호로 클래스를 정의한다. 클래스 이름은 파일명과 동일해야 하므로 반드시 대소문자까지 정확하게 입력해야 한다.


메소드
클래스를 구성하는 요소중의 하나이다. 메소드는 아래와 같은 문법 구조를 가지고 있다.

 public class className {
     ...
     public static void main(String[] args) {
          ...
     }

     public ... returnType methodName(parameter) {
          ...
     }
     ...
}


자바에서 메소드라고 불리우는 것은 절차적 언어에서의 함수(function)에 해당한다. 메소드는 클래스 내부에서만 작성될 수 있으며, 여러 개의 메소드가 존재할 수 있다.

Posted by 리트모스
:
이클립스(eclipse)를 처음 접하는 분들에게 생길 수 있는 고민입니다. 한글로 쓰는게 편하긴 한데 취업하고 나서도 과연 한글판을 계속 쓸 수 있을까 하는 것입니다. 물론 현업에서 이클립스를 사용하시는 분들을 보면 그런 것에 별로 신경쓰지 않습니다.

이클립스(eclipse) 다운로드 : http://www.eclipse.org/downloads/
위 사이트가 아니더라도 네이버 자료실 같이 공개 자료실에서도 다운 받을 수 있습니다.

이클립스(eclipse) 3.2를 기준으로 설명 하겠습니다.

이클립스 한글패치
1. 이클립스내의 Install/Update을 이용하여 한글패치 2. 한글패치 직접 설치

한글패치된 이클립스 영문 버전 실행
1. 실행시 추가 구문 작성

"C:\...\eclipse3.2\eclipse\eclipse.exe" -nl en_US

바로가기의 속성으로 들어간 뒤에 대상안에 위와 같이 '-nl en_US' 라는 문구를 써 주면 된다.
Posted by 리트모스
: