2013년 6월 24일 월요일

javadoc - ant script

0. install JAutodoc eclipse plug-in
 - it helps you to auto generate javadoc comments

1. create javadoc in eclipse

2. run ant script
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="javadoc">
    <target name="javadoc">
        <javadoc package="java" access="package"
        additionalparam=" -encoding UTF-8 -charset UTF-8 -docencoding UTF-8"
        author="true"
        classpath="libraries.jar"
        destdir="doc"
        doctitle="title"
        nodeprecated="false"
        nodeprecatedlist="false"
        noindex="false"
        nonavbar="false"
        notree="false"
        packagenames="packagenames"
        source="1.6"
        sourcepath="src/main/java;"
        splitindex="true"
        use="true"
        version="true"/>
    </target>
</project>

3. then you can see your documents in the doc folder

subversion - install subversion server in centos

0. yum install subversion

1. mkdir /home/svn

2. svnadmin create trunk
 - create repository (trunk... whatever) then,
 - move to the trunk

3. svnserve.conf
 - anon-access = none
 - auth-access = write
 - password-db = passwd
 - realm =  repo-xxx

4.  repo/conf/passwd
 - create user

5. svnserve -d -r /home/svn
 - run daemon
 - checkout url: svn://ipaddress/trunk/

2013년 6월 19일 수요일

jsessionid - tomcat, jetty 세션 공유

0. 하나의 서버에 tomcat, jetty 두개의 WAS를 서비스 하는 경우 세션을 공유하는 문제가 발생한다. 이건 JSESSIONID 때문에 발생하는 문제다.
 - 세션을 공유? 동일한 브라우저에서 tomcat 세션 생성 --> jetty 세션 생성 --> tomcat에 다시 접근하면 이전에 생성된 세션이 날라간다.

1. JSESSIONID?
 - JSESSIONID is a cookie generated by Servlet container like Tomcat or Jetty and used for session management in J2EE web application for http protocol.
 - 즉 tomcat 이건 jetty 건 J2EE web application 이라 디폴트로 JSESSIONID 라는 이름으로 쿠키를 관리한다. 
 - 따라서, 한 쪽에서 이름을 바꿔서 사용하면 세션을 공유하는 문제를 해결할 수 있다.

2. jetty 설정 방법
 - web.xml
  <context-param>
    <param-name>org.mortbay.jetty.servlet.SessionCookie</param-name>
    <param-value>JSESSIONID2</param-value>
  </context-param>

3. 참고
 - Examples of the names that some programming languages use when naming their cookie include JSESSIONID (JSP), PHPSESSID (PHP), and ASPSESSIONID (Microsoft ASP).

2013년 6월 16일 일요일

Form-based File Upload in HTML

0. form-based file upload는 어디에 정의 되어 있을까?

1. Abstract
 - Currently, HTML forms allow the producer of the form to request information from the user reading the form. These forms have proven useful in a wide variety of applications in which input from the user is necessary. However, this capability is limited because HTML forms don't provide a way to ask the user to submit files of data. Since file-upload is a feature that will benefit many applications, this proposes an extension to HTML to allow information providers to express file upload requests uniformly, and a MIME compatible representation for file upload responses.

 2. HTML forms with file submission
 - This proposal makes two changes to HTML:
 1) Add a FILE option for the TYPE attribute of INPUT.
 2) Allow an ACCEPT attribute for INPUT tag, which is a list of media types or type patterns allowed for the input.

 In addition, it defines a new MIME media type, multipart/form-data, and specifies the behavior of HTML user agents when interpreting a form with ENCTYPE="multipart/form-data" and/or <input type="file" /> tags.
(POST form data의 default mime type 인 application/x-www-form-urlencoded 은 큰 바이너리 데이터나, non-ASCII 문자열을 전송하기에 비효율적이다)

 - example
<form action="_URL_" enctype="multipart/form-data" method="POST">
    File to process: <input name="userfile1" type="file" />
    <input type="submit" value="Send File" />
</form>

* ref
http://www.faqs.org/rfcs/rfc1867.html
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2

2013년 6월 12일 수요일

oracle, postgreSQL - migration

  Oracle postgreSQL
 Data Type NUMBER(p) SMALLINT - 2 bytes 
INTEGER - 4 bytes 
BIGINT - 8 bytes 
NUMBER(p,s) NUMERIC(p,s) 
REAL – 4 bytes, 6 decimal places 
DOUBLE PRECISION – 8 bytes, 15 decimal places
X SERIAL
VARCHAR2(size) where maximum size is 4000 CHARACTER VARYING(n) where maximum n is 1 GB
VARCHAR(n) is an alias 
CHAR(size) where maximum size is 2000  CHARACTER(n) where maximum n is 1 GB
CHAR(n) is an alias
It’s suggested that you use TEXT if n > 10 MB
LONG - Character data of variable length up to 2 GB TEXT – variable length up to 1 GB
DATE – holds date and time TIMESTAMP 
TIMESTAMP
X DATE – holds only the date
X TIME – holds only the time (00:00:00.00 – 23:59:59.99)
RAW(size) – binary data of length size bytes (max 2000)
LONG RAW – binary data or variable length up to 2GB 
BYTEA
X BIT(n) – fixed length string of 1’s and 0’s
BIT VARYING(n) – variable length string of 1’s and 0’s 
CLOB – character large object (max 4GB)  TEXT (max 1GB) 
BLOB – binary large object (max 4GB)  BYTEA (max 1GB) 
ROWID  X
X BOOLEAN
X Network address data types: INET, MACADDR, CIDR.
SQL Syntax,
Functions,
Sequences,
Etc.
select sysdate from dual  select ‘now’::datetime  
CREATE SEQUENCE seqname [ INCREMENT BY integer ]
[ MINVALUE integer ] [ MAXVALUE integer ]
[ START
WITH integer ] [ CACHE integer ] [ CYCLE | NOCYCLE ]
CREATE SEQUENCE seqname [ INCREMENT increment ]
[ MINVALUE minvalue ] [ MAXVALUE maxvalue ]
[ START start ] [ CACHE cache ] [ CYCLE ] 
sequence_name.nextval; nextval(‘sequence_name’); 
select sequence_name.nextval from dual;  select nextval(‘sequence_name’);
SELECT product_id,
       DECODE (warehouse_id, 1, ’Southlake’,
                             2, ’San Francisco’,
                             3, ’New Jersey’,
                             4, ’Seattle’,
                             ’Non-domestic’)
       quantity_on_hand 
FROM inventories 
SELECT a, 
       CASE WHEN a=1 THEN 'one' 
            WHEN a=2 THEN 'two' 
            ELSE 'other' 
       END 
FROM test 
select employeeid,
       NVL(hire_date, sysdate)
from employee
where employeeid = 10; 
select employeeid,
       coalesce(hire_date, 'now'::datetime)
from employee 
where employeeid = 10; 
Outer join – “(+)” X
Hierarchical queries – “CONNECT BY” X
SELECT product_id FROM inventories
MINUS
SELECT product_id FROM order_items;
SELECT product_id FROM inventories
EXCEPT
SELECT product_id FROM order_items;
select unique col1, col2 from table1 select distinct col1, col2 from table1
select id,name from employee where id >    = 10;
// There are spaces and tabs between “>” and “=” 
select id,name from employee where id >= 10; 
select mod(10,4) from dual; select 10 % 4; 
select * from employees where rownum < 10 order by name; select * from employees order by name limit 10;
select rownum, name from employees order by name; select oid, name from employees order by name; 

2013년 6월 11일 화요일

http - session & cookie

0. 지난 1년간 web server를 개발한다고 앉아 있으면서 http session이 어떻게 동작하는지 모르고 있었다니...-_-;

1. http session & http cookie
 - session : server에 저장되는 정보
 - cookie : client에 저장되는 정보 (브라우저 마다 저장되는 위치나 형식이 다르다.)

2. login session? session cookie?
 - session을 관리하는 가장 일반적인 방법이 login 시 session을 생성하고, client가 생성된 session id를 cookie에 저장하여 이후 요청 할 때 마다 이 id를 이용하는 것이다. 그래서 login session, session cookie라는 말을 사용하는 것 같다.

3. http header
 - session 정보는 http header에 담겨서 전달된다.
 - requests field 중
Cookiean HTTP cookie previously sent by the server with Set-Cookie (below)
 - responses field 중
Set-CookieAn HTTP cookie

4. how?


















5. URLConnection sample code (client)
 - java application client 에서 session을 관리하기 위해서는 cookie를 받아서 저장 후 다음 request 시 사용해준다. 아래는 cookie 정보를 string으로 변환하는 예. (Collection 객체로 return 된다.)

HttpURLConnection connection = null;
Map m = connection.getHeaderFields();
if(m.containsKey("Set-Cookie")) {
    Collection c =(Collection)m.get("Set-Cookie");
    for(Iterator i = c.iterator(); i.hasNext(); ) {
        cookie = (String)i.next();
    }
}

http - java http client

0. http client가 구현된 java application을 보다가 서로 다른 package를 사용하고 있는 것이 있어서 찾아 봤다.

 - java.net.* (java package - HttpURLConnection)
 - org.apache.commons.httpclient.* (apache commons project - HTTPClient)

1. which one?

 - java.net.* package는 예상되는 대로 general-purpose, lightweight application에 적합하다. 아래 android blog에서 참조 했는데, 이런 이유로 확장성이 더욱 좋기 때문에 Gingerbread 이후에서는 HttpURLConnection API를 사용하도록 권장하고 있다.

 - apache package는 다양한 API를 제공하는 장점이 있다. 코드 보기도 훨씬 편한 것 같다.

* ref

 - http://hc.apache.org/httpclient-3.x/
 - http://android-developers.blogspot.ca/2011/09/androids-http-clients.html

eclipse - tabs & whitespace

0. why?
 - eclipse editor에서는 보이지 않지만 whitespace와 tabs이 섞여 있으면 notepad 같은 editor에서 indent가 뒤죽박죽이다. 그래서 whitespace를 사용해준다. spacebar를 계속 눌러주는 건 아니고 아래 설정으로 편하게 사용한다.

1. For the default text editor:
  • General > Editors > Text Editors > Insert spaces for tabs (check it)
  • General > Editors > Text Editors > Show whitespace characters (check it) - 화면에 whitespace를 점으로 보여준다. (보기 불편하면 skip)
2. For Java:
  • Java > Preferences > Code Style > Formatter > Edit > Indentation (choose "spaces only")
  • Rename the formatter settings profile to save it
3. tip

 - eclipse에서 Ctrl + Shift + f 를 눌러주면 자동 정렬 된다.

express - template engine integration (app.engine)

0. express에서 template engine을 사용하기 위해서 app.engine()를 사용한다.

1. 그러기 위해서 jade, ejs module 등이 아래와 같이 특정 함수를 export해 줘야 한다. 그래야 express가 rendering을 제대로 할 수 있다. 아래는 express가 2.x에서 3.x로 업그레이드 되면서 바뀐 함수 signature다.
Express 2x template engine compatibility required the following module export:
exports.compile = function(templateString, options) {
  return a Function;
};
Express 3x template engines should export the following:
exports.__express = function(filename, options, callback) {
  callback(err, string);
};
2. 이걸 구현 안 한 module은 ? 이런식으로 사용한다.
var markdown = require('some-markdown-library');

app.engine('md', function(path, options, fn){
  fs.readFile(path, 'utf8', function(err, str){
    if (err) return fn(err);
    str = markdown.parse(str).toString();
    fn(null, str);
  });
});
3. 그럼 이건 먼가?
app.engine('html', require('ejs').renderFile);
In this case EJS provides a .renderFile() method with the same signature that Express expects: (path, options, callback), though note that it aliases this method as ejs.__express internally so if you're using ".ejs" extensions you dont need to do anything.
- renderFile 함수 열어 보면 signature가 __express와 같음을 알 수 있다.


4. express 3.x 현재 버전에서 ejs module로는 template을 사용할 수 없다. (못 찾은 건지..) ejs-locals module을 사용한다. (아시는 분 계시면 댓글 좀 달아주세요.)

express - 2.x to 3.x

https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x

util - code 2 html

source code의 syntax를 구분해서 html로 변환해 준다.
http://www.palfrader.org/code/code2html/cgi/
http://www.html.am/

ejs - homepage url

ejs를 치면 http://embeddedjs.com/ 이 친구가 나오는데 -_-;;

진짜는 요기 있네~

homepage : http://www.ejscript.org/

mybatis - hashmap result

0. mybatis 의 result type이 hashmap 인 경우 각 DB vendor에 따라 key값의 대소문자 정책이 다르므로 주의해야 한다.
 - mybatis는 driver에서 올려주는 것을 그대로 return 하기 때문이다.

1. default case of keys
 - oracle : only upper case
 - mssql : any case (써 준대로...)
 - postgre : only lower case

2. column aliases를 사용하자 -_-;;

3. 혹은 이런 것도 가능하겠네.

 - http://blog.naver.com/PostView.nhn?blogId=goolungsoi&logNo=10091410173

mssql - concatenate two columns

0. postgre, orable
 - select a||b from x

1. mssql

 - select a+b from x

mina - CumulativeProtocolDecoder

0. MINA를 이용해 TCP/IP 통신을 구현하는 중 MINA IoBuffer에 하나의 msg가 쪼개지거나, 2~3개의 msg가 동시에 들어오는 현상이 있어서 구글링을 좀 했다.

1. CumulativeProtocolDecoder?
 - ProtocolDecoder that cumulates the content of received buffers to a cumulative buffer to help users implement decoders.
If the received IoBuffer is only a part of a message. decoders should cumulate received buffers to make a message complete or to postpone decoding until more buffers arrive.
 - 일단 api에 설명이 잘 나와 있다. (MINA는 문서화가 잘 안 되어 있어서 머리가 아플때가 좀 있는데 예제까지 있다.)

2. decode()
 - CumulativeProtocolDecoder 클래스의 핵심은 decode() method로 msg 처리가 끝나면 true를 리턴하면 되고, IoBuffer가 다 채워지지 않은 상태면 false를 리턴하면 된다. 
 - false를 리턴 한 후 다시 decode()가 호출 될 때 IoBuffer를 살펴 보면 이전에 받은 msg와 새로 받은 msg가 함께 들어 있다.
 - 따라서 온전한 packet인지 여부를 판단하여 모든 byte가 다 들어 올 때까지 기다리는 로직등이 구현되어야 한다.

3. tip
 - IoBuffer라는 것은 MINA에서 사용하는 byte buffer 다.
 - 혹은 ByteBuffer를 참고하면 되겠다.

 - http://docs.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html

4. sample code (extends CumulativeProtocolDecoder)
    @Override
    protected boolean doDecode(IoSession session, IoBuffer in,
            ProtocolDecoderOutput out) throws Exception {
        int start = in.position();
        int limit = in.limit();
        int winLen, pktLen = 0;
        byte[] b;
        in.position(start);
        while (in.hasRemaining()) {
            winLen = limit - start;
            // STX check
            if(in.get(start) != 0x02){
                in.skip(in.remaining());
                return true;
            }
            // header check
            if(winLen > HEADER_LENGTH){
                pktLen = getFullLength(in, start);
                // length check
                if(pktLen > winLen)
                    return false;
                // ETX check
                if(in.get(start + pktLen -1) != 0x03){
                    in.skip(in.remaining());
                    return true;
                }
            }else{
                return false;
            }
            // write
            b = new byte[pktLen];
            in.get(b);
            out.write(b);
            start = in.position();
        }
        return true;
    }

mssql - excel import

0. 방법
 - 아래 명령을 line by line으로 실행한다.

SP_CONFIGURE 'show advanced options', 1

RECONFIGURE

SP_CONFIGURE 'Ad Hoc Distributed Queries', 1

RECONFIGURE

INSERT INTO  table  (col1, col2)
SELECT * FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0','Excel 8.0;Database=C:\excelfile.xls', 'SELECT * FROM [Sheet1$]')

1. excel file
 - 파일의 형태는 다음과 같다.



express - file upload (issues include JQM)

0. express file upload
 - http://www.hacksparrow.com/handle-file-uploads-in-express-node-js.html
 - 위 사이트를 참고하면 된다. express 2.5.4 이후 버전에서는 bodyParser() middleware 만 사용하면 편리하게 이용할 수 있다.

1. issues
 - req.files가 undefined 로 나오는 것 때문에 삽질을 좀 했는데;;

 - JQM이 form을 post로 보낼 때 enctype으로 application/x-www-form-urlencoded 을 사용하기 때문에 multipart/form-data 사용하지 못한다. (XHR이 fileupload를 지원하지 않기 때문이다.)
  + 해결: data-ajax="false"  속성으로 ajax를 사용하지 않도록 하면 해결된다. 

 - app.use(express.bodyParser({keepExtensions: true, uploadDir:'./uploads'})); 이와 같이 upload dir를 지정할 경우 해당 폴더를 미리 생성해 둬야 한다. -_-;;


 - 당연히 express version도 체크해 줘야 한다.

express - app.render, res.render

0. express 공식 홈페이지
 - http://expressjs.com/

1. app.render(), res.render()
 - api reference를 봐도 이해하기가 쉽지 않네요.

2. http://stackoverflow.com/questions/15403791/in-express-js-app-render-vs-res-render-whats-the-difference
 - 그래서 위 사이트의 answers를 참고해 봅니다.


1. You can call app.render on root level and res.render only inside a route/middleware
 --> 밑에 코드 예시를 보면 res.render()의 경우 단독으로 사용되지 않고 app.get()의 콜백 함수 안에서 실행됩니다. 그래서 route/middleware라는 표현을 했습니다.

2. app.render always returns the html in the callback function 
--> html 을 리턴하는데 이건 클라이언트로 전송이 안됩니다. 즉 string이 리턴된다는 거죠. 아래 처럼 로그남기는 용도 등으로 사용할 수 있겠습니다.
whereas res.render does so only when you've specified the callback function as your third parameter. If you call res.render without the third paramter/callback function the rendered html is sent to the client with a status code of 200. Take a look at the following examples
app.render
app.render('index', {title: 'res vs app render'}, function(err, html) {
  console.log(html)
});

// logs the following string (from default index.jade)
<!DOCTYPE html><html><head><title>res vs app render</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>res vs app render</h1><p>Welcome to res vs app render</p></body></html>
res.render without third parameter
app.get('/render', function(req, res) {
  res.render('index', {title: 'res vs app render'})
})

// also renders index.jade but sends it to the client 
// with status 200 and content-type text/html on GET /render
--> 위 코드는 클라이언트로 전송이 됩니다. res.render()를 까보면 res.send()가 들어가 있습니다.
res.render with third parameter
app.get('/render', function(req, res) {
  res.render('index', {title: 'res vs app render'}, function(err, html) {
    console.log(html);
    res.send('done');
  })
})

// logs the same as app.render and sends "done" to the client instead 
// of the content of index.jade

--> third param으로 callback function이 들어가 있네요 (function(err,html){}) 즉 이경우에는 app.render() 처럼 html string이 콜백 parameter로 들어갑니다. 그 후에 res.send()를 통해서 클라이언트로 'done'을 전송했네요.