From da81a2c4d540a352caa21a3ca77e8b86a02c2b89 Mon Sep 17 00:00:00 2001 From: wenshao Date: Tue, 12 Jul 2011 23:48:54 +0000 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81testWhileIdle=20&=20idleCheck?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: http://code.alibabatech.com/svn/druid/trunk@389 b9813039-fb51-4c41-a8b9-e21c2acb5095 --- .../druid/pool/DruidAbstractDataSource.java | 9 ++ .../alibaba/druid/pool/DruidDataSource.java | 33 +++- .../druid/pool/PoolableConnection.java | 20 +-- .../alibaba/druid/pool/benckmark/Case0.java | 19 ++- .../pool/ui/DruidDataSourceUIManager.java | 141 ++++++++++++------ .../druid/pool/ui/DruidDataStatusPanel.java | 10 +- 6 files changed, 157 insertions(+), 75 deletions(-) diff --git a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java index ae79df2b89..bfdab4701d 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidAbstractDataSource.java @@ -143,6 +143,15 @@ public abstract class DruidAbstractDataSource implements DruidAbstractDataSource protected ValidConnectionChecker validConnectionChecker = null; protected final AtomicLong errorCount = new AtomicLong(); + protected final AtomicLong dupCloseCount = new AtomicLong(); + + public long getDupCloseCount() { + return dupCloseCount.get(); + } + + public void incrementDupCloseCount() { + dupCloseCount.incrementAndGet(); + } public ValidConnectionChecker getValidConnectionChecker() { return validConnectionChecker; diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index f2b56d6424..3632286190 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -251,6 +251,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (isTestOnBorrow()) { boolean validate = testConnection(poolalbeConnection.getRawConnection()); if (!validate) { + LOG.debug("skip not validate connection."); + Connection realConnection = poolalbeConnection.getConnection(); + JdbcUtils.close(realConnection); continue; } } @@ -355,7 +358,9 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (count >= maxIdle) { lock.lock(); try { - conn.close(); + JdbcUtils.close(conn); + destroyCount++; + closeCount++; decrementActiveCount(); } finally { lock.unlock(); @@ -367,6 +372,15 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (isTestOnReturn()) { boolean validate = testConnection(conn); if (!validate) { + lock.lock(); + try { + JdbcUtils.close(conn); + destroyCount++; + closeCount++; + decrementActiveCount(); + } finally { + lock.unlock(); + } return; } } @@ -640,6 +654,8 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat try { if (timeBetweenEvictionRunsMillis > 0) { Thread.sleep(timeBetweenEvictionRunsMillis); + } else { + Thread.sleep(100); // } if (Thread.interrupted()) { @@ -685,11 +701,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat } if (evictCount > 0) { + for (int i = 0; i < evictCount; ++i) { + evictList.add(connections[i]); + } System.arraycopy(connections, evictCount, connections, 0, count - evictCount); for (int i = 0; i < evictCount; ++i) { - int index = --count; - evictList.add(connections[index]); - connections[index] = null; + connections[--count] = null; } } @@ -697,7 +714,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat ConnectionHolder[] idleConnections = new ConnectionHolder[idleCount]; System.arraycopy(connections, 0, idleConnections, 0, idleCount); System.arraycopy(connections, idleCount, connections, 0, count - idleCount); - for (int i = 0; i < evictCount; ++i) { + for (int i = 0; i < idleCount; ++i) { connections[--count] = null; } @@ -705,10 +722,10 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat if (testConnection(idleConnection.getConnection())) { connections[count++] = idleConnection; idleConnection.setLastActiveMillis(System.currentTimeMillis()); + idleCheckCount++; } else { evictList.add(idleConnection); } - idleCheckCount++; } } } finally { @@ -719,12 +736,12 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat Connection connection = item.getConnection(); try { connection.close(); + destroyCount++; } catch (SQLException e) { LOG.error("create connection error", e); } } - - destroyCount++; + evictList.clear(); } catch (InterruptedException e) { break; } diff --git a/src/main/java/com/alibaba/druid/pool/PoolableConnection.java b/src/main/java/com/alibaba/druid/pool/PoolableConnection.java index b24c84f429..5c75d055a2 100644 --- a/src/main/java/com/alibaba/druid/pool/PoolableConnection.java +++ b/src/main/java/com/alibaba/druid/pool/PoolableConnection.java @@ -38,6 +38,8 @@ import javax.sql.ConnectionEventListener; import javax.sql.PooledConnection; import javax.sql.StatementEventListener; +import com.alibaba.druid.logging.Log; +import com.alibaba.druid.logging.LogFactory; import com.alibaba.druid.pool.PoolablePreparedStatement.PreparedStatementKey; import com.alibaba.druid.pool.PreparedStatementPool.MethodType; @@ -46,6 +48,8 @@ import com.alibaba.druid.pool.PreparedStatementPool.MethodType; */ public class PoolableConnection implements PooledConnection, Connection { + private final static Log LOG = LogFactory.getLog(PoolableConnection.class); + protected Connection conn; protected ConnectionHolder holder; @@ -116,6 +120,7 @@ public class PoolableConnection implements PooledConnection, Connection { @Override public void close() throws SQLException { if (holder == null) { + LOG.warn("dup close"); return; } @@ -156,8 +161,7 @@ public class PoolableConnection implements PooledConnection, Connection { } @Override - public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) - throws SQLException { + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { checkOpen(); if (holder.isPoolPreparedStatements()) { @@ -181,8 +185,7 @@ public class PoolableConnection implements PooledConnection, Connection { } @Override - public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, - int resultSetHoldability) throws SQLException { + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { checkOpen(); if (holder.isPoolPreparedStatements()) { @@ -195,8 +198,7 @@ public class PoolableConnection implements PooledConnection, Connection { return poolableStatement; } - PreparedStatement stmt = conn.prepareStatement(sql, resultSetType, resultSetConcurrency, - resultSetHoldability); + PreparedStatement stmt = conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); holder.getDataSource().initStatement(stmt); @@ -305,8 +307,7 @@ public class PoolableConnection implements PooledConnection, Connection { } @Override - public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, - int resultSetHoldability) throws SQLException { + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { checkOpen(); if (holder.isPoolPreparedStatements()) { @@ -370,8 +371,7 @@ public class PoolableConnection implements PooledConnection, Connection { } @Override - public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) - throws SQLException { + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { checkOpen(); Statement stmt = conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); diff --git a/src/test/java/com/alibaba/druid/pool/benckmark/Case0.java b/src/test/java/com/alibaba/druid/pool/benckmark/Case0.java index 43e089ee1c..0be970e2a6 100644 --- a/src/test/java/com/alibaba/druid/pool/benckmark/Case0.java +++ b/src/test/java/com/alibaba/druid/pool/benckmark/Case0.java @@ -37,15 +37,16 @@ public class Case0 extends TestCase { private String user; private String password; private String driverClass; - private int initialSize = 10; - private int minIdle = 0; - private int maxIdle = 8; - private int maxActive = 8; - private String validationQuery = "SELECT 1"; - private boolean testOnBorrow = false; + private int initialSize = 10; + private int minIdle = 3; + private int maxIdle = 8; + private int maxActive = 8; + private String validationQuery = "SELECT 1"; + private boolean testOnBorrow = false; - public final int LOOP_COUNT = 5; - public final int COUNT = 1000 * 1; + private long minEvictableIdleTimeMillis = 3000; + public final int LOOP_COUNT = 5; + public final int COUNT = 1000 * 1; protected void setUp() throws Exception { // jdbcUrl = "jdbc:fake:dragoon_v25masterdb"; @@ -73,6 +74,7 @@ public class Case0 extends TestCase { dataSource.setPassword(password); dataSource.setValidationQuery(validationQuery); dataSource.setTestOnBorrow(testOnBorrow); + dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); for (int i = 0; i < LOOP_COUNT; ++i) { p0(dataSource, "druid"); @@ -95,6 +97,7 @@ public class Case0 extends TestCase { dataSource.setPassword(password); dataSource.setValidationQuery(validationQuery); dataSource.setTestOnBorrow(testOnBorrow); + dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); for (int i = 0; i < LOOP_COUNT; ++i) { p0(dataSource, "dbcp"); diff --git a/src/test/java/com/alibaba/druid/pool/ui/DruidDataSourceUIManager.java b/src/test/java/com/alibaba/druid/pool/ui/DruidDataSourceUIManager.java index 6edf3ba20f..0b1d6994a1 100644 --- a/src/test/java/com/alibaba/druid/pool/ui/DruidDataSourceUIManager.java +++ b/src/test/java/com/alibaba/druid/pool/ui/DruidDataSourceUIManager.java @@ -9,6 +9,8 @@ import java.awt.event.ActionListener; import java.sql.Connection; import java.sql.SQLException; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; import javax.swing.JButton; @@ -72,18 +74,25 @@ public class DruidDataSourceUIManager extends JFrame { private DruidDataStatusPanel statusPanel = new DruidDataStatusPanel(); - private JLabel lbConnecting = new JLabel("Connecting : "); - private JTextField txtConnecting = new JTextField("0"); - - private JLabel lbValidationQuery = new JLabel("ValidationQuery : "); - private JTextField txtValidationQuery = new JTextField(""); + private JLabel lbValidationQuery = new JLabel("ValidationQuery : "); + private JTextField txtValidationQuery = new JTextField(""); + + private JLabel lbTestWhileIdle = new JLabel("TestWhileIdle : "); + private JTextField txtTestWhileIdle = new JTextField("false"); + + private JTextField txtGetStep = new JTextField("1"); + private JTextField txtReleaseStep = new JTextField("1"); private AtomicInteger connectingCount = new AtomicInteger(); + private AtomicInteger connectCount = new AtomicInteger(); + private AtomicInteger closeCount = new AtomicInteger(); private Thread statusThread; private final ConcurrentLinkedQueue activeConnections = new ConcurrentLinkedQueue(); + private ExecutorService executor; + public DruidDataSourceUIManager(){ this.setLayout(new BorderLayout()); @@ -219,35 +228,46 @@ public class DruidDataSourceUIManager extends JFrame { layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtMaxWait, 0, SpringLayout.VERTICAL_CENTER, lbMaxWait); layout.putConstraint(SpringLayout.WEST, txtMaxWait, 0, SpringLayout.WEST, txtUrl); layout.putConstraint(SpringLayout.EAST, txtMaxWait, 0, SpringLayout.EAST, txtUrl); - + // //// - + mainPanel.add(lbMinEvictableIdleTimeMillis); layout.putConstraint(SpringLayout.NORTH, lbMinEvictableIdleTimeMillis, 10, SpringLayout.SOUTH, lbMaxWait); layout.putConstraint(SpringLayout.WEST, lbMinEvictableIdleTimeMillis, 0, SpringLayout.WEST, lbUrl); layout.putConstraint(SpringLayout.EAST, lbMinEvictableIdleTimeMillis, 0, SpringLayout.EAST, lbUrl); - + mainPanel.add(txtMinEvictableIdleTimeMillis); layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtMinEvictableIdleTimeMillis, 0, SpringLayout.VERTICAL_CENTER, lbMinEvictableIdleTimeMillis); layout.putConstraint(SpringLayout.WEST, txtMinEvictableIdleTimeMillis, 0, SpringLayout.WEST, txtUrl); layout.putConstraint(SpringLayout.EAST, txtMinEvictableIdleTimeMillis, 0, SpringLayout.EAST, txtUrl); - + // //// - + mainPanel.add(lbValidationQuery); layout.putConstraint(SpringLayout.NORTH, lbValidationQuery, 10, SpringLayout.SOUTH, lbMinEvictableIdleTimeMillis); layout.putConstraint(SpringLayout.WEST, lbValidationQuery, 0, SpringLayout.WEST, lbUrl); layout.putConstraint(SpringLayout.EAST, lbValidationQuery, 0, SpringLayout.EAST, lbUrl); - + mainPanel.add(txtValidationQuery); layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtValidationQuery, 0, SpringLayout.VERTICAL_CENTER, lbValidationQuery); layout.putConstraint(SpringLayout.WEST, txtValidationQuery, 0, SpringLayout.WEST, txtUrl); layout.putConstraint(SpringLayout.EAST, txtValidationQuery, 0, SpringLayout.EAST, txtUrl); + // //// + + mainPanel.add(lbTestWhileIdle); + layout.putConstraint(SpringLayout.NORTH, lbTestWhileIdle, 10, SpringLayout.SOUTH, lbValidationQuery); + layout.putConstraint(SpringLayout.WEST, lbTestWhileIdle, 0, SpringLayout.WEST, lbUrl); + layout.putConstraint(SpringLayout.EAST, lbTestWhileIdle, 0, SpringLayout.EAST, lbUrl); + + mainPanel.add(txtTestWhileIdle); + layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtTestWhileIdle, 0, SpringLayout.VERTICAL_CENTER, lbTestWhileIdle); + layout.putConstraint(SpringLayout.WEST, txtTestWhileIdle, 0, SpringLayout.WEST, txtUrl); + layout.putConstraint(SpringLayout.EAST, txtTestWhileIdle, 0, SpringLayout.EAST, txtUrl); // //// mainPanel.add(btnInitDataSource); - layout.putConstraint(SpringLayout.NORTH, btnInitDataSource, 10, SpringLayout.SOUTH, lbValidationQuery); + layout.putConstraint(SpringLayout.NORTH, btnInitDataSource, 10, SpringLayout.SOUTH, lbTestWhileIdle); layout.putConstraint(SpringLayout.WEST, btnInitDataSource, 0, SpringLayout.WEST, lbUrl); btnInitDataSource.addActionListener(new ActionListener() { @@ -268,6 +288,8 @@ public class DruidDataSourceUIManager extends JFrame { } }); btnCloseDataSource.setEnabled(false); + btnConnect.setEnabled(false); + btnClose.setEnabled(false); mainPanel.add(btnConnect); layout.putConstraint(SpringLayout.VERTICAL_CENTER, btnConnect, 0, SpringLayout.VERTICAL_CENTER, btnInitDataSource); @@ -280,64 +302,80 @@ public class DruidDataSourceUIManager extends JFrame { } }); + mainPanel.add(txtGetStep); + layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtGetStep, 0, SpringLayout.VERTICAL_CENTER, btnInitDataSource); + layout.putConstraint(SpringLayout.WEST, txtGetStep, 10, SpringLayout.EAST, btnConnect); + layout.putConstraint(SpringLayout.EAST, txtGetStep, 40, SpringLayout.WEST, txtGetStep); + + // txtGetStep + mainPanel.add(btnClose); layout.putConstraint(SpringLayout.VERTICAL_CENTER, btnClose, 0, SpringLayout.VERTICAL_CENTER, btnInitDataSource); - layout.putConstraint(SpringLayout.WEST, btnClose, 10, SpringLayout.EAST, btnConnect); + layout.putConstraint(SpringLayout.WEST, btnClose, 10, SpringLayout.EAST, txtGetStep); btnClose.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - Connection conn = activeConnections.poll(); - if (conn != null) { - try { - conn.close(); - } catch (SQLException ex) { - ex.printStackTrace(); + int step = Integer.parseInt(txtReleaseStep.getText().trim()); + for (int i = 0; i < step; ++i) { + Connection conn = activeConnections.poll(); + if (conn != null) { + try { + conn.close(); + closeCount.incrementAndGet(); + } catch (SQLException ex) { + ex.printStackTrace(); + } + } else { + // System.out.println("close connection is null"); } } } }); + mainPanel.add(txtReleaseStep); + layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtReleaseStep, 0, SpringLayout.VERTICAL_CENTER, btnInitDataSource); + layout.putConstraint(SpringLayout.WEST, txtReleaseStep, 10, SpringLayout.EAST, btnClose); + layout.putConstraint(SpringLayout.EAST, txtReleaseStep, 40, SpringLayout.WEST, txtReleaseStep); + // txtReleaseStep + mainPanel.add(statusPanel); layout.putConstraint(SpringLayout.NORTH, statusPanel, 10, SpringLayout.SOUTH, btnInitDataSource); - layout.putConstraint(SpringLayout.SOUTH, statusPanel, 90, SpringLayout.NORTH, statusPanel); + layout.putConstraint(SpringLayout.SOUTH, statusPanel, 120, SpringLayout.NORTH, statusPanel); layout.putConstraint(SpringLayout.WEST, statusPanel, 0, SpringLayout.WEST, lbUrl); layout.putConstraint(SpringLayout.EAST, txtMaxWait, 0, SpringLayout.EAST, mainPanel); // //// - mainPanel.add(lbConnecting); - layout.putConstraint(SpringLayout.NORTH, lbConnecting, 10, SpringLayout.SOUTH, statusPanel); - layout.putConstraint(SpringLayout.WEST, lbConnecting, 0, SpringLayout.WEST, lbUrl); - layout.putConstraint(SpringLayout.EAST, lbConnecting, 0, SpringLayout.EAST, lbUrl); - - mainPanel.add(txtConnecting); - layout.putConstraint(SpringLayout.VERTICAL_CENTER, txtConnecting, 0, SpringLayout.VERTICAL_CENTER, lbConnecting); - layout.putConstraint(SpringLayout.WEST, txtConnecting, 0, SpringLayout.WEST, txtUrl); - layout.putConstraint(SpringLayout.EAST, txtConnecting, 100, SpringLayout.WEST, txtConnecting); - txtConnecting.setEditable(false); } public void connect_actionPerformed(ActionEvent e) { - Thread connectThread = new Thread() { + int step = Integer.parseInt(txtGetStep.getText().trim()); + for (int i = 0; i < step; ++i) { + final Runnable task = new Runnable() { - public void run() { - try { - connectingCount.incrementAndGet(); - txtConnecting.setText(Integer.toString(connectingCount.get())); + public void run() { + try { + connectingCount.incrementAndGet(); - Connection conn = dataSource.getConnection(); + Connection conn = dataSource.getConnection(); - connectingCount.decrementAndGet(); - txtConnecting.setText(Integer.toString(connectingCount.get())); + connectCount.incrementAndGet(); + connectingCount.decrementAndGet(); - activeConnections.add(conn); - } catch (Exception ex) { - ex.printStackTrace(); + if (conn == null) { + System.out.println("get connection is null"); + return; + } + + activeConnections.add(conn); + } catch (Exception ex) { + ex.printStackTrace(); + } } - } - }; - connectThread.start(); + }; + executor.submit(task); + } } public void closeDataSource_actionPerformed(ActionEvent e) { @@ -357,7 +395,9 @@ public class DruidDataSourceUIManager extends JFrame { btnInitDataSource.setEnabled(true); btnCloseDataSource.setEnabled(false); - + btnConnect.setEnabled(false); + btnClose.setEnabled(false); + statusThread.interrupt(); } @@ -375,9 +415,14 @@ public class DruidDataSourceUIManager extends JFrame { dataSource.setMinIdle(Integer.parseInt(txtMinIdle.getText().trim())); dataSource.setMaxWait(Integer.parseInt(txtMaxWait.getText().trim())); dataSource.setMinEvictableIdleTimeMillis(Integer.parseInt(txtMinEvictableIdleTimeMillis.getText().trim())); + dataSource.setTestWhileIdle(Boolean.parseBoolean(txtTestWhileIdle.getText().trim())); Connection conn = dataSource.getConnection(); + connectCount.incrementAndGet(); conn.close(); + closeCount.incrementAndGet(); + + executor = Executors.newCachedThreadPool(); txtDriverClass.setText(dataSource.getDriverClassName()); txtMinEvictableIdleTimeMillis.setText(Long.toString(dataSource.getMinEvictableIdleTimeMillis())); @@ -396,6 +441,8 @@ public class DruidDataSourceUIManager extends JFrame { btnInitDataSource.setEnabled(false); btnCloseDataSource.setEnabled(true); + btnConnect.setEnabled(true); + btnClose.setEnabled(true); statusThread = new Thread("Watch Status") { @@ -412,6 +459,10 @@ public class DruidDataSourceUIManager extends JFrame { statusPanel.set("RecycleCount", dataSource.getRecycleCount()); statusPanel.set("ActiveCount", dataSource.getActiveCount()); statusPanel.set("PoolingCount", dataSource.getPoolingCount()); + statusPanel.set("IdleCheckCount", dataSource.getIdleCheckCount()); + statusPanel.set("UI_GettingCount", connectingCount.get()); + statusPanel.set("UI_GetCount", connectCount.get()); + statusPanel.set("UI_ReleaseCount", closeCount.get()); try { Thread.sleep(100); diff --git a/src/test/java/com/alibaba/druid/pool/ui/DruidDataStatusPanel.java b/src/test/java/com/alibaba/druid/pool/ui/DruidDataStatusPanel.java index be7dee3d65..03f2e3130b 100644 --- a/src/test/java/com/alibaba/druid/pool/ui/DruidDataStatusPanel.java +++ b/src/test/java/com/alibaba/druid/pool/ui/DruidDataStatusPanel.java @@ -14,12 +14,14 @@ public class DruidDataStatusPanel extends JPanel { private final Map fields = new HashMap(); - private final String[] fieldNames = new String[] { "CreateCount", "CreateErrorCount", "CreateTimespanMillis", "CreateTimespanNano", - "DestroyCount", "ConnectCount", "ConnectErrorCount", "CloseCount", "RecycleCount", "ActiveCount", "PoolingCount", }; + private final String[] fieldNames = new String[] { // + "CreateCount", "CreateErrorCount", "CreateTimespanMillis", "CreateTimespanNano", "DestroyCount", // + "ConnectCount", "ConnectErrorCount", "CloseCount", "RecycleCount", "ActiveCount", // + "PoolingCount", "IdleCheckCount", "UI_GettingCount", "UI_GetCount", "UI_ReleaseCount" }; public DruidDataStatusPanel(){ - this.setLayout(new GridLayout(4, 6)); + this.setLayout(new GridLayout(5, 6)); for (String fieldName : fieldNames) { JLabel label = new JLabel(fieldName + " : "); @@ -31,7 +33,7 @@ public class DruidDataStatusPanel extends JPanel { fields.put(fieldName, textField); } } - + public void set(String fieldName, Object value) { JTextField textField = fields.get(fieldName); textField.setText(String.valueOf(value));