* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Java Database Connectivity
Microsoft Access wikipedia , lookup
Oracle Database wikipedia , lookup
Serializability wikipedia , lookup
Microsoft SQL Server wikipedia , lookup
Microsoft Jet Database Engine wikipedia , lookup
Relational model wikipedia , lookup
Open Database Connectivity wikipedia , lookup
Concurrency control wikipedia , lookup
Clusterpoint wikipedia , lookup
1.0 Introduction to Enterprise and Web Applications 1.1 Introducing the Course Case Study Throughout this course you will be asked to assume the role of a software engineering responsible for developing a student services application for Regis University. This application serves as a distributed system case study focused on demonstrating the concepts presented each week in class. Your weekly programming assignments are also based on demonstrating usage of these concepts. 1.2 Distributed Systems – An Overview This Enterprise and Web Application course is unique among online courses since it is, literally, an Enterprise and Web Application enterprise and web application course. In fact, all Regis online courses are enterprise and web application courses since they are founded upon enterprise and web applications. Consider, for example, that by reading this web page you have already used the most prominent web application when your browser accessed the Regis web server. Likewise, when you use email to complete your course assignments, you will have utilized the most prominent enterprise application. Even your registration for this course via web-advisor utilized enterprise and web applications. These applications, as well as, the course Forum, provide a means of sharing information. The desire to share resources over a network provides the primary motivation for developing enterprise and web applications. Most enterprise and web applications, as well as, the hardware and software technologies used to construct these applications fall under the umbrella of distributed systems. Coulouris, Dollimore, & Kindberg (2005) define a distributed system as “one in which components located at networked computers communicate and coordinate their actions by passing messages.” To design enterprise and web applications that work correctly, you will need a good understanding of how distributed systems are designed and deployed. 1.3 Distributed System Architectures Software engineers have found it useful to decompose the architecture of a distributed system into both vertical layers and horizontal tiers. By example, the distinction between the application, operating system, and hardware layers is apparent to most engineers, as exemplified in the following figure. CS 483 Week 1 Supplementary Material ©2006 Regis University 1 Layer Platform Layer Example Application Layer Internet Explorer Operating System Layer Microsoft XP Hardware Layer Dell Inspiron (pentium) The operating system and hardware layers are collectively referred to as the platform layer. Likewise, the distinction between the client, web server, and persistence tiers in three-tier architectures is also apparent, as exemplified in the following figure. Tier Client Tier Web-Server Tier Persistence Tier Example Internet Explorer Apache Oracle Database As described throughout this course, each tier consists of one or more components that collectively fulfill a common purpose. 1.4 Logical and Physical Tiers Software engineers have also found it useful to distinguish between physical and logical tiers. Physical tiers are typically based on an assumption that the application components found in the different tiers, literally, reside on different host computers. Windows XP Unix Host IE Browser 1 * Client Tier Linux Host Apache Web Server 1 1 Web-Server Tier Oracle Database Database Tier Alternatively, if these components were deployed, for example, on a single host (physical tier), the components are considered to reside within a logically tiered architecture. Windows XP IE Browser Apache Web Server 1 Oracle Database 1 * Client Tier 1 Web-Server Tier Database Tier CS 483 Week 1 Supplementary Material ©2006 Regis University 2 Note: Context plays an important role in what constitutes a physical or logical tier. For example, instead of defining physical tiers according to the computer hosts on which a component resides, a physical tier could alternatively be based on the process in which a component executes. 1.5 Case Study: A Single Tier Architecture The simplicity of single-tier architectures provides a convenient initial framework for subsequently examining more sophisticated multi-tier architectures. Consider, for example, the simplified student services application depicted in the following figure. localhost «Jar» StudentServices Logical Client Tier package sss.ui Logical Server Tier package sss.server Logical Persistence Tier package sss.io AdvisorPanel Advisor FileMgr SchedulePanel Scheduler ObjectStream package sss.doman «create» «create» Schedule Doman is shared between all tiers Student Since this design is deployed on a single host and the communication between all objects occurs via standard object-oriented message passing, this design exemplifies a single tier physical architecture. As the comments in the figure show, the classes have been grouped into logical tiers based on the common functionality. Take a moment to consider what changes you might make to this architecture in order to transform it into a two tier physical architecture. A solution is given in the next section. 1.6 Case Study: A Two-Tiered Physical Architecture The simplified design given in the previous section can be transformed into a two tier physical architecture by deploying the classes related to the client aspects of the design on a different host computer from the classes related to the server aspects of the design. The following figure, which omits the classes for clarity, captures this new design. CS 483 Week 1 Supplementary Material ©2006 Regis University 3 Client Server «Jar» S3Client ui «Jar» S3Server server «tcp/ip» io «import» «import» domain domain Again, take a moment to consider what changes you might make to this architecture to transform it into a three tier physical architecture. A solution is given in the next section. 1.7 Case Study: A Three-Tiered Architecture The simplified two tier architecture presented in the previous section can be transformed into a three tier physical architecture by separating the handling of persistence in the server tier into its own tier. The following figure depicts this new design. Notice that this new design also replaced the handling of persistence by the FileMgr class in the previous io package with a DatabaseMgr (not shown) residing in a database package. Client DbServer Server «Jar» S3Client ui «tcp/ip» «import» domain «Jar» S3Db «Jar» S3Server server «jdbc» db «import» domain «import» Package1 CS 483 Week 1 Supplementary Material ©2006 Regis University 4 1.8 A Multi-Tiered Architecture Although three-tier architectures are considered to be multi-tiered, most enterprise applications are distributed over many additional logical or physical tiers. Consider, for example, the multi-tier architecture, taken from a large telecommunication’s company, depicted in the following deployment diagram. DbServer Client Webserver AppServer DbServer Client Webserver Legacy Client AppServer Webserver Legacy Client The key feature of this architecture concerns the fact that any client can communication with any web server, but these clients cannot directly communicate with other tiers. This design pattern is replicated in each of the other tiers. Also note that the application, database, and legacy servers are able to communicate with each other within a tier. Although this type of multi-tier architecture is more costly to design, implement, and deploy, it addresses a number of challenges associated with deploying successful mid to large scale commercial enterprise and web applications. 1.9 Distributed System Issues A multi-tier architecture provides a solution to two important requirements desired in the operation of an enterprise and web application: Scalability – Enterprise applications must be able to handle a large numbers of users and transactions while sustaining appropriate performance in a fashion that scales gracefully as more users and transactions are handled by the system. The separation of components and hosts into multiple tiers, and replication of these components and hosts, allows for concurrent execution of transactions. This concurrency allows work load to be balance among the various system components. As usage of the enterprise application increases, additional resources can be step-wise added to the architecture. CS 483 Week 1 Supplementary Material ©2006 Regis University 5 Failure Handling – Enterprise applications must also be available for use, often 24x7. Consequently, the application must degrade gracefully when various components fail. In a multi-tier architecture, there is no single point of failure. Replication of components, hosts, and networking allows the failure of a single recourse since work load can be easily sent to another server, component, or via a different network path. Note: As with most software engineering issues, risks must be balanced against costs. However, since most large corporations cannot afford a loss of service or data, they often accept the increased cost of designing their multi-tiered architectures to ensure that tiers, and components within a tier, be located in different cities. This design avoids the risk associated with a single point of failure such as the destruction of a building housing the application (e.g., earthquake, fire, etc.). 1.10 Distributed System Technical Challenges Naturally, there are a number of challenges associated with using a multi-tier design in the development of an enterprise application. In addition to obvious financial and logistical costs, there are technical issues that must also be addressed. Security – The physical distribution of components makes it more difficult to provide appropriate levels of security. For example, while access to a single computer can be controlled by locking the computer away in a room, distributed systems require connecting the corporation’s computers to a network. Typically, this exposes the application to security breeches from any where in the world via the Internet Failures – The distribution and concurrent operation of distributed components results in situations where one component may not be aware that another has failed. Concurrency – The concurrent operation of components requires coordinating the transactions handled by these components. For example, an ATM machine cannot dispense cash without ensuring the customer’s bank debits the account. Transparency – In general, users do not care whether a system is distributed and shouldn’t be expected to know or realize this fact. However, issues such as network latency in a distributed system can noticeably affect system performance. 1.11 Distributed System Business Needs The design of a distributed system must also account for the increasing business pressure towards heterogeneity and openness. Heterogeneity refers to the ability of the distributed system to easily integrate components that are developed, for example, by different vendors or in different application domains. CS 483 Week 1 Supplementary Material ©2006 Regis University 6 Wow, haven’t heard EBCDIC in years. Do you know ASCII? Hey AL A L A, L ?? 193 64 211 65 32 76 Openness refers to the degree in which a distributed system can be easily extended to handle new situations. In many situations, openness is handled by ensuring that system parameters are coded as data, as opposed to being non-mutable values hard-coded into the design, which can be easily configured by the users. The remainder of this course introduces a number of design approaches that address the various challenges associated with developing a commercially viable distributed system and corresponding enterprise and web applications 1.12 Middleware Middleware is a software layer that provides an abstract programming model that hides, via encapsulation, the details associated with heterogeneity in both the layers and tiers of a distributed architecture, while simultaneously providing, in a convenient fashion, a number of sophisticated features required in enterprise-wide applications. These features address, for example, such challenges as heterogeneity, openness, security, failure handling, concurrency, etc. Layers Examples Application Layer Internet Explorer Firefox Browser Middleware Layer Distributed Component Object Model (DCOM) Web Services Platform Layer MS/Dell Sun Solaris CS 483 Week 1 Supplementary Material ©2006 Regis University 7 1.13 Case Study: EJB as Middleware While contemplating the design of the new student services application, you realize that using a middleware platform will result in a more robust application that can be developed in a shorter time. A web survey identifies three major middleware contenders: W3’s Web Services, Microsoft’s .Net, and Sun’s EJB Application Server. A multi-tier architecture for the student services application utilizing a Java 2 Enterprise Edition (J2EE), Java Enterprise Bean (EJB) & corresponding EJB application server middleware technologies is depicted in the following figure. Client S3 User Interface Tiers Business Logic S3 Server Persistence S3 Database Middleware J2EE Client EJB J2EE EJB App Server J2EE Oracle JDBC Platform Microsoft XP (Dell/Pentium) Solaris Unix (Sun) Open Linux (HP) Application Layers Note: With the exception of the specific platform layers and the use of Oracle, this architecture is analogous to the one required in your homework assignments. In general, you will implement these physical tiers as logical tiers on a single physical host and use MySQL instead of Oracle. 1.14 Component Transaction Monitor (CTM) At the heart of the EJB middleware approach is a Component Transaction Monitor. In a nutshell, a Component Transaction Monitor (CTM) is a server-side application that combines the features of traditional Transaction Processing Monitors and more recent distributed Object Request Brokers (Thomas, 1999). Historically, Transaction Processing Monitors (TPMs) emerged at IBM in the 1960s to handle the online transaction processing associated with large enterprise applications such as an airline reservation application with 2,000 simultaneous users. As described in more detail in Week 5, transactions provide a mechanism for handling such enterprise computing issues as concurrency, failure handling, and consistent actions. Recently, Object Request Brokers (ORBs) have emerged to support the deployment of objects across a network. As described in the Week 2 materials, this deployment requires a reliable directory service and communication infrastructure that allows these distributed objects to locate and send remote messages to each other. ORBs also include mechanisms to handle the failure of distributed objects and these remote communications. In many respects, the primary goal of TPMs, ORBs, and their combination into CTMs is to automatically provide the sophisticated features (e.g., distributed transactions) required CS 483 Week 1 Supplementary Material ©2006 Regis University 8 to deploy an enterprise application, thus freeing the software engineer to focus directly on the business logic of application (e.g., airline reservations) being developed. 1.15 Object Life-Cycle CTM application servers provide a number of features supporting the life cycle maintenance of distributed objects. Although, the details of these features are examined in subsequent weeks, a review of non-distributed life cycle maintenance provides a pedagogical basis for understanding the Persistence tier described in the next section. The life cycle of an object refers to the general notion that an object is created, modified during some period of time, and then deleted. Keep in mind that this life cycle refers to the actual object instance and not the domain data associated with an application. For example, when finding an object that has been previously saved in a database, it is still necessary to first create the object instance. After this creation, the attribute values of this object can be assigned to reflect the data previously saved in the database. A factory design pattern is often used to encapsulate the functionality associated with the life cycle maintenance of an object. This pattern separates the business logic of the domain being modeled from the life cycle maintenance of the object. For example, the following Student Factory contains methods for creating, finding, and removing a Student object. Consequently, the Student object itself only contains operations associated with the domain application in which it exists (e.g., addCourse(Course)). StudentFactory «create» Student +create() : Student +find(in id : int) : Student +findByName(in name : String) : Student +remove(in id : int) : void In a non-distributed system, a factory can be conveniently implemented using a singleton design pattern as shown in the example Student Factory in the following figure: StudentFactory -singleton : StudentFactory = new StudentFactory() «create» Student +getSingleton() : StudentFactory -StudentFactory() +create() : Student +find(in id : int) : Student +remove(in id : int) : void Given this singleton design, a new Student object can be created using the following Java code. Student aStudent = StudentFactory.getSingleton().create(); CS 483 Week 1 Supplementary Material ©2006 Regis University 9 In a distributed system, the use of this type of factory will hide the actual location of the business object from the user. For example, in a large enterprise application, it is possible for two different student objects to actually be located on two different server hosts. However, the single find method provided by the factory ‘knows’ how to locate and return the appropriate Student object. 1.16 The Persistence Tier In multi-tier enterprise architectures, the Persistence tier encapsulates the logic for saving data to, and loading data from, persistent storage. Within a CTM (application) server, enterprise information in the business-logic tier is represented using remote objects. As with all objects, a remote object captures state by encapsulating local data as a set of attributes. Consequently, the long-term persistence of an object requires saving its attribute values to non-volatile storage. This raises the question as to what type of non-volatile storage should be used. Simplistically, this data can be saved to local operating system files using XML or as you did with serialized objects in your Java Programming (CS434). However, unless a considerable amount of additional programming effort is implemented, these file-based approaches do not satisfy the distributed system issues introduced in prior sections. Instead CTM application servers generally take advantage of the rich set of features associated with relational databases and consequently save an object by mapping its attribute values to the rows and columns of relational tables. Software engineers have developed a number of design patterns associated with saving objects to a relational database. In general, the same design patterns are useful in both a non-distributed and distributed system environment. Note: although the same patterns are applicable in both environments, care must be taken to not over design the application. For example, for many non-distributed applications, using of all the design patterns described in the remainder of this week in a single application, as done below, can be easily considered as overkill! 1.17 The DAO Design Pattern Similar to the separation of life cycle maintenance and business logic provided by a factory design pattern, current best-practice design uses a delegate Data Access Object (DAO) to separate the business logic aspects of an object from the code used to access persistent storage. Keep in mind that in a distributed system, using a factory to find a remote object does not necessarily require loading the object from persistent storage (it may have been previously loaded and simply be found somewhere on the network). For example, when a business object, such as Student, is sent a message to save itself, this business object will delegate the request, by sending a message, to a corresponding CS 483 Week 1 Supplementary Material ©2006 Regis University 10 data access object, which knows how to save the object. This may require, for example, knowing where a database or file system is being used to save the object. A similar situation occurs when a factory must find an object by loading it from persistent storage. «use» BusinessObject «use» «interface» DataAccessObject +create(in id : int) : BusinessObject +find(in id : int) : BusinessObject +save(in obj : BusinessObject) : void Factory PersistenceMgr «use» «instantiate» DataObject +create(in id : int) : BusinessObject +find(in id : int) : BusinessObject +save(in obj : BusinessObject) : void 1.18 The DAO Factory Pattern A DAO factory pattern is often used to further separate the application server from the persistence engine. For example, consider a situation in which data may be saved either to a relational MySQL database or to a XML file. In this situation, a business object, such as student, would request a data access object from a data access object factory. Since the factory knows which type of persistence is being used, it returns a data access object corresponding to the appropriate persistence engine. More specifically, if the application is currently using a MySQL database for persistence, a MySqlDAO object will be returned. «uses» BusinessObject DaoFactory «uses» DatabaseDaoFactory +create() : DataAccessObject «instantiate» «uses» «interface» DataAccessObject +create(in id : int) : BusinessObject +find(in id : int) : BusinessObject +save(in obj : BusinessObject) : void «implement» XmlFileDaoFactory +create() : DataAccessObject «implement» «instantiate» MySqlDAO XmlDAO +create(in id : int) : BusinessObject +find(in id : int) : BusinessObject +save(in obj : BusinessObject) : void +create(in id : int) : BusinessObject +find(in id : int) : BusinessObject +save(in obj : BusinessObject) : void (adapted from Crawford & Kaplan (2003)) CS 483 Week 1 Supplementary Material ©2006 Regis University 11 1.19 Case Study: Saving a Student Having investigated the benefits of the DAO approach to persistence, you decide to update your Student persistence to utilize a DAO and an associated DAO factory. While developing your design, you realize that you’re not exactly sure how the student data access object should be implemented, but remember that JDBC can be used to save Java objects to a relational database. So, you have your DAO using JDBC (as discussed in the next section). Student «use» -name : String -plan : DegreePlan -schedule : Schedule -studentId : int +getName() : String +setName(in name : String) : void +getPlan() : DegreePlan +setPlan(in p : DegreePlan) : void +getSchedule() : Schedule +setSchedule(in s : Schedule) : void +getStudentId() : int +setStudentId(in id : int) : void +save() : void MySqlDaoFactory «interface» StudentDAO +create(in id : int) : Student +find(in id : int) : Student +save(in s : Student) : void «implements» StudentMySqlDAO «use» JDBC -dbMgr : JDBC +create(in id : int) : Student +find(in id : int) : Student +save(in s : Student) : void «instantiate» +getStudentDAO() : StudentDAO 1.20 JDBC Java DataBase Connectivity (JDBC) consists of a set of interfaces whose methods can be used to connect to and access data within a relational database using SQL. The salient methods of these JDBC interfaces are defined in the following UML diagram. CS 483 Week 1 Supplementary Material ©2006 Regis University 12 package java.sql DriverManager Only a subset of the java.sql interfaces and operations relevant to the examples found in this section are displayed in this diagram. +getConnection(in url : String) : Connection «instantiate» «interface» Driver +connect(in url : String, in info : Properties) : Connection «instantiate» «interface» Connection +createStatement(in sql : String) : Statement +prepareCall(in sql : String) : CallableStatement +prepareStatement(in sql : String) : PreparedStatement «instantiate» «instantiate» «implements» «interface» ResultSet +getFloat(in columnIndex : int) : float +getFloat(in columnName : String) : float +getInt(in columnIndex : int) : int +getInt(in columnName : String) : int +getString(in columnIndex : int) : String +getString(in columnName : String) : String +next() : boolean package com.mysql.jdbc jdbc::Driver «iimplements» jdbc::ResultSet «interface» Statement +executeQuery() : ResultSet +executeUpdate() : int «interface» PreparedStatement +setFloat(in index : int, in x : float) : void +setInt(in index : int, in x : int) : void +setString(in index : int, in x : String) : void «interface» CallableStatement «iimplements» jdbc::PreparedStatement jdbc::Connection Note: Since this course uses JDBC to access a MySQL relational database, it is necessary to obtain a set of concrete classes implementing MySQL access for the JDBC interfaces. See the CS 483 Week 1 Software Installation Guide for details. CS 483 Week 1 Supplementary Material ©2006 Regis University 13 1.20.1 Connecting to the Database The first step in using JDBC is to load the driver you are using into the JVM (Java Virtual Machine). The following code, which only needs to be executed once, will load the MySQL driver. try { Class.forName(“com.mysql.jdbc.Driver”).newInstance(); catch (ClassNotFoundException e) { // Class not on the CLASSPATH . . . catch (InstantiationException e) { // Error in the instantiation . . . catch (IllegalAccessException e) { // Security policy violation . . . } // try Note: Explicitly loading the driver in this fashion allows you to avoid errors that occur in certain JVMs. The next step is to obtain a connection to the database. JDBC uses a Uniform Resource Locator (URL) to specify the information required to establish this connection. The general form of this URL is: jdbc:<subprotocol>:<subname> For example, the URL establishing a connection between a Java application and a MySQL database executing on the same computer is: "jdbc:mysql://localhost/rubs?user=root&password=dbadmin” The jdbc token designates that this URL uses the JDBC protocol. The mysql token indicates that the <subname> adheres to the mysql sub-protocol, which specifies that a MySQL database named rubs located on the localhost is to be used and that our Java application is logging into this database as the user “root” with a password of “dbadmin”. The following code obtains a database connection: String url = "jdbc:mysql://localhost/rubs?user=rickb&password=tampa"; try { Connection dbConn = DriverManager.getConnection(connUrl); } catch (SQLException e) { . . . } // try // Unknown db or login failed CS 483 Week 1 Supplementary Material ©2006 Regis University 14 1.20.2 Querying the Database Assume the following book table is exists the previous rubs database: Id:int 12294 81763 Name:varchar Pride and Prejudice The Little Prince Price:float 7.95 5.50 The SQL query required to obtain the name and price of the book with id 81763 is: select name, price from Book where id = 81763; The JDBC code required to issue this query to the database begins by first declaring a prepared statement. In this prepared statement, the optional arguments of the query are indicated with a question mark. For example, the id in the previous query represents an optional parameter and it is subsequently set by sending the prepared statement a setInt(<position>,<value>) message. Once all of the parameters of the statement have been supplied values, the statement can be executed and the results of this execution will be returned in a result set. int id = 81763; try { String sqlStmt = “select Name,Price from Book where id = ?”; PreparedStatement stmt = conn.prepareStatement(sqlStmt); stmt.setInt(1, id); ResultSet rs = stmt.execute(); . . . } catch (SQLException e) { . . . } // try 1.20.3 Mapping Result Sets to Objects If one or more rows in the table were found, the ResultSet’s next() method returns true. As book ids are unique, a maximum of one row can be found for the previous query. Hence, success can be checked with a single if statement (as opposed to a while loop). Once the database row has been obtained from the database, it is necessary to map the data into an object. This can easily be accomplished by creating a new instance corresponding to the row and using mutator methods to assign the appropriate values. CS 483 Week 1 Supplementary Material ©2006 Regis University 15 if (rs.next()) { Book book = new Book(id); book.setBook(rs.getString(“Name”)); book.setPrice(rs.getFloat(“Price”)); return book; } else { System.out.printl(“There is no book with id “ + id); } // if Note: There are a number of more generic ways to accomplish this mapping, however, to keep things simple, they are not be discussed in this course. 1.20.4 CRUD Operations Analogous to querying the database, creating, updating, and deleting data from the database are also handled by constructing the appropriate SQL statement and using JDBC to execute the corresponding statement. However, since no results are expected from these operations, the executeQuery method is not used. Instead, the executeUpdate method is used, which returns the number of rows that were successfully created, updated, or deleted. The following examples demonstrate each of these operations, beginning with the create: try { sqlStmt = “insert into Book (id, name, price) values (?, ?, ?)”; PreparedStatement stmt = conn.prepareStatement(sqlStmt); stmt.setInt(1, book.getId()); stmt.setString(2, book.getName()); stmt.setFloat(1, book.getPrice()); int rowsInserted = stmt.executeUpdate(sqlStmt); } catch (SQLException e) { . . . } // try CS 483 Week 1 Supplementary Material ©2006 Regis University 16 To delete a row from the database, construct the appropriate SQL delete statement: try { sqlStmt = “delete from into Book where is = ?”; PreparedStatement stmt = conn.prepareStatement(sqlStmt); stmt.setInt(1, book.getId()); int rowsDeleted = stmt.executeUpdate(sqlStmt); } catch (SQLException e) { . . . } // try Likewise, to update a row, construct the appropriate SQL update statement: try { sqlStmt = “update Book set price = ? where id = ?”; PreparedStatement stmt = conn.prepareStatement(sqlStmt); stmt.setPrice(1, newPrice); stmt.setInt(2, book.getId()); int rowsUpdated = stmt.executeUpdate(sqlStmt); } catch (SQLException e) { . . . } // try *** End of CS 483 Week 1 Supplementary Materials *** CS 483 Week 1 Supplementary Material ©2006 Regis University 17