1.27k likes | 1.28k Views
Using Open Source in Java Projects. Jay Sissom jsissom@indiana.edu. Agenda. Expectations Why Open Source Tools Overview Example Application Open Source Tools Ant jRelational Framework Struts jUnit Summary. Expectations. You will NOT be a pro on these tools in 3-1/2 hours!
E N D
Using Open Source in Java Projects Jay Sissom jsissom@indiana.edu
Agenda • Expectations • Why Open Source • Tools Overview • Example Application • Open Source Tools • Ant • jRelational Framework • Struts • jUnit • Summary
Expectations • You will NOT be a pro on these tools in 3-1/2 hours! • You will NOT learn Java today • You will get an idea of how these tools can work in your environment • You will take home a CD with a copy of all the libraries and samples we are using today
Why Use Open Source • Arguments Against Open Source • “No one to sue” • “You get what you pay for” • “No vendor support”
Why Use Open Source • Arguments For Open Source • Why re-invent the wheel? • No $$$ expenditures • Great support via internet (mostly) • Source is available to review design • You may be able to resolve problems faster than a vendor would
Open Source Tools Overview • Ant – automated source code building tool (make for Java) • jRelational Framework – Object to database mapping framework • jUnit – Unit testing framework • Struts – Model/View/Controller user interface framework
Other Open Source Tools • Log4j - Logging • Hsql – 100% Java relational database • Tomcat – Web server, Servlet container • NetBeans – IDE for Java These are just the tip of the iceberg!
Example Application • Personal Address Book Application • Lookup people in an LDAP directory (or database) • Add personal notes for people • Web based user interface • Built with ant, using Struts and jRelational Frameworks, tested with jUnit • Thanks to Southern Illinois University for the use of their LDAP directory for this example.
Example Application (continued) Total Cost: $0 • Tools used in application • Sun JDK 1.4.1 • jRelational Framework 1.7 • Struts 1.0.2 • Hsql Java database • Log4j Logging • Tomcat Servlet container • Ant 1.5 to build application • jUnit 3.8.1 for testing • NetBeans Java IDE (optional) • LDAP directory (optional)
What is Ant? • Tool to Build an application • Similar to the make utility on Unix systems • Written in Java • Configured using XML
What’s wrong with make? • File format difficult to use • Not platform independent • Relies on shell scripts for complex tasks that can be even LESS platform independent • Starting a JVM is time consuming
Ant to the rescue • Ant uses XML for the file format • Ant is a Java application • The JVM starts once and is used for all tasks (unless you tell it not to) • Complex tasks can be written in Java for operating system independence
Example Ant Build File <?xml version=“1.0”?> <project name=“Simple Buildfile” default=“compile” basedir=“.”> <property name=“src.dir” value=“src”/> <property name=“classes.dir” value=“classes”/> <property name=“build.dir” value=“build”/> <target name=“prepare”> <mkdir dir=“${classes.dir}”/> <mkdir dir=“${build.dir}”/> </target> <target name=“compile” depends=“prepare” description=“Compile Code”> <javac srcdir=“${src.dir}” destdir=“${classes.dir”/> </target> <target name=“jar” depends=“compile” description=“Build JAR file”> <jar jarfile=“${build.dir}/output.jar” basedir=“$classses.dir”/> </target> <target name=“clean” description=“Clean compiled code”> <delete dir=“${build.dir}”/> <delete dir=“${classes.dir}”/> </target> <target name=“all” depends=“clean,jar” description=“Builds everything”/> </project>
Build file components - project • Provides: • Name of the project • Default target to use if none are specified • Base directory for project • One per build file • This component holds targets • Example: <project name=“My Killer App” default=“compile”> … </project>
Build file components - target • A target is one unit of work • A target contains one or more task • A target can depend on other targets • Example: <target name=“compile” depends=“prepare”> … </target>
Build file components - task • A task actually does some work • Each task takes it’s own set of parameters • You can write your own tasks in Java if necessary • Example tasks that come with ant: • mkdir, delete, javac, javadoc, jar, war, ear, cvs, mail, unzip
Build file components - task • Tasks that come in the optional.jar file • cab – create a .cab file • csc – compile c# code • ftp – ftp files • junit – run junit tests • rpm – builds a Linux rpm • There are lots more!
Build file components – other • Property • A name-value pair • <property name=“build.dir” value=“build”/> • Use ${build.dir} to reference it
Build file components - other • Path and File lists <path id=“classpath”> <fileset dir=“${lib.dir}”> <include name=“activation.jar”/> <include name=“serlvet.jar”/> </fileset> </path> <path id=“second_classpath”> <fileset dir=“${lib.dir}”> <include name=“**/*.jar”/> <exclude name=“junit.jar”/> </fileset> </path>
Running ant • Command line: • ant target • Used if your build file is named build.xml in the current directory • ant –buildfile filename target • Used if your build file isn’t named build.xml or in a different directory • Run from within a supporting IDE
Example Program Directory Structure (root) src properties test ldap testclasses dist javadoc WEB-INF lib classes
Example ant script – init target <target name="init"> <property file="../build.compile.ant.properties"/> <property name="webapp" value="ldap"/> <property name="classes" value="${webapp}/WEB-INF/classes"/> <property name="lib" value="${webapp}/WEB-INF/lib"/> <property name="src" value="src"/> <property name="test" value="test"/> <property name="testclasses" value="testclasses"/> <property name="properties" value="properties"/> <property name="dist" value="dist"/> …
Example ant script – init target … <!--- Path to compile the application --> <path id="compile.classpath"> <!-- Include all elements that Tomcat exposes to applications --> <pathelement location="${catalina.home}/common/classes"/> <fileset dir="${catalina.home}/common/lib"> <include name="*.jar"/> </fileset> <!-- Application specific lib files --> <fileset dir="${lib}"> <include name="**/*.jar"/> </fileset> </path> …
Example ant script – init target … <!-- Path to test the application --> <path id="test.classpath"> <path refid="compile.classpath"/> <pathelement location="${testclasses}"/> <pathelement location="${classes}"/> </path> </target>
Example ant script – compile target <target name="compile" depends="init" description="Compile"> <mkdir dir="${classes}"/> <javac debug="true" deprecation="true“ destdir="${classes}" srcdir="${src}"> <classpath refid="compile.classpath"/> </javac> </target>
Example ant script - testcompile <target name="testcompile" depends="compile“ description="Compile Tests"> <mkdir dir="${testclasses}"/> <javac debug="true" deprecation="true“ destdir="${testclasses}" srcdir="${test}"> <classpath refid="test.classpath"/> </javac> </target>
Example ant script - javadoc <target name="javadoc" depends="init" description="Javadoc"> <mkdir dir="apidoc"/> <javadoc destdir="apidoc" packagenames="edu.*"> <sourcepath> <pathelement location="${src}"/> </sourcepath> <classpath refid="compile.classpath"/> </javadoc> </target>
Example ant script - dist <target name="dist" depends="init,compile“ description="Build Distribution File"> <mkdir dir="${dist}"/> <jar jarfile="${dist}/ldap.war" basedir="${webapp}"> <exclude name="WEB-INF/lib/junit.jar"/> </jar> </target>
Example ant script - all <target name="all" depends="init,dist" description="Build everything."> <echo message="Application built"/> </target>
Example ant script - test <target name="test" depends="init,compile,testcompile“ description="Junit tests"> <java fork="yes" classname="junit.textui.TestRunner“ taskname="junit" failonerror="true"> <arg value="edu.iu.uis.sit.ldapsearch.test.AllTests"/> <classpath refid="test.classpath" /> </java> </target>
Example ant script - clean <target name="clean" depends="init" description="Clean all build products"> <delete dir="${classes}"/> <delete file="${dist}/ldap.war"/> <delete dir="apidoc"/> <delete dir="${dist}"/> <delete dir="${testclasses}"/> </target>
Ant Summary • Allows developers to build the application consistently no matter what environment, operating system
jRelational Framework (jrf) • Open Source Framework • Object/Database mapping Framework • Automates most of SQL programming • Tables look like objects to programmers
jrf Provides • Object-to-relational mapping for: • Sequenced primary keys • Natural primary keys • Compound primary keys • Insertion of a new object instance into the database. • Updating of existing object instances. • Deleting of existing object instances. • Finding of persistent instances by primary key. • Finding all persistent instances. (Finding all rows in a table). • Finding of a portion of persistent instances that match an application-specific criteria. • Augmentation of persistent object instances with columns from other tables (Joining of tables).
jrf Provides • Aggregation - creation of multiple objects from one result set. • Flexibility to define custom SQL queries for specialized searches. • Database independent validation of objects based on the metadata defined in the AbstractDomain subclass. (i.e. REQUIRED and UNIQUE field constraints). • Database independent defaulting of attribute values when updating and selecting from the database. • Optimistic locking of an object/row using a Timestamp or Integer column. When conflicts occur, an ObjectHasChanged exception is thrown by the framework. • Linking of related objects at retrieval time through the use of a postFind() method.
jrf Provides • Plenty of "hooks" by which you can customize your object before saving, after saving, after finding, etc... • Compatible with database triggers that change the tables. • Generation of basic PersistentObject and AbstractDomain subclasses from an existing database (using the jrf-extras jar). • Connection pooling (Either via the included JDBCHelperPool or via your application server pooling).
Object Mapping • Each RDBMS table is mapped to two objects • Persistent Object (or Entity Object) which represents one row • Domain Object which represents the entire table
Entity Object • Is a JavaBean • Has a property for every column in a table • The setter method must contain a call to this.markModifiedPersistentState(); • Each property MUST be a Java Object, not a built in java type • Parent object is com.is.jrf.PersistentObject
Domain Object • Represents an entire table • Has a method to return lists of all rows • Has a method to return a single row via the primary key • Has a method to return a list of rows based on a specified where clause • Has method to add, update or delete single row • Parent object is com.is.jrf.AbstractDomain • A Domain object can have “hooks” for various events in the object lifecycle
JDBCHelper • JDBCHelper is the jrf class to wrap a JDBC driver • You’ll need to work with JDBCHelper any time you talk to the database • JDBCHelpers will also let you manage database transactions
Creating a Domain Object • Create a subclass of com.is.jrf.AbstractDomain • Implement a protected void setup() method which should • set the DatabasePolicy • set the table name • Add Column specs for each column
Creating a Domain Object • Override the newPersistentObject method and return a new instance of your entity object
Column Specs • Each column in the table needs to be defined in the setup method of the Domain object • There are ColumnSpec objects for many different data types: • StringColumnSpec • IntegerColumnSpec • LongColumnSpec
Column Specs • The constructor for a xColumnSpec object needs the following parameters: • column name • getter method name • setter method name • default value • zero or more options
Column Specs – default value • Default Value constants • DEFAULT_TO_NULL • DEFAULT_TO_EMPTY_STRING • DEFAULT_TO_ZERO (Integer only) • DEFAULT_TO_ONE (Integer only) • DEFAULT_TO_NOW • DEFAULT_TO_TRUE • DEFAULT_TO_FALSE
Column Specs - options • Option constants • SEQUENCED_PRIMARY_KEY • NATURAL_PRIMARY_KEY • OPTIMISTIC_LOCK • REQUIRED • UNIQUE • Max of 3 options • Primary key options shouldn’t be used with other options (Required & Unique assumed)
Column Specs • The Domain object has a method called addColumnSpec that lets you add each Column Spec object this.addColumnSpec(new StringColumnSpec(“user_nm”, ”getUser_nm”,”setUser_nm”, DEFAULT_TO_EMPTY_STRING,REQUIRED)
Finders • Finders allow you to retrieve lists of rows that meet certain requirements • jrf supplies a finder by primary key, a finder for all rows, and one for a where clause • You’ll need to write additional ones • Finder methods belong in the Domain object
Finders • Example Finders • findByUserNm(String user_nm) • findByID(Integer id) • findByAccount(String fin_coa_cd, String account_nbr) • findNamesStartingWith(String s)
Finders • jrf provides a findWhere method • Example findByUserNm method public List findByUserNm(String user_nm,JDBCHelper j) { String user = JDBCHelper.delimitString(user_nm,”’”); return this.findWhere(this.getTableAlias() + “.user_nm = ” + user,j); }