java.io.NotSerializableException
問題
java.io.NotSerializableException
とあるオブジェクトをこのtoByte()でbyteに変換しようとしたらエラーがでた。
Javaで大量データをメモリに展開するテクニックの考察 - Symfoware
解決方法
import java.io.Serializable; public class TransientExample implements Serializable { private static final long serialVersionUID = 6128016096756071380L; private transient Pair pair = null; public TransientExample(String key, Integer value) { this.pair = new Pair(key, value); } @Override public String toString() { return pair.toString(); } }
適当なクラスを作って、
・implements Serializableつける
・問題のあるクラスをtransient で定義しなおす
でエラーきえた。
~~~
あれ、逆か。transientは不要っぽい。
それと、そもそもOAuthConsumerをSerializeしようとしていてエラーが発生したのがきっかけだが、少し複雑な感じ。
結論からいくと、OAuthConsumerはサーバ側で保持する必要はなく、Providerだけ保持していればいいっぽい。
Issue 11 - oauth-signpost - Make OAuthProvider and OAuthConsumer serializable - Simple OAuth message signing for Java - Google Project Hosting
そして、OAuthConsumerはnewで初期化した時点ではserialize可能だが、たぶんproviderと混ぜてURL生成なんかをしていると、途中からserializeできなくなる。(しようとするとnullが返された。serializeするライブラリによってはエラーを吐く)
url = provider.retrieveRequestToken(consumer, callback);
~~~
最終的にうまくいったのでまとめ。
oauthの各ステップ
- STEP01:認証URLの生成
- consumerとproviderを初期化
- sessionやDBとかでproviderは保持しておく
- consumerが持っているaccessTokenKeyとSecペアをsessionやDBで保持しておく(これがわかりにくかった)
- STEP02:認証ページからのCALLBACK
- callback先に認証キーがGETパラメータで返ってくるので、それをsessionとかDBで保持しておく
- STEP03:利用
- providerは保持しておいたやつをそのまま使う
- consumerはSTEP01と同様に初期化した後、STEP01で保持しておいたaccessTokenKeyとSecをconsumerに適用する(これがわかりにくかった)
- providerにconsumerとSTEP02で得た認証キーを適用する
- 後は公式通りに利用
公式には
consumer.setTokenWithSecret(ACCESS_TOKEN, TOKEN_SECRET);
とだけあり、ACCESS_TOKENやTOKEN_SECRETは、callbackで得られるkeyとsecのペアのことかと思っていた。
しかし、これはSTEP01でcosumerが持っているやつを使わなければいけない。
STEP01
OAuthConsumer consumer = new DefaultOAuthConsumer("XXX","XXX"); OAuthProvider provider = new DefaultOAuthProvider("XXX","XXX"); authUrl = provider.retrieveRequestToken(consumer, CALLBACK_URL); // accessTokenをsessionやDBに保持 ↓こいつら System.out.println(consumer.getToken()); System.out.println(consumer.getTokenSecret()); //...
STEP02
//認証元からGETで受け取った認証キーをsessionやDBに保持 //...
STEP03
OAuthProvider provider = (OAuthProvider)session.getAttribute("provider"); OAuthConsumer consumer = new DefaultOAuthConsumer("XXX","XXX"); consumer.setTokenWithSecret("STEP01のaccessTokenKey", "STEP01のaccessTokenSec"); provider.retrieveAccessToken(consumer, "STEP02で認証元からうけとった認証キー"); //あとは普通通り URL url = new URL("認証が必要なリソースURL"); //...略
~~~
さらにハマった。。
上の手順だとSTEP03を2回以上くりかえすと、2回目からは401がでてしまう。
理由は、retrieveAccessTokenするとaccessTokenとaccessTokenSecretが更新されるから。
なので、
STEP02でretrieveAccessTokenを済ませて置き、そこで新しく発行されるtokenを保持し、STEP03で何度も同じものを使うというふうにしなければいけない。
STEP01
OAuthConsumer consumer = new DefaultOAuthConsumer("XXX","XXX"); OAuthProvider provider = new DefaultOAuthProvider("XXX","XXX"); authUrl = provider.retrieveRequestToken(consumer, CALLBACK_URL); // accessTokenをsessionやDBに保持 ↓こいつら System.out.println(consumer.getToken()); System.out.println(consumer.getTokenSecret()); //... // providerもsessionなんかで保持しておく session.setAttribute("provider", provider);
STEP02 (retrieveAccessTokenを済ませて置き、そこで新しく発行されるtokenを保持)
OAuthProvider provider = (OAuthProvider)session.getAttribute("provider"); OAuthConsumer consumer = new DefaultOAuthConsumer("XXX","XXX"); provider.retrieveAccessToken(consumer, "GETパラメータでうけとった認証キー"); // ここで実はconsumerのaccesstokenが更新されている。 // のでそいつらを保持しておく System.out.println(consumer.getToken()); System.out.println(consumer.getTokenSecret()); //... // providerはもう用済みなので消してよい
STEP03
OAuthConsumer consumer = new DefaultOAuthConsumer("XXX","XXX"); consumer.setTokenWithSecret("STEP02のaccessTokenKey", "STEP02のaccessTokenSec"); //あとは普通通り URL url = new URL("認証が必要なリソースURL"); //...略
munin-node | mysqlのレプリケーション関係で動かない
mysqlのリプリケーションをやったサーバでmunin-nodeを起動しても動作しなかった
それ以外の状況が全く同じサーバについては普通通りに動いている。
ログをみると、/var/log/munin-node/munin-node.logだけがでている。
sudo -u munin /usr/bin/munin-cron
これで無理やり実行すると、/var/log/munin/munin-update.logに大量の"mysql_"なんたら というエラーが見つかった。
mv /etc/munin/plugins/mysql_* /etc/munin/plugins/bak/
と退避させて2回強制実行するとすべてのログが正常化した。
それでもなお自動実行はされない。
crontabに登録したが、なぜか動かなかった。
/5 * * * * sudo -u munin /usr/bin/munin-cron
ので、仕方なく、スクリプトで走らせることにした。はぁ・・ださい
while(1){ print "go\n"; `sudo -u munin /usr/bin/munin-cron`; sleep 300; }
スカッとインストールできないもんかねー
1つのサーバにmysql複数プロセス立ち上げる
基本
MySQLプロセスを一台のサーバで複数起動 [GameCreator'sNote]
mysql dirの初期化だけはこちらの手順
MySQLのデータベースを初期化する - Qiita
つまり
vim /etc/my2.cnf mkdir /var/lib/mysql2 chown mysql:mysql /var/lib/mysql2 # init dir su mysql mysql_install_db --datadir=/var/lib/mysql2 exit # mkdir -pv /var/lib/mysql2 chown mysql:mysql /var/lib/mysql2 # check log. no error tail -f /var/log/mysqld2.log # 最終行がこんな感じであればOK # Version: '5.5.42' socket: '/var/lib/mysql2/mysql2.sock' port: 3307 MySQL Community Server (GPL) # login mysql -uroot -p --socket=/var/lib/mysql2/mysql2.sock
/etc/my2.cnf
[mysqld]
datadir=/var/lib/mysql2
socket=/var/lib/mysql2/mysql2.sock# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0#log-bin
server-id=1001
port=3307[mysqld_safe]
log-error=/var/log/mysqld2.log
pid-file=/var/run/mysqld2/mysqld2.pid
さくらVPSでmysqlレプリケーションを構築してみる
前提
centos6
mysql5.5
まず、mysql5.5を入れる。
【シンプル】CentOS6にMySQL5.5をyumで簡単にインストールする手順 | 田舎に住みたいエンジニアの日記
最初5.6を入れてすすめていたが、5.1から5.6への移行は推奨されないというのを見て、嫌な予感がして5.5にすることにした。
MySQL 5.1→5.6のmy.cnfの差分とか - (ひ)メモ
service mysqld start で起動するとエラー
これの2と3で解決
[Web] さくらVPSでのメンテナンスについて: ものづくりログ
いくつかのサーバはなぜかさらに別のエラーがでて起動できなかった(復旧にコケたみたいなエラーだった)。エラーログでググってもあまりHITしなかったので、MySQLを初期化する方法を試してみたらすんなりいった。
MySQLのデータベースを初期化する - Qiita
-
- 休憩 --
メイン
新規のサーバでセットアップ の節
現場指向のレプリケーション詳説
図9のところはmysqlのバージョンのせいか、できなかった
[mysqld]
server-id=11
master-host=mymaster
master-user=repl
master-password=qa55wd
ので、そこだけ、こちらの手順でやる。
MYSQLレプリケーション設定 - エーエイチレフ linuxサーバー技術情報
# slaveのmysqlにログイン
CHANGE MASTER TO
MASTER_HOST='マスターのIPアドレス',
MASTER_USER='repl',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000004',
MASTER_LOG_POS=189;
で、これをmysqlに打ち込んだあとにさらに下を打つと、ようやくレプリケーションが始まる。
mysql> START SLAVE;
Query OK, 0 rows affected, 1 warning (0.00 sec)
MySQL 5.5 Server as Replication Slave « Code-Kolbold Code Talk
最初は権限の問題でうまくいかなかった
とりあえずすべて接続元からを許可するように「%」とするとうまくいった。(TODO:後から調べる!)
図4’
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%' IDENTIFIED BY 'qa55wd';
からの、glassfishからconnection poolして利用
まずは、管理画面でconnection poolの作成
GlassFish v3.1.2.2でのMySQL/JDBC設定
java sourceからの利用
Connection con = null; try { DataSource source = (DataSource)new InitialContext().lookup("jdbc/mysql1"); con = source.getConnection(); // 接続を使用する System.out.println("connection is successs."); try { Statement stmt = (Statement) con.createStatement(); ResultSet rs = stmt.executeQuery("select * from aaa limit 2"); while(rs.next()){ Integer no = rs.getInt("id"); String eid = rs.getString("name"); System.out.println(id+" : " + name); } } catch (SQLException ex) { Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex); } } catch (SQLException e) { // エラーのログを取る Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, e); } catch (NamingException e) { // JNDI内にDataSourceが見つからない System.out.println("JNDI内にDataSourceが見つからない"); } finally { if (con != null) { try { con.close(); } catch (SQLException e) {} } }
jax-rsでNoSuchMethodErrorにハマる
問題
java.lang.NoSuchMethodError: com.sun.research.ws.wadl.Response.getRepresentationOrFault()Ljava/util/List;
at com.sun.jersey.server.wadl.WadlGeneratorImpl.createResponse(WadlGeneratorImpl.java:198)
at com.sun.jersey.server.wadl.WadlBuilder.generateResponse(WadlBuilder.java:397)
というエラーが発生。restart-domainすると発生しなくなるが、一度でもdeployするとずっと発生する。
jax-rsに関する依存をこの2つに変えたら問題は起きなくなった。
<dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-bundle</artifactId> <version>1.18.1</version> </dependency> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.7.7</version> </dependency>
参考
spring - REST Exception: java.lang.reflect.InvocationTargetException - Stack Overflow
web server (apache) → app server (glassfish) 構成
web server (apache) → app server (glassfish) の構成にする。
ApacheとGlassFishを連携する mod_proxy編 - Webサービスで起業を目指すプログラマーblog
これによって、無駄にport開放をしなくてよくなった。ユーザのアクセスはすべてapacheの80に集約される。
sqlite + java + connection pool + glassfish
Glassfishの設定
http://sourceforge.net/p/sqlite-connpool/wiki/How%20To%20Setup%20a%20SQLite%20Connection%20Pool%20on%20Glassfish/
Java source code
http://sourceforge.net/p/sqlite-connpool/home/Home/
おまけ 設定
java - Set SQLite connection properties in c3p0 connection pool - Stack Overflow
- -
- -
2015-07-14
Class.forName("org.sqlite.JDBC");でエラーがでるようであれば、sqlite-jdbc-3.7.2.jarを適切な場所に配置してglassfishを再起動したら直るもよう。置く場所はdomain/domain1/libだったと思う。