久しぶりにJavaしている今日この頃です
新たに4月から3ヶ月で5,000万の仕事*1も(゚Д゚)ハァ?なんて話を聞き流しながら、3月に入ってからは久しぶりにJavaしているわけですが。
LL言語とかRails以降のフレームワークになれた身としてはかったるいな〜(´・_・`)というか、今はそのかったるい部分を少しは楽にするための準備期間。*2
とりあえずSpringをベースとした骨組みの準備を。
Springも今は設定ファイルを書かない時代になったし、コンポーネントはみんなAutowiredなカンジで(・∀・)
ところでsessionスコープなオブジェクトを使った単体テストを実行しようとすると怒られてしまうわけですが(´・ω・`)
で、ネットで調べてこんなクラスを作ることで対応しますた。
public class SpringWebTestCase extends AbstractTransactionalDataSourceSpringContextTests { private static final String REQUEST_ATTRIBUTES_ATTRIBUTE = RequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES"; private HttpServletRequest request; private HttpServletResponse response; protected HttpServletRequest getHttpServletRequest() { return this.request; } public HttpServletResponse getHttpServletResponse() { return this.response; } public final void runBare() throws Throwable { initializeContext(); setUp(); try { runTest(); } finally { tearDown(); finalizeContext(); } } private void initializeContext() { this.request = new MockHttpServletRequest(); this.response = new MockHttpServletResponse(); ServletRequestAttributes attributes = new ServletRequestAttributes(this.getHttpServletRequest()); this.getHttpServletRequest().setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes); LocaleContextHolder.setLocale(this.getHttpServletRequest().getLocale()); RequestContextHolder.setRequestAttributes(attributes); } private void finalizeContext() { ServletRequestAttributes attributes = (ServletRequestAttributes)this.getHttpServletRequest().getAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE); ServletRequestAttributes threadAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); if (threadAttributes != null) { if (attributes == null) { attributes = threadAttributes; } RequestContextHolder.setRequestAttributes(null); LocaleContextHolder.setLocale(null); } if (attributes != null) { attributes.requestCompleted(); } } protected ConfigurableApplicationContext createApplicationContext(String[] locations) { GenericWebApplicationContext context = new GenericWebApplicationContext(); context.setServletContext(new MockServletContext(new FileSystemResourceLoader())); customizeBeanFactory(context.getDefaultListableBeanFactory()); createBeanDefinitionReader(context).loadBeanDefinitions(locations); context.refresh(); return context; } }
使い方はこんなん。
@Service @Scope("session") public class ShoppingCart implements Serializable { ... }
みたいなコンポーネントにたいしてこんな記述で。
public class SessionScopeTest extends SpringWebTestCase { @Autowired private ShoppingCart shoppingCart; protected String[] getConfigLocations() { setAutowireMode(AUTOWIRE_BY_NAME); return new String[] {"/WEB-INF/conf/applicationContext.xml"}; } ... }
やっているのorg.springframework.web.context.request.RequestContextListenerと同じような事。
これでsessionスコープなオブジェクトのテストもできました(・∀・)
で、Springを使ったコンポーネント管理や宣言的トランザクション他は準備できたので、後はデータアクセス層とかも用意。
データアクセスは堅いところでiBATISでDAOパターンという、品質を保つためにそれなりに考えてるんだけどあまり心は弾まない構成で。
とりあえずテーブル単位のCRUD基本処理(ROW_NUMBERを使ったページングやVersionNoくらいには対応)については、DBを覗いてスキーマからDTOとXMLを自動生成するツールを作ってみたり。
ツールはC#で作っていますけどね(・∀・)
後のSQLは個別に書くさ(・ω・)
まあ、今回はDB直接の処理はそんなに多くなくて、途中にキャッシュ/検索エンジンをはさんで、そちらからのデータ取得がメインになるという話ですが。
っで、DAOとLogic層についてはこんなんでイイかな〜とか、そんな事をやっていた今週。
来週はVC層について考えようっと(´ー`)