태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

요새 Groovy on Grails를 공부하고 있는데요, 재미있군요.

java base 에서Rails 스타일로 프로그래밍을 가능하게 해줘서 생산성을 높여주는데 촛점이 맞춰진 언어입니다.

기본적인 내용들은 자료가 많이 있으니 찾아 보시면 될 것 같구요.


오늘은 Maven을 Integration하는 방법을 정리 해보려고 합니다.


기본적인 내용은 일단 아래 링크를 참조하시구요.

http://grails.org/doc/latest/guide/4.%20The%20Command%20Line.html#4.5%20Ant%20and%20Maven

간략하게 핵심만 정리해 보도록 하겠습니다.



기본적인 컨셉은 다음과 같습니다.

1. grails maven plugin을 이용하여 프로젝트 생성
2. 프로젝트 초기화
3. maven을 이용하여 Grails controller등 생성
4. maven을 이용하여 실행


프로젝트 생성

아래 명령에서 적절한 group id와 artifact id를 지정해줍니다.

mvn archetype:generate -DarchetypeGroupId=org.grails -DarchetypeArtifactId=grails-maven-archetype -DarchetypeVersion=1.3.4 -DgroupId=com.my-group -DartifactId=my-project

명령을 수행하면 버전 정보를 묻는 창이 뜨는데,

0.0.1-SNAPSHOT 같은 적당한 버전 이름을 지정해주면 됩니다.

성공적으로 수행이 되면 pom.xml 파일이 생성되고 기본적인 프로젝트 트리가 생성됩니다.



프로젝트 초기화

생성된 프로젝트 폴더로 가서 initialize를 시킵니다. 실행하면 grails 폴더 트리들이 자동으로 생성됩니다.
cd my-project
mvn initialize



Maven을 이용하여 Grails 명령어 실행

이제부터 Grails명령어들을 이용하기 위하여서는 Maven을 사용해야 합니다.

Bbs 모델 class가 이미 존재한다고 가정하고,

컨트롤러 및 기타 생성
mvn grails:exec -Dcommand=generate-controller -Dargs=com.my-project.common.model.entity.Bbs
mvn grails:exec -Dcommand=generate-all -Dargs=com.my-project.common.model.entity.Bbs

어플리케이션 실행
mvn grails:run-app


이런식으로 실행을 하면 됩니다.


이제부터는 pom.xml 파일에 Maven repository에 있는 레거시 Jar 패키지들을 Dependency 추가해주면 그대로 사용이 가능합니다.
물론 grails 파일들 외에 기존 사용하던 Java class들도 Dependency를 추가해주면 그대로 사용이 가능합니다.










Posted by Breeze.Kang

댓글을 달아 주세요

Cassandra GUI Client 프로그램을 찾던중에 괜찮은 녀석을 발견해서 올려봅니다.

Java 기반이고 war를 tomcat의 webapp 디렉토리에 넣어주기만 하면 됩니다.

처음실행시

Cassrandra Host , Thrift Port (보통 9160) , JMX port 를 입력해주시면 접속이 됩니다.

왼쪽의 Configuration 메뉴에서도 변경 가능하구요.



다운로드 페이지
http://github.com/suguru/cassandra-webconsole



소개하는 블로그
http://nosql.mypopescu.com/post/611576467/cassandra-web-console



스크린샷











Posted by Breeze.Kang

댓글을 달아 주세요

${RequestParameters['test']}

또는

${RequestParameters.test}

로 사용하면 HttpRequest의 모든 Parameter를 사용할 수 있다.



또한 httpRequest의 Attribute를 사용하고 싶다면 다음과 같이 하면 된다.

${Request['AttributeName']}

또는

${Request.AttributeName}

Posted by Breeze.Kang

댓글을 달아 주세요


Effective Java에 나오는 내용이긴 합니다만, 우리가 자주 저지르는 실수가 있습니다.

프로그램을 하다가 보면 자주 난수(Random number)를 발생시켜야 할 때가 있습니다.

아래와 같은 코드를 사용하여 많이 발생을 시키죠.


private static final Random rnd = new Random();

static int random(int n) {
   return Math.abs(rnd.nextInt()) % n;
}


논리적으로는 아무런 문제가 없어 보입니다.

그렇지만 실제적으로 다음과 같은 코드를 사용하여 테스트를 해보도록 합시다.

public static void main(String[] args) {
   int n = 2 * (Integer.MAX_VALUE / 3);
   int low = 0;
   for (int i = 0; i < 1000000; i++)
       if (random(n) < n/2)
           low++;
   System.out.println(low);
}

위의 코드데로라면  100만번 테스트를 해서 기준값보다 작은 수가 나오는 경우는 50% 가깝게 나와야 정상입니다.

그렇지만 실제로 돌려보면 항상 666,666에 가까운 수가 나옵니다.

난수가 제대로 발생하고 있지 않다는 이야기죠.

실제적으로 이런식의 버그는 찾아내기가 쉽지 않습니다.

로직상으로는 아무런 문제가 없기 때문이죠.


따라서 저런 프로그램으로 Load Balancing하거나 데이터를 분산하고 있다면 제대로 처리가 되고 있지 않을 것입니다.

java 1.2부터 추가된 Random.nextInt(int) 를 사용하거나,  apache commons의 RandomUtils.nextInt()를 사용해야 제대로 동작을 합니다.



Posted by Breeze.Kang

댓글을 달아 주세요


Java Object를 XML로 변환하고자 할때 과거에는 포맷에 맞춰서 XML을 일일이 출력해주는 방식도 사용을 했었다.

그렇지만 굉장히 노가다이고, 짜증나는 작업이 아닐수 없다. 

이런 노가다를 줄이기 위하여 Java Object를 XML로 변환해주는 많은 툴들이 나와있다.

그중에 가장 많이 사용되는 것이 JAXB(Java Architecture for XML Binding) 이다.

Using JAXB

기본적인 지식을 얻고 싶다면 아래의 주소에서 확인을 하자.
http://java.sun.com/developer/technicalArticles/WebServices/jaxb/


Maven을 사용하고 있다면 Pom.xml에 Dependency를 추가하여 필요한 라이브러리를 다운받자. 

         <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.0.5</version>
        </dependency>


Java annotation을 사용하여 편리하게 어떤 내용을 XML에 포함 시킬것인가 말것인가, 그리고 어떤 이름으로 XML에 표현할 것인가를 나타낼 수 있다.


아래 예제 소스는 Hibernate Entity class로써 DB table에 매핑되는 데이터를 나타낸다.

굵은 글쓰로 나타낸것이 JAXB에서 참조하는 annotation이다.

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;


@Entity
@Table(name="vct")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Vct extends AbstractEntity<Long>{
   
    /**
     *
     */
    private static final long serialVersionUID = 8595404797996134818L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
   
    @ManyToOne(targetEntity = VctInfo.class, optional = false)
    @JoinColumn(name = "vctinfo_id", nullable = false, updatable = false)
    @org.hibernate.annotations.ForeignKey(name = "fk_vct_vctinfo")
    private VctInfo vctinfo;
   
    @ManyToOne(targetEntity = Uct.class, optional = false)
    @JoinColumn(name = "uct_id", nullable = false, updatable = false)
    @org.hibernate.annotations.ForeignKey(name = "fk_vct_uct")
    private Uct uct;
   
    @Column(name = "name", length = 100, nullable = false)
    private String name;
   
    @Column(name="vct_parentid" , nullable=true)
    private Long vctParentId;
   
    @Column(name="sort_order" , nullable=false)
    private Integer sortOrder;
   
    @Column(name="visible" , nullable=false)
    private CategoryVisible visible;
   
    @Column(name="moved" , nullable=false)
    private CategoryMoved moved;
   
    @Column(name="shortcut" , nullable=false)
    private CategoryType shortcut;
   
    @Column(name="hierachy" , length=1024, nullable=false)
    private String hierachy;
   
    @Column(name="hierachyStr" , length=1024, nullable=false)
    private String hierachyStr;   

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public VctInfo getVctinfo() {
        return vctinfo;
    }

    public void setVctinfo(VctInfo vctinfo) {
        this.vctinfo = vctinfo;
    }

    public Uct getUct() {
        return uct;
    }

    public void setUct(Uct uct) {
        this.uct = uct;
    }
   
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getVctParentId() {
        return vctParentId;
    }

    public void setVctParentId(Long vctParentId) {
        this.vctParentId = vctParentId;
    }

    public Integer getSortOrder() {
        return sortOrder;
    }

    public void setSortOrder(Integer sortOrder) {
        this.sortOrder = sortOrder;
    }

    public CategoryVisible getVisible() {
        return visible;
    }

    public void setVisible(CategoryVisible visible) {
        this.visible = visible;
    }

    public CategoryMoved getMoved() {
        return moved;
    }

    public void setMoved(CategoryMoved moved) {
        this.moved = moved;
    }

    public CategoryType getShortcut() {
        return shortcut;
    }

    public void setShortcut(CategoryType shortcut) {
        this.shortcut = shortcut;
    }

    public String getHierachy() {
        return hierachy;
    }

    public void setHierachy(String hierachy) {
        this.hierachy = hierachy;
    }
   
    public String getHierachyStr() {
        return hierachyStr;
    }

    public void setHierachyStr(String hierachyStr) {
        this.hierachyStr = hierachyStr;
    }

    @Override
    public boolean equals(final Object other) {
        if (!(other instanceof Vct))
            return false;
        Vct castOther = (Vct) other;
        return new EqualsBuilder().append(id, castOther.id).isEquals();
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this).append("id", id).append("vctinfo",
                vctinfo).append("uct", uct).append("vctParentId", vctParentId)
                .append("sortOrder", sortOrder).append("visible", visible)
                .append("moved", moved).append("shortcut", shortcut).append(
                        "hierachy", hierachy).append("hierachyStr", hierachyStr).toString();
    }
}


이 Entity class를 XML로 변환하고 싶다고 한다면 다음과 같이 해주면 된다.

        JAXBContext context = JAXBContext.newInstance(Vct.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        m.marshal( vct, response.getWriter());

물론 vct에는 어떤 값이 들어있어야 한다.


이 Vct라는 class의 List값을 출력하고 싶을때는 다음과 같은 List용 class를 생성한다.

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "vcts")
@XmlAccessorType(XmlAccessType.FIELD)
public class VctList {

    @XmlElement(name = "vct")
    protected List<Vct> vcts;

    public List<Vct> getVctList() {
        if (vcts == null) {
            vcts = new ArrayList<Vct>();
        }
        return this.vcts;
    }

    public void setVctList(List<Vct> vcts) {
        this.vcts = vcts;
    }
}

VctList라는 class는 Vct의 리스트를 가지고 있는 class이고,

annotation으로 vcts라는 이름으로 XML의 root element를 만든다고 나타냈다.

아래의 class는 Spring의 View interface를 구현하여 웹상에서 xml을 바로 볼수 있게 해줄 목적으로 만들었다.

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import org.springframework.web.servlet.View;


public class VctXmlView implements View {

    private Object modelKeyName;

    public VctXmlView(Object key) {
        modelKeyName = key;
    }

    @Override
    public String getContentType() {
        return "text/xml;charset=utf-8";
    }

    @SuppressWarnings("unchecked")
    @Override
    public void render(Map model, HttpServletRequest request,
            HttpServletResponse response) throws Exception {

        if (model == null) {
            return;
        }
        response.setContentType(getContentType());
        List<Vct> vcts = (List<Vct>) model.get(modelKeyName);
        VctList vctList = new VctList();
        vctList.setVctList(vcts);

        if (vcts == null) {
            return;
        }

        JAXBContext context = JAXBContext.newInstance(VctList.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        m.marshal(vctList, response.getWriter());

    }
}

실행한 결과는 다음과 같다.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<vcts>
<vct>
<id>1</id>
<vctinfo>
<country>
<id>1</id>
<name>KR</name>
  </country>
<createUser>
<email></email>
<name></name>
<password></password>
<readLevel></readLevel>
<writeLevel></writeLevel>
  </createUser>
<createdAt>2009-05-18T15:05:51+09:00</createdAt>
<description></description>
<language>
<description>한국어</description>
<name>Ko</name>
</language>
            <name></name>
</vctinfo>
<uct>
<createUser>
<email></email>
<name>breeze</name>
<password></password>
                <readLevel>uctVct</readLevel>
<writeLevel>uctVct</writeLevel>
</createUser>
<createdAt>2009-05-14T14:28:10+09:00</createdAt>
<description></description>
<hierachy>6 7 8 9 11</hierachy>
            <hierachyStr></hierachyStr>
<name>itemshop</name>
<parentId>9</parentId>
</uct>
<name>아이템몰</name>
<sortOrder>1</sortOrder>
        <visible>show</visible>
<moved>notMoved</moved>
<shortcut>shortcut</shortcut>
<hierachy>1</hierachy>
<hierachyStr>아이템몰</hierachyStr>
</vct>
    <vct>
<id>2</id>
<vctinfo>
<country>
<id>1</id>
<name>KR</name>
</country>
            <createUser>
<email></email>
<name>breeze</name>
<password></password>
<readLevel>uctVct</readLevel>
<writeLevel>uctVct</writeLevel>
</createUser>
            <createdAt>2009-05-18T15:05:51+09:00</createdAt>
<description>Shop에서 사용할 VCT</description>
<language>
<description>한국어</description>
<name>Ko</name>
</language>
<name>Itene Shop</name>
        </vctinfo>
<uct>
<createUser>
<email></email>
<name>breeze</name>
<password></password>
<readLevel>uctVct</readLevel>
                <writeLevel>uctVct</writeLevel>
</createUser>
<createdAt>2009-05-19T16:23:26+09:00</createdAt>
<description>hair chage item</description>
<hierachy>6 7 8 9 11 20</hierachy>
<hierachyStr></hierachyStr>
            <name>Hair change</name>
<parentId>11</parentId>
</uct>
<name></name>
<vctParentId>1</vctParentId>
<sortOrder>1</sortOrder>
        <visible>show</visible>
<moved>notMoved</moved>
<shortcut>shortcut</shortcut>
<hierachy>1 2</hierachy>
<hierachyStr></hierachyStr>
</vct>
</vcts>


Posted by Breeze.Kang

댓글을 달아 주세요

  1. 으아니.. 프로그래밍 포스팅도하시네요? ㅎㅎㅎ 잘지내시죠? 저도 요기능 필요해서 검색하다가 눈에 익어서 들어왔네요.

    2009/06/03 17:01 [ ADDR : EDIT/ DEL : REPLY ]
    • Breeze

      ㅋㅋ 라이덴 오랜만!
      아, 이젠 프로그래밍 관련 포스팅도 하려고~

      2009/06/03 17:34 [ ADDR : EDIT/ DEL ]
  2. 오 좋네요. 좋은정보좀 많이 포스팅해주세요. 전 요새 트위터로 뭐할거 없을까 뒤져보는 중이에요. 트위터아이디 raidenz 입니다 :) 아 결혼도 곧 합니다. 연락드립죠. ㅎㅎ

    2009/06/03 18:07 [ ADDR : EDIT/ DEL : REPLY ]