Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Professional Java.JDK.5.Edition (Wrox)

.pdf
Скачиваний:
31
Добавлен:
29.02.2016
Размер:
12.07 Mб
Скачать

Chapter 2

Element

Description

 

 

Repository

Source configuration management repository information

Versions

(Optional) Contains information on previous version releases

Branches

(Optional) Contains information on previous project branches

mailingLists

Contains mailing lists for project

Developers

Describes the committers to a project

Contributors

Describes contributors to a project

Licenses

Describes licenses for a project

Dependencies

Describes the dependencies of a project

Build

Describes the environment of a project

Reports

Describes the reports that should be included with distribution

Properties

Project properties that will be used

 

 

For the sake of brevity, this example will not include many of the project elements described above. As shown in the Ant example previously, consistency across your builds is a important goal for development operations. Maven will allow you to satisfy your build and deployment goals, like Ant, but with a different technique. This scenario will give you a small taste on how to implement Maven to automate your build activities (see Figure 2-6).

I need to automate my build processes for my web

Maven

 

 

 

 

 

applications so that I can hand it off to an operations person

 

 

 

and concentrate on my current task that is consuming most

 

 

 

of my time. How can I pull everything together to make my

maven.xml

 

file system:

life easier for deployments and ensure that builds are made

 

in a consistent fashion?

 

 

- java

 

 

 

 

- web components

 

project.xml

 

 

- tests

 

 

 

 

 

 

 

WAR / Tests

Developer

 

 

 

Figure 2-6

When you run this example, the target sequence will be war:init, war:web-app, followed by war:war when a user types in maven at the command line:

96

Tools and Techniques for Developing Java Solutions

<!-- maven.xml ‡ <project default=”war”

xmlns:j=”jelly:core”

xmlns:m=”maven”

xmlns:deploy=”deploy”>

</project>

The project descriptor, project.xml, dictates all of the relevant elements that will be utilized for the Web application build:

<!-- project.xml ‡ <?xml version=”1.0”?> <project>

<pomVersion>1</pomVersion>

<id>maven-war-example</id> <name>Maven Example</name> <currentVersion>1.0</currentVersion>

<package>org.apache.maven.examples.war</package>

The <dependencies> tag indicates what libraries are needed for the application build to be successful. The following example specifies dependencies with the log4j and servlet 2.3 libraries:

<dependencies>

<dependency>

<id>log4j</id>

<version>1.2.8</version>

<properties><war.bundle>true</war.bundle></properties>

</dependency>

<dependency>

<id>servletapi</id>

<version>2.3</version>

</dependency>

</dependencies>

The <build> tag indicates where the source and test code directories are on the file system for compilation and testing by JUnit test scripts:

<build>

<sourceDirectory>src/java</sourceDirectory>

<unitTestSourceDirectory>src/test/java</unitTestSourceDirectory>

<unitTest>

<resources><resource>

<directory>src/test/java</directory>

<includes><include>**/*</include></includes> <excludes><exclude>**/*.java</exclude></excludes>

</resource></resources>

<includes>

<include>**/*Test.java</include>

</includes>

</unitTest>

</build>

</project>

97

Chapter 2

You can generate a build script with countless operations to manipulate and package your applications for deployment. The table below specifies a few for consideration in your build coverage.

Target

Action

 

 

Maven clean

Clean up directories

Maven

Compile source code and build WAR file

Maven test

Compile code and run tests on it

 

 

JUnit

Countless books have been written about JUnit and its numerous library extensions. Their usefulness in testing applications does not need to be recounted, but it is important to remember, when developing these tests with JUnit tools, to consider the objectives behind your testing coverage.

Ideally, your tests will exercise the constraints of your deployment system. This generally means that valid/invalid inputs of application components (Textfield, RadioButton, and so forth) will be tested as well as data points on your system. This testing needs to have a complementary problem-tracking tool to support your iterative development practices and to ensure that problems have been recorded and addressed in a timely fashion.

JUnit incorporates the XP philosophy of testing continuously so that problems do not manifest themselves in the latter stages of your development activities, which will bog down deployment schedules.

The scenario described here is an all too often occurrence that can be handled with the use of JUnit test scripts that allow developers to better understand the current state of their code and where it needs to be (see Figure 2-7).

 

JUnit

 

I keep getting pestered about some code not working I

 

 

wrote several months ago and I have forgotten how it was

 

 

written because my current activites have consumed all of

 

JUnit test

my time and thinking. How can I quickly determine what the

 

suite

code does and see if other developers who work on the

Dev 1 Dev 12

 

same CVS repository have not introduced those problems

 

 

 

to that code?

 

 

 

code + tests

Test results

Good Bad

Developer

Figure 2-7

98

Tools and Techniques for Developing Java Solutions

The build.xml file runs two test scenarios, test1 and test2, after compiling the test code to ensure that your source code has not been corrupted by modifications to that code. Ideally, you would want to create a target in your build file to check out both the test and source code files from a common repository to ensure that your tests are being performed on working code that is being implemented in your development and deployments:

<?xml version=”1.0”?>

<project name=”junitTest” default=”test”>

<target name=”init”>

<property name=”test.dir” value=”.” /> </target>

<target name=”compile” depends=”init”>

<javac srcdir=”.” destdir=”.” classpath=”junit.jar” /> </target>

<target name=”test1” depends=”compile”> <echo message=”Running JUnit tests (1).” /> <junit printsummary=”true”>

<!-- <formatter type=”plain” usefile=”false” /> --> <formatter type=”xml” />

<test name=”TestScenarios1” /> <classpath>

<pathelement location=”.” /> </classpath>

</junit>

<junitreport todir=”.”> <fileset dir=”.”>

<include name=”TEST-*.xml” /> </fileset>

<report format=”frames” todir=”.” /> </junitreport>

</target>

<target name=”test2” depends=”compile”> <echo message=”Running JUnit tests (2).” /> <junit printsummary=”true”>

<!-- <formatter type=”plain” usefile=”false” /> --> <formatter type=”xml” />

<test name=”TestScenarios2” /> <classpath>

<pathelement location=”$(testdir}” /> </classpath>

</junit>

<junitreport todir=”.”> <fileset dir=”.”>

<include name=”TEST-*.xml” /> </fileset>

<report format=”frames” todir=”.” /> </junitreport>

</target>

</project>

99

Chapter 2

The TestScenarios1 test script reads the meta data affiliated with the employees table in the sample_project database and checks the attribute names of that table to ensure that someone has not corrupted the table itself. Alternatively, tests can be performed on database connections and the data that is stored in that table to ensure that bugs have not been introduced into the table:

import java.sql.*; import java.util.*;

import junit.framework.TestCase;

public class TestScenarios1 extends TestCase {

private static final String DRIVER=”org.gjt.mm.mysql.Driver”;

private static final String URL=”jdbc:mysql://localhost/project-sample”; private static final String USER=””;

private static final String PASSW=””;

private static final String QUERY=”Select * from employees”;

public DbTestCase(String name) {super(name);} public void noTestCase() {}

public void testCase() {} public void testCase(int arg) {}

void testCase1() {

try {

Class.forName(DRIVER);

// connect to the MySQL db

Connection conn = DriverManager.getConnection(URL, USER, PASS); Statement stmt = conn.createStatement();

ResultSet rslt = stmt.executeQuery(QUERY);

//Get the resultset meta-data ResultSetMetaData rmeta = rslt.getMetaData();

//Use meta-data to determine column #’s in each row int numColumns = rmeta.getColumnCount();

String[] s = new String[numColumns];

for (int i=1; i < numColumns; i++) { s[i] = rmeta.getColumnName(i);

}

// check to see if db columns are correct assertTrue(s[1].equals(“employee-id”)); assertTrue(s[2].equals(“employee-name”)); assertTrue(s[3].equals(“employee-salary”)); assertTrue(s[4].equals(“position-desc”)); assertTrue(s[5].equals(“start-date”)); assertTrue(s[6].equals(“end-date”)); assertTrue(s[7].equals(“conditions-of-discharge”));

100

Tools and Techniques for Developing Java Solutions

assertTrue(s[8].equals(“salary”));

// close connection conn.close();

}

catch(Exception e) {}

}

}

When automated JUnit tests discover that code does not do what requirements prescribe, or indicate that an error has been introduced into your build, developers can use these tests as a point of reference to discover what is wrong with code and rectify it in a procedural manner. The alternative is to code and fix on the fly without any process to ensure things have been rectified properly and hope that things work out in the end, which is not a promising practice.

XDoclet

XDoclet is a wonderful tool that can be downloaded from the SourceForge Web site at http:// xdoclet.sourceforge.net/ to ensure that consistencies are realized with your development operations. XDoclet can be especially helpful on projects that involve disparate sets of developers who are working from a common source code repository. Consider all the times you have halted your development activities because someone forgot to add entries in the deployment descriptor and included the code that refers to that entry or when the entry itself was delivered but the code was not checked in. That can be particularly frustrating during final deployment migrations. XDoclet can alleviate those occurrences because developers can embed their mapping in their code and build files can parse through that code to generate the appropriate mappings needed for deployment. Additionally, extraneous mappings can be appended to the deployment descriptor (web.xml) by making entries in servlets.xml and servlet-mappings.xml. This scenario appends JavaServer Page mappings to the deployment descriptor through the servlets.xml file for browser visualization (see Figure 2-8).

 

XDoclet (Hibernate / Middlegen)

 

I need to make updates to my database and my web

 

 

Create database mapping files from Middlegen(*.hbm.xml)

applications that access data from the tables that need

 

 

modifications, but I’m afraid it may mean so much work

 

 

 

 

that my schedule will slip. What tools can I use to

 

 

facilitate these activities?

Step 1

 

 

 

 

Database

Step 2

 

 

Create domain objects from database mapping files using

Hibernate extensions

Developer

Figure 2-8

101

Chapter 2

You can implement the following script to properly map your servlet and JSP entries in your deployment descriptor using the XDoclet libraries. Naturally, the first part of your script outlines the properties needed for file transfer, manipulation, and packaging:

<?xml version=”1.0” encoding=”UTF-8”?>

<project name=”XDoclet servlet/jsp” default=”build-war” basedir=”.”>

<description>XDoclet script generation for Servlets/JSPs</description>

<property name=”app.name” value=”resubmit”/>

<property name=”src.dir” location=”src”/> <property name=”build.dir” location=”build”/> <property name=”dist.dir” location=”dist”/> <property name=”lib.dir” location=”lib”/> <property name=”merge.dir” location=”mergeDir”/>

<property name=”generated.dir” location=”generated”/>

<property name=”web.deployment.dir” location=”${generated.dir}/webdeployment”/> <property name=”xdoclet.lib.dir” location=”xdocletlib”/>

<path id=”compile.path”>

<fileset dir=”${lib.dir}” includes=”*.jar”/> </path>

<path id=”xdoclet.lib.path”>

<fileset dir=”${lib.dir}” includes=”*.jar”/>

<fileset dir=”${xdoclet.lib.dir}” includes=”*.jar”/> </path>

The clean target is typically used to clean up operations prior to operations so that a clean slate can be worked on without having to worry about residual files corrupting processing activities. The target block also creates new directories for file transfer and deployment once the previous directories have been purged from the file system:

<target name=”clean”>

<delete dir=”${gen.src.dir}/org”/> <delete dir=”${web.deployment.dir}”/> <delete dir=”${build.dir}”/>

<delete dir=”${dist.dir}”/> <delete dir=”${generated.dir}”/> <mkdir dir=”${build.dir}” />

<mkdir dir=”${build.dir}/WEB-INF” />

<mkdir dir=”${build.dir}/WEB-INF/classes” /> <mkdir dir=”${build.dir}/WEB-INF/lib” />

</target>

The generate-web target implements the WebDocletTask libraries to parse the servlet source file to strip the servlet’s mapping attributes. Once that has been performed, the Ant script copies the deployment descriptor to the /WEB-INF directory of the Web application and the JavaServer Pages to the Web directory:

102

Tools and Techniques for Developing Java Solutions

<target name=”generate-web”>

<taskdef name=”webdoclet” classname=”xdoclet.modules.web.WebDocletTask” classpathref=”xdoclet.lib.path”/>

<webdoclet destdir=”${build.dir}/WEB-INF/classes” mergeDir=”${merge.dir}”> <fileset dir=”${src.dir}”>

<include name=”**/*.java” /> </fileset>

<deploymentdescriptor destdir=”${web.deployment.dir}” distributable=”false”

/>

</webdoclet>

// copy files to appropriate directories

<copy todir=”${build.dir}/WEB-INF”> <fileset dir=”${web.deployment.dir}”>

<include name=”**/*.xml” /> </fileset>

</copy>

<copy todir=”${build.dir}”> <fileset dir=”${basedir}/web/jsp”>

<include name=”**/*.jsp” /> </fileset>

</copy>

</target>

The compile target is invoked from the build-clean target. This compiles the source code so that it can be properly packaged for deployment:

<target name=”compile” depends=”generate-web”>

<javac destdir=”${build.dir}/WEB-INF/classes” classpathref=”xdoclet.lib.path”> <src path=”${src.dir}”/>

</javac>

</target>

The package target creates a Web ARchive file (WAR) for distribution. Ideally, you could build a target to deploy the WAR file to your application server’s Web container for execution:

<target name=”package” depends=”generate-web”>

<jar destfile=”${build.dir}/${app.name}.war” basedir=”${build.dir}”/> </target>

<target name=”build-clean” depends=”clean,compile”/> <target name=”build-war” depends=”build-clean,package”/>

</project>

The next scenario is common for many distributed system applications that use Hibernate as their Object/Relational (O/R) tool to gain access to back-end data with domain objects (see Figure 2-9).

103

Chapter 2

I know I have to integrate my web applications with the other team member’s components. How can I ensure that my modifications to the deployment descriptor (web.xml) properly migrate for deployment without stepping on other’s development activities?

Developer

Additional mappings

servlets.xml

<servlet> <servlet-name>form</servlet-name> <jsp-file>/ticketForm.jsp</jsp-file>

</servlet>

servlet-mappings.xml

XDoclet

Servlet

@web.servlet name="ControllerServlet: @web.servlet-init-param name="id" value="id" @web.servlet-mapping url-pattern="/ControllerServlet"

web.xml

<servlet> <servlet-name>ControllerServlet</servlet-name> <servlet-class>book.ControllerServlet</servlet-class>

<init-param> <param-name>id</param-name> <param-value>id</param-value>

</init-param>

</servlet>

<servlet-mapping> <servlet-name>ControllerServlet</servlet-name> <url-pattern>/ControllerServlet</url-pattern>

</servlet-mapping>

Figure 2-9

The DOCTYPE script uses XML entity references to include the test.xml fragment where the script includes an &database reference. As in all of these scripts, property settings precede the targets’ entries to ensure proper paths are specified prior to file manipulation and migration:

<?xml version=”1.0”?> <!DOCTYPE project [

<!ENTITY database SYSTEM “file:./config/database/test.xml”>

]>

<project name=”Middlegen Hibernate” default=”all” basedir=”.”>

<property file=”${basedir}/test.properties”/>

<property name=”name” value=”test”/>

 

<property environment=”env”/>

 

<property name=”build.dir”

value=”${basedir}/build”/>

<property name=”lib.dir”

value=”${basedir}/lib”/>

<property name=”src.dir”

value=”${basedir}/src”/>

<property name=”build.java.dir”

value=”${build.dir}/java”/>

<property name=”build.gen-src.dir”

value=”${build.dir}/gen-src”/>

<property name=”build.classes.dir”

value=”${build.dir}/classes”/>

104

Tools and Techniques for Developing Java Solutions

&database;

<property name=”datasource.jndi.name” value=”${name}/datasource”/>

The path id element is created so that similar path-like structures can be used for one or more tasks. The <path> element is placed at the same level as targets in your script, and they are referenced via their id attribute:

<path id=”lib.class.path”>

<pathelement path=”${database.driver.classpath}”/> <fileset dir=”${lib.dir}”>

<include name=”*.jar”/> </fileset>

<fileset dir=”${basedir}/middlegen-lib”>

<include name=”*.jar”/> </fileset>

<fileset dir=”${build.gen-src.dir}”> <include name=”**/*.hbm.xml”/>

</fileset>

</path>

The middlegen target runs the Middlegen application that opens up a user-specified database and creates mappings of its tables. Table mappings contain *.hbm.xml extensions. Once these are created, then the hbm2java target can run to generate *.java domain object files to access your database:

<target name=”middlegen” description=”Run Middlegen”>

<mkdir dir=”${build.gen-src.dir}”/> <taskdef

name=”middlegen”

classname=”middlegen.MiddlegenTask”

classpathref=”lib.class.path”

/>

<middlegen appname=”${name}” prefsdir=”${src.dir}” gui=”${gui}”

databaseurl=”${database.url}” initialContextFactory=”${java.naming.factory.initial}” providerURL=”${java.naming.provider.url}” datasourceJNDIName=”${datasource.jndi.name}” driver=”${database.driver}” username=”${database.userid}” password=”${database.password}”

schema=”${database.schema}” catalog=”${database.catalog}”

>

<hibernate destination=”${build.gen-src.dir}”

105

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]