Commits

jhyun  committed 9226de8

javadocs, comments... done

  • Participants
  • Parent commits 84fc4f2

Comments (0)

Files changed (19)

 	--> @Context으로 HttpServletRequest 같은것들.
 
 
-* jersey unit-test?
+DONE * jersey unit-test?
 	CANCEL - http://jersey.java.net/nonav/documentation/latest/test-framework.html
 	DONE - TODO: destination url via app-configs + junit w/injected jersey-connection.
 	DONE - Plus
-	- TODO: Transactions
+	DONE - Transactions
 
 
 * javadocs!

File src/main/java/jhyun/mybatis_with_guice/controllers/HelloController.java

 import com.google.inject.Inject;
 import com.google.inject.servlet.RequestScoped;
 
+/**
+ * 테스트용 "Hello" 컨트롤로/리소스.
+ * 
+ * @author jhyun
+ * @since 2012-08-30
+ * 
+ */
 @Path("/hello")
 @RequestScoped
 public class HelloController {
 
 	private Logger logger = LoggerFactory.getLogger(HelloController.class);
 
+	/** very cliched... */
 	@GET
 	@Path("/greet")
 	@Produces("text/plain")
 
 	/*
 	 * SECTION: Sessions, Connections
-	 * *********************************************
 	 */
 
 	@Context
 	private HttpServletRequest request;
 
+	/** 현재 클라이언트의 HTTP세션 정보를 보여줌. (HTTP세션 연동 예시) */
 	@GET
 	@Path("/httpSession")
 	@Produces(MediaType.TEXT_PLAIN)
 	@Inject
 	private SqlSession sqlSession;
 
+	/** myBatis 세션 객체 얻기 예시. (Guice Injection와 Guice + myBatis의 예시) */
 	@GET
 	@Path("/sqlsession")
 	@Produces("text/plain")
 		return s;
 	}
 
-	/* SECTION: PLUSes ********************************************* */
+	/*
+	 * SECTION: PLUSes
+	 */
 
+	/** 덧셈 예시 (Query Parameter을 활용) */
 	@GET
 	@Path("/plusWithQueryParams")
 	@Produces(MediaType.APPLICATION_JSON)
 		return m;
 	}
 
+	/** JSON으로 인자, 결과 전달하는 덧셈 예시 */
 	@POST
 	@Path("/plusWithJson")
 	@Consumes(MediaType.APPLICATION_JSON)
 		return new PlusResult(params, params.getA() + params.getB());
 	}
 
+	/** POJO을 JSON으로 되돌리는 예시 */
 	@GET
 	@Path("/examplePlusParams")
 	@Produces(MediaType.APPLICATION_JSON)
 		return new PlusParams(3, 4);
 	}
 
+	/** XML으로 POJO 인자와 결과를 주고 받는 덧셈 예시 */
 	@POST
 	@Path("/plusWithXml")
 	@Consumes(MediaType.APPLICATION_XML)
 		return new PlusResult(params, params.getA() + params.getB());
 	}
 
-	/* SECTION: Transactions ********************************************* */
+	/*
+	 * SECTION: Transactions
+	 */
 
 	@Inject
 	private HelloMapper hello;
 
+	/** 트랜잭션 테스트용 테이블 초기화. */
 	@GET
 	@Path("/transaction/init")
 	@Produces(MediaType.TEXT_PLAIN)
 		return "Ok?";
 	}
 
+	/** 트랜잭션 테스트용 테이블 JSON으로 전체 리스팅. */
 	@GET
 	@Path("/transaction/list")
 	@Produces(MediaType.APPLICATION_JSON)
 		return hello.listAllTestingTable();
 	}
 
+	/** 트랜잭션 테이블에 값 하나 넣기. (QueryParam으로 지정한 정수값.) */
 	@GET
 	@Path("/transaction/add/{n}")
 	@Produces(MediaType.TEXT_PLAIN)
 		return "Inserted.";
 	}
 
+	/** 올바른 트랜잭션 처리 예시. (3개 넣고, 예외를 발생하여, 하위 트랜잭션 롤백 되도록.) */
 	@GET
 	@Path("/transaction/addThreeCleanly")
 	@Produces(MediaType.TEXT_PLAIN)
 		throw new Exception("JUST ABORTED FOR TESTING-PURPOSES.");
 	}
 
+	/** 틀린 트랜잭션 처리 예시. (3개 넣고, 예외를 발생했지만, @Transactional이 없어서 정상적으로 롤백 되지 않음.) */
 	@GET
 	@Path("/transaction/addThreeDirty")
 	@Produces(MediaType.TEXT_PLAIN)
 		throw new Exception("JUST ABORTED FOR TESTING-PURPOSES.");
 	}
 
+	/** 테이블의 내용들 전체 지우기. */
 	@GET
 	@Path("/transaction/deleteAll")
 	@Produces(MediaType.TEXT_PLAIN)

File src/main/java/jhyun/mybatis_with_guice/injections/GuiceJerseyListener.java

 package jhyun.mybatis_with_guice.injections;
 
+import javax.servlet.ServletContextListener;
+
 import com.google.inject.Injector;
 import com.google.inject.servlet.GuiceServletContextListener;
 
+/**
+ * web.xml에서 Context Listener으로서 지정하며, 이를 통해 기본 Injector을 생성하고 이를 Servlet
+ * Context와 연관짓는다.
+ * 
+ * 
+ * @author jhyun
+ * @since 2012-09-03
+ * 
+ * @see ServletContextListener
+ * @see GuiceServletContextListener
+ * @see Guicer
+ */
 public class GuiceJerseyListener extends GuiceServletContextListener {
 
 	@Override

File src/main/java/jhyun/mybatis_with_guice/injections/Guicer.java

 /**
  * Guice Injector.
  * 
+ * app.guice-modules으로 지정된 모듈 클래스들을 새로운 인스턴스를 만들어 초기화하고 Guice모듈로 활용한다.
+ * 
  * @author jhyun
  * @since 2012-08-30
+ * 
+ * @see <a
+ *      href="http://google-guice.googlecode.com/git/javadoc/com/google/inject/Module.html">Guice
+ *      / Module</a>
  */
 public class Guicer {
 	private static Logger logger = LoggerFactory.getLogger(Guicer.class);
 	private static Injector injector;
 
 	static {
-		//
+		// 초기화!
 		Configuration config = AppConfig.load();
 		List<Module> moduleObjs = bindModules(config);
 		injector = Guice.createInjector(moduleObjs);
 	}
 
+	/** app.guice-modules에 리스트로 지정된 전체 클래스 경로를 찾아 인스턴스를 생성하고 모듈로 사용. */
 	private static List<Module> bindModules(Configuration config) {
 		List<Object> moduleClassFqns = config.getList("app.guice-modules",
 				new ArrayList<Object>());

File src/main/java/jhyun/mybatis_with_guice/injections/JerseyServletModule.java

 import jhyun.mybatis_with_guice.config.AppConfig;
 import jhyun.mybatis_with_guice.servlets.DefaultWrapperServlet;
 
+import org.apache.commons.configuration.Configuration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.inject.servlet.ServletModule;
 import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
 
+/**
+ * Jersey요청 처리를 위해서 web.xml 대신에 Guice 바인딩으로 HTTP요청을 JAX-RS으로 처리하도록.
+ * 
+ * ServletModule을 활용하여, Guice Module들으로 Servlet Mapping을 대신함.
+ * 
+ * app.jerset-modules에 지정된 클래스FQN들으로 Guice에 바인딩하여 Jersey 리소스 클래스로 활용. 이렇게 Guice에
+ * 바인딩한 Jersey 리소스 클래스들을 또한 Guice을 통해서 초기화되고, 이들로부터 멤버들을 주입 받으므로, 아무런 추가 코드 없이
+ * Guice으로 @Inject 멤버들을 활용할 수 있다.
+ * 
+ * @author jhyun
+ * @since 2012-09-03
+ * 
+ * @see ServletModule
+ * @see GuiceContainer
+ * @see DefaultWrapperServlet
+ * @link <a href="http://code.google.com/p/google-guice/wiki/ServletModule">
+ *       ServletModule</a>
+ */
 public class JerseyServletModule extends ServletModule {
 	private static Logger logger = LoggerFactory
 			.getLogger(JerseyServletModule.class);
 		 */
 		params.put("com.sun.jersey.config.feature.Redirect", "true");
 		params.put("com.sun.jersey.api.json.POJOMappingFeature", "true");
-		//
-		serveRegex("/public/.*").with(DefaultWrapperServlet.class);
-		serve("/*").with(GuiceContainer.class, params);
+		// serving urls
+		Configuration config = AppConfig.load();
+		serveRegex(config.getString("default-serve-url-regex", "/public/.*"))
+				.with(DefaultWrapperServlet.class);
+		serve(config.getString("jersey-serve-url-pattern", "/*")).with(
+				GuiceContainer.class, params);
 	}
 
+	/**
+	 * 모든 Jersey 리소스 클래스들을 등록. 실제로 모듈로서 이들을 활용하지 않고(인스턴스로 만들지도 않음.), 단지 바인딩만 하여
+	 * 이후 요청에 있어서 처리에만 활용한다.
+	 * 
+	 * @param jerseyModuleClassFqns
+	 */
 	private void bindJerseyModules(final List<Object> jerseyModuleClassFqns) {
 		for (final Object jerseyModuleClassFqn : jerseyModuleClassFqns) {
 			try {

File src/main/java/jhyun/mybatis_with_guice/injections/MyBatisXmlModule.java

 /**
  * Simple MyBatis + Guice Configuration By XML Module.
  * 
+ * Guicer의 의해서 생성된다. 상속을 통한 Injection의 용도도 있고(SqlMapper, SqlSession등
+ * MyBatis특유의), 설정파일을 읽어 MyBatis을 초기화하는 목적도 있다.
+ * 
+ * 여기서 SqlMapper등의 Injection을 위해서는 XMLMyBatisModule을 상속하는것으로.
+ * 
+ * 설정 파일을 읽고, 기본 환경을 설정하는것은 initialize 메서드에서.
+ * 
  * @author jhyun
  * @since 2012-08-30
+ * 
+ * @see Guicer
+ * @see AppConfig
+ * @see XMLMyBatisModule
  */
 public class MyBatisXmlModule extends XMLMyBatisModule {
 	private static Logger logger = LoggerFactory

File src/main/java/jhyun/mybatis_with_guice/servlets/DefaultWrapperServlet.java

 
 import com.google.inject.Singleton;
 
+/**
+ * Jersey이 처리하지 않고, 정적 파일이나 다른 요청으로 매핑될 경우에 Redirector.
+ * 
+ * @author jhyun
+ * @since 2012-09-03
+ */
 @Singleton
 public class DefaultWrapperServlet extends HttpServlet {
 

File src/main/java/jhyun/mybatis_with_guice/sqlmaps/HelloMapper.java

  */
 public interface HelloMapper {
 
+	/** 1+1 */
 	int onePlusOne();
 
+	/** a+b */
 	int plus(@Param("a") final int a, @Param("b") final int b);
 
+	/**
+	 * 테스트 테이블 (FOO) 생성.
+	 * 
+	 * @param ifNotExists
+	 *            true이면 존재하지 않을때만 생성하도록. (테이블 존재하도록 확증용).
+	 */
 	void createTestingTable(@Param("ifNotExists") final boolean ifNotExists);
 
+	/** 테스트 테이블 제거. (FOO) */
 	void dropTestingTable();
 
+	/** 테스트 테이블(FOO)의 전체 목록. [{ID=..}, ...] */
 	List<Map> listAllTestingTable();
 
+	/** 테스트 테이블에 정수 하나를 넣기. (FOO) */
 	void insertIntoTestingTable(@Param("n") final String n);
 
+	/** 테스트 테이블의 모든 행들을 삭제. (FOO) */
 	void deleteAllTestingTable();
 
 }

File src/main/resources/app-config.xml

 		<jersey-modules>
 			jhyun.mybatis_with_guice.controllers.HelloController
 		</jersey-modules>
+		<default-serve-url-regex>/public/.*</default-serve-url-regex>
+		<jersey-serve-url-pattern>/*</jersey-serve-url-pattern>
 	</app>
 	<test>
 		<api-url-prefix>http://localhost:8080</api-url-prefix>

File src/main/resources/mybatis-config.xml

 		</environment>
 	</environments>
 	<mappers>
+		<!-- NOTE: 이하에 늘어나는 매퍼 XML들을 적어주세요. -->
 		<mapper resource="sqlmaps/hello.xml" />
 	</mappers>
 </configuration>

File src/main/resources/sqlmaps/hello.xml

   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="jhyun.mybatis_with_guice.sqlmaps.HelloMapper">
+	<!-- NOTE: mapper xml은 이를 자바측에서 접근할때 활용한 매퍼 인터페이스를 하나 갖춰야 합니다. 이는 DAO와 유사하지만, 
+		DAO이 모든 내용을 손수 구현해준것과 달리, XML와 인터페이스만으로 dynamic-proxy으로서 이를 자동으로 구현해줍니다. -->
 
 	<select id="onePlusOne" resultType="int">
 		select 1+1 from dual
 	</select>
-	
+
 	<select id="plus" parameterType="map" resultType="int">
-		select #{a} + #{b} from dual
+		select #{a} +
+		#{b} from dual
+	</select>
+
+
+
+	<update id="createTestingTable" parameterType="map">
+		CREATE TABLE
+		<if test="ifNotExists">IF NOT EXISTS</if>
+		FOO (
+		id INT PRIMARY KEY
+		)
+	</update>
+
+	<update id="dropTestingTable">
+		DROP TABLE IF EXISTS FOO
+	</update>
+
+	<select id="listAllTestingTable" resultType="map">
+		SELECT id FROM FOO
 	</select>
-	
-	
-
-    <update id="createTestingTable" parameterType="map"> 
-        CREATE TABLE <if test="ifNotExists">IF NOT EXISTS</if> FOO (
-                id             INT PRIMARY KEY 
-        ) 
-    </update>
-    
-    <update id="dropTestingTable" >
-    	DROP TABLE IF EXISTS FOO
-    </update>
-    
-    <select id="listAllTestingTable" resultType="map" >
-    	SELECT id FROM FOO 
-    </select>
-    
-    <insert id="insertIntoTestingTable" parameterType="map">
-    	INSERT INTO FOO (id) VALUES(#{n})
-    </insert>
-    
-    <delete id="deleteAllTestingTable" >
-    	DELETE FROM FOO
-    </delete>
-	
+
+	<insert id="insertIntoTestingTable" parameterType="map">
+		INSERT INTO
+		FOO (id) VALUES(#{n})
+	</insert>
+
+	<delete id="deleteAllTestingTable">
+		DELETE FROM FOO
+	</delete>
+
 </mapper>

File src/main/webapp/WEB-INF/web.xml

 	<welcome-file-list>
 		<welcome-file>index index.jsp index.html</welcome-file>
 	</welcome-file-list>
+
+	<!-- NOTE: Guice Injector을 ServletContext와 연관짓는다. -->
+	<listener>
+		<listener-class>jhyun.mybatis_with_guice.injections.GuiceJerseyListener
+		</listener-class>
+	</listener>
 	
-	<!-- 
-	<servlet>
-		<servlet-name>Jersey Web Application</servlet-name>
-		<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer
-		</servlet-class>
-	</servlet>
-	<servlet-mapping>
-		<servlet-name>Jersey Web Application</servlet-name>
+	<!-- NOTE: GuiceFilter으로 요청, 응답 등을 Inject하고 Scope처리. -->
+	<filter>
+		<filter-name>Guice Filter</filter-name>
+		<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
+	</filter>
+	<filter-mapping>
+		<filter-name>Guice Filter</filter-name>
 		<url-pattern>/*</url-pattern>
-	</servlet-mapping>
-	 -->
-	 
-	 <listener>
-       <listener-class>jhyun.mybatis_with_guice.injections.GuiceJerseyListener</listener-class>
-     </listener>
-     <filter>
-       <filter-name>Guice Filter</filter-name>
-       <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
-     </filter>
-     <filter-mapping>
-       <filter-name>Guice Filter</filter-name>
-       <url-pattern>/*</url-pattern>
-     </filter-mapping>
-	
-	
+	</filter-mapping>
+
+
 </web-app>

File src/test/java/jhyun/mybatis_with_guice/tests/AllTests.java

 package jhyun.mybatis_with_guice.tests;
 
 import jhyun.mybatis_with_guice.tests.test_cases.AppConfigTestCase;
+import jhyun.mybatis_with_guice.tests.test_cases.DirtyAndCleanTransactionClientTestCase;
 import jhyun.mybatis_with_guice.tests.test_cases.MybatisWithGuiceTestCase;
 import jhyun.mybatis_with_guice.tests.test_cases.PlusWithJsonJerseyClientTestCase;
 import jhyun.mybatis_with_guice.tests.test_cases.SimpleTransactionClientTestCase;
 import org.junit.runners.Suite;
 import org.junit.runners.Suite.SuiteClasses;
 
+/**
+ * 전체 테스트 묶음. 단위 테스트를 모두 수행하려면, 이 클래스를 Test Runner에서 실행하세요.
+ * 
+ * @author jhyun
+ * @since 2012-09-03
+ */
 @RunWith(Suite.class)
 @SuiteClasses({ AppConfigTestCase.class, MybatisWithGuiceTestCase.class,
-		PlusWithJsonJerseyClientTestCase.class, SimpleTransactionClientTestCase.class })
+		PlusWithJsonJerseyClientTestCase.class,
+		SimpleTransactionClientTestCase.class,
+		DirtyAndCleanTransactionClientTestCase.class })
 public class AllTests {
 
 }

File src/test/java/jhyun/mybatis_with_guice/tests/helpers/JerseyTestingClient.java

 import com.sun.jersey.api.client.config.DefaultClientConfig;
 import com.sun.jersey.api.json.JSONConfiguration;
 
+/**
+ * Jersey Client을 활용하는 단위 테스트 도우미.
+ * 
+ * app-config.xml등의 설정에서 test.api-url-prefix 설정에 영향을 받음.
+ * 
+ * @author jhyun
+ * @since 2012-09-03
+ */
 public class JerseyTestingClient {
 
 	public static WebResource webResource() {

File src/test/java/jhyun/mybatis_with_guice/tests/helpers/SimpleTransactionHelper.java

 
 import com.google.common.base.Objects;
 
+/**
+ * 간단한 MyBatis 연동 API 테스트용 헬퍼.
+ * 
+ * @author jhyun
+ * @since 2012-09-03
+ */
 public class SimpleTransactionHelper {
 
 	public List listAll() {

File src/test/java/jhyun/mybatis_with_guice/tests/test_cases/AppConfigTestCase.java

 import org.apache.commons.configuration.Configuration;
 import org.junit.Test;
 
+/**
+ * app-config 단위 테스트. (초간단..)
+ * 
+ * @author jhyun
+ * @since 2012-09-03
+ */
 public class AppConfigTestCase {
 
 	@Test

File src/test/java/jhyun/mybatis_with_guice/tests/test_cases/MybatisWithGuiceTestCase.java

 
 import com.google.inject.Injector;
 
+/**
+ * mybatis + guice 연동이 잘 되는지?
+ * 
+ * @author jhyun
+ * @since 2012-09-03
+ * 
+ */
 public class MybatisWithGuiceTestCase {
 
 	private Injector getInjector() {

File src/test/java/jhyun/mybatis_with_guice/tests/test_cases/PlusWithJsonJerseyClientTestCase.java

 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * Jersey Client을 활용한 덧셈 테스트.
+ * 
+ * @author jhyun
+ * @since 2012-09-03
+ * 
+ */
 public class PlusWithJsonJerseyClientTestCase {
 
 	private static Logger logger = LoggerFactory

File src/test/java/jhyun/mybatis_with_guice/tests/test_cases/SimpleTransactionClientTestCase.java

 
 import com.google.inject.Inject;
 
+/**
+ * Jersey Client을 활용하여 RESTful-API 호출하는 예시.
+ * 
+ * @author jhyun
+ * @since 2012-09-03
+ */
 public class SimpleTransactionClientTestCase {
 
 	public SimpleTransactionClientTestCase() {