2016年6月8日水曜日

いまこれ読んでる

今は下の本にチャレンジ中。
ちょくちょくと読む。
chefも使っていたので、比較しながら。




 適宜メモを書いていくことにしよう。



以前だとこんなのもあった。



 こっちも持ってるけども古いので使い物にならない印象。

2016年5月29日日曜日

ansible.cfgの参照順序

ANSIBLE_INVENTORY: 対象ホストを指定するホストファイル(?)を指定する。
 指定しておかないと、
[WARNING]: provided hosts list is empty, only localhost is available
やら
skipping: no hosts matched

のエラーが出る。 どっちがどんな条件で出るかは忘れた。

export ANSIBLE_INVENTORY=ホストファイルのフルパス
上記間違いです。

ansible.cfgをいろいろ使い分けたい場合に使う?
ちなみにansible 1.5よりも後のもの対象。

ansible.cfgの参照順序

  1. ANSIBLE_CONFIG(環境変数)
  2. カレントディレクトリ(./ansible.cfg)
  3. ホームディレクトリの隠しファイル?(~/.ansible.cfg)
  4. /etc/ansible/ansible.cfg





(備忘録) DNSをLinuxで指定する

CentOS 6.xでDNSを指定する。


/etc/sysconfig/network/ifcfg-{インタフェース名}にDNS1とDNS2を設定。
あたいには、Googleのpublic DNSを指定する。

DEVICE="eth0"
BOOTPROTO="dhcp"
IPV6INIT="yes"
NM_CONTROLLED="yes"
ONBOOT="yes"
TYPE="Ethernet"
UUID="f943ed1a-bc9c-4660-b021-101714e6e29f"
DNS1=8.8.8.8
DNS2=8.8.4.4

設定したらネットワークを再起動させる。

sshで公開鍵認証設定&パスなしログインを行う

Ansibleで色々と作業をするので、ansibleユーザで公開鍵認証できると嬉しい。
そこで、作業を行った。

ひとまずできるようにしているだけで、設定として適切とか
セキュリティ的な側面で問題ないかといったことは一切考えてないので注意。

<1>公開鍵を使ったパスなしログイン
1. 事前作業
公開鍵でログインできるようにする準備。

(1) sshでログイン
 ssh ansible@ホスト名
(2) .sshディレクトリを作成
 mkdir .ssh
 chmod 700 .ssh
(3) authorized_hostファイルを作成
 touch .ssh/authorized_keys
 chmod 600 .ssh/authorized_keys

2. 公開鍵をauthorized_keysに追加する
 cat ~/.ssh/id_rsa.pub | ssh ansible@ホスト名 'cat >> .ssh/authorized_keys'

ここまでで、一旦パスなしでのログインは実現

<2>sudo権限のansibleユーザへの付与
(1) sshでログイン
 ssh rootになれるユーザ@ホスト名
   sudo su -
(2) /etc/sudoers.d配下にファイルを作る
   vi /etc/sudoers.d/ansible
        (ファイルを作成)
   chomod 600 /etc/sudoers.d/ansible

(/etc/sudoers.d/ansibleの内容)
Defaults !requiretty

ansible         ALL=(ALL)       NOPASSWD: ALL

2016年1月17日日曜日

NFSマウント

個人用メモ

■ NFSサーバ
NFSサーバーの設定

■ NFSクライアント
NFSクライアントの設定(CentOS)

細かいチューニングとかは後々考えよう。

Zabbix on CentOS7

ZabbixとPacemakerを使うことになったので、メモを整理。


  Zabbix : インストール

このページの管理者って何者なんやろ。すごいよね。


NICが2つあるときは、デフォルトルート周りでおかしなことになるので、
nmtuiとか使って適当に設定。

CentOS7 ネットワークの設定変更

…ちゃんとLinuxのネットワークはきちんと勉強したいなぁ…


  Zabbix : インストールのページだとMariaDBベースなので、
MySQLベースに変えよう。下記ページを参考にMySQLをインストール。

CentOS7.1 64bitのyumリポジトリにMySQLを追加し、最新バージョンをインストール


最小インストールだとwgetが入ってないので、yumでインストールしときましょ。

パスワードの設定やらをしくじったら以下の手順で初期化。
Mysqlのrootユーザのpasswordを初期化(変更)する

後は  Zabbix : インストール にしたがってインストールすればよろし。
※パスワードやらはもちろんこのままじゃだめだけれども。

Zabbixのログインの際の初期パスワードなどは以下にある。
ログイン後変更するようしましょう。

1 ログインとユーザーの設定

2016年1月15日金曜日

嫁からの質問

嫁からLINEで質問が、

ITわからない人にNICのボンディングをするにはどうすれば?との話が。

はい、わかりました。
書きましょう。
(内容が正しいかは別として)

はて?

転職しました。
1月から新しい職場で働き始めました。
まあ、IT屋さんになのは変わってないです。

で、話していると一部の方から他の人と間違われている気がする...(;´д`)
そんなにこのblog自体も積極的にやってるわけではないし...

うーん...ひとまず、自分に似た人に負けないように頑張ります。

2015年9月12日土曜日

Glassfish+Derby+JDBCレルムについて(ソースコード解説)

JDBCレルムについてソースコード内容について概要を記述。
下記GitHubのコードの解説である。
https://github.com/Fufuhu/SimpleAuthentication

NetBeans上でMavenのWebプロジェクトで作成している。


Servletとjspだけで構成されたシンプルな構成になっている。
(Webページディレクトリ直下のindex.jspは無視してもらって構いません。)

■画面遷移について

以下のような形で画面遷移を構成しています。


index.jspがログインページLoginServletにてJDBCレルム認証を実行後、
認証を通過すればtoppage.jsp, 失敗すればerror.jspに遷移する。


■index.jsp
ログインページ。ユーザ名とパスワードの入力したのちに、
ログインボタンクリックで、LoginServletを呼び出し、JDBCレルム
認証を実行することができる。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>ログイン</title>
    </head>
    <body>
        ログイン情報<br/>
        <form method="POST" action="../LoginServlet">
            ユーザ名:<input type="text" name="username"/> <br/>
            パスワード:<input type="password" name="password"/><br/>
            <input type="submit" method="GET" value="ログイン"/>
        </form>
    </body>
</html>



■LoginServlet(一部抜粋)
42行目のrequest.login(username, password);でJDBCレルム認証を実行している。
index.jspで入力されたユーザ名、パスワードの内容に応じてログイン可否を判断している。
loginメソッドで認証ができれば、そのままtoppage.jspへの遷移を続行。(ユーザ認証情報がセッションに含まれるようになる。)できなければServletExceptionがスローされるので、error.jspに遷移する。

package authentication;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author USER
 */
@WebServlet(name = "LoginServlet", urlPatterns = {"/LoginServlet"})
public class LoginServlet extends HttpServlet {

   
    private final String topPage = "/login/toppage.jsp";
    private final String errorPage = "/login/error.jsp";
    /**
     *
     * @param request servlet request
     * @param response servlet response
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        response.setContentType("text/html;charset=UTF-8");
            String username = request.getParameter("username");
            String password = request.getParameter("password");
           
            ServletContext sc = getServletContext();
           
            try {
                //JDBCレルム認証部分(認証に失敗すると例外をスロー)
                request.login(username, password);
            } catch (ServletException ex) {
                Logger.getLogger(LoginServlet.class.getName()).log(Level.SEVERE, null, ex);
                try {
                    sc.getRequestDispatcher(errorPage).forward(request, response);
                } catch (ServletException ex1) {
                    Logger.getLogger(LoginServlet.class.getName()).log(Level.SEVERE, null, ex1);
                }
            }
            try {
                sc.getRequestDispatcher(topPage).forward(request, response);
            } catch (ServletException ex) {
                Logger.getLogger(LoginServlet.class.getName()).log(Level.SEVERE, null, ex);
            }
    } 
    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}

■toppage.jsp
仮のトップページ。ウェルカムメッセージと、
ログアウトのための処理呼び出しが可能なだけ。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>トップページ</title>
    </head>
    <body>
        <h1>ログインに成功しました。</h1><br/>
        <form action="./LogoutServlet">
            ${param["username"]}様、いらっしゃいませ。<br/>
            <input type="submit" value="ログアウト"/>
        </form>
    </body>
</html>

■LogoutServlet(一部抜粋)
request.getSession().invalidate();でセッション情報を明示的に破棄するとともに
request.logout();でログアウト処理を実行している。

package authentication;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author USER
 */
@WebServlet(name = "LogoutServlet", urlPatterns = {"/LogoutServlet"})
public class LogoutServlet extends HttpServlet {

    private final String indexPage = "./login/index.jsp";
    private final String errorPage = "./login/error.jsp";
    /**
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code>
     * methods.
     *
     * @param request servlet request
     * @param response servlet response
     */
    /**
     * @param request servlet request
     * @param response servlet response
     * @throws java.io.IOException
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException
    {
        //セッションを明示的に破棄する。
        request.getSession().invalidate();
        ServletContext sc = getServletContext();
       
        try {
           //認証からのログアウトを行う処理。
            request.logout();
        } catch (ServletException ex) {
            Logger.getLogger(LogoutServlet.class.getName()).log(Level.SEVERE, null, ex);
            try {
                sc.getRequestDispatcher(errorPage).forward(request, response);
            } catch (ServletException ex1) {
                Logger.getLogger(LogoutServlet.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }
        response.sendRedirect(indexPage);      
    }
    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }
}


■error.jsp
ログイン処理時にrequest.login()に失敗するとこちらのページに遷移する。

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>

        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h1>ログイン失敗</h1><br/>
        <a href="./index.jsp">ログインページへ</a>
    </body>
</html>


次の記事では、コードではなく、アクセス制御(web.xml)の記入について説明します。
※生のxmlを書くわけではなく、NetBeansにおんぶにだっこで設定します。

Glassfish+Derby+JDBCレルムについて(Glassfishの設定)

Glassfish側の設定。

以下の項目を作成していきます。

  1. コネクションプール
  2. JNDIリソース
1.についてはもともとあるものを流用してもよいのですが、
個人的に気持ち悪さを感じてしまうのであえて新しく作成することにします。

1. コネクションプールの作成
Glassfishの管理画面にログインします。
ローカルで実行している場合は、
http://localhost:4848にアクセスしてもらえれば管理画面に
アクセスできるはずです。
初期状態では特にパスワードなどは設定していないので
そのまま管理画面にアクセスできるはずです。

アクセス後は、管理画面の「JDBC」→「JDBC Connection Pools」と
選択をしていきます。作成済みのコネクションプールの一覧が
表形式で表示されるので、「New」ボタンをクリックしたのち、下記画面の内容を入力します。


これで以前の記事で作成したデータベースに対する
JDBCのコネクションプールは作成完了です。

一枚目の画像の「Ping」ボタンをクリックして

コネクションプールの名前にAuthenticationPoolと名付けたことを覚えておいて
ください。

2. JNDIリソースの作成

次はJNDIリソースを作成します。
管理画面の「JDBC」→「JDBC Resources」を選択します。
作成済みのJDBCプールのJNDIリソースの一覧が表示されるので、
「New」ボタンをクリックしたのち、下記の内容を入力します。


3. JDBCレルム設定の作成

「Conifgurations」→「Conifgurations」→「Security」→「Realms」を選択したのち、
「New」ボタンをクリックします。

下記画像の設定を投入します。


設定内容は以前の記事にて作成したDerbyのデータベースの設定に
準拠しています。

これでGlassfish側のJDBCレルムの設定は完了です。




2015年9月10日木曜日

Glassfish+Derby+JDBCレルムについて(Derby(JavaDB)の設定)

JDBCレルム認証を実現するためにはまずデータベースの作成が必要です。
ここでは、NetBeansをつかってローカルのJavaDB上にJDBCレルム認証に利用するデータベースを構築する方法を説明します。


NetBeansのサービスタグを選択、JavaDBを右クリックしてデータベースの
作成を選択します。


ここでは、データベース名をAuthenticationSampleとして作成しています。
ユーザ名はAPP, パスワードもユーザ名と同じにしています。
(当然ですが、本番環境での利用の際にはユーザ名、パスワードともに配慮が必要です。)

これで、JavaDB上にAuthenticationSampleデータベースが作成されました。



次は新規の接続先として先ほど作成したAuthenticationSampleに接続します。
下記のような設定を行ってください。


これで、接続先の設定が完了しました。
次にテーブルの作成に移ります。

テーブルの作成には先ほど作成した接続先を右クリックし、
コマンドの実行を選択します。新しい画面が開くので、下記のSQLを入力し、
usertableとgrouptableを作成します。


create table usertable (
username varchar(20) NOT NULL CONSTRAINT USER_PK PRIMARY KEY ,
mailaddress varchar(100) NOT NULL,
password varchar(128) NOT NULL
);


create table grouptable(
username varchar(20) NOT NULL,
groupid varchar(20) NOT NULL,
CONSTRAINT GROUP_PK PRIMARY KEY(username, groupid),
CONSTRAINT USER_FK FOREIGN KEY(username)
REFERENCES usertable(username) ON DELETE
);

これで、JDBCレルム認証用のデータベースが作成できました。
次以降の設定で必要となる内容は以下の通りです。

usertableのパスワード列には生パスワードではなく、SHA-256でハッシュ化した
値を入れないといけません。こちらについてはサンプルコードを
寺田佳央さんが提供してくれています。
https://github.com/yoshioterada/JDBC-Realm-Sample/tree/master/src/main/java/jp/co/oracle/jdbcrealm/SHADigestUtil


以下の情報は次回以降に利用するため、記載しておきます。

JDBC URL: jdbc:derby//localhost:1527/AuthenticationSample
データベース名: AuthenticationSample
データベースのユーザ名/パスワード: APP/APP
ユーザテーブル: usertable
ユーザ名: username
パスワード: password

グループテーブル: grouptable
ユーザ名: username
グループ名: groupid




Glassfish + Derby + JDBCレルムについて

JDBCレルム認証を説明した可能な限りシンプルなコードを作成しました。


https://github.com/Fufuhu/SimpleAuthentication


具体的な説明は後日。

2015年9月7日月曜日

Glassfish + Derby + JDBCレルムについて(導入編)

私の妄想が7割くらいなので、正しい理解なのかは保証しません。
図にしないと理解しづらい低能なので、JDBC、JNDI、JDBCレルムの依存関係はこんな感じ。
(コネクションプールを利用する場合)



  • JDBC Connection Pool ... どこにあるDBに接続するか
  • JDBC Resource(JNDI) ... JNDIとしてJDBC Connection Poolを取り扱えるようにする。
  • JDBCレルム ... JNDIからJDBC Connection Poolへ接続し、特定のテーブルからユーザ名・パスワードとロール名を読み取る。
JDBCレルムでパスワードを取り扱う際には、生パスワードをDBに書き込むことができないのでうっかりさんも安心。寺田さんの記事の例ではSHA-256でハッシュ化してあります。

一応私の方でも実装編を解説しようかと思います。以下の寺田さんの例だとJSFを使っているので、前提知識多めな感じになってしまっているので...私の方ではもっとシンプルにServletとJSPを使って実装しようかと思います。

2015年9月5日土曜日

JSFのfaceletsきめぇな方へ

JSFってエンジニアにはうれしいけど、デザイナにとってはつらいよね。

漢らしい業務臭い画面ってそれはそれで味があっていいけれども、
かわいらしいデザインって欲しいじゃない?

ってことでHTMLっぽくJSFを記述する方法をちょいと調べてみた。

JSF 2.2 でさらに便利になったMarkupを使ってみよう


公式に近い部分だとこれかな??
HTML(5) Friendly Markup in JSF 2.2


これをつかえばcssとかJavaScriptも一緒に使えるかな??

CDIメモ(自分向け)

完全に自分向けメモ。
ぼやっと本読んでたら何やら理解できて来た気がするので……

内容が正しいかはまったくもって保証しません。

■ CDI(Context and Dependency Injection)


    @Named(value = "injectSample")
    public class InjectSample {
        @Inject InjectedSample injected;
        public void sample() {
            injected.execute();
        }
    }


通常であればinjectedはどこかでインスタンス化する
必要がある(new InjectedSample();)が、CDIを利用することで
これをしなくてよくなる。

これによって、
InjectSampleとInjectedSampleの間の依存関係を疎にすることができる。
(その代わりInjectedSampleは引数を受け付けないコンストラクタによって
インスタンス化される)

■ コンテキスト

上記の内容を理解するにはコンテキスト(Context)にるいて理解する必要がある。

CDIにおけるコンテキストとは
スコープアノテーションによって指定されたオブジェクトの存続設定

■スコープアノテーション

CDIビーンに対して設定されるオブジェクトの存続期間


  • @RequestScoped
  • @SessionScoped
  • @ApplicationScoped
  • @ConversationScoped
  • @Dependent

■CDIビーン

管理ビーンの一種。CDIサービスによって管理される。
管理ビーンはコンテナ内で管理されており、
スコープに応じて適切なオブジェクトが自動で選択され、
変数に代入される。

2015年9月1日火曜日

WebSocketのサンプルコード(クライアント編)


WebSocketのクライアント(ブラウザ)側の実装サンプル。

テキストフィールドにメッセージを入れてSubmitボタンをクリックすると
他のクライアントにもメッセージが配信される。そんだけ。


Bootstrapを使ってみたけど、説明するって意味では、
明らかにコード可読性の低下要因でしかないな~......


以下の解説の用語とかは信用しないでください。
jQueryとBootstrap使ってるけれども正しい使い方ではないと思う。
基本的には、

  1. Websocketプロトコルでのアクセス先(wsUri)を指定
  2. Websocketをnewする(websocket)
  3. websocketに対して必要なメソッドを実装(ここではonerror, onopen, onmessage)
  4. クライアント上の操作内容に応じてjQueryでぐりぐりする
(ここでは、submitボタンをクリックするとテキストフィールドに入力したメッセージが 送信される。同時に他のクライアントにもメッセージが配信される。)
<html>
    <head>
        <title>Chatter</title>
        
        
        <link href="css/bootstrap.min.css" rel="stylesheet"></link>
        <script src="./js/jquery-2.1.1.js" type="text/javascript"></script>
        <script type="text/javascript">
            $(function(){
                var wsUri = "ws://" + document.location.host + "/WebSocketChatter/MessageReceiptor";
                var websocket = new WebSocket(wsUri);
                websocket.onerror = function(evt) {
                    
                };
                websocket.onopen = function(evt) {
                    
                };
                websocket.onmessage = function(message) {
                    console.log('Received Text:'+message.data);
                    $('<div class="well row" style="margin-bottom: 2px;">
'+message.data+'</div>
').appendTo('#container_message');
                };
                
                $('#btn_submit').on('click', function(){
                    var text = $('#text_message').val();
                    if(text !== '') {
                        websocket.send(text);                        
                        console.log('Send Text:'+text);
                    }
                });
                
                $('#btn_clear').on('click', function(){
                    $('#text_message').val('');
                });
            });
        </script>
    </head>
    <body>
        <div class="row">
            <div class="col-lg-3">
</div>
<div class="col-lg-3">
                <h1 class="label-primary" style="border-radius: 3px 3px;">
WebSocketChatter</h1>
</div>
</div>
<div class="row">
            <div class="col-lg-3">
</div>
<div class="col-lg-3">
                <h2 class="label-info">
入力項目</h2>
</div>
</div>
<div class="row">
            <div class="col-lg-3">
</div>
<div class="col-lg-3">
                <label for="text_message">Message</label>
                <input class="form-control" id="text_message" placeholder="Text Message" type="text" />
            </div>
</div>
<div class="row">
            <div class="col-lg-3">
</div>
<div class="col-lg-4 btn-toolbar">
                <div class="btn-group">
                    <button class="btn btn-success" id="btn_submit" type="button">Submit    <span class="glyphicon glyphicon-check"></span></button>
                    <button class="btn btn-danger" id="btn_clear" type="button">Clear   <span class="glyphicon glyphicon-remove"></span></button>
                </div>
</div>
</div>
<div class="row">
            <div class="col-lg-3">
</div>
<div class="col-lg-3">
                <h2 class="label-info">
メッセージコンテナ</h2>
<div class="col-lg-12" id="container_message">
                </div>
</div>
</div>
</body>
</html>

2015年8月31日月曜日

WebSocketのサンプルコード(サーバサイド)

GlassFish 4.1 + Java 1.7で記述。
(サポート切れててゴメン。たぶん1.8でも動くよ(祈り)。)

なんか画面の表示下のコード表示が微妙にバグ踏んでるけど、まあいいや。
(勝手に<Session>を</session>で閉じなくていいんだよ......</session>消せないし...)
※102行目の</session></session>は無視おねがいします。

package websocketchatter;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

/**
 * WebSocketのURIを指定。
 * @author USER
 */
@ServerEndpoint("/MessageReceiptor")
public class MessageReceiptor {

    private static Set peers = Collections.synchronizedSet(new HashSet());
    private static File file;
    private static BufferedWriter writer;

  /* いずれかのセッションからメッセージが送信された場合のメソッド */
    @OnMessage
    public String onMessage(String message) {
       for(Session s : peers) {
      /*
             非同期に各セッションにメッセージを送る。
           */
           s.getAsyncRemote().sendText(message);
           try {
               System.out.println(message);
               writer.write(message, 0, message.length());
               writer.newLine();
               writer.flush();
           } catch (IOException ex) {
               Logger.getLogger(MessageReceiptor.class.getName()).log(Level.SEVERE, null, ex);
           }
           System.out.println(message);
       }
        return null;
    }
  /* セッションがクローズされた際に呼び出されるメソッド */
    @OnClose
    public void onClose(Session peer) {
        peers.remove(peer);
    }

    /* セッションがオープンされた際に呼び出されるメソッド */
    @OnOpen
    public void onOpen(Session peer) {
    /*
         この処理は非常に雑なので参考にしないで。
     永続化に際してはJPAとかを使ってRDBに書き込んだりしたほうがいいと思います。
     滅茶苦茶雑な処理です。(こんな書き方はしてはいけません。)
         修正したら正式版を別記事で挙げます。
        */
        if(file == null) {
            Date date = new Date();
            SimpleDateFormat format = new SimpleDateFormat("YYYYMMdd");
            String str = format.format(date);
            file = new File(str+".log");
            try {
                System.out.println("File Path:" + file.getCanonicalPath());
            } catch (IOException ex) {
                Logger.getLogger(MessageReceiptor.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        if(writer == null) {
            try {
                writer = new BufferedWriter(new FileWriter(file));
            } catch (IOException ex) {
                Logger.getLogger(MessageReceiptor.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        
        try {
            BufferedReader reader = new BufferedReader(new FileReader(file));
            for(String str = reader.readLine(); str != null; str = reader.readLine()) {
                peer.getAsyncRemote().sendText(str);
            }
        } catch (FileNotFoundException ex) {
            Logger.getLogger(MessageReceiptor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(MessageReceiptor.class.getName()).log(Level.SEVERE, null, ex);
        }       
        peers.add(peer);
    }    
}


そのうち、クライアント側処理(jQuery + Bootstrapを組み合わせた場合かな~...)
と組み合わせた時の画像か動画でも載せます。

ちな、jQueryとBootstrapの使い方として正しいのかは保証しません。

なので、今後のToDoとしては以下の通り

  1. クライアント側(ブラウザ側実装の提示)
  2. PowerPointスライド(画像)によるサーバサイド処理の内容の表示
  3. @OnOpen処理の屑さ加減の改善(JPAを使ったRDBによる永続化

JFreeChartで横軸の値を縦書きにする

JFreeChartでグラフを作るときに悩ましいのが、
横軸のラベル(って言えばいいのでしょうか?)の管理。
横軸ラベルの文字列が長くなると本来の値が
...に置換されてしまい残念な結果になってしまいます。
一応の対応策としては、ラベルを縦書きにすることで
問題を解消できます。
こんな感じで、修正可能です。
JFreeChart chart = ChartFactory.createBarChart("サンプルグラフ", "横軸", "縦軸", dataset);
chart.setAntiAlias(true);
CategoryPlot plot = chart.getCategoryPlot();
CategoryAxis axis = plot.getDomainAxis();
axis.setCategoryLabelPositions(CategoryLabelPositions.UP_90);

JFreeChartから上記処理に基づいて
CategoryAxisを取得しsetCategoryLabelPositionsメソッドで
向きを変更することができます。

2015年8月28日金曜日

なんだこれ

以下の記事だけやたらと閲覧数が多い。なんでだ?
対した記事ではないと思うんだけど。
所詮はjQueryのことを良く知らない人間が勉強し始めて即日書いたものなのに......


http://ryoma0923.blogspot.jp/2015/01/jquerycss.html


律儀に動画を作成したのがよかったのかな?

ユーザ主導の技術革新(まだ案レベル)

とくにパブリッククラウドに限った話になりますが、
技術革新はユーザ手動で起こるという印象を受けます。

詳細は改めて説明しますね。