Javaアプレットからデータベースに接続する

「Java アプレット データベース」などの検索キーワードで当サイトを訪れる方が多いことには以前から気づいていた。当サイトのアクセス解析で毎月、何度か必ず見かける検索キーワードである。

けれども、どうやらJavaアプレットからDBに接続に書いた内容とは少し違うものを探しているのではないかという気がしてきたのは、今年に入ってからである。

それで、その探しているであろう内容を勝手に推測して作成したのが、Javaアプレットからデータベースに接続する(applet-db-policy.html)というページ今回のエントリである。

探している人にとって、的を射た内容になっていたならば幸い。作った甲斐があったというものである。

Excelで書いてHTML形式で出力したものなので、PC環境によっては閲覧できない可能性あり。を、ブログ移転(cocolog-nifty.comからsakura.ne.jp)に伴い、このエントリの記事として修正。

Javaアプレットからデータベースに接続する

以下のようにJavaアプレットを提供しているWWWサーバーがDBサーバーを兼ねている場合、Javaアプレットはデータベースに接続できる。

しかし、以下のようにWWWサーバーとDBサーバーが分かれている場合、JavaアプレットはDBサーバーに接続できない。

基本的にJavaアプレットがアクセスできるのは、Javaアプレットを提供しているWWWサーバーのみ。

WWWブラウザでJavaアプレットのページを表示させようとすると、たいてい正常に表示されずにJavaコンソールにスタックトレースが出力される。

Java Plug-in 1.6.0_17
	使用中の JRE のバージョン 1.6.0_17-b04 Java HotSpot(TM) Client VM
	ユーザのホームディレクトリ = C:\Documents and Settings\hoge
	----------------------------------------------------
	c:   コンソールウィンドウをクリア
	f:   ファイナライズキューのオブジェクトをファイナライズ
	g:   ガベージコレクト
	h:   このヘルプメッセージを表示
	l:   クラスローダリストをダンプ
	m:   メモリ使用率を表示
	o:   トリガログ
	q:   コンソールを非表示
	r:   ポリシー設定を再ロード
	s:   システムプロパティと配備プロパティをダンプ
	t:   スレッドリストをダンプ
	v:   スレッドスタックをダンプ
	x:   クラスローダキャッシュをクリア
	0-5: トレースレベルを  に設定
	----------------------------------------------------
	com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
	Last packet sent to the server was 0 ms ago.
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Unknown Source)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
	at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1074)
	at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2103)
	at com.mysql.jdbc.ConnectionImpl.(ConnectionImpl.java:718)
	at com.mysql.jdbc.JDBC4Connection.(JDBC4Connection.java:46)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
	at java.lang.reflect.Constructor.newInstance(Unknown Source)
	at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
	at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:302)
	at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:282)
	at java.sql.DriverManager.getConnection(Unknown Source)
	at java.sql.DriverManager.getConnection(Unknown Source)
	at javadb.DBConnectApplet.start(DBConnectApplet.java:40)
	at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
	Caused by: java.net.SocketException: java.security.AccessControlException: access denied (java.net.SocketPermission 192.168.0.14:3306 connect,resolve)
	at com.mysql.jdbc.StandardSocketFactory.unwrapExceptionToProperClassAndThrowIt(StandardSocketFactory.java:404)
	at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:265)
	at com.mysql.jdbc.MysqlIO.(MysqlIO.java:280)
	at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2026)
	... 14 more

このような場合は、Javaアプレットのセキュリティ・ポリシー(java.policy)を変更・追加することによって、データベースに接続できるようになる。

Javaアプレットのセキュリティ・ポリシーを変更・追加するには、Policy Toolを使用する。

Policy Tool(policytool.exe)は、%JAVA_HOME%\bin\配下にインストールされている。

Policy Tool(policytool.exe)を実行すると、以下のようなウィンドウが起動する。

起動したら、[ファイル]メニューから[開く]を選択する。

%java_home%\lib\security\配下のjava.policyを選択して、[開く]を押下する。

java.policyに登録されているポリシーエントリが一覧表示されるので、[ポリシーエントリの追加]を押下する。

ポリシーエントリが開いたら、CodeBaseにJavaアプレットのCodeBase属性を入力し、[アクセス権の追加]を押下する。

以下の例では “http://192.168.0.4/javadb/bin/” となる。

追加したいアクセス権を選択して、[了解]ボタンを押下する。

以下の例は、 “AllPermission” を選択する場合。

同様に必要なアクセス権を追加していって、最後に[完了]ボタンを押下する。

アクセス権は、設定手順を簡単に説明するために “AllPermission” のみとしている。

実際には、最低限必要なアクセス権のみを設定しましょう。

ポリシーエントリの一覧に追加されていることを確認する。

追加したセキュリティ・ポリシーを有効にするために、[ファイル]メニューから[保存]を選択する。

保存に成功したら、以下のようなダイアログが表示されるので、[了解]ボタンを押下する。

以上でセキュリティ・ポリシーの設定は完了しているので、設定内容を確実に反映させるためにWWWブラウザやJavaが保持しているキャッシュをクリアしておく。

以下は、Javaが保持しているキャッシュのクリア手順。詳しい説明は割愛。

WWWブラウザでJavaアプレットのページを表示させてみて、正常に表示され、Javaコンソールにもスタックトレースやエラーが出力されていなければOK。

以上です。

java.policyやアクセス権についての詳細については、別のサイトで補完してください。

というか、私に教えて欲しいw。

2009年11月08日(日) 22時33分  

Javaで非矩形・半透明ウィンドウ(Swing版)(その2)

先日作成したSwingによる非矩形ウィンドウはJWindowのみ可能で、JFrameでは対応できなかった。

その後、いろいろと調べて試行錯誤を繰り返してみた結果、JFrameでも同様に非矩形ウィンドウを作成することができた。以下、そのソースコード。

先日作成したソースコードを流用して、またいじくりまわしているので、汚いのはご容赦のほど。

package swing;

import java.awt.Component;
import java.awt.Container;
//import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.GeneralPath;
//import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
//import javax.swing.JPanel;
import javax.swing.JPopupMenu;
//import javax.swing.JWindow;
//import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import com.sun.awt.AWTUtilities;

public class TransSwingWindow extends JFrame implements ActionListener {
    /**
     *
     */
    private static final long serialVersionUID = 1L;

    public static final String TITLE    = "Swing版 半透明ウィンドウテスト";
    public static final String VERSION    = "Ver0.01";
    public static final int DEFAULT_SIZE = 64;

    Window window = null;
    Shape shape = null;
    Image image = null;
    private Point start = null;
    private Point point = null;
    private JPopupMenu popupMenu = null;

    public static void main(String[] args) {
//        new TransSwingWindow();

//        SwingUtilities.invokeLater(new Runnable(){
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
//                javax.swing.JFrame.setDefaultLookAndFeelDecorated(true);
                new TransSwingWindow();
            }
        });
    }

    public TransSwingWindow() {
        super();
        getRootPane().setDoubleBuffered(true);
        ((JComponent)getContentPane()).setDoubleBuffered(true);

        //UIをWindowsに設定
        //右クリックメニューで使用
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (ClassNotFoundException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        }

        window = this;

        //イメージファイルの読み込み
        ImageIcon icon = null;
        int width = DEFAULT_SIZE;
        int height = DEFAULT_SIZE;
        try {
            icon = new ImageIcon(getClass().getClassLoader().getResource("suiseiseki.png"));

            shape = getImageShape(icon);

            image = icon.getImage();
            width = Math.max(icon.getIconWidth(), DEFAULT_SIZE);
            height = Math.max(icon.getIconHeight(), DEFAULT_SIZE);
        } catch (Exception e) {
            System.out.println("ImageLoadError");
        }

        addPopupMenu();
        addMouseEvent();

        if (window instanceof javax.swing.JFrame) {
            ((JFrame)window).setTitle(TITLE + " " + VERSION);
        }
        this.setSize(width, height);

        if (window instanceof javax.swing.JFrame) {
            ((JFrame)window).setUndecorated(true);
        }

        Container contentPane = getContentPane();

        //JWindowに非矩形ウィンドウの元となる画像を描画させると
        //右クリックでJPopupMenuを起動した時に表示ががおかしくなるので、
        //JPanelに画像を描画させる
//        Canvas panel = new Canvas(image);
//        contentPane.add(panel);

        //今回はJWindowに画像を描画させないで、JLabelを使用してみた
        JLabel label = new JLabel(icon);
        contentPane.add(label);

//        pack();

        if (window instanceof javax.swing.JFrame) {
            ((JFrame)window).setResizable(false);
            ((JFrame)window).setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }

//        this.setLocationRelativeTo(null);
        this.setLocation(100, 100);

//        AWTUtilities.setWindowShape(this, new RoundRectangle2D.Double(0, 0, getWidth(), getHeight(), 100, 100));
        AWTUtilities.setWindowShape(this, shape);
        AWTUtilities.setWindowOpacity(this, (Float)0.70f);

        this.setVisible(true);
    }

    private void addPopupMenu() {
        popupMenu = new JPopupMenu();
        JMenuItem menuItem = new JMenuItem();
        menuItem.setText("終了" );
        menuItem.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                System.exit(0);
            }
        });
        popupMenu.add(menuItem);
    }

    private void addMouseEvent() {
        this.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                Component com = (Component)e.getComponent();

                switch (e.getButton()) {
                case MouseEvent.BUTTON1:
                    popupMenu.setVisible(false);
                    break;
                case MouseEvent.BUTTON3:
                    popupMenu.show(com, e.getX(), e.getY());
                    break;
                default:
                    popupMenu.setVisible(false);
                    break;
                }
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                // TODO 自動生成されたメソッド・スタブ
                Component c = (Component) e.getComponent();
                point = c.getLocation();
                c.setLocation(point);
            }

            @Override
            public void mousePressed(MouseEvent e) {
                // TODO 自動生成されたメソッド・スタブ
                start = e.getPoint();
                point = e.getPoint();

//                if (e.getClickCount() >= 2) {
//                    System.exit(0);
//                }
            }
        });

        this.addMouseMotionListener(new MouseMotionListener() {

            @Override
            public void mouseMoved(MouseEvent e) {
                // TODO 自動生成されたメソッド・スタブ

            }

            @Override
            public void mouseDragged(MouseEvent e) {
                // TODO 自動生成されたメソッド・スタブ
                Component c = (Component) e.getComponent();
                point = c.getLocation(point);
                int x = point.x - start.x + e.getX();
                int y = point.y - start.y + e.getY();
                c.setLocation(x, y);
            }
        });
    }

    /**
     * ImageIconからアルファ値が0でない画素からなるShapeを得る
     * */
    public Shape getImageShape(ImageIcon icon){
        GeneralPath shape = new GeneralPath();

        final BufferedImage bi = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
        icon.paintIcon(null, bi.createGraphics(), 0, 0);

        ColorModel cm = bi.getColorModel();

        //元(上)のループが縦方向にスキャンしていたので、横方向にスキャンするように変更してみた
        //いまどきのOS/PCではグラフィック処理にラスターを意識しなくても良い?
        for (int y = 0; y < bi.getHeight(); y++) {
            for (int x = 0; x < bi.getWidth(); x++) {

                //完全に透過していなければshapeに追加
                if (cm.getAlpha(bi.getRGB(x, y)) > 0) {
                    int start = x;
                    int width = 0;
                    while (x < bi.getWidth() && cm.getAlpha(bi.getRGB(x++, y)) > 0) {    //forをwhileに変更
                        width++;
                    }

                    shape.append(new Rectangle(start, y, width, 1), true);
                }
            }
        }

        return shape;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO 自動生成されたメソッド・スタブ
    }

//    private class Canvas extends JPanel {
//        /**
//         *
//         */
//        private static final long serialVersionUID = 1L;
//
//
//        private Image image = null;
//
//
//        public Canvas(Image image) {
//            super();
//            this.image = image;
//        }
//
//
//        public void paintComponent(Graphics g) {
//            if (image == null) {
//                return;
//            }
//
//            g.drawImage(image, 0, 0, this);
//        }
//    }
}

今回は、先日のものをJFrameに対応させた上で半透明処理を施してみた。

ソースコード中でウィンドウを非矩形、半透明にしている部分は、以下の部分。

        AWTUtilities.setWindowShape(this, shape);
        AWTUtilities.setWindowOpacity(this, (Float)0.70f);

実際に動作している様子を動画にしたものがこちら。動画の中で実行しているjarファイルはこれ

動画サイズを抑えた結果、画質がやや荒くなってしまっているが、翠星石の形状にウィンドウが作られて、かつ半透明になっているのが確認できると思う。

ただ1点問題があって、ポップアップメニューなどの表示も非矩形・半透明の設定の影響を受けてしまい、表示が欠けてしまう(下図参照)。

この点については、私の実装方法に問題があるのか、JFrameで非矩形ウィンドウを実装した際に起きる不具合なのかは不明。

とりあえず、SwingでJWindowだけでなくJFrameでも半透明+非矩形ウィンドウが実装できたので、よしとしよう。

2009年04月29日(水) 23時36分  

Javaで非矩形・半透明ウィンドウ(Swing版)

以前、Javaで非矩形ウィンドウの記事を書いたが、その時点は結局Wicocoの拡張APIを使わないでSWTで実装したのだが、Swingでも実装できることがTACの雑記というサイトで紹介されていた。

実装できるようになったのがJava6 Update10のリリース以降からなのか、それとも以前からなのかはわからないが、Swingでも非矩形ウィンドウが実装できることがわかったのはうれしい限り。

というわけで、早速TACの雑記のコードを参考に、あれこれいじくりまわしてみた。以下がそのソースコード。そして、出来上がったのがこれ。実際に動作している様子はこちら

package swing;

import java.awt.Component;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;

import javax.swing.ImageIcon;
import javax.swing.JComponent;
//import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import com.sun.awt.AWTUtilities;

public class SwingWindow extends JWindow implements ActionListener {
    /**
     *
     */
    private static final long serialVersionUID = 1L;

//    public static final String TITLE    = "Swing版 非矩形ウィンドウテスト";
//    public static final String VERSION    = "Ver0.01";
    public static final int DEFAULT_SIZE = 64;

    JWindow window = null;
    Shape shape = null;
    Image image = null;
    private Point start = null;
    private Point point = null;
    private JPopupMenu popupMenu = null;

    public static void main(String[] args) {
        new SwingWindow();
    }

    public SwingWindow() {
        super();
        getRootPane().setDoubleBuffered(true);
        ((JComponent)getContentPane()).setDoubleBuffered(true);

        window = this;

        //イメージファイルの読み込み
        int width = DEFAULT_SIZE;
        int height = DEFAULT_SIZE;
        try {
            ImageIcon icon = new ImageIcon(getClass().getClassLoader().getResource("panel.png"));

            shape = getImageShape(icon);

            image = icon.getImage();
            width = Math.max(icon.getIconWidth(), DEFAULT_SIZE);
            height = Math.max(icon.getIconHeight(), DEFAULT_SIZE);
        } catch (Exception e) {
            System.out.println("ImageLoadError");
        }

        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                AWTUtilities.setWindowShape(window, shape);
            }
        });

        //UIをWindowsに設定
        //右クリックメニューで使用
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (ClassNotFoundException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        } catch (UnsupportedLookAndFeelException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        }

        addPopupMenu();
        addMouseEvent();

//        this.setTitle(TITLE + " " + VERSION);
        this.setSize(width, height);

        Container contentPane = getContentPane();

        //JWindowに非矩形ウィンドウの元となる画像を描画させると
        //右クリックでJPopupMenuを起動した時に表示ががおかしくなるので、
        //JPanelに画像を描画させる
        Canvas panel = new Canvas(image);

        contentPane.add(panel);

//        pack();

//        this.setResizable(false);
//        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.setLocationRelativeTo(null);
        this.setLocation(100, 100);

        this.setVisible(true);
    }

    private void addPopupMenu() {
        popupMenu = new JPopupMenu();
        JMenuItem menuItem = new JMenuItem();
        menuItem.setText("終了" );
        menuItem.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                System.exit(0);
            }
        });
        popupMenu.add(menuItem);
    }

    private void addMouseEvent() {
        this.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                Component com = (Component)e.getComponent();

                switch (e.getButton()) {
                case MouseEvent.BUTTON1:
                    popupMenu.setVisible(false);
                    break;
                case MouseEvent.BUTTON3:
                    popupMenu.show(com, e.getX(), e.getY());
                    break;
                default:
                    popupMenu.setVisible(false);
                    break;
                }
            }
        });

        this.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseReleased(MouseEvent e) {
                // TODO 自動生成されたメソッド・スタブ
                Component c = (Component) e.getComponent();
                point = c.getLocation();
                c.setLocation(point);
            }

            @Override
            public void mousePressed(MouseEvent e) {
                // TODO 自動生成されたメソッド・スタブ
                start = e.getPoint();
                point = e.getPoint();

//                if (e.getClickCount() >= 2) {
//                    System.exit(0);
//                }
            }
        });

        this.addMouseMotionListener(new MouseMotionListener() {

            @Override
            public void mouseMoved(MouseEvent e) {
                // TODO 自動生成されたメソッド・スタブ

            }

            @Override
            public void mouseDragged(MouseEvent e) {
                // TODO 自動生成されたメソッド・スタブ
                Component c = (Component) e.getComponent();
                point = c.getLocation(point);
                int x = point.x - start.x + e.getX();
                int y = point.y - start.y + e.getY();
                c.setLocation(x, y);
            }
        });
    }

    /**
     * ImageIconからアルファ値が0でない画素からなるShapeを得る
     * */
    public Shape getImageShape(ImageIcon icon){
        GeneralPath shape = new GeneralPath();

        final BufferedImage bi = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB);
        icon.paintIcon(null, bi.createGraphics(), 0, 0);

        ColorModel cm = bi.getColorModel();

        //元(上)のループが縦方向にスキャンしていたので、横方向にスキャンするように変更してみた
        //いまどきのOS/PCではグラフィック処理にラスターを意識しなくても良い?
        for (int y = 0; y < bi.getHeight(); y++) {
            for (int x = 0; x < bi.getWidth(); x++) {

                //完全に透過していなければshapeに追加
                if (cm.getAlpha(bi.getRGB(x, y)) > 0) {
                    int start = x;
                    int width = 0;
                    while (x < bi.getWidth() && cm.getAlpha(bi.getRGB(x++, y)) > 0) {    //forをwhileに変更
                        width++;
                    }

                    shape.append(new Rectangle(start, y, width, 1), true);
                }
            }
        }

        return shape;
    }

//    @Override
//    public void paint(Graphics g) {
//        g.drawImage(image, 0, 0, this);
//    }

    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO 自動生成されたメソッド・スタブ
    }

    private class Canvas extends JPanel {
        /**
         *
         */
        private static final long serialVersionUID = 1L;

        private Image image = null;

        public Canvas(Image image) {
            super();
            this.image = image;
        }

        public void paintComponent(Graphics g) {
            if (image == null) {
                return;
            }

            g.drawImage(image, 0, 0, this);
        }
    }
}

このコードを書く上で、ちょっとはまった箇所があるので紹介。

私がいじくりまわしたコードでは、終了は右クリックでポップアップメニューを表示させて選ぶように実装している。

しかし、参考にさせていただいたコードのまま(JWindowクラスで画像を描画)だと、以下の画像のような現象が発生してしまった。

どうやら追加したポップアップメニューが引き金となっているようなのだが、原因は不明。repaint()をコールしても改善されない。

結局、非矩形ウィンドウの下地となる画像はJWindowクラスで直接描画せずに、JPanelクラスを実装して描画させることで一応解決できた。

一応解決できたのだが、原因がわからずじまいなので、なんだかすっきりしない(苦笑)。

けれども、良い勉強になった。TACの雑記に感謝!

2009年04月26日(日) 23時33分  

Java6 Update10リリース

先日リリースされたJava6 Update10で、半透明ウィンドウと非矩形ウィンドウがサポートされた模様。

早速、試している方(yunoの日記帳)がいらっしゃった。

これでやっとSwingでもまともな半透明/非矩形ウィンドウのアプリが作成できそう。

2008年10月18日(土) 23時33分  

Javaの文字コードエンコーディング設定

覚え書き。

Javaが標準出力とかに出力する文字列の文字コードは、

環境変数_JAVA_OPTIONSに

-Dfile.encoding=MS932

とか、

-Dfile.encoding=UTF-8

とかを設定することで変更可能。

環境変数への設定は、Windowsならば、

set _JAVA_OPTIONS=-Dfile.encoding=UTF-8

2008年07月13日(日) 23時48分  

JavaアプレットからDBに接続

帰宅して、JavaアプレットからMySQLのデータベースに接続するプログラムを書いてみる。いや、正しくは先日作成したJavaアプリケーションやJSPのソースをコピーしただけと言ったほうが正しいかも。まずはJavaアプレットから。

package javadb;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.sql.*;

public class DBConnectApplet extends JApplet {
    /**
     *
     */
    private static final long serialVersionUID = 1L;

    private Connection db = null;

    public void init() {
        try {
            //JDBCドライバの読み込み
            Class.forName("com.mysql.jdbc.Driver").newInstance();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void start() {
        String sql_server = "localhost";
        String sql_user    = "hogehoge";
        String sql_pass    = "fizzbuzz";
        String sql_db    = "dbname";
        //String sql_url    = "jdbc:mysql://localhost/" + sql_db;
        String sql_url = "jdbc:mysql://localhost/dbname?user=hogehoge&password=fizzbuzz";
        try {
            //MySQLのデータベースへ接続
            //db = DriverManager.getConnection(sql_url, sql_user, sql_pass);
            db = DriverManager.getConnection(sql_url);

            //目的のテーブルを操作

            //ステートメントオブジェクトの取得
            Statement stmt = db.createStatement();

            //クエリの準備
            String query = "select id, name, address, tel, fax, mail, site, station from company";

            //クエリーを実行して結果セットを取得
            ResultSet rs = stmt.executeQuery(query);

            //テーブルカラムの設定
            String[] tableColumn = {    " id",    "name",    "address",    "tel",    "fax",    "mail",    "site",    "station",    };

            DefaultTableModel tableModel = new DefaultTableModel(tableColumn, 0);
            JTable table = new JTable(tableModel);

            //検索された行数分ループ
            while (rs.next()) {
                Object[] tableData = {
                        String.format("%4d", rs.getInt("id")),
                        rs.getString("name"),
                        rs.getString("address"),
                        rs.getString("tel"),
                        rs.getString("fax"),
                        rs.getString("mail"),
                        rs.getString("site"),
                        rs.getString("station"),
                };

                //テーブルデータをテーブルに登録
                tableModel.addRow(tableData);

                //コンソールにも出力してみる
                System.out.printf("%2dt%st%st%st%st%st%st%sn",
                        rs.getInt("id"),
                        rs.getString("name"),
                        rs.getString("address"),
                        rs.getString("tel"),
                        rs.getString("fax"),
                        rs.getString("mail"),
                        rs.getString("site"),
                        rs.getString("station")
                );
            }

            //スクロールペインにテーブルを登録
            JScrollPane scroll = new JScrollPane();
            scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
            scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
            scroll.getViewport().add(table);

            //スクロールペインをアプレットに登録
            getContentPane().add(scroll);

            //データベースから切断
            stmt.close();

            //MySQLのデータベースとの接続を切断
            db.close();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

次に、HTMLファイル中のappletタグの部分を抜粋。

<applet height="480" archive="./mysql-connector-java-5.1.5-bin.jar" width="640" code="javadb.DBConnectApplet.class"></applet>

違うのは、JDBCドライバを登録する部分と、データを表示させる部分ぐらいかもしれない。JDBCドライバは、Javaアプレットの場合は<applet>タグに指定する形になる。ちなみにJavaアプレットでは、セキュリティの関係上からDBに接続することはほとんど無い模様。いろいろと制約があるので、確かに不便かも。

データを表示させる部分は、コンソール出力に加えて、アプレットなのでJTableを使用してみた。

コンソール出力の結果はどこで確認出来るかというと、Internet Explolerの場合だと、Javaコンソールで確認出来る。

追記: Javaアプレットからデータベースに接続する (2009/11/08追加)

package javadb;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.sql.*;

public class DBConnectApplet extends JApplet {
/**
*
*/
private static final long serialVersionUID = 1L;

private Connection db = null;

public void init() {
try {
//JDBCドライバの読み込み
Class.forName(“com.mysql.jdbc.Driver”).newInstance();
}
catch (Exception e) {
e.printStackTrace();
}
}

public void start() {
String sql_server = “localhost”;
String sql_user    = “hogehoge”;
String sql_pass    = “fizzbuzz”;
String sql_db    = “dbname”;
//String sql_url    = “jdbc:mysql://localhost/” + sql_db;
String sql_url = “jdbc:mysql://localhost/dbname?user=hogehoge&password=fizzbuzz”;
try {
//MySQLのデータベースへ接続
//db = DriverManager.getConnection(sql_url, sql_user, sql_pass);
db = DriverManager.getConnection(sql_url);

//目的のテーブルを操作

//ステートメントオブジェクトの取得
Statement stmt = db.createStatement();

//クエリの準備
String query = “select id, name, address, tel, fax, mail, site, station from company”;

//クエリーを実行して結果セットを取得
ResultSet rs = stmt.executeQuery(query);

//テーブルカラムの設定
String[] tableColumn = {    ” id”,    “name”,    “address”,    “tel”,    “fax”,    “mail”,    “site”,    “station”,    };

DefaultTableModel tableModel = new DefaultTableModel(tableColumn, 0);
JTable table = new JTable(tableModel);

//検索された行数分ループ
while (rs.next()) {
Object[] tableData = {
String.format(“%4d”, rs.getInt(“id”)),
rs.getString(“name”),
rs.getString(“address”),
rs.getString(“tel”),
rs.getString(“fax”),
rs.getString(“mail”),
rs.getString(“site”),
rs.getString(“station”),
};

//テーブルデータをテーブルに登録
tableModel.addRow(tableData);

//コンソールにも出力してみる
System.out.printf(“%2d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n”,
rs.getInt(“id”),
rs.getString(“name”),
rs.getString(“address”),
rs.getString(“tel”),
rs.getString(“fax”),
rs.getString(“mail”),
rs.getString(“site”),
rs.getString(“station”)
);
}

//スクロールペインにテーブルを登録
JScrollPane scroll = new JScrollPane();
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scroll.getViewport().add(table);

//スクロールペインをアプレットに登録
getContentPane().add(scroll);

//データベースから切断
stmt.close();

//MySQLのデータベースとの接続を切断
db.close();
}
catch (SQLException e) {
e.printStackTrace();
}
}
}

2008年02月29日(金) 23時45分  

データベース接続部分を比較してみた

ふと、自分が扱えるプログラミング言語でデータベースへ接続する部分を比較してみたくなったので、書いてみた。表示のさせ方はそれぞれ異なるけれど、取得しているデータはどのプログラミング言語も同じ。

接続先はデスクトップPC上のMySQLサーバーで、テーブルは去年PHPの勉強で作成したものを利用。

Perl

#!/usr/local/bin/perl

use strict;
use warnings;
binmode STDERR, ":encoding(shiftjis)";
$/ = "\r\n";

use Encode;
use Encode::Guess qw/euc-jp shiftjis 7bit-jis/;
use DBI;

#MySQLの設定
my $sql_server = 'localhost';
my $sql_user   = 'hogehoge';
my $sql_pass   = 'fizzbuzz';
my $sql_db     = 'dbname';

#MySQLのデータベースへ接続
my $db = DBI->connect("DBI:mysql:$sql_user:$sql_server", $sql_user, $sql_pass, {RaiseError => 0, PrintError => 1});

#クエリの準備
my $sth = $db->prepare("select id, name, address, tel, fax, mail, site, station from company");

#クエリーを実行して結果を取得
$sth->execute;
while (my @row = $sth->fetchrow_array) {
    #undef要素があれば、 "null" という文字列を代入(warning回避)
    @row = map {    $_ = (defined($_) ? $_ : "null")    } @row;
    #grep {    $_ = (defined($_) ? $_ : "null")    } @row;    #上の行は、grepを使っても書ける

    print encode("shiftjis", decode("Guess", join("\t", @row))), "\n";
}
$sth->finish;

#データベースから切断
$db->disconnect;

exit;

PHP

<?php
print '<?xml version="1.0" encoding="EUC_JP"?>'."\n";
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; Charset=euc-jp" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta name="Robots" content="noindex, nofollow" />
<meta name="Robots" content="noarchive" />

<title>db-connect</title>

<link type="text/css" rel="stylesheet" href="./default.css" />
<link type="text/css" rel="stylesheet" href="./default-style.css" />
</head>

<body>
<h1>db-connect</h1>

<hr />

<table>
<caption>Company List</caption>
<tr>
<th>id</th>
<th>name</th>
<th>address</th>
<th>tel</th>
<th>fax</th>
<th>mail</th>
<th>site</th>
<th>station</th>
</tr>

<?php
$sql_server = "localhost";
$sql_user = "hogehoge";
$sql_pass = "fizzbuzz";
$sql_db  = "dbname";

//MySQLのデータベースへ接続
$db = mysql_connect($sql_server, $sql_user, $sql_pass);

//データベースの選択
mysql_select_db($sql_db, $db);

//クエリの準備
$query = "select id, name, address, tel, fax, mail, site, station from company";

//クエリーを実行して結果を取得
$rows = mysql_query($query, $db);

//データベースから切断
mysql_close();

//検索された行数分ループ
while ($row = mysql_fetch_assoc($rows)) {
    print <<<TEXT_HTML

<tr>
<td>{$row['id']}</td>
<td>{$row['name']}</td>
<td>{$row['address']}</td>
<td>{$row['tel']}</td>
<td>{$row['fax']}</td>
<td>{$row['mail']}</td>
<td>{$row['site']}</td>
<td>{$row['station']}</td>
</tr>

TEXT_HTML;
}
?>

</table>

<hr />

</body>
</html>

JSP

<?xml version="1.0" encoding="EUC_JP"?>
<%@ page import="java.sql.*" %>
<%@ page language="java" contentType="text/html; charset=euc-jp" pageEncoding="euc-jp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; Charset=euc-jp" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta name="Robots" content="noindex, nofollow" />
<meta name="Robots" content="noarchive" />

<title>db-connect</title>

<link type="text/css" rel="stylesheet" href="./default.css" />
<link type="text/css" rel="stylesheet" href="./default-style.css" />
</head>

<body>
<h1>db-connect</h1>

<hr />

<table>
<caption>Company List</caption>
<tr>
<th>id</th>
<th>name</th>
<th>address</th>
<th>tel</th>
<th>fax</th>
<th>mail</th>
<th>site</th>
<th>station</th>
</tr>

<%
    String sql_server = "localhost";
    String sql_user = "hogehoge";
    String sql_pass = "fizzbuzz";
    String sql_db = "dbname";
    //String sql_url = "jdbc:mysql://localhost/" + sql_db;
    String sql_url = "jdbc:mysql://localhost/dbname?user=hogehoge&password=fizzbuzz";

    try {
        //JDBCドライバの読み込み
        Class.forName("com.mysql.jdbc.Driver").newInstance();

        //MySQLのデータベースへ接続
        //Connection db = DriverManager.getConnection(sql_url, sql_user, sql_pass);
        Connection db = DriverManager.getConnection(sql_url);

        //ステートメントオブジェクトの取得
        Statement stmt = db.createStatement();

        //クエリの準備
        String query = "select id, name, address, tel, fax, mail, site, station from company";

        //クエリーを実行して結果を取得
        ResultSet rs = stmt.executeQuery(query);

        //検索された行数分ループ
        while(rs.next()){
%>

<tr>
<td><%= rs.getInt("id") %></td>
<td><%= rs.getString("name") %></td>
<td><%= rs.getString("address") %></td>
<td><%= rs.getString("tel") %></td>
<td><%= rs.getString("fax") %></td>
<td><%= rs.getString("mail") %></td>
<td><%= rs.getString("site") %></td>
<td><%= rs.getString("station") %></td>
</tr>

<%
        }

        //データベースから切断
        stmt.close();

        //MySQLのデータベースとの接続を切断
        db.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
%>

</table>

<hr />

</body>
</html>

Javaアプリケーション

import java.sql.*;

public class DBConnect {
    public static void main(String[] args) {
        String sql_server = "localhost";
        String sql_user    = "hogehoge";
        String sql_pass    = "fizzbuzz";
        String sql_db    = "dbname";
        //String sql_url    = "jdbc:mysql://localhost/" + sql_db;
        String sql_url = "jdbc:mysql://localhost/dbname?user=hogehoge&password=fizzbuzz";

        try {
            //JDBCドライバの読み込み
            Class.forName("com.mysql.jdbc.Driver").newInstance();

            //MySQLのデータベースへ接続
            //Connection db = DriverManager.getConnection(sql_url, sql_user, sql_pass);
            Connection db = DriverManager.getConnection(sql_url);

            //目的のテーブルを操作

            //ステートメントオブジェクトの取得
            Statement stmt = db.createStatement();

            //クエリの準備
            String query = "select id, name, address from company";

            //クエリーを実行して結果を取得
            ResultSet rs = stmt.executeQuery(query);

            //検索された行数分ループ
            while (rs.next()) {
                System.out.printf("%2d\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
                    rs.getInt("id"),
                    rs.getString("name"),
                    rs.getString("address"),
                    rs.getString("tel"),
                    rs.getString("fax"),
                    rs.getString("mail"),
                    rs.getString("site"),
                    rs.getString("station")
                );
            }

            //データベースから切断
            stmt.close();

            //MySQLのデータベースとの接続を切断
            db.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

こうしてみると、JavaアプリケーションとJSPはデータを表示させる部分が異なるだけで、データベースへ接続する処理は全く同じなのがわかる。異なるのは、JSPの場合はJDBCドライバを所定のディレクトリに用意しておくぐらい。

PHPはphp.iniの設定でデータベースを扱えるように変更、PerlはDBIモジュールとDBD::mysqlモジュールをuseすれば、それぞれデータベースにアクセス出来るようになる。

本当はRubyとExcelでも試してみたかったのだが、Rubyはまだ習得出来ておらず、またExcelはMyODBCは用意出来たのだが、データベースクエリが用意出来なかったので、今回は割愛。

今回試した中では、一番手軽にデータベースへ接続出来たのは、Perlだった。なんと言ってもモジュールさえ利用出来れば、接続出来てしまうというのが理由。

その次は、PHP。設定が必要だが、一度設定してしまえば、あとは関数をコールするだけというお手軽さ。実行速度の面もPerlと並んで申し分ない。

残るJSPとJavaアプリケーションは、コードの再利用性という面では一番かもしれないけれど、接続出来るようにするまでの手間は微妙、実行速度は早いと思う。

以上、独断と偏見に満ちた、私の環境での比較結果。

また時間が出来たら、次回はRubyとExcel、Javaアプレット等からデータベースへ接続できるかどうかも試してみたい。

2008年02月24日(日) 23時50分  

JSPの勉強(その2)

昨日に引き続いて、今日もJSPとサーブレットの勉強。詳細は、また後日。

2008年01月20日(日) 23時18分  

JSPの勉強

ネットで情報収集しながら、Tomcatの設定とJSPの勉強。

Tomcatは、去年の夏頃にデスクトップPCにインストールして、簡単なJSPを動かしてみてからずっと放置していたので、忘れている事柄が多い。再勉強する必要がありそう。

また、開発環境もEclipseを3.3に移行してからTomcatプラグインをインストールしていなかったので、再インストール。ついでに、JSPの編集の為にEclipseHTMLEditorプラグインを新たにインストールしてみた。

今回はJSPだけではなく、サーブレットも動かしてみようと思っているので、コンテキスト.xmlだけではなく、server.xmlやweb.xmlの勉強も必要になりそう。

2008年01月19日(土) 23時54分  

Javaで非矩形ウィンドウ(その3)

SWTについてあれこれ調べながら試行錯誤した末に完成したのがこれ(swt_test.zip)

下のswfは、某所より拝借した画像を使ってeclipse上から実験プログラムを実行した様子である。なお、swt_test.zipにはペイントで適当に作成したベタ画像しか同梱されていないので、そのつもりで。

非矩形(四角形ではない)ウィンドウを表示するだけの実験プログラムだけれど、SWTの勉強になった。SWTで非矩形ウィンドウの作成方法を調べている過程で、透明(半透明)ウィンドウも気になったので、機会があれば透明(半透明)ウィンドウも試してみたい。

Javaで非矩形・半透明ウィンドウ(Swing版) (2009/11/11追加)

2007年10月16日(火) 01時48分