2013년 12월 30일 월요일

Spring Exclude Interceptor

Interceptor와 Filter의 차이는?
Spring의 Interceptor와 Servlet의 Filter의 기능상의 차이는 없다. 지정된 URL이 호출되기 전에 실행된다는 것은 같다.
하지만 호출되는 시점에서 그 차이가 발생한다.

Spring의 DispatcherServlet을 기준으로 Spring 호출 전에 Filter가 호출되고, Interceptor는 Spring의 Controller가 호출되기 전에 실행된다.



Spring Intercepter을 적용하는 방법

HandlerInterceptorAdapter  Class을 상속받아 사용자 Interceptor을 만든다.

Override 메서드는 3가지가 있는데 그 기능은 아래와 같다.
  • preHandle - Controller 실행 요청전
  • postHandle - view(jsp)로 forward되기 전에
  • afterCompletion - 끝난뒤

Spring-Config에 설정
  1. mapping path을 지정하지 않는 경우- “LocaleChangeInterceptor” 처럼 - 모든 URL에 대하여 호출된다.
  2. 특정 URL에 대하여 제외하고 싶은 경우 “exclude-mapping”을 사용한다.
  3. 특정 URL에 대해서만 호출을 지정할수 있다.

<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
<mvc:interceptor>
   <mvc:mapping path="/**"/>
   <exclude-mapping path="/admin/**"/>
   <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
   <mvc:mapping path="/secure/*"/>
   <bean class="org.example.SecurityInterceptor" />
</mvc:interceptor>

2013년 12월 6일 금요일

비유클리드 기하학

일반상대성이론을 공부하다가, 가속(중력도 가속계)하는 물체의 공간은 휘어진다는 것을 설명하면서 비유클리드 기하학에대한 개념이 나왔다. 좀더 이해를 위해서 여기 정리해본다.


유클리드 기하학(-幾何學, Euclidean geometry)은 그리스의 수학자 유클리드(Euclid, C330?~BC275?)에 의해 구축된 수학 체계로, 그의 《원론》은 기하학에 관한 최초의 체계적인 논의로 알려져 있다. 유클리드의 방법은 직관적으로 인지되는 공리를 참으로 간주함에 바탕을 두며, 그것들로부터 연역적으로 명제(정리)를 이끌어낸다. 이러한 공리론적 구성법에서는 직선 · 평면 등의 기본적인 개념이 무정의(無定意) 요소이다. 2천년 동안 유클리드의 공리는 어떤 정리도 유도해 낼 수 있을 만큼 직관적으로 매우 명백한 것으로 보였고, 절대적인 의미에서 참으로 간주되었다.


유클리드 공준
  1. 임의의 점과 다른 한 점을 연결하는 직선은 단 하나뿐이다.
  2. 임의의 선분은 양끝으로 얼마든지 연장할 수 있다.
  3. 임의의 점을 중심으로 하고 임의의 길이를 반지름으로 하는 원을 그릴 수 있다.
  4. 직각은 모두 서로 같다.
  5. 두 직선이 한 직선과 만날 때, 같은 쪽에 있는 내각의 합이 2직각(180˚)보다 작으면 이 두 직선을 연장할 때 2직각보다 작은 내각을 이루는 쪽에서 반드시 만난다.



비유클리드 기하학의 탄생
유클리드의 다섯번째 공준인 평행선 공준은 다른 네 공준이 자와 컴퍼스를 이용해 경험적으로 이해될 수 있는 것과 달리 복잡하고 직관적이지 못하다. 따라서 몇몇 수학자들은 이 공준이 다른 명제들로부터 증명될 수 있을지도 모른다고 생각했다. 또한 다른 몇몇 수학자들은 이 공준의 부정을 가정하여 모순을 이끌어내려고 하였다.


대표적으로 이탈리아의 수학자 사케리(Girolamo Saccheri, 1667~1733)는 다섯 번째 공리를 부정해 모순을 증명하려고 했다. 그 과정에서 사케리는 새로운 정리를 많이 얻었으나 새로운 사실을 알았음에도 불구하고 다섯 번째 공리의 모순을 얻지 못했다는 이유로 연구한 것을 모두 버렸다. 결국 19세기에 이탈리아의 수학자 벨트라미(Eugenio Beltrami, 1835~1899)에 의해 이 공준은 증명될 수 없음이 밝혀졌고, 또한 이것의 반대 상황을 가정해도 모순이 없다는 것이 밝혀졌다. 1829년 러시아의 니콜라이 이바노비치 로바쳅스키(Nikolai Ivanovich Lobachevskii, 1792~1856)는 평행선 공리를 도입하지 않은 새로운 기하학을 한 러시아 저널에 발표하였다.


독일의 카를 프리드리히 가우스(Karl Friedrich Gauss, 1777~1855)는 제5공준 대신 평행선을 몇 개나 그을 수 있다는 공리에서 출발하여도, 모순이 없는 비유클리드 기하학(쌍곡기하학)이 만들어진다는 것을 보여주었다. 이 비유클리드 기하학 연구는 발표되지 않았고 1831년 가우스의 친구 볼프강 보여이의 아들인 헝가리의 보여이 야노시(헝가리어: Bolyai János, 1802~1860)에 의해서 연구되어 그의 아버지의 논문에 발표되었다.


1854년 가우스의 제자인 리만(Georg Friedrich Bernhard Riemann, 1826~1866)은 기하학의 기초에 관한 강연을 했다. 그는 곡률이라는 개념을 도입해 다섯 번째 공리가 성립하는 공간은 곡률이 0인 공간(유클리드 기하학)이고 평행선 공리 없이, 곡률이 1이면 구면처럼 평행선이 없는 공간(구면기하학 또는 타원기하학), 곡률이 -1이면 평행선이 무수히 많은 공간(쌍곡기하학)이 된다는 것을 이론으로 발표했다. 나아가 곡률이 정해진 수로 나타나지 않는 공간에 대한 이론도 세워 곡면 위의 기하학으로 일반화하였다.


비유클리드 기하학의 중요성
비유클리드 기하학과 공간의 성질에 대한 이해가 점진적으로 이루어지면서 유클리드 기하학의 관점은 크게 흔들리게 되었고, 논리와 산술에서 논쟁의 주제로 남게 되었다. 로바쳅스키는 자신의 신기하학(비유클리드 기하학)은 천문학 연구 및 미소(微小) 현상의 범위 연구에 주어진다고 생각하고, 통상의 유클리드 기하학은 지구상의 차원에 적용된다고 했다. 이 견해는 칸트의 인식론에서 얘기되는 공간의 아 프리오리설에 큰 타격을 가했다. 로바쳅스키에 의하면, 인식은 지각을 통해 획득되는 것이며, 의식에 선천적으로 부여된 무엇인가의 작용에 의한 것이 아니다.
새로운 기하학이 발표된 지 약 60년 뒤, 아인슈타인(Albert Einstein, 1879~1955)은 우주가 평평하지 않고 중력에 의해서 휘어 있음을 보였다. 그리고 일반상대성이론은 공간에 대한 기초 이론을 비유클리드 기하학에서 찾았다. 이처럼 유클리드의 다섯 번째 공리에 관한 의심에서 출발한 비유클리드 기하학은 미시공간과 극대 공간을 해석하는 이론으로 폭넓게 사용되고 있다.


“나는 기하학의 이러한 해석이 대단히 중요하다고 생각한다. 만일 내가 그 기하학을 몰랐다면 나는 결코 상대성 이론을 만들어 낼 수 없었을 것이다.” – 알버트 아인슈타인



비유클리드 기하학과 유클리드 기하학의 차이점



유클리드기하학
쌍곡기하학
구면기하학
평행선
단 한개 존재한다.
수없이 많이 존재한다.
존재하지 않는다.
삼각형의
세 내각의 합
*180°
*삼각형의 넓이에 관계없이 세 내각의 크기의 합은 일정하다.
*180°보다 작다.
*삼각형의 넓이가 넓어질수록 세 내각의 크기의 합은 작아진다.
*180°보다 크다.
*삼각형의 넓이가 넓어질수록 세 내각의 크기의 합은 커진다.
측지선
직선
*길이는 무한대이다.
*두 점을 지나는 직선은 단 한 개다.
곡선
*길이는 무한대이다.
*두 점을 지나는 직선은 단 한 개다.
대원
*길이가 유한이고, 일정하다.
*두 점을 지나는 직선은 단 한 개로 한정되지 않는다.


2013년 11월 29일 금요일

What is the way of Direct Memory Access in Java?

Java was initially designed as a safe, managed environment. Nevertheless, Java HotSpot VM contains a “backdoor” that provides a number of low-level operations to manipulate memory and threads directly.
This backdoor class – sun.misc.Unsafe – is widely used by JDK itself in packages like “java.nio” or “java.util.concurrent”. However, using this backdoor is certainly not suggested for use in the production environment, because this API is extremely dangerous, non-portable, and volatile. The Unsafe class provides an easy way to look into HotSpot JVM internals and to do some tricks. Sometimes it can be used to study VM internals without C++ code debugging, sometimes it can be leveraged for profiling and development tools.

How to use ‘sun.misc.Unsafe’
package com.blogspot.daddycat.test;

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public class UnsafeTest {

   public static void main(String... args) {
       Unsafe unsafe = null;

       try {
           Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
           field.setAccessible(true);
           unsafe = (sun.misc.Unsafe) field.get(null);
       } catch (Exception e) {
           throw new AssertionError(e);
       }

       int ten = 10;
       byte size = 1;
       long mem = unsafe.allocateMemory(size);
       unsafe.putAddress(mem, ten);
       long readValue = unsafe.getAddress(mem);
       System.out.println("Val: " + readValue);

       try {
Object o = unsafe.allocateInstance(java.lang.String.class);
System.out.println("Type: "+o.getClass().getCanonicalName());
} catch (InstantiationException e) {
e.printStackTrace();
}
   }
}

Console log
Val: 10
Type: java.lang.String

2013년 11월 27일 수요일

The Protocol Semantics of HTTP

There are rules. In a RESTful system, clients and servers interact only by sending each other messages that follow a predefined protocol.
The HTTP standard defines eight different kinds of messages, These four are the most commonly used:

GET
Get a representation of this resource.

DELETE
Destroy this resource.

POST
Create a new resource underneath this one, based on the given representation.

PUT
Replace this state of this resource with the one described in the given representation.

These two methods are mostly used as a client explores an API:

HEAD
Get the headers that would be sent along with a representation of this resource, but no the represntation itself.

OPTIONS
Discover with HTTP methods this resource respons to.

The other two methods defined in the HTTP standard, CONNECT and TRACE, are only used with HTTP proxies. I won’t be covering them.

I recommend that API designers consider a ninth HTTP method, defined not in the HTTP standard but in a supplement, RFC 5789:

PATCH
Modify part of the state of this resource based on the given representation. If some bit of resource state is not mentioned in the given representation, leave it alone.

PATCH is like PUT, but allows for fine-grained changes to resource state.

2013년 11월 26일 화요일

log4j의 SMTPAppender


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<appender name="mailAppender" class="org.apache.log4j.net.SMTPAppender">
<param name="BufferSize" value="50" />
<param name="SMTPHost" value="sniper.xxxx.co.kr" />
<param name="SMTPPort" value="25" />
<param name="SMTPUsername" value="inter999@xxxx.co.kr" />
<param name="SMTPPassword" value="mypassword" />
<param name="From" value="inter999@xxxx.co.kr" />
<param name="To" value="myID@gmail.com" />
<param name="Subject" value="Testing Log4j mail notification" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{ISO8601}]%n%n%-5p%n%n%c%n%n%m%n%n" />
</layout>
<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="error" />
<param name="LevelMax" value="fatal" />
</filter>
</appender>

<root>
<priority value="info" />
<appender-ref ref="mailAppender" />
</root>
</log4j:configuration>
log4j을 사용하지 않는 프로젝트는 없겠죠. 가장 많이 쓰는 Appender는 

ConsoleAppender, DailyRollingFileAppender, FileAppender 이정도 일것이다.

하지만 알고 보면 유용한 Appender들이 있으니
JDBCAppender, JMSAppender, SMTPAppender, SocketAppender, TelnetAppender 등이 있다.

2013년 11월 22일 금요일

Remote Intent를 이용한 안드로이드 장치 간 비동기식 메시지 푸싱 프레임워크

안드로이드 장치용으로 모바일 애플리케이션을 개발할 때 안드로이드의 인텐트(intent)는 안드로이드 장치에서 애플리케이션 내부와 애플리케이션 간의 메시지 전달 메커니즘으로 사용된다. 그러나 안드로이드의 인텐트는 서로 다른 안드로이드 장치 간의 인텐트를 이용한 메시지 전송은 지원되지 않고 있다. 만약 서로 다른 안드로이드 장치 간에 인텐트를 전송하는 기능이 지원된다면 좀 더 다양한 애플리케이션 구현을 쉽게 할 수 있다. 서로 다른 안드로이드 장치 간에 메시지 전송을 할 때 Socket을 이용하여 메시지를 전송 할 수는 있지만, 항상 연결을 유지하여야 한다는 단점이 있다. 따라서 본 논문에서는 서로 다른 안드로이드 장치 간의 메시지 전송을 위한 BRIF(Broadcasting Remote Intent FrameWork) 프레임워크를 제안한다. BRIF 프레임워크는 구글의 C2DM 서비스를 이용하여 서로 다른 안드로이드 장치 간의 메시지 전송을 비동기적으로 푸쉬하는 기능을 서비스하는 프레임워크다. 이것은 기존의 로컬 기기내에서 인텐트를 사용하는 것과 동일한 방법으로 원격지에 사용자 정의 인텐트를 보내는 코드를 쉽게 작성할 수 있다.

키워드 : 애플리케이션, 프레임워크, 인텐트, 안드로이드, 비동기

문서보기

안드로이드 애플리케이션을 테스트하기 위한 액티비티 기반의 테스트 케이스 생성 방법


사용자가 원하는 프로그램을 자유롭게 설치/삭제 할 수 있는 특징을 가진 스마트폰의 등장으로 인해, 수많은 개발자들이 스마트폰 애플리케이션 개발 시장에 뛰어들면서 좋은 애플리케이션을 빨리 개발하려는 경쟁이 더욱 치열해지고 있다. 그러나 안드로이드 환경은 애플리케이션 개발 및 배포 절차가 간단하여 누구나 쉽게 개발에 참여할 수 있어서 충분히 검증되지 않은 애플리케이션들이 배포될 가능성이 높다. 따라서 적은 부담으로 안드로이드 기반의 애플리케이션을 검증할 수 있는 체계적인 방법이 필요하다. 이에 본 논문에서는 안드로이드 애플리케이션을 위한 GUI 기반의 테스트 시나리오 자동 생성 방법을 제시한다. 자동화된 테스트 시나리오 생성을 통해 테스트에 소요되는 시간을 줄임으로써 테스트 단계에서의 생산성을 향상시킬 수 있다.

키워드 : 안드로이드 애플리케이션, GUI 테스팅, 테스트 케이스 생성

문서보기

2013년 11월 21일 목요일

Durable Subscriptions Topic

JMS Topic 에서는 Subscriber가 Server에 접속한 시점부터 발생한 Message을 받아오게 되어 있다. Subscriber가 종료되어 있는 시점에서 발생한 Message는 다시 받을 수 없게 되어 있다. 이러한 방식의 Nondurable Subscription이라한다. 반면  Durable Subscription의 경우는 Subscriber가 종료되어 있는 동안 발생한 Message을 다음 시작시점에 받아오게 되어 있다. 즉 누락되는 Message없이 Topic을 사용할수 있다는 것이다.

Nondurable Subscribers and Subscriptions


A Durable Subscriber and Subscription

Durable Subscriber Code


package example.durabletopic;

import java.util.Date;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Producer {

private static String url = ActiveMQConnection.DEFAULT_BROKER_URL;

public static void main(String[] args) throws JMSException {

ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(url);
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);

Topic topic = session.createTopic("example.topic");

MessageProducer producer = session.createProducer(topic);

TextMessage message = session.createTextMessage();

for(int i=0; i<1000; i++) {
message.setStringProperty("date", new Date().toString());
message.setText("HELLO JMS WORLD");
producer.send(message);
System.out.println("Sent message '" + message + "'");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

connection.close();
}
}
Message을 보내는 쪽에서는 Nondurable이든 Durable이든 차이가 없다. 차이는 Message을 받는 쪽에서 생긴다.


package example.durabletopic;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicSubscriber;
import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;

public class Consumers {
public static void main(String[] args) throws JMSException {
new Consumer("C1").start();
}
}

class Consumer extends Thread {

private static String url = ActiveMQConnection.DEFAULT_BROKER_URL;
private String clientID;
public Consumer(String clientID) {
this.clientID = clientID;
}

@Override
public void run() {
Connection connection = null;
try {
ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
url);
connection = connectionFactory.createConnection();
connection.setClientID(clientID);
connection.start();

Session session = connection.createSession(false,
Session.CLIENT_ACKNOWLEDGE);

Topic topic = session.createTopic("example.topic");

TopicSubscriber durable = session.createDurableSubscriber(topic, "test_durable");

MessageListener listner = new MessageListener() {
public void onMessage(Message message) {
try {
String currentDate = message.getStringProperty("date");
System.out.println("Date:" + currentDate);

if (message instanceof TextMessage) {
TextMessage textMessage = (TextMessage) message;
System.out.println("Received message"
+ textMessage.getText() + "'");
}
} catch (JMSException e) {
System.out.println("Caught:" + e);
e.printStackTrace();
}
}
};
durable.setMessageListener(listner);
System.out.println("waiting...");
while (true) {
try {
this.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

} catch (JMSException e) {
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}

}

}
Client의 Durable 속성은 “clientID”로 구분되어 서버에서 관리되기 때문에 ClientID는 전체에서 유니크 해야 한다.
최초 clientID로 접속한 이후 부터 Durable 속성이 적용된다. 만일 서버에 등록된 ClientID을 삭제하고 싶다면 “session.unsubscribe(name)”을 사용하면되고, 각 JMS 서버에서 관리하는 설정 값을 사용해도 된다.

ETL 솔루션 환경

ETL 솔루션 환경 하둡은 대용량 데이터를 값싸고 빠르게 분석할 수 있는 길을 만들어줬다. 통계분석 엔진인 “R”역시 하둡 못지 않게 관심을 받고 있다. 빅데이터 역시 데이터라는 점을 볼때 분산처리와 분석 그 이전에 데이터 품질 등 데이...