in black and white
Main menu
Share a book About us Home
Biology Business Chemistry Computers Culture Economics Fiction Games Guide History Management Mathematical Medicine Mental Fitnes Physics Psychology Scince Sport Technics

More Java Pitfalls Share Reactor - Daconta M,C.

Daconta M,C. More Java Pitfalls Share Reactor - Wiley publishing, 2003. - 476 p.
ISBN: 0-471-23751-5
Download (direct link): morejavapitfallssharereactor2003.pdf
Previous << 1 .. 14 15 16 17 18 19 < 20 > 21 22 23 24 25 26 .. 166 >> Next

08 private LDAPConnection m_ld = null;
// 1 and 2 argument constructors removed for brevity...
20 public AccessControl(String hostname, int portnumber,
int ldapversion)
21 {
22 m_host = hostname;
23 m_port = portnumber;
24 m_ldapversion = ldapversion;
25 }
26 private void createConnection() throws LDAPException
27 {
28 m_ld = new LDAPConnection();
29 m_ld.connect(m_host, m_port);
30 }
31 /**
32 * The purpose of this function is to authenticate to
33 * the Directory Server with credentials.
34 *
35 * @param uname the user name
36 * @param pw the password
37 * ©return successful authentication
38 */
Listing 4.1 A bad example of abstracting details (continued)
40 Item 4
39 public boolean authenticate(String uname, String pw)
40 {
41 boolean result = false;
42 String dn = "uid=" + uname + ",ou=People,";
43 try
44 {
45 createConnection();
46 m_ld.authenticate( m_ldapversion, dn, pw );
47 result = true;
48 }
49 catch ( LDAPException e )
50 {
51 //here, result is originally set to false, so do nothing
52 }
53 return (result);
54 }
55 }
Listing 4.1 (continued)
In lines 39 through 54 of Listing 4.1, there exists a method called authenticate!) that returns a boolean value, denoting a successful login to the access control mechanism. In line 42, the username is turned into a LDAP distinguished name, and in lines 45 and 46, the method creates a connection and attempts to authenticate the user. If an LDAPException is thrown, the method simply returns false.
This is a good example of how ignoring exceptions for the purpose of hiding detail can cause hours and hours of pain for developers using this code. Of course, this class compiles fine. If the infrastructure is in place for this example (network connectivity, a directory server, the correct username and password), the method will return a boolean true value, and everything will work correctly. However, if there is another problem, such as a directory server problem or network connectivity problems, it will return false. How does the implementer using this API handle the problem or know what the problem is? The original API used by this class throws an LDAPException, but the authenticate method in listing 4.1 simply ignores it and returns false.
What is the API developer of this class to do? First of all, a simple design change to use an interface that has the authenticate() method could be used along with a creational design pattern. This way, multiple implementation classes could be written (LDAPAccessControl, DatabaseAccessControl, etc.) that can realize this interface, depending on which mechanism we are using. The developer using the API would still not need to know the internals but would have to handle an exception thrown by that method, as shown in the code segment below.
When Information Hiding Hides Too Much 41
public interface iAccessControl {
public boolean authenticate(String user, String passwd) throws AccessException;
The inclusion of a new exception brings up another possible pitfall, however. We have created a new AccessException class because we do not want the API user to have to handle exceptions such as LDAPException that are dependent on our hidden implementation. In the past, developers have handled this in a way shown in Listing 4.2.
01 public boolean authenticate(String uname, String pw) throws AccessException
02 {
03 boolean result = false;
04 String dn = "uid=” + uname + ",ou=People,”;
05 try
06 {
07 createConnection();
08 m_ld.authenticate( m_ldapversion, dn, pw );
09 result = true;
10 }
11 catch ( LDAPException e )
12 {
13 throw new AccessException(e.getMessage());
14 }
15 return (result);
16 }
17 }
Listing 4.2 Losing information with a new exception
On line 13 of Listing 4.2, we throw a new AccessException class to hide the LDAP-specific exception from the API user. Unfortunately, sometimes this complicates debugging because we lose a lot of information about the original cause of the exception, which was contained in our original LDAPException. For example, perhaps there was an actual bug in the LDAP API we are using. We lose a vast majority of debugging information by discarding the "causative exception," which was LDAPException in our example.
Prior to JDK 1.4, situations like these presented quite a few problems for debugging. Thankfully, JDK 1.4 released much-needed enhancements to allow "chained exceptions." Changes to the java.lang.Throwable class can be seen in Table 4.1, and the implementation of Throwable.printStackTrace() was also changed to show the entire "causal" chain for debugging purposes. As you can see by looking at Table 4.1, Throwable classes can now be associated as the "cause" for other Throwable classes.
42 Item 4
Table 4.1 New Chained Exception Capabilities Added to Throwable in JDK 1.4
public Throwable getCause() Returns the cause of this throwable or null if the cause is nonexistent or unknown. (The cause is the throwable that caused this throwable to get thrown.)
Previous << 1 .. 14 15 16 17 18 19 < 20 > 21 22 23 24 25 26 .. 166 >> Next