480 likes | 608 Views
Session: I10. Java and IDS: Part 2 - JSP. Guy Bowerman IBM Information Management. Wed, October 4, 2006 • 11:00 a.m. – 12:00 a.m. Platform: Informix. Agenda. JSP vs. PHP vs. ASP vs. ??? Configuring Apache Tomcat 5.x for IDS JSP Example – Simple Select Authentication & Sessions
E N D
Session: I10 Java and IDS: Part 2 - JSP Guy Bowerman IBM Information Management Wed, October 4, 2006 • 11:00 a.m. – 12:00 a.m. Platform: Informix
Agenda • JSP vs. PHP vs. ASP vs. ??? • Configuring Apache Tomcat 5.x for IDS • JSP Example – Simple Select • Authentication & Sessions • Pagination – Cursor-less cursors • Inserting & Streaming Byte Data • JSP Connection Pool • AJAX Made Simple
JSP vs. PHP vs. ASP vs. ??? • JSP • Variety of ready-made libraries, beans • Platform independence • Reliance on JVM • PHP • Scalability • Increasing popularity • ASP • Limited to VBScript/COM • Windows or Windows • Browser incompatibilities • Consider Tapestry/Cocoon vs. Rails etc…
Apache Tomcat 5.x & Informix JDBC Configuration • Install Tomcat • Copy ifx*.jar to $CATALINA_HOME/common/lib/ • Restart Tomcat – Done! Create new applications under $CATALINA_HOME/webapps/. Create a WEB-INF directory in application dir, e.g: $CATALINA_HOME/webapps/jspdemo/WEB-INF
JSP Application Directory Layout • *.html, *.jsp, etc.. • /WEB-INF/web.xml • Web Application Deployment Descriptor • /WEB-INF/classes/ • Java class files required by application. • /WEB-INF/lib/ • JAR files used by application.
JSP Example – Simple Select $CATALINA_HOME/webapps/jspdemo/demo1.jsp: <%@ page import="java.sql.*" errorPage="error.jsp"%> <head> <title>JSP Demo 1</title> </head> <body> <ul> <h3>Customers by city</h3><br/><% // initialize Informix JDBC driverClass.forName("com.informix.jdbc.IfxDriver");….
Connect and Create Statement …// connection URLString url = "jdbc:informixsqli://mymachine:1526/stores_demo” + “:INFORMIXSERVER=ol_myserver"; // get database connectionConnection conn = DriverManager.getConnection(url, "informix", “mypasswd"); // create statement and execute queryStatement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery( "select city, company from customer order by 1,2");%>…
JSP Example – Display Results <table border=1><%// process result setwhile (rs.next()) { %><tr> <td><b><%=rs.getString(1)%></b></td> <td><%=rs.getString(2)%></td> </tr><%} %></table>
JSP Example – Close Objects <%// close ResultSet and Statement objectsrs.close();stmt.close(); // close connectionconn.close(); %></ul></body>
Error Handling error.jsp: <%@ page language="java" isErrorPage="true"%> <head><title>An error has occurred</title></head> <body><center><h1>Oops</h1> </center><br></br><ul> <font size=+1>Something bad happened...<br></br> <ul> <font color="red"><%=exception.toString()%></font> </ul><br>Try to stay calm, I'm sure there is a rational explanation.</br></font></ul> </body>
JSP Authentication Options • Handle your own authentication • Use a standard Tomcat Realm • JDBCRealm • DataSourceRealm • JNDIRealm (LDAP based authentication) • MemoryRealm (conf/tomcat-users.xml). • JAASRealm • Implement your own Realm plug-in
Implementing a JDBCRealm • Write a login page • Write a login error page • Create a user table • Create a user roles table • Add a Realm definition to server.xml • Add security-constraint, login-config and security-role definitions to WEB-INF/web.xml
Tomcat Realm login page <head><title>Authentication Page</title></head> <body> <center><h2>Please log in to view the customer database</h2><br/><br/> <form method="POST" action="j_security_check"> <table><tr><td>Username: <input type="text" size="15" maxlength="32" name="j_username"> </td></tr><tr><td> Password: <input type="password" size="15" maxlength="32" name="j_password"> </td></tr><tr> <td><input value="Login" type="submit"> <input value="Clear" type="reset"></td> </tr></table></form></center> </body>
Tomcat Realm Login Error Page <head><title>Authentication Error!</title></head><body><center><h1>Access Denied!</h1><br/><br/><a href="javascript:history.back(1)">Tryagain?</a></center> </body>
JDBCRealm User Tables Make sure your database is logged! create table users(username varchar(32) unique, password varchar(32)); create table roles(username varchar(32), rolename varchar(32));insert into users values("guyb", "test");insert into users values("user2", "test2");insert into roles values("guyb", "admin");insert into roles values("guyb", "manager");insert into roles values("user2", "custAdmin");
Define JDBCRealm in conf/server.xml <!-- Comment out the old Realm definition --> <Realm className="org.apache.catalina.realm.JDBCRealm" driverName="com.informix.jdbc.IfxDriver" connectionURL= "jdbc:informixsqli://mymachine:1526/stores_demo:INFORMIXSERVER=ol_myserver"; connectionName="informix" connectionPassword="mypasswd" userTable="users" userNameCol="username" userCredCol="password" userRoleTable="roles" roleNameCol="rolename"/>
Add security-constraint to WEB-INF/web.xml <security-constraint><web-resource-collection><web-resource-name>Authorization Test</web-resource-name><description>custAdmin role</description><url-pattern>/*</url-pattern><http-method>GET</http-method><http-method>POST</http-method><http-method>PUT</http-method><http-method>DELETE</http-method></web-resource-collection><auth-constraint> <description>These roles allowed</description> <role-name>custAdmin</role-name></auth-constraint> </security-constraint>
Add login-config and security-role to web.xml <login-config><auth-method>FORM</auth-method><realm-name>Protected Area</realm-name><form-login-config> <form-login-page>/login.jsp</form-login-page> <form-error-page>/loginerror.jsp</form-error-page> </form-login-config> </login-config> <security-role><description>custAdmin role only</description><role-name>custAdmin</role-name> </security-role>
Session Management • Once logged in, access user name with request.getUserPrincipal().getName(), e.g.<h3>Hello<%=request.getUserPrincipal().getName()%></h3> • Tomcat provides a “session” object, e.g.session.setAttribute("userName“,request.getUserPrincipal().getName());session.setAttribute("loggedIn", "1");if (session.getAttribute("loggedIn“).equals("1") { … }
Pagination Problem • Display output in pages, 10 rows at a time, with next and previous buttons. Solution • Use the IDS 10.0 SELECT SKIP offset option with FIRST e.g.select SKIP 20 FIRST 10 col1, col2 from tab1 • Keep a count of rows and pass the count as a parameter to the JSP program. Use parameter to dynamically generate the next SKIP value
Inserting Binary Files Problem • Insert binary files from a browser into an Informix database Solution • Use the Jakarta Commons FileUpload Package with the PreparedStatement.setBinaryStream() Method
Inserting Binary File – HTML Upload Form <form action="docupload.jsp" method="post" enctype="multipart/form-data"> <input type="file" name="docfile"/><input type="submit" name="Action" value="Upload"/> </form>
Inserting Binary File – Get FileInputStream <%@ page import="org.apache.commons.fileupload.*, java.io.* %> DiskFileUpload dfu = new DiskFileUpload();List fileItems = dfu.parseRequest(request);Iterator itr = fileItems.iterator();FileInputStream docstream = null; dfu.setSizeMax(10000000); // throw exception if > 10 Mb while(itr.hasNext()) { FileItem fi = (FileItem) itr.next(); if (!fi.isFormField()) { // only process files here, not form fields docfilename = fi.getName(); docsize = fi.getSize(); docstream = (FileInputStream) fi.getInputStream(); }
Inserting Binary File – Insert into Table if (docsize > 0) { // insert into document table String sqlStr = "insert into document values("'" + docfilename + "',?)“ PreparedStatement pstmt = conn.prepareStatement(sqlStr); pstmt.setBinaryStream(1, docstream, (int) docsize); pstmt.executeUpdate(); pstmt.close();}
Downloading Binary Files Problem • Select a binary file from a database and stream it to the browser Solution • Set content type to APPLICATION/OCTET-STREAM • Use the ResultSet.getBinaryStream() method
Downloading Binary Files <%@ page import="java.sql.*, java.io.*, " errorPage="error.jsp"%><% // Important – do not print linefeeds or text before streaming file..… String sqlStr = "select docdata from document where filename = " + docfilename;ResultSet rs = stmt.executeQuery(sqlStr);rs.next(); // set content typeresponse.setContentType("APPLICATION/OCTET-STREAM");response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\""); FileInputStream fileData = (FileInputStream) rs.getBinaryStream(1); // stream file to browserwhile ((i = fileData.read()) != -1) out.write(i);out.close(); %>
JSP Connection Pools • JSP applications can be slowed down by frequent connects/disconnects • Apache Tomcat comes with Jakarta Commons Database Connection Pool (commons-dbcp) • Straightforward to configure and use for most database systems
Creating an Informix JSP Connection Pool • Add a Context entry to conf/server.xml • Add a Resource reference to WEB-INF/web.xml • In application initialize Context and get DataSource from Context. • Get Connection object from DataSource
Connection Pool Example – Server.xml Add Context entry to $CATALINA_HOME/conf/server.xml …<Context path="/jspdemo" docBase=“jspdemo" debug="0" reloadable="true" crossContext="true"> <Resource name="jdbc/jspdemo" auth="Container" type="javax.sql.DataSource" maxActive="20" maxIdle="10" maxWait="1000" username="informix" password=“mypasswd" driverClassName="com.informix.jdbc.IfxDriver“ url="jdbc:informix-sqli://mymachine:1526/stores_demo:INFORMIXSERVER=ol_myserver"/> </Context>…. </Host>
Connection Pool Example – Web.xml Add Resource reference to: $CATALINA_HOME/webapps/myapp/WEB-INF/web.xml <?xml version="1.0" encoding="ISO-8859-1"?><web-app xmlns=http://java.sun.com/xml/ns/j2ee xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation=http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd version="2.4"> <resource-ref> <description>Informix Datasource example</description> <res-ref-name>jdbc/jspdemo</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth></resource-ref> </web-app>
Connection Pool – Application Changes <%@ page import="java.sql.*,javax.naming.*,javax.sql.*" errorPage="error.jsp"%> … <% // get database connectionContext initContext = new InitialContext();Context envContext = (Context) initContext.lookup("java:/comp/env");DataSource ds = (DataSource) envContext.lookup("jdbc/jspdemo");Connection conn = ds.getConnection();// replaces:// Connection conn = DriverManager.getConnection(url, user, passwd);…
What is AJAX? • Asynchronous JavaScript and XML • Dynamically update parts of an HTML page by means of JavaScript calls to server routines
AJAX Components • JavaScript function to call server routine via a browser independent XMLHttpRequest object • JavaScript processResponse() function to handle response from server and update page • Server routine to display updated data
AJAX Example – Triggering the Update Give an ID to the section of the page to update – in this case an HTML table column – the AJAX update is triggered here by moving the mouse over the column (onMouseOver) <tr> <td><b><%=city%></b></td> <td id="customer<%=custno%>"> <a href="javascript:custContact(<%=custno%>)" onMouseOver="javascript:custContact(<%=custno%>)"><%=company%></a> </td> </tr>
AJAX Example – XMLHttpRequest Object <script language="Javascript" type="text/javascript"> <!-- function createRequestObject() { // return appropriate request object for browser (Mozilla/IE) if (window.ActiveXObject) return new ActiveXObject("Microsoft.XMLHTTP"); else return new XMLHttpRequest(); } var xmlHttp = createRequestObject();
AJAX Example – Call Server Routines var elementId = ''; // AJAX call to display contact details for a customerfunction custContact(cust) { elementId = 'customer' + cust; xmlHttp.open('get', 'ccity_serv.jsp?cust=' + cust); xmlHttp.onreadystatechange = processResponse; xmlHttp.send(null);} // AJAX call to revert display to company namefunction closeContact(cust) { elementId = 'customer' + cust; xmlHttp.open('get', 'ccity_serv.jsp?closeCust=' + cust); xmlHttp.onreadystatechange = processResponse; xmlHttp.send(null);}
AJAX Example – Process Response // set ID tag to output from AJAX requestfunction processResponse() { if (xmlHttp.readyState == 4) { if (xmlHttp.status == 200) document.getElementById(elementId).innerHTML = xmlHttp.responseText; else document.getElementById(elementId).innerHTML = '<font color="red">Error: ' + xmlHttp.status + '</font>'; }} --> </script>
AJAX Example – Server Routines The server routines only display the HTML required to update the section of the page specified by the ID tag.. String cust = request.getParameter("cust"), closeCust = request.getParameter("closeCust"); if (cust != null) { … // execute select stmt to get contact details and display a table } else if (closeCust != null) {…// execute select stmt to get company name and display it }
AJAX Server Routine - Cust if (cust != null) { rs = stmt.executeQuery("select fname, lname, company, " + " address1, address2, city, state, zipcode from customer where " + "customer_num = " + cust); rs.next(); String comp = rs.getString("company").trim(); %> <table><tr><td> <table border=1><tr><td bgcolor="pink"><font size=+1> <%=rs.getString("fname")%> <%=rs.getString("lname").trim()%>,<br/> <%=comp%>,<br/> <%=rs.getString("address1").trim()%>,<br/> …
AJAX Server Routine - Cust <% if (rs.getString("address2") != null) { %> <%=rs.getString("address2").trim()%>,<br/> <% } %> <%=rs.getString("city")%><%=rs.getString("state")%> <%=rs.getString("zipcode")%></font> </td></tr></table></td><td> <a href="javascript:closeContact(<%=cust%>)" onMouseOver="javascript:closeContact(<%=cust%>)">Close</a></td></tr> </table> <% }
AJAX Server Routine - closeCust // re-display the original HTML showing customer name else if (closeCust != null) { rs = stmt.executeQuery("select company from customer where " + "customer_num = " + closeCust); rs.next(); String comp = rs.getString("company").trim(); %> <a href="javascript:custContact(<%=closeCust%>)" onMouseOver="javascript:custContact(<%=closeCust%>)"><%=comp%></a> <% }
Session I10 Java and IDS: Part 2 - JSP Guy Bowerman IBM Information Management guyb@us.ibm.com