Head First Java, 2nd Edition by Kathy Sierra and Bert Bates is the introductory Java entry in O'Reilly Media's Head First Series
. The approach of this unique series is to inject humor, imagery, basic explanations, and a lot of fun into their subject matter. While not for everyone, the series does provide a solid learning experience.
The ideal reader of Head First Java is someone that has done some programming (maybe even some Java), but is fairly new to Java and/or Object Oriented programming. Advanced Java developers are probably not going to get a lot out of this book, but the topics covered are pretty extensive. The topics include: objects and classes, object oriented design, inheritance, polymorphism, constructors, garbage collection, static classes and methods, swing, multithreading, generics, java web start, and RMI. That may sound like a lot of topics, but each one is explained very effectively.
The Head First Series strives to break topics down into very easy to understand explanations, with numerous code examples and exercises. In fact, complex topics are explained multiple times to cover all facets of the subject matter. You won't become an expert, but you will have a very solid understanding and be able to code simple applications right away. More importantly, you will understand why Java developers uses language features in specific ways.
The authors of Head First Java avoid tool distractions by designing the book around using only the JDK and a simple text editor. No other tools or applications are required to use the examples in the book. The major code examples in the book concern two programs that are incrementaly developed through the chapters. One is a very primitive battleship game, focusing on game design logic, rather than a GUI (there is no GUI). The other is a beatbox midi sequencer, which includes functionality from the Java Sound API, a Swing GUI, and a client/server architecture.
Chapter Summary:
Chapter 1 (Breaking the Surface) discusses basic details on classes, and how to interface with the main() method. Also included is more basic programming details on conditionals, looping and and other flow control mechanisms.
Chapter 2 (A Trip to Objectville) gets into objects, object oriented principles, and the importance of unit testing. Garbage collection is briefly discussed.
Chapter 3 (Know Your Variables) covers variables including primitives and object references. Both primitive and object arrays are mentioned and their limitations discussed. More details on the garbage collection system is detaled. There is also a useful table showing all of Java's reserved keywords.
Chapter 4 (How Objects Behave) mentions more details on classes, methods (parameters vs arguments, return values, and pass-by-value), and encapsulation. Included is a discussion on instance vs. local variables.
Chapter 5 (Extra-Strength Methods) contains a more detailed discussion on object oriented design and unit testing. The new Java 5 enhanced for loop syntax is mentioned along with type casting of primitives.
Chapter 6 (Using the Java Library) dives into Java standard libraries with ArrayLists, importing, and packages. Also mentioned are parameterized types and boolean expressions.
Chapter 7 (Better Living in Objectville) continues the object oriented discussion with inheritance (both what it is and how to use it properly) and polymorphism. Both method overriding and method overloading are covered as well.
Chapter 8 (Serious Polymorphism) covers abstract classes and methods. More details on polymorphism and object casting is discussed. Java's version of multiple inheritance called interfaces is introduced.
Chapter 9 (Life and Death of an Object) details the stack and the heap, and how they impact objects and local variables. The chapter also discusses object constructors and superclass constructors, including the use of overloaded constructors. This is followed by a decription of the scoping rules of local variables and factors affecting object lifetime and when garbage collection kicks in.
Chapter 10 (Numbers Matter) provides details on the static and final, when used with both variables and methods. Also included is a mention of wrapper classes for primitive to object conversion (and vice versa), how this conversion can be automatic with autoboxing in Java5.0+. The discussion continues with number formatting, dates, and calendars. Methods from the Math class are covered briefly at the beginning of the chapter.
Chapter 11 (Risky Behavior) discusses details on exception handling, how to use try/catch/finally blocks to deal with exceptions, and how to declare that your method can throw exceptions. Exception objects are explained including exception inheritance, polymorphism, and how to properly catch different types of exceptions. Development on the MIDI application continues with details on the JavaSound API and MIDI events.
Chapter 12 (A Very Graphic Story) gets into the swing of things with coverage of the Swing GUI library. Included in the discussion is an introduction to frames, buttons, listening to events with event listeners, and drawing graphics with Graphics2D. How to utilize inner classes with event listeners for increased flexibility is also covered.
Chapter 13 (Work on Your Swing) gives examples of the use of a few different swing components and several GUI layout managers. Components discussed include JButton, JTextField, JTextArea, JCheckBox, JList, and JPanel. Detailed descriptions on the use of BorderLayout, FlowLayout, and BoxLayout are also included.
Chapter 14 (Saving Objects) covers saving (and restoring) objects through serialization via Serializable. Included is a discussion of the input and output streams of the Java I/O libraries. The Java I/O File and BufferedReader classes are also mentioned.
Chapter 15 (Make a Connection) has details on sockets, multithreading, and synchronization. The chapter builds an example (client and server) chat program to illustrate use of the Socket class, specifically how to read from and write to a socket. A excellent discussion of multithreading is covered in great detail with example code using the Runnable and Thread classes. Also included are details on the unpredictability of the thread scheduler. The chapter wraps up with solid coverge of concurrencies issues when using multithreading and how to avoid it with synchronization.
Chapter 16 (Data Structures) mentions sorting of collection objects using the Comparable class. The collections discussed include ArrayList, HashSet, TreeSet, and HashMap. The concept of generics is explained in greater detail, along with generic method declaration syntax to support polymorphism. Also included is brief mention on the difference between Sets and Maps.
Chapter 17 (Release Your Code) is all about setting up your application for distribution. This includes details on JAR files, how to structure them, what special files they need to contain, and how executable JAR files work. The importance of using packages is covered as well, along with the command line compiler syntax required. Use of Java Web Start to distribute your application to end users is discussed briefly.
Chapter 18 (Distributed Computing) touches on distributed computing topics such as RMI (Remote Method Invocation), servlets, EJB, and Jini. For RMI, the chapter provides a detailed explanation of how the proxy concept works and a dicussion of the process for setting up the remote implementation, the stubs and skeletons required, and the RMI registry. The concept of servlets and EJB are covered but only very briefly (be sure to read Head First Servlets for extensive converage on servlets). The chapter goes on to discuss Jini in great detail, including the discovery process and self-healing nature of the technology. It covers what you need to make it work, then adds the necessary code to enable Jini in the beat box program, both client and server versions.
If you're new to Java, Head First Java will get you started right away. It's approach utilizing humor and imagery may seem childish at first, but once you get started, you'll realize how effective the Head First Series
learning series is.
Other topics in the Head First Series:
Tuesday, March 31, 2009
Book Review: Head First Java
Thursday, January 22, 2009
Java: JOptionPane Dialog Examples Part 1 - Basic
Java has a huge amount of functionality for creating GUI's for your applications. Some of the more complex GUI's require lots of code. However, sometimes you just need a plain old, nothing fancy, quick-and-dirty, keep it simple dialog. In these situations, the JOptionPane works really well. Basic JOptionPane dialog examples are the core of this article.
Although it's Java's workhouse dialog, there are a few limitations. It helps to understand those limitations such that it fulfills your expectations. The first limitation (some consider this a feature) is modality. The thread which creates the JOPtionPane dialog will wait until the user closes the dialog. The other limitation is that it cannot be resized. The user won't be able to make the dialog bigger in order to see its contents better.
If these limitations are cramping your style, you'll need to move towards JDialog based dialogs. Otherwise, read on for more JOptionPane information.
The Methods
There are four commonly used static methods for JOPtionPane dialogs:
- showMessageDialog()
- showInputDialog()
- showConfirmDialog()
- showOptionDialog()
All four methods allow for an icon on the left hand side and one or more buttons along the bottom. Both of these are controllable and behave somewhat differently depending on which method is used.
All three of showMessageDialog(), showConfirmDialog(), and showOptionDialog() are capable of displaying some form of information to the user, but each allows the user to respond in different ways. showMessageDialog() allows for only for a message and an OK button. showConfirmDialog() allows for various combinations of OK, YES, NO, and CANCEL buttons. showOptionDialog() allows you to display buttons containing the text of your choice.
Only showInputDialog() allows for the user to enter arbitrary information either in a text field or with a combo-box style list of values. It provides only OK and CANCEL buttons.
Message Types
All four dialog types have options to display a predefined icon. The following icon types are listed below, each of which is a static field of the JOptionPane class. The actual icons displayed depends upon the java look and feel active at that time.
- JOptionPane.ERROR_MESSAGE -- red letter x, or a "no entry" sign
- JOptionPane.INFORMATION_MESSAGE -- letter i in a circle
- JOptionPane.WARNING_MESSAGE -- excalamation point
- JOptionPane.QUESTION_MESSAGE -- question mark
- JOptionPane.PLAIN_MESSAGE -- no standard icon
Option Types
The showConfirmDialog() and showOptionDialog() methods have provisions for an "option type", which are the buttons that will be displayed.
- JOptionPane.DEFAULT_OPTION -- OK button
- JOptionPane.YES_NO_OPTION -- YES and NO buttons
- JOptionPane.YES_NO_CANCEL_OPTION -- YES, NO, and CANCEL buttons
- JOptionPane.OK_CANCEL_OPTION -- OK and CANCEL buttons
Return Values
Both showConfirmDialog() and showOptionDialog() return an int that you can use to figure out how the user responded to the dialog. Did they hit YES, NO, or OK? Just analyze the value using the list below. Perhaps the user closed the dialog window and did not hit one of your buttons? It's an important piece of logic to add to your program.
- JOptionPane.YES_OPTION -- YES button
- JOptionPane.OK_OPTION -- OK button
- JOptionPane.NO_OPTION -- NO button
- JOptionPane.CANCEL_OPTION -- CANCEL button
- JOptionPane.CLOSED_OPTION -- User closed the dialog without using a button
For what it's worth, YES_OPTION and OK_OPTION are actually the same value.
Parent Component
In these examples, null is used for the parent component, which creates a standalone dialog, usually centered on the screen. A parent UI component can be used to center the dialog on that component if that is desireable.
User Specified Icon
Some of the method signatures allow for a user specified icon to be used in the dialog box. Even if a particular message type is requested, if a non-null ImageIcon is supplied, that icon will be used in the dialog. This parameter is always optional. null can be used wherever an icon needs to be specified.
Beyond the scope of this article is placement of the icon file. The presumption of this article is that the icon file is in the working directory of the java process. In a more practical application, you will want to locate the icon file in your jar file or in a specific folder. Each of these approaches has a different set of steps to define and will be discussed in a future article.
Method: showMessageDialog()
The dialog produced by showMessageDialog() is a basic dialog displaying a message to the user. The user will see your message with only an "OK" button to close the dialog. No value is returned.
Example 1a: Dialog displaying "Hello!", with OK button, standard "info" icon, and title "Message".
JOptionPane.showMessageDialog(null, "Hello!");
Example 1b: Dialog displaying "Hello!", with OK button, no standard icon, and title "Message Title".
int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon
JOptionPane.showMessageDialog(null, "Hello!", "Message Title", messageType);
Example 1c: Dialog displaying "Hello!", with OK button, non-standard icon from GIF file, and title "Message Title".
int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon
ImageIcon icon = new ImageIcon("blob.gif", "blob");
JOptionPane.showMessageDialog(null, "Hello!", "Message Title", messageType, icon);
Method: showInputDialog()
showInputDialog() prompts the user for a value from a text field or within a dropdown combo-box style component. The method returns a String.
Example 2a: Dialog with empty text field, "Enter value:" prompt string, plus OK and CANCEL buttons
String res = JOptionPane.showInputDialog("Enter value:");
System.out.println( "showInputDialog: " + res );
Example 2b: Dialog with text field initialized to "Hello!", "Enter value:" prompt string, plus OK and CANCEL buttons
String res = JOptionPane.showInputDialog("Enter value:", "Hello!");
System.out.println( "showInputDialog: " + res );
Example 2c: Dialog with empty text field, "Enter value:" prompt string, plus OK and CANCEL buttons
String res = JOptionPane.showInputDialog(null, "Enter value:");
System.out.println( "showInputDialog: " + res );
Example 2d: Dialog with text field initialized to "Hello!", "Enter value:" prompt string, plus OK and CANCEL buttons
String res = JOptionPane.showInputDialog(null, "Enter value:", "Hello!");
System.out.println( "showInputDialog: " + res );
Example 2e: Empty text field, "Enter value:" prompt string, plus OK and CANCEL buttons
int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon
String res = JOptionPane.showInputDialog(null, "Enter value:", "Message Title", messageType);
System.out.println( "showInputDialog: " + res );
Example 2f: Combo box displaying values from selValues array with value initialized to selValues[0], "Enter value:" prompt string, plus OK and CANCEL buttons
Object[] selValues = { "abc", "def", "ghi" };
int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon
ImageIcon icon = new ImageIcon("blob.gif", "blob");
Object res = JOptionPane.showInputDialog(null, "Enter value:", "Message Title",
messageType, icon, selValues, selValues[0]);
System.out.println( "showInputDialog: " + res );
Method: showConfirmDialog()
showConfirmDialog() produces a dialog similar to that from showMessageDialog(), except that it provides more options for buttons. Button combinations available are OK, YES+NO, YES+NO+CANCEL, and OK+CANCEL. The int return value indicates the button pressed, if any.
Example 3a: Dialog displaying "Hello!", with YES+NO+CANCEL buttons, standard "question mark" icon, and title "Select an Option".
int res = JOptionPane.showConfirmDialog(null, "Hello!");
Example 3b: Dialog displaying "Hello!", with YES+NO+CANCEL buttons, standard "question mark" icon, and title "Message Title".
int optionType = JOptionPane.YES_NO_CANCEL_OPTION; // YES+NO+CANCEL
int res = JOptionPane.showConfirmDialog(null, "Hello!", "Message Title", optionType);
Example 3c: Dialog displaying "Hello!", with YES+NO+CANCEL buttons, no standard icon, and title "Message Title".
int optionType = JOptionPane.YES_NO_CANCEL_OPTION; // YES+NO+CANCEL
int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon
int res = JOptionPane.showConfirmDialog(null, "Hello!", "Message Title",
optionType, messageType);
Example 3d: Dialog displaying "Hello!", with YES+NO+CANCEL buttons, "blob" icon, and title "Message Title". XXX
int optionType = JOptionPane.YES_NO_CANCEL_OPTION; // YES+NO+CANCEL
int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon
ImageIcon icon = new ImageIcon("blob.gif", "blob");
int res = JOptionPane.showConfirmDialog(null, "Hello!", "Message Title",
optionType, messageType, icon);
Example 3e: Handling Return Values of showConfirmDialog()
The int value returned by showConfirmDialog() tells you which button the users pressed, or if they simply closed the dialog without using any buttons at all.
// User hit YES
if (res == JOptionPane.YES_OPTION) { System.out.println( "YES_OPTION" ); }
// User hit OK
if (res == JOptionPane.OK_OPTION) { System.out.println( "OK_OPTION" ); }
// User hit NO
if (res == JOptionPane.NO_OPTION) { System.out.println( "NO_OPTION" ); }
// User hit CANCEL
if (res == JOptionPane.CANCEL_OPTION) { System.out.println( "CANCEL_OPTION" ); }
// User closed the window without hitting any button
if (res == JOptionPane.CLOSED_OPTION) { System.out.println( "CLOSED_OPTION" ); }
Method: showOptionDialog()
showOptionDialog() displays buttons whose labels are based on the values in the input array, with one of the buttons being the default option. If one of the buttons is selected, showOptionDialog() returns the array index number of the selected button.
If the dialog is closed without selecting a button, showOptionDialog() returns -1. It seems to ignore the "option type" parameter.
Example 4a: Dialog displaying "Hello!", with button labels from selValues array, "blob" icon, and title "Message Title".
int optionType = JOptionPane.DEFAULT_OPTION;
int messageType = JOptionPane.PLAIN_MESSAGE; // no standard icon
ImageIcon icon = new ImageIcon("blob.gif", "blob");
Object[] selValues = { "abc", "def", "ghi" };
// Shows message, choices appear as buttons
int res = JOptionPane.showOptionDialog(null, "Hello!", "Message Title",
optionType, messageType, icon,
selValues, selValues[0]);
Example 4b: Handling Return Values of showOptionDialog()
System.out.println( "showOptionDialog: " + res);
if (res >= 0) {
System.out.println( "showOptionDialog: " + res + " (" + selValues[res] + ")" );
}
if (res == JOptionPane.CLOSED_OPTION) { System.out.println( "CLOSED_OPTION" ); }
These are the basic uses of the JOptionPane. As you can see here, for a simple dialog, there are numerous options, and I have only described a fraction of it's capabilities.
In Part 2, I'll discuss some poorly documented features of JOptionPane, but they may just blow your mind.
Tuesday, November 11, 2008
Intralink SQL: User and Group Folder Authorizations
Intralink stores folder authorizations in four Oracle tables. Two for user authorizations (PDM_USERFOLAUTH and PDM_USERFOLRLAUTH) and two for group authorizations (PDM_USERGRFOLAUTH and PDM_USERGRFOLRLAUTH).
The PDM_USERFOLAUTH and PDM_USERGRFOLAUTH tables contain folder role authorizations. The PDM_USERFOLRLAUTH and PDM_USERGRFOLRLAUTH tables contain folder authorizations by release level.
Query for user folder role authorizations:
-- user folder auth
--
set linesize 135
col folpath format a60
col userexpname format a12
col rolename format a15
--
select
FOLPATH,
USEREXPNAME,
ROLENAME
from
pdm.PDM_USERFOLAUTH ufa,
pdm.PDM_ROLE role,
pdm.PDM_FOLDER fol,
pdm.PDM_USER usr
where
role.ROLEID=ufa.ROLEID and
ufa.FOLID=fol.FOLID and
ufa.USERID=usr.USERID
;
Query for user folder/releaselevel role authorizations:
-- user folder/releaselevel auth
--
set linesize 135
col folpath format a60
col userexpname format a12
col rlname format a15
col rolename format a15
--
select
FOLPATH,
USEREXPNAME,
RLNAME,
ROLENAME
from
pdm.PDM_USERFOLRLAUTH ufrla,
pdm.PDM_RELEASELEVEL rl,
pdm.PDM_ROLE role,
pdm.PDM_FOLDER fol,
pdm.PDM_USER usr
where
role.ROLEID=ufrla.ROLEID and
ufrla.RLID=rl.RLID and
ufrla.FOLID=fol.FOLID and
ufrla.USERID=usr.USERID
;
Query for group folder role authorizations:
-- group folder auth
--
set linesize 135
col folpath format a60
col rolename format a15
col grexpname format a25
--
select
FOLPATH,
GREXPNAME
ROLENAME,
from
pdm.PDM_USERGRFOLAUTH gfa,
pdm.PDM_ROLE role,
pdm.PDM_FOLDER fol,
pdm.PDM_USERGROUP grp
where
role.ROLEID=gfa.ROLEID and
gfa.FOLID=fol.FOLID and
gfa.GRID=grp.GRID
;
Query for group folder/releaselevel role authorizations:
-- group folder/releaselevel auth
--
set linesize 135
col folpath format a60
col grexpname format a25
col rlname format a15
col rolename format a15
--
select
FOLPATH,
GREXPNAME,
RLNAME,
ROLENAME
from
pdm.PDM_USERGRFOLRLAUTH gfrla,
pdm.PDM_RELEASELEVEL rl,
pdm.PDM_ROLE role,
pdm.PDM_FOLDER fol,
pdm.PDM_USERGROUP grp
where
role.ROLEID=gfrla.ROLEID and
gfrla.RLID=rl.RLID and
gfrla.FOLID=fol.FOLID and
gfrla.GRID=grp.GRID
;
Putting it all together
To streamline these queries, unions can be used to combine the output into one report. In the following example, user and group names are reported under the 'ID' column. The final where clause can be used to filter for a specific user or group. Leave it out to report authorizations for everyone.
The report is also enhanced in that the order of the release levels in the output matches the output one would see in the folder authorization window in Intralink Admin.
The syntax is somewhat inefficient because it is setup to allow outer joins based on folders (see end of article). However, even for very large numbers of folders, user, and groups, the combined query is still pretty fast.
-- user & group auth
--
set linesize 200
column folpath format a70
column rolename format a20
column rlname format a15
column id format a25
--
select FOLPATH,id,rlname,rolename,rlseqnum
from
(
select
folpath,
(select userexpname from pdm.pdm_user where userid=ufa.userid) as id,
'' as rlname,
to_number('') as rlseqnum,
(select rolename from pdm.pdm_role where roleid=ufa.roleid) as rolename
from
pdm.pdm_userfolauth ufa,
pdm.pdm_folder fol
where
ufa.folid=fol.folid
UNION
select
FOLPATH,
(select userexpname from pdm.pdm_user where userid=ufrla.userid) as id,
(select rlname from pdm.pdm_releaselevel where rlid=ufrla.rlid) as rlname,
(select rlseqnum from pdm.pdm_releaselevel where rlid=ufrla.rlid) as rlseqnum,
(select rolename from pdm.pdm_role where roleid=ufrla.roleid) as rolename
from
pdm.PDM_USERFOLRLAUTH ufrla,
pdm.PDM_FOLDER fol
where
ufrla.FOLID=fol.FOLID
UNION
select
folpath,
(select grexpname from pdm.pdm_usergroup where grid=ugfa.grid) as id,
'' as rlname,
to_number('') as rlseqnum,
(select rolename from pdm.pdm_role where roleid=ugfa.roleid) as rolename
from
pdm.pdm_usergrfolauth ugfa,
pdm.pdm_folder fol
where
ugfa.folid=fol.folid
UNION
select
FOLPATH,
(select grexpname from pdm.pdm_usergroup where grid=gfrla.grid) as id,
(select rlname from pdm.pdm_releaselevel where rlid=gfrla.rlid) as rlname,
(select rlseqnum from pdm.pdm_releaselevel where rlid=gfrla.rlid) as rlseqnum,
(select rolename from pdm.pdm_role where roleid=gfrla.roleid) as rolename
from
pdm.PDM_USERGRFOLRLAUTH gfrla,
pdm.PDM_FOLDER fol
where
gfrla.FOLID=fol.FOLID
)
where
id like '%smith%'
order by folpath,id,rlseqnum
;
Outer Joins for More Information
To show all folders, regardless of whether they contain any authorization settings, add the following outer join syntax to the above:
...folid(+)=fol.folid
There will be some minor duplications, but it does give a good sense of where the authorizations are set in your folder hierarchy.