1 / 75

Application Design

EE557: Server-Side Development. Application Design. EE557: Server-Side Development. Model 1 Architecture. EE557: Server-Side Development. Model 1 Architecture Problems. Duplication of functionality in servlets/JSPs Ties business logic and presentation logic together!

Download Presentation

Application Design

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. EE557: Server-Side Development Application Design

  2. EE557: Server-Side Development Model 1 Architecture

  3. EE557: Server-Side Development Model 1 Architecture Problems • Duplication of functionality in servlets/JSPs • Ties business logic and presentation logic together! • Difficult to create a new view (eg. WML interface) • Internationalisation • Any of these familiar?

  4. EE557: Server-Side Development Model 2 Architecture • ‘Controller’ receives all requests for the application. • It processes the request and interacts with the ‘Model’ • Prepares data to present to the ‘View’. Response to user is presented in the ‘View’ • ‘View’ typically JSPs

  5. EE557: Server-Side Development Model 2 Architecture • MVC is a design pattern - a blueprint for constructing a • time-tested solution to a given problem • It is not an implementation • Three layers of functionality: • - Model Components: The data and business logic • - View Components: Presentation • - Controller Components: The flow control

  6. EE557: Server-Side Development Model Components • Provide access to our business data and logic to manipulate data • Typically interacts with a persistent storage mechanism (DBMS) • Controller components typically don’t embed code for • manipulating data -> instead they communicate with the Model • which performs data access and manipulation • Model components can be implemented as JavaBeans, Enterprise • JavaBeans (EJBs) and a range of other options

  7. EE557: Server-Side Development View Components • Responsible for displaying data from the Model to the user • Typically simple JSPs or HTML pages • Seperation of business and presentation logic, allows other view • technologies such as WML • Open to future presentation technologies

  8. EE557: Server-Side Development Controller Components • Core part of MVC Architecture • Handle all requests from the user and selects the View to return • Typically a servlet, which manages the flow of data between the • Model and the View • When Controller receives a request it forwards the details to an • appropriate Handler, which determines what action to take • The handler might call on the Model to perform a specific function • After the Controller selects the View to send back to the user • based on the state of the Model’s data

  9. EE557: Server-Side Development Internationalisation (i18n) & Localisation (l10n) • The means of adapting computer software to different languages • and regional differences • Acrynoms based on counting letters between first and last letter • Creating multiple versions of applications is NOT a viable option • - updating becomes a nightmare • Internationalisation is the process of designing an application so • that it can adapt to various languages and regions WITHOUT • engineering changes! • Localisation is the process of adapting internationalised software • for a specific region or language by adding locale-specific components • and translating text.

  10. EE557: Server-Side Development Internationalisation (i18n) & Localisation (l10n) • Internationalisation and localisation handled in most situations by • the abstraction of language away from underlying code • Most MVC frameworks will provide functionality for doing so • Example Struts: • - ApplicationResources.properties • - ApplicationResources_fr.properties • - ApplicationResources_de.properties • etc. • When browsers make requests, they pass along a HTTP header • (Accept-Language) that indicates the user’s Locale • (country, language etc.)

  11. EE557: Server-Side Development ApplicationResources.properties #errors associated with the Login page error.username.required=username is required. error.password.required=password is required. error.login.invalid=Login Failure: The DCU Novell username/password …. #login page text login.title=Welcome to EE557 - Please Login login.message=Enter your username and password: login.username=Username: login.password=Password: login.button.commit=Login login.help.message=Login Help #loggedin page text loggedin.title=Login Project loggedin.msg=Welcome, {0}. You are now logged in.

  12. EE557: Server-Side Development Object-Relational Persistence • Majority of Applications require persistent data, typically in a DBMS • Relational DBMS are designed to be understandable in a human way • Java Applications are written with an object-oriented approach • Relational tables in rows and columns vs objects with attributes • and associations • There is an overhead in moving from objects -> relational data and from relational data -> objects • This programming overhead is known as the object-relational gap • Let’s look at some code!

  13. EE557: Server-Side Development Object-Relational Persistence public class Customer { private Long ID; private String surname; private String firstname; private String email; // Constructor public Customer(Long ID, String surname, String firstname, String email) { this.ID = ID; this.surname = surname; this.firstname = firstname; this.email = email; } // Now the get methods public Long getID() { return ID; } public String getName() { return firstname + " " + surname; } public String getSurname() { return surname; } public String getFirstname() { return firstname; } public String getEmail() { return email; } // And some set methods public void setID(Long value) { ID = value; } public void setSurname(String value) { surname = value; } public void setFirstname(String value) { firstname = value; } public void setEmail(String value) { email = value; } }

  14. EE557: Server-Side Development Object-Relational Persistence • We can manually perform something like the following • public boolean addCustomer(Customer customer) { • // JDBC Connection and statement setup..... • PreparedStatement pstmt = con.prepareStatement("INSERT INTO CUSTOMERS (ID,SURNAME,FIRSTNAME,EMAIL) VALUES (?,?,?,?)"); • pstmt.clearParameters(); • pstmt.setString(1, customer.getID()); • pstmt.setString(2, customer.getFirstname()); • pstmt.setString(3, customer.getSurname()); • pstmt.setString(4, customer.getEmail()); • pstmt.executeUpdate(); // handle closing down of connections etc. • } • Rather simply we just map each field of the object to one column in a • database table called CUSTOMERS • This works correctly!

  15. EE557: Server-Side Development Object-Relational Persistence • However, what happens with our objects have many separate multi-dimensional • fields and nested relationships? • Consider if we wanted to add a Vector of billing addresses to our Customer object • ... private String email; • private Vector billingAddresses; .... • public Vector getBillingAddresses() { return billingAddresses; } • public void setBillingAddresses(Vector value) { billingAddresses = value; } .... • So how do we handle this two dimensional array of addresses? • - Create a nested table in the DBMS (if supported) ? • - Create a separate table CUSTOMERADDRESSES + FK/PK relationship • How to handle relationships with other object tpes… Eg. Customers with Orders • As the data structures become more complicated so do our DBMS structures and • persistence code

  16. EE557: Server-Side Development Object-Relational Persistence • Estimated by some, that 35% of application code is spent on these conversions • Look at some options! • Hand-Coding • There are design patterns which help handwrite the JDBC code to interact • with databases. • However, the work involved is often considerable as we have discussed • Serialization • As we have seen, serialization provides the ability to write objects to a byte-stream • We can then persist this byte-stream in a database • Not suitable for searches or arbitrary data retrieval. Eg. to change an email address • of a customer you would need to deserialise, change the object and serialise again

  17. EE557: Server-Side Development Object-Relational Persistence • Entity Beans (EJBs) • Very popular approach for persisting object data • BMP (Bean Managed Persistence) requires handcoded JDBC, with associated • problems • CMP (Container Managed Persistence) Beans let the container handle persistence • with the database • CMP mapping configuration difficult, discrepancies between application servers • and varying capabilities  many developers looking for alternative solutions

  18. EE557: Server-Side Development Object-Relational Persistence • Object-Oriented Database Systems • In the mid-90s object-oriented database management systems (OODBMS) gained • attention • OODBMS offer seamless integration into the object-oriented application • environment • OODBMS have not had much uptake and are not a popular solution • RDBMS still contain the vast majority of the market share

  19. EE557: Server-Side Development Object-Relational Persistence • Object/Relational Mapping (ORM) • ORM is the automated persistence of objects in a Java application to tables in • a relational database • This is achieved through configuration, where you define the way you map your • classes to tables once (which property to which column, which class to which table • etc.) • Now we can: • orm.save(myCustomer); • or • myCustomer = orm.load(Customer.class, customerID); • ORM implementations are complex and not recommended for small projects due • to their steep learning curve. However they have considerable advantages.

  20. EE557: Server-Side Development Object-Relational Persistence • Object/Relational Mapping (ORM) • Advantages • Productivity – Eliminates much of the grunt work for developers • Maintainability – Few lines of developer code, modifications to data structure only • require changes to the ORM configuration (rather than code + SQL) • Performance – ORM is known for its database efficiency • Vendor Independence – ORMs abstract your application away from underlying • SQL databases, SQL dialects and reliance on application servers (like with EJBs)

  21. EE557: Server-Side Development Object-Relational Persistence • Hibernate • Hibernate is the most mature and complete open-source, object relational mapper • Developed by a team of Java software developers from around the world • It can significantly reduce development time on large-scale projects • Has experienced considerable growth in popularity in recent years How does it work?

  22. EE557: Server-Side Development Hibernate package edu.ee.beans; public class Customer { private int id; private String username; private String password; private String firstname; private String surname; private String email; public Customer(int id, String username, String password, String firstname, String surname, String email) { super(); this.id = id; this.username = username; this.password = password; this.firstname = firstname; this.surname = surname; this.email = email; } public Customer() { } public int getId() { return id; } public void setId(int id) { this.id = id; }

  23. EE557: Server-Side Development Hibernate public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getSurname() { return surname; } public void setSurname(String surname) { this.surname = surname; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }

  24. EE557: Server-Side Development Hibernate • Hibernate code to create a new Customer: • Customer customer = new Customer(); • customer.setUsername("smithj"); • customer.setPassword("mypass"); • customer.setFirstname("John"); • customer.setSurname("Smith"); • customer.setEmail("john.smith@dcu.ie"); • Session hibernateSession = HibernateUtil.getSession(); hibernateSession.save(customer); • OK – so there’s a little more to it than this!

  25. EE557: Server-Side Development Hibernate • Where is the SQL? There isn’t any! • Behind the scenes: Hibernate will use some mapping information • to generate appropriate SQL for the underlying database, such as: • insert into CUSTOMERS (ID, USERNAME, PASSWORD, FIRSTNAME,SURNAME, EMAIL) values (1, ‘smithj’, ‘mypass’, ‘John’, ‘Smith’, ‘john.smith@dcu.ie’); • Most of the work in Hibernate is on developing these mappings • - Configuration of which database/details we will be using • - Configuration of the mappings for CRUD operations on our classes • Developers still need to understand SQL for a range of reasons • In particular, even for Hibernate we still need a strong understand of • primary and foreign key relationships and data integrity

  26. EE557: Server-Side Development Hibernate • Previous technique for performing mappings • <hibernate-mapping> • <class name=”edu.ee.beans.Customer table=”Customer”> • <id name=”id” column=”id”> • <generator class=”native”/> • </id> • <property name=”username” column=”username”> • <property name=”password” column=”password”> • <property name=”firstname” column=”firstname”> • <property name=”surname” column=”surname”> • <property name=”email” column=”email”> • </class> • </hibernate-mapping>

  27. EE557: Server-Side Development Hibernate • New technique using Java Annotations, introduced in Java 1.5 • Removes reliance on awkward XML configuration files (apart from one) • Rather than having a separate configuration file, we “annotate” our • JavaBeans directly putting the mapping information into the beans

  28. Annotated Bean package edu.ee.beans; import javax.persistance.*; @Entity public class Customer { private int id; private String username; private String password; private String firstname; private String surname; private String email; public Customer(int id, String username, String password, String firstname, String surname, String email) { super(); this.id = id; this.username = username; this.password = password; this.firstname = firstname; this.surname = surname; this.email = email; } public Customer() { } @Id @GeneratedValue public int getId() { return id; } public void setId(int id) { this.id = id; } ….. ….. other getter and setter methods as before…..

  29. EE557: Server-Side Development Hibernate • @Entity - tells Hibernate that it will be responsible for handing the • database operations for this bean • @Id - identifies the primary key • @GeneratedValue - indicates that the primary key will be automatically • generated • By default, all of the remaining fields are mapped to columns of the same • name (hence, few annotations in this example – can be overridden)

  30. EE557: Server-Side Development Handwritten JDBC vs Hibernate • Hibernate takes time to learn – temptation to just continue writing JDBC/SQL • Want to change to a different database system (RDBMS) which has a considerably different implementation of SQL?  Hand-written JDBC Code: Big problem!  Rewrite of most embedded SQL.Hibernate: No problem! Change three lines in a Hibernate configuration file!  • Fed up manually creating table structures using the ‘CREATE TABLE’ statement?Hand-written JDBC Code: Keep doing it (or use a UI)Hibernate: ONE line of code can be used to create ALL of your tables automatically, in whichever database dialect you have configured. • Tired of constantly getting database errors because you are moving between Java objects and relational database tables?Hand-written JDBC Code: No other optionHibernate: work with objects 100% of the time and never write SQL manually again!

  31. EE557: Server-Side Development Hibernate – Getting Started • What do we need? • A JDBC compliant database: Hibernate will work with all popular databases.  (Already have this!) • JDK 5.0 or better: as annotations didn’t exist before Java 5. (Already have this!) • JDBC Drivers for your database: the JDBC drivers are used by Hibernate to connect to the database.  (Already have this!) • Eclipse: our development environment (Already have this!) • Hibernate: we require the various JAR files and libraries which form Hibernate. (New!) • A hibernate.cfg.xml file on your classpath (New!)

  32. EE557: Server-Side Development Hibernate – Getting Started • 5. Hibernate JAR Files and Libraries • To use Hibernate we require a number of JAR files, containing both • Hibernate and Hibernate Annotations support. • Up until Hibernate Version 3.4 Hibernate Core and Annotations libraries • Were separate downloads • Version 3.5.x onwards Hibernate Annotations is bunded with Core • There are additionally a number of support libraries that Hibernate uses, • which we must also include – these are also bundled • We actually include about a dozen individual JAR files in our Hibernate • applications (import into WEB-INF/lib and set up build paths)

  33. EE557: Server-Side Development Hibernate – Getting Started • 6. A Working hibernate.cfg.xml file • Special configuration file that tells Hibernate • where our database is • what database driver to use to connect to the database • what type of database “dialect” to use • what the connection URL is • what the database username and password are • other configurations…

  34. EE557: Server-Side Development Hibernate • <?xml version='1.0' encoding='utf-8'?> • <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> • <hibernate-configuration> • <session-factory> <!-- Database connection settings --> • <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> • <property name="connection.url">jdbc:oracle:thin:@136.206.35.131:1521:SSD</property> • <property name="connection.username">ee_user</property> • <property name="connection.password">ee_pass</property> • <!-- JDBC connection pool (use the built-in) --> • <property name="connection.pool_size">0</property> <!-- SQL dialect --> • <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> • <property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property> • <!-- Enable Hibernate's current session context --> • <property name="current_session_context_class">thread</property> • <!-- Echo all executed SQL to stdout --> • <property name="hibernate.show_sql">true</property> • <!-- Echo all executed SQL to stdout --> • <property name="show_sql">true</property> • </session-factory> • </hibernate-configuration> • Do not try to learn off these configuration files!

  35. EE557: Server-Side Development HibernateUtil.java • Not listed in Steps 1-6 as it is an additional optional step for our setup • Support helper class we will use to directly interact with Hibernate • Provides a number of methods which make interacting with Hibernate • easier and with fewer lines of code • Open HibernateUtil in Eclipse • Number of methods in HibernateUtil

  36. EE557: Server-Side Development HibernateUtil.java (don’t learn this off!) • getInitializedConfiguration(): Configures and AnnotationConfiguration • object. This is where we tell Hibernate to manage responsibility for • database operations for our beans. Simply annotating beans is not enough! • recreateDatabase() – once the AnnotationConfiguration object has been • configured, Hibernate can automatically generated the SQL required to • automatically create all of the applicable tables • Note: We need to be careful with this method! • getSession() – the key to performing database operations. When we are • calling Hibernate operations, we always open a session • beginTransaction() – most database operations are performed within a • ‘Transaction’ providing the scope to commit and rollback. • commitTransaction(), rollbackTransaction(), closeSession()

  37. EE557: Server-Side Development Hibernate Eclipse Project • Download the hibernate.zip to your local harddrive • In Eclipse, select File -> Import -> General -> Existing • Projects into Workspace -> Next • Select Archive File -> Browse to the hibernate.zip file -> • Select the Project -> Next

  38. EE557: Server-Side Development Creating,Reading,Updating,Deleting • Previously covered in SQL using INSERT, SELECT, UPDATE and DELETE • We want to use Hibernate code to automatically generate these SQL statements • Will demonstrate using the existing template we have created • i.e. the Customer bean

  39. EE557: Server-Side Development Creating • Simple create a new Customer object, populate it and ask a Hibernate Session to • ‘save’ the object • Session hibernateSession = HibernateUtil.beginTransaction(); • Customer customer = new Customer(); • customer.setUsername("smithj"); • customer.setPassword("mypass"); • customer.setFirstname("John"); • customer.setSurname("Smith"); • customer.setEmail("john.smith@dcu.ie"); • hibernateSession.save(customer); • HibernateUtil.commitTransaction();

  40. EE557: Server-Side Development Retrieving (HQL) • As with SQL queries, a little more complicated than adding a record: • Session hibernateSession = HibernateUtil.beginTransaction(); • List<Customer> allCustomers = null; • Query queryResult = hibernateSession.createQuery("from Customer"); • allCustomers = (List<Customer>) queryResult.list(); • for (int i = 0; i < allCustomers.size(); i++) {    • Customer customer = (Customer) allCustomers.get(i);     • System.out.println("Customer name is : " + customer.getFirstname() + " " + customer.getSurname()); • } • HibernateUtil.commitTransaction();

  41. EE557: Server-Side Development Retrieving (HQL) • Looks suspiciously like SQL • Query queryResult = hibernateSession.createQuery("from Customer"); • This is a HQL (Hibernate Query Language) query • Object oriented equivalent of ‘select * from Customer_David123’ • Note the case on ‘Customer’. HQL operates on the objects themselves, we are • not referring to a database table called Customer. Case sensitive! (unlike SQL) • Instead of returning rows, we are returning a List of Customer objects • No need to convert back into object oriented form – use your beans immediately! • More on HQL later!

  42. EE557: Server-Side Development Retrieving a Unique Entity • Returning all entities not always efficient (tables with millions of rows?) • Frequently we want to return one entity, based on a primary key value • We have already defined ‘id’ as the primary key of our Customer class • How we would do it in JDBC handwritten code: • // All of the code to create connection above here • String mySQLQuery = "select * from customer_david123 where id = ?"; PreparedStatement ps = con.prepareStatement(mySQLQuery); • ps.setString(1, idVariable); • ResultSet rs = ps.executeQuery(); • if (rs.next()) { • // continue code here.. manually create the Customer object using the various row • // components...

  43. EE557: Server-Side Development Retrieving a Unique Entity • Using Hibernate, we do something similar to PreparedStatements • In Hibernate we achieve ‘variable injection’ by preceding the variable name with • a colon • Because we are expecting a single entity to be returned, we don’t return a List like • before. Rather we return a Customer object directly • Session hibernateSession = HibernateUtil.beginTransaction(); • String queryString = "from Customer where id = :id"; • Query query = session.createQuery(queryString); • query.setInteger("id", idVariable); • Customer customer = (Customer) query.uniqueResult(); System.out.println("Customer Name = " + customer.getFirstname() + " " + • customer.getSurname()); • HibernateUtil.commitTransaction();

  44. EE557: Server-Side Development Updating • Updating is straightforward – really a combination of retriving, modifying the entity • and then saving. • Example to change the passwords of all Customer objects • save(): new entry, update(): existing entry, alternatively saveOrUpdate() • Session hibernateSession = HibernateUtil.beginTransaction(); • List<Customer> allCustomers = null; • Query queryResult = hibernateSession.createQuery("from Customer"); allCustomers = (List<Customer>) queryResult.list(); • for (int i = 0; i < allCustomers.size(); i++) {    • Customer customer = (Customer) allCustomers.get(i); customer.setPassword("password"); • hibernateSession.update(customer); • } • HibernateUtil.commitTransaction();

  45. EE557: Server-Side Development Deleting • Delete is the same as the update() example, except we use delete() instead of • update() • In previous example, update() to delete() would delete all Customer entities • More commonly we want to delete a specific Customer (by primary key) • Session hibernateSession = HibernateUtil.beginTransaction(); • Customer customer = new Customer(); • customer.setId(1); • hibernateSession.delete(customer); • HibernateUtil.commitTransaction()

  46. EE557: Server-Side Development Combined CRUD Example • Deploy and demonstrate CRUDExample.java • View all of the generated SQL in the output of the application

  47. EE557: Server-Side Development Moving Database Vendor • Consider our previous example (and any other code we might write). To move: • Handwritten SQL • Rewrite all ‘CREATE TABLE’ statements and any other DDL • Download new JDBC JAR file, import into project • Rewrite all methods containing JDBC code (potentially) • Debug and test SQL • Hibernate • Download new JDBC JAR file, import into project • Edit 5 lines in hibernate.cfg.xml

  48. EE557: Server-Side Development Hibernate Query Language • Why learn another query language!? I just spent ages learning SQL! • Number of differences between SQL and HQL • Different syntax – need to be learned separately • Database Independence: HQL is database independent, SQL is not • Relational vs Object Based: HQL is object based, SQL is relational • Relationship with Database Structure: in SQL, statements explicitly refer • to the database table and column names. In HQL instead we rely on the • mappings. Hence changes in database structures, renaming of tables • and fields are easier to handle under HQL. Only the mappings need to • be changed, not the HQL • Later on we will look at the Criteria API which will even remove much of the • Need to learn HQL

  49. EE557: Server-Side Development Basic HQL To retrieve all Customer objects: Session session = HibernateUtil.beginTransaction(); Query query = session.createQuery("from Customer"); List customers = query.list(); for (int i = 0; i < customers.size(); i++) { Customer customer = (Customer) customers.get(i); / / Now we can do whatever we want with these objects System.out.println("Customer firstname is " + customer.getFirstname()); }

  50. EE557: Server-Side Development Basic HQL • Don’t always want to return all columns • To return particular columns only • Query query = session.createQuery("SELECT firstname from Customer"); • List names = query.list(); • for (int i = 0; i < names.size(); i++) { • String name = (String) names.get(i); • System.out.println("Name is " + name); • } • Example with a where clause: • Query query = session.createQuery("from Customer where firstname='David'); • // List results in the usual manner using Customer objects

More Related