sinsengumi血風録
WTPのTomcat7.0でDataSource(PostgreSQL)からConnectionを取得する
- 2011年7月20日 3:45 AM
- Java
コネクションプーリングをするために、DataSourceからコネクションを取得しようと思ったら、かなりハマってしまったので、備忘録です。
手順は以下。PostgreSQLの例ですが、大体どのDB製品でも同じだと思います。
- (サーバの)server.xmlにResourceを定義
- (アプリケーションの)web.xmlにresource-refを定義
- JDBCドライバを配備
- コネクション取得
(サーバの)server.xmlにResourceを定義
まずserver.xmlにResourceを定義します。WTPでサーバを動かしている場合は、以下のようにServersプロジェクト内にserver.xmlがあると思います。
この中にアプリケーションのContextタグがあると思うので、そこにResourceを追加する。
ここが、Tomcat 6.0と記述が異なっていたので、かなりハマってしまいました。しっかりマニュアルのほうを読まないといけませんね。
server.xml
<Context docBase="Sample" path="/Sample" reloadable="true" source="org.eclipse.jst.jee.server:Sample"> <Resource name="jdbc/postgresql" auth="Container" type="javax.sql.DataSource" driverClassName="org.postgresql.Driver" url="jdbc:postgresql://localhost/SampleDB" username="postgres" password="xxxxxx" maxActive="20" maxIdle="10" maxWait="-1" /> </Context>
(アプリケーションの)web.xmlにresource-refを定義
次にアプリケーション内のweb.xmlにresource-refを定義します。サーバのweb.xmlではないので注意。
web.xml
<resource-ref> <res-ref-name>jdbc/postgresql</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>
JDBCドライバを配備
WTPでサーバを起動している場合は、サーバプログラム本体のcommon/libにいくらjarを置いてもクラスパスには追加されません。
WTPでjarを追加するには以下のようにします。
プロジェクト・エクスプローラーを右クリック → 実行(実行構成) → クラスパス → ユーザー・エントリでjarを追加
コネクション取得
これで準備ができたので、実際にServletからコネクションを取得してみます。
SampleServlet
package jp.co.njk.nems.controller.authentication;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
@WebServlet("/SampleServlet")
public class SampleServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private Connection connection;
public void init(ServletConfig config) throws ServletException {
try {
InitialContext context = new InitialContext();
DataSource dataSource = (DataSource) context.lookup("java:comp/env/jdbc/postgresql");
connection = dataSource.getConnection();
} catch (NamingException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println(connection);
}
}
参考
- Comments: 0
- Trackbacks: 0
TeedaのラジオボタンにString型ではなく列挙型(Enum)を使う
- 2011年3月11日 12:42 AM
- Java
Teedaのラジオボタンは通常、String型でPageクラスに定義します。
http://teeda.seasar.org/ja/extension/reverse/input.html#%E3%83%A9%E3%82%B8%E3%82%AA%E3%83%9C%E3%82%BF%E3%83%B3_%E9%9D%99%E7%9A%84
が、そこを列挙型(Enum)することができます。こちらの方が型安全になっていいかなと思います。
もちろん、静的・動的両方いけます。
以下、サンプルです。
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:te="http://www.seasar.org/teeda/extension" xml:lang="ja"
lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Enumのサンプル</title>
</head>
<body>
<form id="Form">
<span id="allMessages"></span>
<h1>ラジオボタン(静的)</h1>
<div id="sex">
<label><input type="radio" name="sex" value="MALE" />男性</label>
<label><input type="radio" name="sex" value="FEMALE" />女性</label>
</div>
<h1>ラジオボタン(動的)</h1>
<input type="hidden" id="languageItemsSave" />
<span id="language">
<input type="radio" name="language" />
</span>
<p><input type="submit" value="送信" id="doSubmit" /></p>
</form>
</body>
</html>
列挙型
public enum Sex {
MALE("男性"),
FEMALE("女性");
private String japaneseName;
private Sex(String japaneseName) {
this.japaneseName = japaneseName;
}
public String getJapaneseName() {
return japaneseName;
}
}
public enum Language {
JAPANESE("日本語", "JAPANESE", "こんにちわ"),
ENGLISH("英語", "ENGLISH", "Hello");
private String label;
private String value;
private String greeting;
private Language(String label, String value, String greeting) {
this.label = label;
this.value = value;
this.greeting = greeting;
}
public String getLabel() {
return label;
}
public String getValue() {
return value;
}
public String getGreeting() {
return greeting;
}
}
Pageクラス
public class EnumSamplePage {
public Sex sex;
public Language language;
public List<Language> languageItems;
public Class<?> initialize() {
// 初期値の設定
sex = Sex.FEMALE;
language = Language.ENGLISH;
languageItems = new ArrayList<Language>();
for (Language lang : Language.values()) {
languageItems.add(lang);
}
return null;
}
public Class<?> prerender() {
return null;
}
public Class<?> doSubmit() {
System.out.println(sex.getJapaneseName());
System.out.println(language.getGreeting());
return null;
}
}
注意としては、
静的なラジオボタンで使う場合は、value属性に“列挙子”を指定すること(サンプルだと「MALE」「FEMALE」)
静的なラジオボタンで使う場合は、列挙型のフィールドに“label”と“value”を変数名にもつ値を定義すること。
あと、HTMLにhidden属性に”~~ItemsSave”を配置すること。これをしないとPOSTしたときにデータが消えてしまう(これはString型でも同じですが)
- Comments: 0
- Trackbacks: 0
livedoor Reader をJavaから操作する何か作った
- 2011年2月21日 12:21 AM
- Java
追記
Github にホスティングしました。これからはGithub 使います。
https://github.com/sinsengumi/LDR4J
掲題の通り、livedoor Reader をJavaからHTTPアクセスして未読記事取ったり、ピン付けたりするライブラリ「ldr4j」を作りました。
実はAndroidでlivedoor Readerクライアントアプリを作りたくて、その前段階としてこのラッパーライブラリを作った感じです。
で、生まれてはじめて、まとまったコードをOSSとして公開してみました。
コードはSourceForge.JPでホスティングしています。
(eclipseプラグインのEGITがよさそうであれば、githubでホスティングしたいと思います。)
「ldr4j」プロジェクトページ
http://sourceforge.jp/projects/ldr4j/
以下で、Subversionからチェックアウトできます。
http://svn.sourceforge.jp/svnroot/ldr4j/
※なお、livedoor Reader API はlivedoor から正式にアナウンスされているAPIではないので、仕様変更で使えなくなる可能性はあります。
livedoor Reader が大好きで、もうこれがないとネット生活していけないくらいですね。
今回 ldr4j を作っていく過程で、livedoor Reader がどういう風に出来ているかもなんとなくですがわかりました(livedoor ReaderのOSS版である fastladder を参考にしました。)
このライブラリはこれからもちゃんとメンテナンスしていこー。テストとかもちゃんと書きたいし。
参考
- Comments: 2
- Trackbacks: 0
よく見るClosable使ったコード
- 2011年2月16日 8:23 PM
- Java
Streamなんかを閉じる(close)時のコードなんかでよく見るパターン。
nullチェックして、closeする。さらにそのcloseはチェック例外出すからめんどいよ、ってことなのかしら。
結構有名なのかな?
private void close(Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
- Comments: 0
- Trackbacks: 0
JavaでFTPアップロードを行う。
- 2011年2月1日 9:00 PM
- Java
JavaでFTPを使用するにはいくらか方法がありますが、仕事でcommons-netのFTPを使ったのでその備忘録です。
実行環境は以下です。
- JRE 1.6
- commons-net-2.0.jar
はまった箇所が2点ほどあって、ひとつはエンコーディングの設定は必ずコネクトする前に行うこと。とPASVモードについてです。
commons-netのFTPClientクラスで、PASVモードにできそうな名前のメソッドが2つあって、それのどっちを使えばいいのか、もしくは違うのか結構悩みました。
- enterLocalPassiveMode()
- enterRemotePassiveMode()
結果的にいうと、どっちも違くて、FTPClientの親クラスであるFTPクラスのpasv()メソッドでOKでした。
これらの違いは、ソースやJavadocを見た感じ、恐らく以下のような感じだと思います。
pasv()
FTPのPASVコマンドを発行する。
enterLocalPassiveMode()
dataConnectionModeを「2」に設定する。
enterRemotePassiveMode()
内部的にpasv()を呼び出している。
以下、サンプルコードです。
public class FTPUpload {
private static final String FTP_HOST = "127.0.0.1";
private static final String FTP_USER = "username";
private static final String FTP_PASSWORD = "password";
private static final String UPLOAD_FILE = "C:\\サンプル.xls";
private static final String UPLOADED_FILENAME = "リネーム.xls";
public static void main(String[] args) {
try {
execute();
} catch (ApplicationException e) {
e.printStackTrace();
}
}
private static void execute() throws ApplicationException {
FTPClient ftpClient = new FTPClient();
try {
// エンコーディングの設定は、connectする前に行う。
ftpClient.setControlEncoding("SJIS");
// FTPサーバに接続
ftpClient.connect(FTP_HOST);
printFtpReply(ftpClient);
// ログイン
ftpClient.login(FTP_USER, FTP_PASSWORD);
printFtpReply(ftpClient);
// PASVモードに設定
ftpClient.pasv();
printFtpReply(ftpClient);
// データの変換モードをバイナリに設定
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
printFtpReply(ftpClient);
// ファイル転送
FileInputStream fis = new FileInputStream(UPLOAD_FILE);
ftpClient.storeFile(UPLOADED_FILENAME, fis);
printFtpReply(ftpClient);
} catch (NumberFormatException e) {
throw new ApplicationException("FTPポートの値が数値ではありません。", e);
} catch (SocketException e) {
throw new ApplicationException("Socket通信に失敗しました。", e);
} catch (FileNotFoundException e) {
throw new ApplicationException("アップロードするファイルが見つかりません。", e);
} catch (IOException e) {
throw new ApplicationException("IOレベルで例外が発生しました。", e);
} finally {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
} catch (IOException e) {
// ignore
}
}
}
}
private static void printFtpReply(FTPClient ftpClient)throws ApplicationException {
System.out.print(ftpClient.getReplyString());
int replyCode = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(replyCode)) {
throw new ApplicationException("送信したFTPコマンドは失敗しました。");
}
}
}
PASVモードやFTPのプロトコルに関しては、以下が大変参考になりました。
http://www.atmarkit.co.jp/fnetwork/rensai/netpro10/netpro01.html
- Comments: 0
- Trackbacks: 0
フレームワークを調査するときにやること
- 2011年1月17日 10:43 PM
- その他
仕事でSeasarプロジェクトのTeedaというフレームワークでWebアプリケーションを作ることになったので、その調査ということで、色々やったので、そのメモです。
とりあえず以下の事をやれば、一製造メンバーとしては役に立てるかな。
以下の事をやりました。
- チュートリアルを動かしてみる
- マニュアルを読む
- MLを眺める
- 課題管理(バグレポート)を眺める
- ブログを読む
- ソースを読む
以下、詳細。
1. チュートリアルを動かしてみる
大体のフレームワークには、チュートリアルがサイトに載っていたり、サンプルコードをダウンロードできたりするので、それをとりあえず動かしてみる。
Teedaの場合、html-tutorialという素晴らしいサンプルコード群が配布されているので、それをひと通り眺めると、出来ることのイメージが掴めました。
2. マニュアルを読む
もちろん、必須です。
Teedaの場合、S2やS2Daoなんかも絡んでくるので、そこらへんのマニュアルもひと通り目を通す。
分からないところがあってもとりあえず目を通す。そうすると、後で分からないことがあったときに「あそこに書いてあったような・・・」みたいな当たりが付けられるので。
あと、先にチュートリアルやっておくと実際の動きのイメージをつけながらマニュアルを読めるので、先にチュートリアルやったほうがいい。
3. MLを眺める
MLを眺める&登録しておく。
だいたい行き詰まるところは同じなので、求める答えはMLにあったりするのがほとんどだったりする。
隅から隅まで読むのは無理なので、気になるタイトルのやつだけ読んでました。
あとML登録しておくと、コミュニティの活発具合とか雰囲気がわかる気がして楽しい。
4. 課題管理(バグレポート)を眺める
フレームワークの歴史が垣間見れて面白い。
どのバージョンでこういう機能が追加されたんだ、とか分かる。
最新バージョンを使えるようなら問題ないけど、理由あって古いバージョンを使わなくちゃいけないとか言う場合に、この機能は使えないとかを調査したりする。
5. ブログを読む
これは実装してたらだいたいすると思うけど、Teedaだったら検索に引っかかったブログのTeedaカテゴリーは全部読むとか。
6. ソースを読む
これができたら最高なんだけど、、、、まだ技術力不足で無理です。。。
- Comments: 0
- Trackbacks: 0
Windowsでどのポートが何のアプリケーションで使用されているか確認する
- 2011年1月15日 2:01 PM
- その他
Eclipse内のWTPでTomcatを起動したら、以下のようなエラーメッセージが出て、起動できませんでした。
ローカル・ホスト の Tomcat v6.0 サーバー で必要なポート 8009 はすでに使用中です。サーバーはすでに別のプロセスで稼働中であるか、システム・プロセスがそのポートを使用中である可能性があります。このサーバーを始動するには、他のプロセスを停止するか、ポート番号を変更する必要があります。
どうもポートがかぶっていそうな感じだったので、ポートが何のアプリケーションで使用されているかを調べてみました。
方法は以下。
ポートのPIDを確認する
以下のコマンドで、ポートのPIDを確認する。
C:\>netstat -nao アクティブな接続 プロトコル ローカル アドレス 外部アドレス 状態 PID TCP 0.0.0.0:135 0.0.0.0:0 LISTENING 996 TCP 0.0.0.0:445 0.0.0.0:0 LISTENING 4 TCP 0.0.0.0:902 0.0.0.0:0 LISTENING 3632 TCP 0.0.0.0:912 0.0.0.0:0 LISTENING 3632 TCP 0.0.0.0:990 0.0.0.0:0 LISTENING 760 TCP 0.0.0.0:1521 0.0.0.0:0 LISTENING 2976 TCP 0.0.0.0:1862 0.0.0.0:0 LISTENING 2176 TCP 0.0.0.0:2869 0.0.0.0:0 LISTENING 4 TCP 0.0.0.0:5357 0.0.0.0:0 LISTENING 4 TCP 0.0.0.0:5432 0.0.0.0:0 LISTENING 3400 TCP 0.0.0.0:8009 0.0.0.0:0 LISTENING 3476 TCP 0.0.0.0:8308 0.0.0.0:0 LISTENING 3476 TCP 0.0.0.0:17500 0.0.0.0:0 LISTENING 4068 TCP 0.0.0.0:49152 0.0.0.0:0 LISTENING 684
これでポート「8009」がPID「3476」で使用されていることがわかる。
PIDから使用されているアプリケーションを特定する
タスクマネージャを開いて、使用アプリケーションを特定する。
- 「Ctrl + Alt Delete」でタスクマネージャを開く。
- 「プロセス」タブを開く。
- デフォルトだとPIDが表示されていないので、「全ユーザーのプロセスを表示する(S)」「表示(V)→列の選択(S)→PID(プロセスID)」にそれぞれにチェックを入れる。
すると、PID「3476」がtomcat6.exeで使用されていることがわかる。
最後に該当の行を右クリックするなどして「プロパティ」などを見れば、使用されているアプリケーションが特定できる。めでたしめでたし。
- Comments: 0
- Trackbacks: 0
Teedaでcolspanする
- 2011年1月14日 10:45 PM
- Java
Teedaでcolspanするにはダイナミックプロパティを利用すればできます。
colspan.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:te="http://www.seasar.org/teeda/extension" xml:lang="ja" lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Teedaでcolspan</title> </head> <body> <form id="Form"> <table border="1"> <tr> <th>OS名</th> <th id="versionColspan" colspan="1">バージョン</th> </tr> <tr> <td><span id="osName">dummy</span></td> <div id="versionItems"> <td><span id="codeName">dummy</span><br /><span id="number">dummy</span></td> </div> </tr> </table> </form> </body> </html>
ColspanPage.java
package org.sample.web.fnc;
import java.util.ArrayList;
import java.util.List;
public class ColspanPage {
public int versionColspan;
public List<VersionDto> versionItems;
public String codeName;
public String number;
public String osName;
public Class<?> initialize() {
return null;
}
public Class<?> prerender() {
osName = "Mac";
// Macのバージョン
versionItems = new ArrayList<ColspanPage.VersionDto>();
VersionDto mac1 = new VersionDto();
mac1.number = "10.3";
mac1.codeName = "Panther";
versionItems.add(mac1);
VersionDto mac2 = new VersionDto();
mac2.number = "10.4";
mac2.codeName = "Tiger";
versionItems.add(mac2);
VersionDto mac3 = new VersionDto();
mac3.number = "10.5";
mac3.codeName = "Leopard";
versionItems.add(mac3);
VersionDto mac4 = new VersionDto();
mac4.number = "10.6";
mac4.codeName = "SnowLeopard";
versionItems.add(mac4);
return null;
}
class VersionDto {
public String codeName;
public String number;
}
public int getVersionColspanColspan() {
return versionItems.size();
}
}
- Comments: 0
- Trackbacks: 0
JavaでMapコレクションの繰り返し
- 2010年10月22日 11:34 AM
- Java
毎回忘れて、調べてるのでメモ。
public class Sample {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(0, "Kondou");
map.put(1, "Hijikata");
for (Entry<Integer, String> e : map.entrySet()) {
System.out.print(e.getKey());
System.out.print(" ");
System.out.println(e.getValue());
}
}
}
- Comments: 0
- Trackbacks: 0
JavaのHttpClient 4 を触ってみた。
- 2010年10月7日 11:30 AM
- Java
HttpClientの3.0系はレガシーということで、4系を触ってみました。
実行環境は以下です。
- JRE 1.6
- HttpClient 4.0.3 (httpclient-4.0.3.jar)
- HttpCore 4.0.1 (httpcore-4.0.1.jar)
- Commons Logging 1.1.1 (commons-logging-1.1.1.jar)
簡単に、HTTP接続ができていい感じです。
サンプルは以下。
public class HTTPSample {
private static HttpClient httpClient = new DefaultHttpClient();
public static void main(String[] args) {
// プロキシがある場合は、以下のようにして設定する
//HttpHost proxy = new HttpHost("XXX.XXX.XXX.XXX", 8080);
//httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
Map<String, String> requestParams = new HashMap<String, String>();
requestParams.put("pattern", "ltrim");
requestParams.put("lang", "ja");
httpGet("http://jp2.php.net/manual-lookup.php", requestParams);
// httpPost("http://jp2.php.net/manual-lookup.php", requestParams);
// HTTP接続を閉じる(shutdownを実行するとセッションが切れます)
httpClient.getConnectionManager().shutdown();
}
private static void httpGet(String url, Map<String, String> requestParams) {
HttpGet httpGet = null;
try {
// リクエストパラメータの設定
StringBuilder builder = new StringBuilder(url);
builder.append("?");
for (Map.Entry<String, String> entry : requestParams.entrySet()) {
builder.append((String) entry.getKey());
builder.append("=");
builder.append((String) entry.getValue());
builder.append("&");
}
String tmpUrl = builder.toString();
tmpUrl = tmpUrl.substring(0, tmpUrl.length() - 1);
httpGet = new HttpGet(tmpUrl);
System.out.println("executing request " + httpGet.getURI());
System.out.println("-------------------------------------");
HttpResponse response = httpClient.execute(httpGet);
// レスポンスヘッダーの取得
System.out.println(response.getStatusLine().getStatusCode());
Header[] headers = response.getAllHeaders();
for (Header header : headers) {
System.out.println(header.getName() + ": " + header.getValue());
}
System.out.print(System.getProperty("line.separator"));
// レスポンスボディの取得
HttpEntity httpEntity = response.getEntity();
System.out.println(EntityUtils.toString(httpEntity));
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (httpGet != null) {
httpGet.abort();
}
}
}
private static void httpPost(String url, Map<String, String> requestParams) {
HttpPost httpPost = null;
try {
// リクエストパラメータの設定
List<NameValuePair> params = new ArrayList<NameValuePair>();
for (Map.Entry<String, String> entry : requestParams.entrySet()) {
params.add(new BasicNameValuePair((String) entry.getKey(), (String) entry.getValue()));
}
httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
System.out.println("executing request " + httpPost.getURI());
System.out.println("-------------------------------------");
// レスポンスヘッダーの取得
HttpResponse response = httpClient.execute(httpPost);
System.out.println(response.getStatusLine().getStatusCode());
Header[] headers = response.getAllHeaders();
for (Header header : headers) {
System.out.println(header.getName() + ": " + header.getValue());
}
System.out.print(System.getProperty("line.separator"));
// レスポンスボディの取得
HttpEntity httpEntity = response.getEntity();
System.out.println(EntityUtils.toString(httpEntity));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (httpPost != null) {
httpPost.abort();
}
}
}
}
参考
- Comments: 0
- Trackbacks: 0
- Search
- Feeds
- Meta


