Hatena::ブログ(Diary)

IT-Walker on hatena このページをアンテナに追加 RSSフィード

2007-02-02 XMLHttpRequestに関するIEのひどいバグ発見

最近調査を行ってわかったのですが、IE上ではwindow.openで

開いた子ウィンドウでXMLHttpRequestを使用する際には注意が必要です。

(というより使うべきではない)

ウィンドウを開く、閉じるの操作を数回以上行うとブラウザが高確率で

フリーズします。

この問題は、

1.XMLHttpRequestによるHTTPリクエスト発信

2.サーバHTTPレスポンスを戻す

という一連の流れの中で、サーバがレスポンスを戻す前に子ウィンドウを

閉じると発生します。

その理由は、IEはじめ近年のブラウザHTTPの同時接続数が2に制限されていま

すが、前述の操作を行うと、子ウィンドウが閉じられているにも関わらず

IEは同時接続数のカウントを減らしません。

よって、子ウィンドウを開く⇒閉じるを繰り返しているうちに同時接続数

の上限に達し、IEはもうHTTPのリクエストを行わなくなります。

(その状態でいろいろ操作していると、IEが異常終了したりします)

解決策は、XMLHttpRequestを使用せずIFrameを使用

する、window.openを使用し

ない、などでしょうか。

Swingやることになった

久しぶり、社会人1年目以来でSwingやることになりました。

で、今回の命題はパフォーマンス。遅い、重いと昔から悪口雑言の格好の的だったSwingなだけに不安を抱えていましたが、JTableに100万行突っ込む以下のコード(Sunのサイトから落としたコードをいじった)がほんの数秒で表示されたのを見て驚愕。


import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

public class SimpleTableDemo extends JPanel {
	private boolean DEBUG = false;

	public SimpleTableDemo() {
		super(new GridLayout(1, 0));

		final String[] columnNames = {"Row No", "First Name", "Last Name", "Sport", "# of Years", "Vegetarian" };

		Object[] row = {null, "Mary", "Campione", "Snowboarding", new Integer(5), new Boolean(false) };
		
		Object[][] data = {
				{ "Mary", "Campione", "Snowboarding", new Integer(5), new Boolean(false) },
				{ "Alison", "Huml", "Rowing", new Integer(3), new Boolean(true) },
				{ "Kathy", "Walrath", "Knitting", new Integer(2), new Boolean(false) },
				{ "Sharon", "Zakhour", "Speed reading", new Integer(20), new Boolean(true) },
				{ "Philip", "Milne", "Pool", new Integer(10), new Boolean(false) } };

		final List<Object[]> rowData = new ArrayList<Object[]>();
		for (int i = 0; i < 1000000; i++) {
			Object[] r = (Object[])row.clone();
			r[0] = new Integer(i);
			rowData.add(r);
		}
		final JTable table = new JTable(new AbstractTableModel() {
		    public String getColumnName(int col) {
		        return columnNames[col].toString();
		    }
		    public int getRowCount() { return rowData.size(); }
		    public int getColumnCount() { return columnNames.length; }
		    public Object getValueAt(int row, int col) {
		    	Object[] rowDatum = rowData.get(row);
		        return rowDatum[col];
		    }
		    public boolean isCellEditable(int row, int col)
		        { return true; }
		    public void setValueAt(Object value, int row, int col) {
		    	Object[] rowDatum = rowData.get(row);
		    	rowDatum[col] = value;
		        fireTableCellUpdated(row, col);
		    }
		});
		
		table.setPreferredScrollableViewportSize(new Dimension(500, 70));

		if (DEBUG) {
			table.addMouseListener(new MouseAdapter() {
				public void mouseClicked(MouseEvent e) {
					printDebugData(table);
				}
			});
		}

		// Create the scroll pane and add the table to it.
		JScrollPane scrollPane = new JScrollPane(table);

		// Add the scroll pane to this panel.
		add(scrollPane);
	}

	private void printDebugData(JTable table) {
		int numRows = table.getRowCount();
		int numCols = table.getColumnCount();
		javax.swing.table.TableModel model = table.getModel();

		System.out.println("Value of data: ");
		for (int i = 0; i < numRows; i++) {
			System.out.print("    row " + i + ":");
			for (int j = 0; j < numCols; j++) {
				System.out.print("  " + model.getValueAt(i, j));
			}
			System.out.println();
		}
		System.out.println("--------------------------");
	}

	/**
	 * Create the GUI and show it. For thread safety, this method should be
	 * invoked from the event-dispatching thread.
	 */
	private static void createAndShowGUI() {
		// Create and set up the window.
		JFrame frame = new JFrame("SimpleTableDemo");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		// Create and set up the content pane.
		SimpleTableDemo newContentPane = new SimpleTableDemo();
		newContentPane.setOpaque(true); // content panes must be opaque
		frame.setContentPane(newContentPane);

		// Display the window.
		frame.pack();
		frame.setVisible(true);
	}

	public static void main(String[] args) {
		// Schedule a job for the event-dispatching thread:
		// creating and showing this application's GUI.
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				createAndShowGUI();
			}
		});
	}
}

すごいじゃないか!今回の仕事にはなんの不安も無いな。