달력

4

« 2024/4 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

'분류 전체보기'에 해당되는 글 87

  1. 2009.07.17 Mac에서 IPv6 disable하기
  2. 2009.07.14 Spring Roo 간략 소개
  3. 2009.07.06 또 다른 EJB 때의 실수를 반복하고 있는 우리들... 2
  4. 2009.02.18 TDD의 원칙
  5. 2008.11.28 단아함 1
  6. 2008.11.28 세상 밖으로
  7. 2008.11.28 늦가을
  8. 2008.04.25 jvm option
  9. 2008.04.23 Ruby Programming Tip
  10. 2008.04.16 Artifactory 사용하기
2009. 7. 17. 14:02

Mac에서 IPv6 disable하기 Mac2009. 7. 17. 14:02

Servet.getRemoteAddr을 호출하면 "127.0.0.1" 등이 아니라 "0:0:0:0:0:0:0:1%0"와 같이 이상한 ip가 나와서 IP 종속적인 뭔가를 못하는 상황이 발생할 수 있다.
이 경우 IPv6를 disable하는 방법은 아래와 같다.

1. IPv6 사용 안하도록 설정하기
시스템 환경설정 / 네트워크 / 고급 / TCP/IP / IPv6구성 값을 "끔"으로 설정한다.
2. /etc/hosts 파일 수정하기
::1         localhost 
fe80::1%lo0 localhost
hosts 파일에서 위 2라인을 제거한다.

:
Posted by codetemplate
2009. 7. 14. 17:34

Spring Roo 간략 소개 프레임워크2009. 7. 14. 17:34

http://phillyspring.ning.com/forum/topics/july-meeting-springsource-roo

위 url에 있는 발표 자료를 간략하게 정리해 봤다.

1. Roo란 ?
spring & java 환경을 위한 RAD(Rapid Application Development) 플랫폼
    - domain-centric design of database entities
    - Auto-scaffolding of UI elements
    - Builds a full stack Spring web application
    - Target build process managed by Maven
java, spring 환경에서 개발할 때 많은 xml 설정을 상당 부분 CoC(Convention over Configuration)으로 변경한 프레임워크.

2. Roo 개발 절차
Roo는 grails/rails 처럼 커맨드 라인 쉘을 제공한다.
이 쉘을 이용해서
     - 메이븐으로 빌드되는 프로젝트를 생성
     - roo와 개발툴에서의 변경이 서로 동기화되는 round-trip을 제공한다.
     - 특정 기능을 제공하기 위해 aspect를 사용한다.
     - aspect를 관련된 클래스 파일에 위빙한다.

3. 사용된 기술들
AspectJ ITD(Inter-Type Declarations)
     - maven/eclipse에서 aspectj 컴파일러를 사용한다.
     - roo 어노테이션된 클래스에 컴파일 타임에 코드(aspect에 구현된)를 추가한다.
Roo 커맨드 쉘
     - 훌룡한 빌드 환경을 생성/유지한다.
     - 동적으로 .aj 파일을 생성하고, web UI scaffold를 제공한다.

4. Creating a roo project
     - 디렉토리 생성하기
     - 해당 디렉토리에서 roo 쉘 실행
     -  create project 명령 수행

flibbity-floo:roo-demo krimple$ roo
____ ____ ____
/ __ \/ __ \/ __ \
/ /_/ / / / / / / /
/ _, _/ /_/ / /_/ /
/_/ |_|\____/\____/ 1.0.0.M1 [rev 64]
Welcome to Spring Roo. For assistance press TAB or type "hint" then hit ENTER.

roo> create project -topLevelPackage com.chariot.demo.roodemo

Created /Users/krimple/svn-projects/...roodemo/pom.xml
Created SRC_MAIN_JAVA
Created SRC_MAIN_RESOURCES
Created SRC_TEST_JAVA
Created SRC_TEST_RESOURCES
Created SRC_MAIN_WEBAPP
Created SRC_MAIN_RESOURCES/applicationContext.xml
Created SRC_MAIN_WEBAPP/WEB-INF
Created SRC_MAIN_WEBAPP/WEB-INF/roodemo-servlet.xml
Created SRC_MAIN_WEBAPP/WEB-INF/web.xml
Created SRC_MAIN_WEBAPP/WEB-INF/jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/index.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/urlrewrite.xml

5. Installing JPA
'install jpa' 명령을 사용해서 Open JPA, Hibernate, EclipseLink 중 하나의 persistence F/W를 설치한다.

roo> install jpa -provider HIBERNATE -database MYSQL

Created SRC_MAIN_RESOURCES/META-INF
Created SRC_MAIN_RESOURCES/META-INF/persistence.xml
Created SRC_MAIN_RESOURCES/database.properties
please enter your database details in src/main/resources/database.properties
Managed SRC_MAIN_RESOURCES/applicationContext.xml
Managed ROOT/pom.xml

6. Adding a Persistent JPA Entity
‘new persistent class’ 명령을 사용해서 새로운 도메인 클래스를 설정한다.
후에 'add field' 명령을 사용해서 필드를 추가할 수 있다.

roo> new persistent class jpa -name ~.Conference

Created SRC_MAIN_JAVA/com/chariot/roodemo
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference.java
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_Plural.aj
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_Entity.aj
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_ToString.aj
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_Configurable.aj

7. What Got Created?
지금까지의 작업을 수행했다면 Roo는 아래와 같은 파일들을 생성했을 것이다.
     - Conference.java - the file you edit, containing Roo annotations and your properties
     - Conference_Roo_Configurable.aj - adds @Configurable to the entity
     - Conference_Roo_Entity.aj - Adds all JPA persistence methods, an id, and a version
     - Conference_Roo_JavaBean.aj - Adds getters/ setters for all of your private properties

8. Setting up JPA fields
필드나 관계를 추가할 수 있다. 이러한 필드들은 물리적으로 자바 파일에 추가된다. 또 추가된 필드들을 위한 support 메소드들이 자동으로 wired된다.

roo> add field string name
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference.java
Created SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_JavaBean.aj
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_ToString.aj

roo> add field string description
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference.java
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_JavaBean.aj
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_ToString.aj

roo> add field date jpa -type java.util.Date -fieldName created
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference.java
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_JavaBean.aj
Managed SRC_MAIN_JAVA/com/chariot/roodemo/Conference_Roo_ToString.aj

9. Building a Relationship

roo> new persistent class jpa -name ~.domain.Conference
roo> add field string -fieldName conferenceName -notNull -sizeMin 1 -sizeMax 40
roo> add field date jdk -type java.util.Date -notNull -fieldName startDate
roo> add field date jdk -type java.util.Date -notNull -fieldName endDate

roo> new persistent class jpa -name ~.domain.ConferenceSession
roo> add field string -notNull -fieldName title -sizeMax 80
roo> add field reference jpa -fieldName conference -type com.chariot.demo.contrack.domain.Conference
roo> add field set jpa -element ~.domain.ConferenceSession -fieldName session -class com.chariot.demo.contrack.domain.Conference

10. Entity Validation
JSR-303 annotation에 의해 entity를 validate할 수 있다.
    @NotNull, @Nullable, @Size, @DecimalMin, @DecimalMax, etc...
자동 생성되는 Controller에는 이러한 Bean Validation API를 통해 validation을 호출하는 코드가 포함된다.

javax.validation.Validation.
    buildDefaultValidatorFactory().getValidator().
    validate(conference))

11.  Validation Examples

@Size(min = 5, max = 30, message = "Please enter a name between {min} and {max} characters.")
private String name;

@Size(min = 10, max=2048, message = "{description.required}")
private String description;

@Temporal(TemporalType.TIMESTAMP)
@Column(insertable=true, updatable=false)
@NotNull
private Date created;

12. Configuring logging

roo> configure logging -level TRACE
Created SRC_MAIN_RESOURCES/log4j.properties
Managed SRC_MAIN_WEBAPP/WEB-INF/web.xml

<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>classpath:log4j.properties</param-value>
</context-param>

#Updated at Tue Jun 09 09:21:45 EDT 2009
#Tue Jun 09 09:21:45 EDT 2009
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout.ConversionPattern=%d [%t] %-5p %c - %m%n
log4j.rootLogger=TRACE, stdout, R
log4j.appender.R.File=application.log
log4j.appender.R.MaxFileSize=100KB
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.MaxBackupIndex=1
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.R=org.apache.log4j.RollingFileAppender

13. Generating a Controller

roo> new controller automatic -name com.chariot.roodemo.domain.ConferenceController
Created SRC_MAIN_JAVA/com/chariot/roodemo/domain/ConferenceController.java
Created SRC_MAIN_JAVA/com/chariot/roodemo/domain/ConferenceController_Roo_Controller.aj
Created SRC_MAIN_WEBAPP/images
Created SRC_MAIN_WEBAPP/images/banner-graphic.png
Created SRC_MAIN_WEBAPP/images/springsource-logo.png
Created SRC_MAIN_WEBAPP/images/list.png
Created SRC_MAIN_WEBAPP/images/show.png
Created SRC_MAIN_WEBAPP/images/create.png
Created SRC_MAIN_WEBAPP/images/update.png
Created SRC_MAIN_WEBAPP/images/delete.png
Created SRC_MAIN_WEBAPP/styles
Created SRC_MAIN_WEBAPP/styles/roo.css
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/header.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/footer.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/includes.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/dataAccessFailure.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/uncaughtException.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/conference
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/conference/list.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/conference/show.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/conference/create.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/conference/update.jsp
Created SRC_MAIN_WEBAPP/WEB-INF/jsp/menu.jsp
Managed SRC_MAIN_WEBAPP/WEB-INF/jsp/menu.jsp

19.  Example Aspect: show
In ConferenceController_Roo_Controller.aj:

@org.springframework.web.bind.annotation.RequestMapping(
value = "/conference/{id}", method = org.springframework.web.bind.annotation.RequestMethod.GET)
public java.lang.String ConferenceController.show(
    @org.springframework.web.bind.annotation.PathVariable("id") Long id,
    org.springframework.ui.ModelMap modelMap) {
    if (id == null) throw new IllegalArgumentException("An Identifier is required");
    modelMap.addAttribute("conference", com.chariot.roodemo.domain.Conference.findConference(id));
    return "conference/show";
}

Uses findConference in Conference_Roo_Entity.aj

public static com.chariot.roodemo.domain.Conference Conference.findConference(java.lang.Long id) {
    if (id == null) throw new IllegalArgumentException(
        "An identifier is required to retrieve an instance of Conference");
    javax.persistence.EntityManager em = new Conference().entityManager;
    if (em == null) throw new IllegalStateException(
        "Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects
        library?)");
    return em.find(Conference.class, id);
}

20. Get it working!
mvn jetty:run이나 mvn tomcat:run을 통해서 웹 어플리케이션을 실행할 수 있다.
Hit the webapp url and get a menu of choices

21.  IDE Support
Roo는 SpringSource Tool Suite(STS)를 사용하면 보다 편하게 사용할 수 있다. STS는 다음과 같은 편의를 제공한다.
    - AJDT AspectJ editing support is very good
    - Roo Console available via Right-click if installed
하지만 STS 사용시 mvn eclipse:eclipse를 빈번하게 수행해야 하고, F5를 자주 눌러야 한다.
이런 불편은 eclipse에서 mvn eclipse:eclipse를 external command로 등록하고 수행 후에 프로젝트를 refresh하도록 설정하면 해결된다.

22.  Resources
Roo JIRA: http://jira.springframework.org/browse/ROO
Roo Forum: http://forum.springsource.org/forumdisplay.php?f=67

:
Posted by codetemplate
요즘 여유가 있어서 인지, 아님 진짜 내가 업무적으로 가장 긴급하게 수행해야 하는 작업이 "유지보수 용이성"인지 모르겠지만, 유지보수 용이성을 위한 개선 작업을 진행 중이다. 
Design Pattern을 마스터했다고는 말하기 어렵겠지만 그래도 책을 서너번 봤고, 관련된 다른 책들도 봤고, 많은 기사들도 봤는데도, 요즘 작업을 하고 있는 코드를 들여다 보면 아쉬움이 넘쳐 나온다. 이런 상황에 빠지게 된 원인을 나열해 보면...
  • 정말로 편한 spring framework의 사용
  • up-front가 아니여도 맨땅에 헤딩을 쉽게 해주는 eclipse와 같은 IDE
  • 작업자들의 OOAD, Design Pattern, Refactoring 등에 대한 이해 부족(???)
이상을 들을 수 있을 것 같다.

특히 spring framework는 자체적으로 비난 받을 이유는 없지만 이로 인해 우리가 OO스럽지 않은 코드를 작성하고 있는 것 같다.
state, strategy, factory 등은 정말 자주 사용되는 패턴인데 spring에 익숙해지려고 노력하다 보면 뭐가 중요한지 잊고 한쪽에 치우치는 것 같다. 

소프트웨어 개발자로서 나는 성능(performance, efficiency) 보다는 유연성(flexibility, maintainability, open to change)가 더 중요하게 여긴다. 특히 2년여에 걸쳐 성능 안정화를 이룬 시스템을 유지하고 있는 요즘의 현실로서는 더욱 그렇다.
일례로 오래 전에 구현된 기능과 관련하여 새로운 기능을 추가할 때 빈번히 자잘한 문제를 겪는다. 이는 Aggregate를 적용한 Domain Model 기반의 코드가 아니라 코드의 중복이 많은 Transactional Script 형태의 코드여서 발생했다고 생각한다.

코드의 양이 얼마 되지 않고 빨리 구현하는 것이 목적일 때는 Transactional Script는 아무런 문제가 되지 않았다. 오히려 OOAD에 대한 지식이 부족한 요새의 개발자들에게는 보다 빨리 구현할 수 있는 잇점을 제공했다.

하지만 코드에 지속적으로 기능을 추가해야 하는 요즘은 Transactional Script는 우리의 발목을 잡는다. 또 Hibernate과 같은 ORM을 사용하지 않고 쉽고, 제어가 편하다는 이유로 사용하기 시작한 iBatis는 Aggregate를 사용하기 어렵게 만들었다.

넘 아쉽다. 첨부터 다시 할 수 있는 기회가 있었으면 좋겠다. 지금 조금씩 개선(수정)하고 있지만 너무 괴롭다. 확 바꾸기가 어려우니...

혹 이글을 보신 분들 중 Java 기반으로 새로운 어플리케이션을 구현하고자 하는 분이 있다면 아래와 같은 사항들을 권하고 싶다.
  • transaction script를 사용하지 말고 domain model을 사용하라.
  • integration test, functional test 없이 unit test만으로도 최대한의 test coverage가 나오도록 노력하라.
  • 유지보수 용이성 외의 다른 이슈(예. 성능)는 해당 이슈가 진정으로 필요할 때 까지 결정(고민???)을 최대한 미루라.
이와 관련하여 같은 고민을 한 분들이 있다면 정보를 공유할 수 있었으면 좋겠다.
:
Posted by codetemplate
2009. 2. 18. 21:44

TDD의 원칙 TDD2009. 2. 18. 21:44

1. 첫번째 법칙: 실패하는 테스트 코드를 작성하기 전에는 프로덕션 코드를 작성하지 않는다.
2. 두번째 법칙: 실해하는 테스트가 수행되는 만큼만 테스트를 작성한다(컴파일될 만큼만).
3. 세번째 법칙: 현재 실패하는 테스트를 성공시키는 만큼만 프로덕션 코드를 작성할 수 있다. 그 이상은 안된다.

이러한 법칙을 따르면 개발자들은 어쩌면 30초 정도의 주기를 갖는 싸이클 작업을 하게 된다.

참 중요한 법칙 하나 더...

Quick & Dirty로 working 코드를 만드는 것이 끝이 아니다.

시간이 없어서 refactoring을 안하고 dirty 코드를 누적시키면 점점 더 시간이 없어질 것이다...

지금 시간이 없더라도 working 코드를 후에 변경/추가가 용이하도록 refactoring 해야 만 후에 시간이 남게 될 것이다.

Refactoring은 TDD/Agile에서 선택이 아닌 필수이다.
:
Posted by codetemplate
2008. 11. 28. 14:14

단아함 일상2008. 11. 28. 14:14


:
Posted by codetemplate
2008. 11. 28. 14:13

세상 밖으로 일상2008. 11. 28. 14:13


:
Posted by codetemplate
2008. 11. 28. 14:12

늦가을 일상2008. 11. 28. 14:12


:
Posted by codetemplate
2008. 4. 25. 11:43

jvm option Java2008. 4. 25. 11:43

jmx 연결을 위한 옵션

java 
-Dcom.sun.management.jmxremote.port=portNo
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false MyApp
:
Posted by codetemplate
2008. 4. 23. 20:28

Ruby Programming Tip Ruby2008. 4. 23. 20:28

TextMate Tip


프로젝트를 열기


mate .

. 현재 열려 있는 루비 프로그램 수행하기
cmd+r
  • API Manual 보기
. 포맷팅 설정하기
export RI="--format ansi --width 70"

. 클래스에 대한 정보 보기
ri GC

. 메소드에 대한 정보 보기
ri garbage_collect

. 모든 클래스 보기

ri -c
:
Posted by codetemplate
2008. 4. 16. 10:39

Artifactory 사용하기 프레임워크2008. 4. 16. 10:39

1. 설치하기

http://www.jfrog.org/sites/artifactory/latest에서 최신 버전을 다운로드하고 적절한 디렉토리에서 압축을 푼다.

2. 설정하기
$ARTIFACTORY_HOME/etc에 있는 artifactory.config.xml 파일을 아래과 같이 수정한다.
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://artifactory.jfrog.org/xsd/1.1.0"
xsi:schemaLocation="http://artifactory.jfrog.org/xsd/1.1.0
http://www.jfrog.org/xsd/artifactory-v1_1_0.xsd">
<localRepositories>
<localRepository>
<key>daum-internal-repository</key>
<description>daum internal repository</description>
<handleReleases>true</handleReleases>
<handleSnapshots>true</handleSnapshots>
</localRepository>
<localRepository>
<key>third-party-repository</key>
<description>third party repository</description>
<handleReleases>true</handleReleases>
<handleSnapshots>true</handleSnapshots>
</localRepository>
</localRepositories>
<remoteRepositories>
<remoteRepository>
<key>ibiblio</key>
<handleReleases>true</handleReleases>
<handleSnapshots>false</handleSnapshots>
<excludesPattern>org/artifactory/**,org/jfrog/**</excludesPattern>
<url>http://repo1.maven.org/maven2</url>
</remoteRepository>
<remoteRepository>
<key>codehaus-snapshots</key>
<blackedOut>true</blackedOut>
<handleReleases>false</handleReleases>
<handleSnapshots>true</handleSnapshots>
<excludesPattern>org/artifactory/**,org/jfrog/**</excludesPattern>
<url>http://snapshots.repository.codehaus.org</url>
</remoteRepository>
<remoteRepository>
<key>apache-m2-snapshots</key>
<handleReleases>false</handleReleases>
<handleSnapshots>true</handleSnapshots>
<url>http://people.apache.org/repo/m2-snapshot-repository</url>
</remoteRepository>
<remoteRepository>
<key>apache-snapshots</key>
<handleReleases>false</handleReleases>
<handleSnapshots>true</handleSnapshots>
<url>http://people.apache.org/maven-snapshot-repository</url>
</remoteRepository>
</remoteRepositories>
</config>

3. 실행하기
$ARTIFACTORY_HOME/bin에서 artifactory.sh를 수행한다. 이 스크립트는 jetty를 이용해서 $JAVA_HOME 환경 변수 설정이 필요하다.
8081 포트로 artifactory가 실행된다.

4. settings.xml
~/.m2/settins.xml 파일을 아래와 같이 설정한다.
<settings xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
<profiles>
<profile>
<id>gaia</id>
<repositories>
<repository>
<id>central</id>
<url>
http://media-install:8081/artifactory/repo
</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>snapshots</id>
<url>
http://media-install:8081/artifactory/repo
</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>
http://media-install:8081/artifactory/repo
</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>snapshots</id>
<url>
http://media-install:8081/artifactory/repo
</url>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
</settings>

5. maven에서 artifactory 연결하기
mvn 실행시 settings.xml에서 정의한 프로파일을 정의하기 위해 '-Pgaia'를 지정하면 된다.

6. 정상적으로 동작하는지 확인하기
http://media-install:8081/artifactory로 접속 admin/password로 로긴한다. 왼쪽 메뉴에서 "Browsing/Repositories Tree"를 클릭해서 artifactory들이 보이면 정상 동작하는 것이다.

7. 3rd party artifact나 사내 artifact 등록하기
왼쪽 메뉴에서 "Deploy an Artifacts" 클릭. "찾아보기" 버튼으로 deploy할 artifact 선택하고, "Upload!" 버튼 클릭. 다음에 나오는 화면에서 groupId, artifactId 확인하고 적절하게 설정하고 deploy한다.

:
Posted by codetemplate