1

In a DbInterface class a function openDB() opens connection to a Oracle DB on a server. For security reasons the user has to enter their password in a JFrame textarea before the program can proceed with the connection. Now this Jframe has an action listener which waits for the user to enter the password and calls the OpenDBContinue() method.

Now the issue is: openDB() does not wait on Jframe IO to finish and assuming DB has been opened returns back control to the calling class (whoever called openDB()) and they go ahead and start quering the DB which obviously fails!

Now how do I make openDB() wait on Jframe IO to finish? Here is the code to give you an idea.

public void openDB(int inFileInx,String inRemoteDBURLFull) throws FileNotFoundException
{   
    if(this.password!=null)
        try
        {   openDBcontinue(inFileInx,inRemoteDBURLFull);
        }
        catch(Exception exp)
            {   DpmLogger.dtlException("SPDBInterfaceException:OpenDB", exp);
            }
    else {
            passwd  =       new JFrame();
            passwd.setLocation(SpdMain.bTabbedPanel.getWidth()/2,SpdMain.bTabbedPanel.getHeight()/2);
            passwd.setTitle("Enter Passwd for user "+username);
            JPasswordField p =new JPasswordField(10);
            p.addActionListener(this);
            p.setActionCommand(inFileInx+","+inRemoteDBURLFull);
            passwd.add(p);
            passwd.setPreferredSize(new Dimension(300,50));
            passwd.pack();
            passwd.setVisible(true);
            pass=new Thread(new Runnable()  
            {   
                public void run() {
                    DpmLogger.dtlTraceOut("The password thread has completed and has got password from the user",DpmLogger.TRACE_RARE,myId);
                }

            });

            try {
                    pass.join();
                } catch (InterruptedException e) 
                    {
                        DpmLogger.dtlTraceOut("Password thread unable to join",DpmLogger.TRACE_RARE,myId);
                    }

                DpmLogger.dtlTraceOut("Password thread now joined",DpmLogger.TRACE_RARE,myId);
        }

}


public void actionPerformed(ActionEvent e) 
{   JTextField p=(JTextField)e.getSource();
    if(password==null)
    password=p.getText();
    passwd.setVisible(false);

    String[] inVars=e.getActionCommand().split(",");
    try
    {   openDBcontinue(Integer.parseInt(inVars[0]),inVars[1]);
             pass.start();
    }
    catch(Exception exp)
    {   DpmLogger.dtlException("SPDBInterfaceException:OpenDB", exp);
    }
}

As you can see I am trying to make the method wait on a 'pass' thread with join(). The action listener starts the pass thread when IO finishes. But it does not work. OpenDB() returns without waiting on 'pass' to run. Is this because the method is not inside a thread? Do I have to make this DBInterface class extend Thread class? I am confused!

Sid
  • 36
  • 4
  • 1
    What's wrong with a [`JDialog`](http://docs.oracle.com/javase/tutorial/uiswing/components/dialog.html)? – MadProgrammer Dec 10 '12 at 04:30
  • All events are processed in a separate thread (event dispatcher thread) in swing. I think you are applying `pass.join()` in the wrong thread (which makes the **current** thread to wait until pass is finished) while you want to wait on JFrame IO to finish. If there is anything time consuming to process, you should consider `SwingWorker` for example so that your UI doesn't freeze – vishal_aim Dec 10 '12 at 04:33
  • Oh sorry I do use JPasswordField (you can see it in the code). I must have forgotten to mention that but that is not my question anyway – Sid Dec 10 '12 at 04:51

2 Answers2

3

For security reasons the user has to enter their password in a JFrame textarea

For:

  1. Convenience (and a possible solution) swap the JFrame for a modal dialog or JOptionPane. E.G. as seen in this answer.
  2. Security use a JPassWordField instead of the 'textarea' as seen in the tutorial.
    enter image description here
Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
3

You could use a JDialog, but that would require you to manage the close operations (add buttons and mess about with states), or you could simply use a JOptionPane

Either (when set to modal) will cause the Event Dispatching Thread to pause execution at that point until they are closed.

enter image description here

public class TestDialog01 {

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

    public TestDialog01() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                PasswordPane pane = new PasswordPane();
                int result = JOptionPane.showConfirmDialog(null, pane, "Password", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
                if (result == JOptionPane.OK_OPTION) {
                    // get the result...
                }

            }
        });
    }

    public class PasswordPane extends JPanel {

        private JTextField userName;
        private JPasswordField password;

        public PasswordPane() {
            userName = new JTextField(12);
            password = new JPasswordField(12);

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(2, 2, 2, 2);
            gbc.gridx = 0;
            gbc.gridy = 0;
            add(new JLabel("User Name:"), gbc);
            gbc.gridx++;
            add(userName, gbc);

            gbc.gridy++;
            gbc.gridx = 0;
            add(new JLabel("Password:"), gbc);
            gbc.gridx++;
            add(password, gbc);
        }

        public String getUserName() {

            return userName.getText();

        }

        public char[] getPassword() {

            return password.getPassword();

        }
    }
}

Check out How to Make Dialogs for more info

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • So, you're not calling OpenDB from within the Event Dispatching Thread then. – MadProgrammer Dec 10 '12 at 05:23
  • Does not work still. OpenDB() always returns not waiting for JOptionPane to return OK_OPTION. This is what happens: openDBcalled joptionPane will show dialog openDBreturns back to filemgr after calling openDB joptionpane: password is recorded as test – Sid Dec 10 '12 at 05:27
  • `JOptionPane` must be made visible within the EDT in order to block the thread. Do you have some sample code? – MadProgrammer Dec 10 '12 at 05:34