The Friday Night Project #7 – A Console Veneer

UDA
The UDA channel is for Teradata’s Unified Data Architecture including the Analytical Ecosystem and other UDA influences. This channel provides information specific to the integration and co-existence of multiple systems, in particular when a mix of Aster, Teradata, and Hadoop are present. It is also meant to support information around the UDA enabling technologies so products like Viewpoint, Data Mover, Connectors, QueryGrid, etc.
Teradata Employee

The Friday Night Project #7 – A Console Veneer

In this session of the Friday Night Project we are finally going to create a Presentation Veneer that will use the Simple Quotation Engine business process we created last week.

However, don’t go getting all excited about MVC Web Pages, Portlets or Web services as we are going back to basics for this one with a plain old Command Line or Console Application interface. Think of it like “Basic Training” Toto, where we establish a usage pattern that we can apply across all further Presentation Veneers.

Quick Recap: TZA-Insurance operates as a Property Insurance Underwriter, allowing other Insurance Brokers to offer insurance services (insurance quotes and policies) to the final customer. The core proposition for the business is that we have a Quotation Engine that applies a set of Risk Factors to the property details associated with a given House or Apartment (Value, Size, Insurance level required etc) in order to generate a quotation. These Risk Factors can be managed based upon the physical location of the property (as defined by it's ZipCode) in order to allow the Quotation Engine to generate a quotation that reflects the risks present in a given area (higher Fire Risk in California balanced against higher risk of Flooding along the Mississippi Delta).

Create a Java Console application project.

Start up your Eclipse IDE (including the Teradata Plug-In) against your Friday Night Project Workspace.

Workspace Launcher

Once the IDE is started, create a New Project.

  • Select File -> New -> Project -> Java -> Java Project -> Next
  • In the New Java Project Dialog fill in the Project name: TZA-InsuranceConsole.

New Java Project

  • Select Next >
  • In the Java Settings dialog select the "src" directory and select "Remove source folder 'src' from build path".
  • Select the "Create a new source Folder" link.
  • Define the Folder name: as "src/java" and select Finish.
  • Repeat for the rest of the normal Source Folders we will use src/config and src/resources.
  • Finally change the Default Output folder to TZA-InsuranceConsole/build and select Finish.

New Java Project

Select Finish and Eclipse will build you a basic Java Console application whose file structure will look like this in the Project Explorer view:

Project Explorer Base

Create "/lib/runtime" directory.

Within a Console application where we wish to use external Libraries or JAR files we place them in a User Library directory (/lib/runtime) that can then be referenced as part of the Class Path of the application (Note the use of /runtime as we will actually execute this program hence we require the libraries that are required to build TZA-InsuranceConsole as well as all of the libraries required to operate this and any dependent libraries).

  • Right click on TZA-InsuranceConsole project and select New > Folder
  • Set the Folder name: = "lib/runtime" and Select Finish

New lib/runtime folder

Within the Project Explorer view the TZA-InsuranceConsole project with the "src/java", "src/config", "src/resources" and "lib/runtime" folders will look like this.

Project Folder with lib/runtime

Populate the TZA-InsuranceConsole Project.

We now start to populate the TZA-InsuranceConsole Project with elements such as the JDBC Driver JAR’s that allows us to access the Teradata Database.

When we need to add an external library such as commons-logging we can download a copy of the required library typically these downloads come as a large .ZIP or .TAR file that require you to extract the required jar files using an approach appropriate to your Operating System (such as WinZip on Windows), and save the required jar files to the /lib/runtime directory before adding them to the application classpath.

Add JDBC Driver

The first thing we do to populate the TZA-InsuranceConsole Project is add the necessary JAR files to the “lib/runtime” folder.

  • Add the Teradata JDBC Driver JAR’s you downloaded and used as part of the getting-started-with-teradata-plug-in-for-eclipse exercise.
  • Copy the two JAR files, namely tdgssconfig.jar and terajdbc4.jar from the download location (typically C:\TeraJDBC) and Paste them into the “lib/runtime” folder within the TZA-InsuranceConsole project.

Add Apache Commons JAR's

JAR's from the Apache Commons project (http://commons.apache.org/) are used in this and other projects for Logging and Database Connection Pooling.

Externally you need to download Apache Commons Pool, Apache Commons DBCP and Apache Commons Logging JAR's to the /lib/runtime directory of the project.

Apache commons-pool can be obtained from http://commons.apache.org/pool/.

  • Download the latest commons-pool.jar file to your local /lib/runtime directory.

Apache commons-dbcp can be obtained from http://commons.apache.org/dbcp/.

  • Download the latest commons-dbcp.jar file to your local /lib/runtime directory.

Apache commons-logging can be obtained from http://commons.apache.org/logging/.

  • Download the latest commons-logging.jar file to your local /lib/runtime directory.

Add Log4J.

Log4J is used to implement the Logging Interface used within commons-logging. Download the log4j package from http://logging.apache.org/log4j/1.2/download.html. Extract the latest log4j.jar file (at the time of writing this was Log4j.1.2.15.jar) to the /lib/runtime directory (i.e. C:\Projects\FridayNightProject\TZA-InsutanceConsole\lib\runtime).

  • Download the latest log4j.jar file to your local /lib/runtime directory.

Add tdcommons-context.

We use Context Capture to maintain a record of application context throughout the Thread of Execution. To utilize these Teradata Common Components download the tdcommons-context.ZIP file and export tdcommons-context.jar into the /lib/runtime directory of your project.

 

  • Select tdcommons-context.zip (Open with WinZip) and export tdcommons-context.jar into the /lib/runtime directory of the project.

Add tdcommons-access.

The Teradata Access approach is used to provide a consistent approach to accessing a Teradata Database through a JDBC based Data Source / Connection Pool. To utilize these Teradata Common Components download tdcommons-access.jar and save it to the /lib/runtime directory of your project.

  • Select tdcommons-access.zip (Open with WinZip) and export tdcommons-access.jar into the /lib/runtime directory of the project.

Add TZA-InsuranceProcess.

TZA-InsuranceProcess provides a utility JAR file that ultimately will contain all of the Business Processes used within TZA-Insurance (for now it only contains the Simple Quotation Engine).

  • Within the TZA-InsuranceProcess project Right Click on the TZA-InsuranceProcess.jar within the /dist directory and select Copy.
  • Paste this file into the /lib/runtime directory of the TZA-InsuranceConsole project.

Add spring-framework JAR

We will be using the spring-framework to wire our application together. Download the spring-framework from http://www.springframework.org/download and extract spring.jar into your /lib/runtime directory.

  • Right Click spring.jar and Save the file in the /lib directory of the project.

Refresh Eclipse

Whenever changes are made to the directory structure of an Eclipse Project (out with the Eclipse environment) it is necessary to let Eclipse know what is going on "under the covers".

  • Select the TZA-InsuranceConsole project and use the F5 function key to refresh the environment (alternatively Right Click on TZA-InsuranceConsole and select the Refresh option).

Create a User Library classpath reference to the JAR's in /lib/runtime

Once all the libraries (JAR files) have been added to the /lib/runtime directory they can be added to the project classpath within Eclipse, this allows Eclipse to make these classes available within the editing environment and compile all of the code without errors.

  • Right click on TZA-InsuranceConsole and select Build Path > Configure Build Path...
  • In the Properties for TZA-InsuranceConsole dialog select the "Libraries" tab -> Add Library... -> User Library
  • Select Next >, User Libraries..., New... and provide a User library name like InsuranceConsoleRuntimeLib.
  • Use the Add JARs.. button to browse to the TZA-InsuranceConsole/lib/runtime directory.
  • Add all the JAR files to the classpath (Use the Shift Key to select all the files at once).
  • Select Open to "Add" these to your 'InsuranceConsoleRuntimeLib' User Library.

Add User Library

  • Select OK, then Finish, then OK.

The InsuranceConsoleRuntimeLib and its associated JAR files will appear in Project Explorer like this.

Project Explorer User Lib

Create the Canary Quotation User Interface Veneer

The CanaryQuotation class acts as an entry point to the QuotationEngine Business Process where we take in a command line argument of the ZipCode to use and then construct a 'Canary' Property Details object that we can apply to the QuotationEngine.

Add Console Quotation Package

We start by adding a Java Package to the src/java folder to hold the Console Quotation classes (note this illustrates the concept of Cohesion where we group similar elements in a single place).

  • Create a new package within src/java (Right Click src/java -> New -> Package ->
  • Set the Name: = com.teradata.tza.insurance.console.quotation.

Add CanaryQuotation

The CanaryQuotation class is slightly different from the rest of the Interface and Implementation classes we create within the Friday Night Project in that it has a "main" entry point.

The main class definition (within CanaryQuotation) sets up the applicationContext used by the Spring Framework to wire all the POJO's together. The static loading of this class instantiates Spring using the com/teradata/tza/insurance/console/quotation/SqlApplicationContext.xml file held within the src/resources directory, which will be on the runtime classpath.

Start by creating a new class (CanaryQuotation.java) in package com.teradata.tza.insurance.console.quotation.

  • Right Click on src/java and select New -> Class
  • set the Package Name to "com.teradata.tza.insurance.console.quotation ".
  • Set the class Name to CanaryQuotation.
  • Select the method stub "public static void main(String[] args)".

New Java Class - CanarayQuotation

  • Click Finish and a template source file will open within the Eclipse editor.
package com.teradata.tza.insurance.console.quotation;

public class CanaryQuotation {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

}
}

The CanaryQuotation class can then be built up by replacing the template code with the following code segment within the CanaryQuotation.java file using copy and paste.

/** 
* The contents of this file are Teradata Public Content and have been released to the Public Domain.
* Please see the license.txt file in the top level directory for more information.
*
* @author Mike.Coutts@Teradata.com
*/
package com.teradata.tza.insurance.console.quotation;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.math.BigDecimal;

import com.teradata.commons.context.ApplicationDescription;
import com.teradata.commons.context.ThreadLocalContext;

import com.teradata.tza.insurance.process.exception.ApplicationException;
import com.teradata.tza.insurance.process.exception.SystemException;
import com.teradata.tza.insurance.process.businessObject.Ownership;
import com.teradata.tza.insurance.process.businessObject.Property;
import com.teradata.tza.insurance.process.businessObject.PropertyType;
import com.teradata.tza.insurance.process.quoteEngine.businessProcess.QuotationEngine;

/**
* CanaryQuotation Veneer into TZA-InsuranceConsole
*/
public class CanaryQuotation
{
/** Logger for this class **/
private static Log log = LogFactory.getLog(CanaryQuotation.class);

/**
* main entry point to the CanaryQuotation class
* @param args
*/
public static void main(String[] args)
{
// Setup applicationContext in order to use the Spring Framework
ApplicationContext applicationContext =
new ClassPathXmlApplicationContext("com/teradata/tza/insurance/console/quotation/SqlApplicationContext.xml");

// At first point of Application Entry initialize ThreadLocalContext
ThreadLocalContext.setClientUser(System.getProperty("USER"));
ThreadLocalContext.setGroup("TZA_BROKER");
ThreadLocalContext.setProxyUser("TZA_PROXY_USER");
ThreadLocalContext.setProxyRole("TZA_PROXY_ROLE");
ThreadLocalContext.setSource(CanaryQuotation.class.toString());
ThreadLocalContext.setAction("main");

// Use applicationDescription bean to get ApplicationName and Version
ApplicationDescription applicationDescription = (ApplicationDescription)applicationContext.getBean("applicationDescription");
ThreadLocalContext.setApplicationName(applicationDescription.getApplicationName());
ThreadLocalContext.setVersion(applicationDescription.getVersion());

// Validate the Input Parameter(s)
if ((args != null) && (args.length > 0) && (args[0] != null))
{
// Create the Canary House - Property Details
Property canaryHouse = new Property();
canaryHouse.setHouseNameNumber("A3-2203");
canaryHouse.setStreetAddress1("17095 Via Del Campo");
canaryHouse.setStreetAddress2("");
canaryHouse.setStreetAddress3("");
canaryHouse.setStreetAddress4("");
canaryHouse.setCity("San Diego");
canaryHouse.setState("CA");
canaryHouse.setOwnership(new Ownership(Ownership.Mortgaged));
canaryHouse.setNumBedrooms(2);
canaryHouse.setYearBuilt("1965");
canaryHouse.setPropertyType(new PropertyType(PropertyType.Condominium));
canaryHouse.setBuildingsAmountInsured(new BigDecimal(500000.00));
canaryHouse.setBuildingsCover(true);
canaryHouse.setBuildingsAccidentalCover(true);
canaryHouse.setContentsAmountInsured(new BigDecimal(50000.00));
canaryHouse.setContentsCover(true);
canaryHouse.setContentsAccidentalCover(true);
canaryHouse.setSingleItemLimit(new BigDecimal(5000));
canaryHouse.setAlarmed(true);
canaryHouse.setSecurityPatrolled(true);

// Add the Dynamic part of the canaryHouse PropertyDetails - the ZipCode from args[0]
canaryHouse.setZipCode(args[0]);

try
{
// Get the Quotation Engine to use from the applicationContext
QuotationEngine quotationEngine = (QuotationEngine)applicationContext.getBean("sqlQuotationEngine");

// Call the QuotationEngine to get a quotation for the canaryHouse
BigDecimal quotation = quotationEngine.getQuotation(canaryHouse);

log.info("Canary Quotation for " + args[0] + " = $" + quotation.setScale(2, BigDecimal.ROUND_HALF_EVEN));
}
catch (ApplicationException appEx)
{
log.error("Canary Quotation failed due to " + appEx);
}
catch (SystemException sysEx)
{
log.error("Canary Quotation failed due to " + sysEx);
}
}
else
{
log.error("Canary Quotation failed: invalid arguments");
}
} // end main

} // end CanaryQuotation

Within the CanaryQuotation Class we define a holder object for the QuotationEngine that we will be using and provide a setter for the ApplicationDescription property, the implementation of which will be provided at run time based upon the definition in the SqlApplicationContext.xml file.

The main() entry point for the application is defined and as soon as we enter the module we establish the ThreadLocalContext, setting up various aspects of the ThreadLocalContext with default information. The ApplicationDescription property is used to get static application information like the Application Name and version number. Note: some aspects of ThreadLocalContext such as the startTime property are set as an inherent part of accessing the class.

The input parameters are validated before we instantiate a PropertyDescription object and fill in the Canary House properties including the ZipCode from the args[0] property.

Finally we get the QuotationEngine (from the applicationContext provided by Spring) and use the Canary House details to get a quotation. The output of the Console Application is simply to log the results, or any exceptions, to the console.

If you expand the package within src/java your Project Explorer view should now look like this.

Project Explorer with src/java

Using the Spring Framework to wire the Presentation Veneer to the Business Process

The Spring Framework is usually associated with Java EE applications such as Dynamic Web applications, however, it can equally well be used to wire up the Java Objects in a Console application. Spring uses XML based configuration files to define which concrete implementation of a given Interface is to be used. It can also be used to include supporting libraries that your code may wish to use. In the Console Application we will use it to include the Apache DBCP Connection Pool (while this may seem excessive for a single run of a console application it is essential when we progress to Enterprise class Web applications that must maintain a Connection Pool to the database in order to operate in a responsive manner).

SqlApplicationContext.xml

As we will create a number of different versions of the Canary Quotation Console applications in the future (to demonstrate the use of Macros, Stored Procedures etc) we will deliberately separate out the specific part of the application context that relates to the CanaryQuotation class. This will also allow us to demonstrate how we can import one context file into another to help with Isolation.

Create a new package within src/resources

  • Right Click src/resources -> New -> Package ->
  • Set Package Name: = com.teradata.tza.insurance.console.quotation.

New Resource Package

Now add the SqlApplicationContext.xml file to this package.

  • Right Click src/resources -> New -> Other -> XML –> XML -> Next.
  • Browse the Parent folder tree to com/teradata/tza/insurance/console/quotation.
  • Set the File Name to SqlApplicationContext.xml

New XML File SqlApplicationContext.xml

  • Click Finish and a template source file will open within the XML Eclipse editor.
<?xml version="1.0" encoding="UTF-8"?>

The SqlApplicationContext.xml file can then be built up by replacing the template code with the following code segment within the SqlApplicationContext.xml file using copy and paste.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<!-- Main Interface Veneer - CanaryQuotation -->
<bean id="CanaryQuotation"
class="com.teradata.tza.insurance.console.quotation.CanaryQuotation">
</bean>

<!-- Import the base applicationContext -->
<import resource="classpath:applicationContext.xml" />

<!-- Import the TZA-InsuranceProcess SqlQuoteEngine context -->
<import resource="classpath:com/teradata/tza/insurance/process/quoteEngine/sqlQuoteEngineAppContext.xml" />

</beans>

This Application Context file is relatively simple for two reasons. Firstly the Canary Quotation application its self is fairly simple (we simply map the CanaryQuotation Been ID to the corresponding class), however, more importantly we can see how we can import both local Application Context information (classpath:applicationContext.xml) and remote Application Context information (classpath:com/Teradata/tza/insurance/process/quoteEngine/sqlQuoteEngineAppContext.xml). This illustrates our Isolation Principal where the TZA-InsuranceProcess.jar file provides the implementation of the QuotationEngine Interface as well as the means to configure its use.

ApplicationContext.xml

We must now provide the details of how we will "wire" up all of the Plain Old Java Objects (POJO's) and library resources that ultimately make up the full Console Veneer. As this will be common to this and future Console Veneers we define a single applicationContext.xml file (which can be imported into individual Application Context files as show above).

Start by adding a new XML file to the src/resources folder:

  • Right Click src/resources -> New -> Other -> XML –> XML -> Next.
  • Set the File Name to applicationContext.xml
  • Click Finish and a template source file will open within the XML Eclipse editor.
<?xml version="1.0" encoding="UTF-8"?>

The applicationContext.xml file can then be built up by replacing the template code with the following code segment within the applicationContext.xml file using copy and paste.

NOTE: There is a bug in the way the xsi:schemaLocation is displayed by this source viewer (it converts it to an HREF URL) the line should be as follows:

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<?xml version="1.0" encoding="UTF-8" ?> 
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- Define the ApplicationDescription -->
<bean id="applicationDescription" class="com.teradata.commons.context.ApplicationDescription">
<property name="applicationName" value="TZA-InsuranceConsole"/>
<property name="version" value="01.00.00.00"/>
</bean>

<!-- =================== Query Band Configuration Bean ============================== -->
<bean id="queryBandConfig" class="com.teradata.commons.access.QueryBandConfig">
<property name="queryBandingEnabled" value="${query-banding-enabled}"/>
</bean>

<!-- JDBC Teradata Access Object Session manager used by Quotation Processes -->
<bean id="jdbcTaoSessionManager"
class="com.teradata.commons.access.JdbcTaoSessionManager"
scope="prototype">
<property name="dataSource" ref="dataSource"></property>
<property name="queryBandConfig" ref="queryBandConfig"></property>
</bean>

<!-- Property Configurer used to bring in the JDBC.Properties -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>

<!-- dataSource Bean based on Apache Commons Database Connection Pool using JDBC properties -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="validationQuery" value="${dbcp.validationQuery}"/>
<property name="maxWait" value="${dbcp.maxWait}"/>
<property name="maxIdle" value="${dbcp.maxIdle}"/>
<property name="maxActive" value="${dbcp.maxActive}"/>
</bean>

</beans>

The file starts by referencing the springframework spring-beans.dtd, then defines the Thread Local Context support Beans applicationDescription and queryBandConfig. We then define the JDBC TAO Session Manager that will give us JDBC access to the database. The propertyConfigurer bean lets us split pure JDBC configuration information into it’s own jdbc.properties file while the dataSource bean description lets us setup our Apache DBCP based Connection Pool. Note we could have defined the dataSource as a pure JDBC connection as a Connection Pool is over kill in this situation (but it is useful to get into good habits from the start), we could have used an alternative Connection pool such as c3p0.

Configuring the JDBC Driver / Connection Pool

As mentioned above, we use a configuration file (jdbc.properties) to manage the properties of the JDBC Connections within the DBCP Connection Pool. To add this to the runtime class path you need to place the configuration file into the src/config folder of your project.

Create a new file and add the following code segments.

  • Right Click src/config -> New -> Other.. -> General -> File -> Next -> File
  • Set the File Name as jdbc.properties
  • Select Finish and a template source file will open within the Eclipse editor.

The jdbc.properties file can then be built up by replacing the template code with the following using copy and paste.

# Properties file with JDBC-related settings.
# Applied by PropertyPlaceholderConfigurer from "applicationContext.xml".
# Targeted at system administrators, to avoid touching the context XML files.

# Teradata Instance information -
server=Local-12
dbs.port=1025

# Name of the Default Database we are going to use
base.db=TZA_DB

# JDBC-related settings.
jdbc.driverClassName=com.teradata.jdbc.TeraDriver
jdbc.url=jdbc:teradata://${server}/DATABASE=${base.db},DBS_PORT=${dbs.port},TMODE=ANSI
jdbc.username=TZA_USER
jdbc.password=TZA_PASS

# query-banding-enabled
# Enables Query Banding. Use only for TD version 12 or higher.
query-banding-enabled=false

# DBCP-related settings.
dbcp.validationQuery=select current_timestamp
dbcp.maxWait=300
dbcp.maxIdle=10
dbcp.maxActive=50

Note you may need to change the server and dbs.port values to reflect your preferred Teradata instance.

Configuring Logging

TZA-InsuranceConsole uses a Log4j configuration file to manage what is logged and how. To add this to the runtime class path you need to place the configuration file into the src/config folder of your project.

Create a new file and add the following code segments.

* Right Click src/config -> New -> Other.. -> XML -> XML -> Next

* Set the File Name as log4j.xml

* Select Finish and a template source file will open within the Eclipse editor.

The log4j.xml file can then be built up by replacing the template code with the following using copy and paste.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">

<!--
Log4j boils down to 3 parts:

1. "Appenders" are objects that handle the "writing" of the logged message, like to
a file or the console display.

2. "PatternLayout" specifies what each logged event contains, similar to a format string.

3. "loggers" specify the specific classes to log, what level is logged (debug, info, etc) and
and which appenders to sent to.

Handy links:
The official home: http://logging.apache.org/log4j/docs/documentation.html
A pragmatic source, though a bit dated: http://www.vipan.com/htdocs/log4jhelp.html

=================================================================================
Appenders
This log4j.xml configuration file specifies several different appenders:

* a common file appender (DEFAULT) that can be sent all log events, written to the system.log.
* several module-specific file appenders; each appender specifies its output file path
* a "sockethub" appender which can send log events to remote log browsing app (Chainsaw) (commented out)
* the DEFAULT appender is a file appender that is currently configured to contain most detail. Chainsaw
can use this file as its "source"; there is a chainsaw-config.xml that specifies this file as a Chainsaw
receiver

Note: this is intended as a template. Each developer/tester/field person can and should modify this to
fit their needs. The "Threshold" attribute on each appender is the first place I would go to modify
logging detail: I would put the appenders that handle objects I don't care about to "ERROR" or "WARN"
(logging to file can be a performance drag, so minimize where possible), and put my module to "DEBUG" to
get more information.

Though you probably shouldn't need to, feel free to tweak other attributes of the appenders (see links
listed above).

PatternLayout
This specifies the format of the log event and is an attribute of the appender. (This doesn't impact
the Chainsaw SocketHubAppender; it's format is handled by the receiver on the socket connection).
You can tweak the format on appenders as you see fit, though some format items are performance drags
(noted below). Also, a Chainsaw LogFilePatternReceiver (defined in chainsaw-config.xml), defines
a format that needs to fit with the format of the DEFAULT log file appender.

Examples of various pattern format characters: =================================

Thread "name"
%t (example output: "Http-Processor25")

Dates:
%d{ABSOLUTE} (example output: "15:48:13,343")
%d{ISO8601} (example output: "2007-04-25 16:05:40,517")

Priority (level) padded to 5 spaces
%-5p (example output: "INFO ")

Message content:
%m

Source info, equivalent to %C.%M(%F:%L).
%l (Warning: potential performance drag)

FQ class/path
%C (example output: "com.teradata.trm.common.db.Query")

Class/package name, where n is an integer representing number of elements of class/pkg to display
(Warning: potential performance drag)
%C{n} (example output for %C{2}: "db.Query")

Method name (Warning: potential performance drag)
%M

Logger
%c

File name
%F (Warning: potential performance drag)

Source line number
%L (Warning: potential performance drag)

MDC parameters available:
%X{username}
%X{sessionId}
%X{url}

=================================================================================
loggers
Loggers specify what classes get logged at what level and sent to what appender(s).
They have an inheritance-like relationship, where logger named "com.x.y" inherits the
appenders of the logger "com". This will result in double output where both loggers have
the same "appender-refs", *unless* the additivity is set to "false". The "root" is like a
base logger, inherited by all loggers.

In this example, the logger "com.x.y" logs at DEBUG level and declares additivity=false to
prevent double logging to CONSOLE.

<logger name="com" additivity="false">
<level value="WARN" />
<appender-ref ref="DEFAULT"/>
<appender-ref ref="CONSOLE"/>
</logger>

<logger name="com.x.y" additivity="false">
<level value="DEBUG" />
<appender-ref ref="My-XY-Appender"/>
<appender-ref ref="CONSOLE"/>
</logger>

=================================================================================
Log levels (priorities) are symbols with numeric relationship, such that
TRACE > DEBUG > INFO > WARN > ERROR > FATAL

Enabling a certain level implies that all levels below it are also enabled.

Note: the loggers included here are intended as working examples. You should modify and add
loggers to fine-tune what you want to see (set level to DEBUG) and what you don't want to see (set
level to INFO, WARN, ERROR, etc).

========================================================================================================
-->

<!-- ==== Console display -->
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<param name="Threshold" value="DEBUG" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%t %d{ISO8601} %p [%m] %n" />
</layout>
</appender>

<!-- ==== Main system log file -->

<appender name="DEFAULT" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="dist/logs/system.log" />
<param name="Append" value="true" />
<param name="Threshold" value="DEBUG" />
<param name="MaxFileSize" value="10MB" />
<param name="MaxBackupIndex" value="10" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %p [%X{username}] [%t] [%c] [%m] %n" />
</layout>
</appender>

<!--
===== loggers ============================================
-->

<logger name="com">
<level value="INFO" />
</logger>

<logger name="org">
<level value="WARN" />
</logger>

<!-- MODULE loggers -->

<logger name="com.teradata.tza.insurance.console" additivity="false">
<level value="INFO" />
<appender-ref ref="CONSOLE"/>
<appender-ref ref="DEFAULT"/>
</logger>

<root>
<level value="INFO" />
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEFAULT" />
</root>

</log4j:configuration>


Refresh Eclipse

Whenever changes are made to the directory structure of an Eclipse Project (out with the Eclipse environment) it is necessary to let Eclipse know what is going on "under the covers".

  • Select the TZA-InsuranceConsole project and use the F5 function key to refresh the environment (alternatively Right Click on TZA-InsuranceConsole and select the Refresh option).

If you expand the src/config and src/resources directories your Project Explorer view should now look like this.

Project Explorer - Final View

Run Canary Quotation Console Application

In order to Run or Debug the CanaryQuotation we need to setup a Run Configuration.

  • From the main menu bar Select Run -> Run Configurations..
  • Select the Java Application and either double click or select the New Icon (give the configuration a name, say CanaryQuotation).
  • In the Main tab select the Browse button and select the Project: TZA-InsuranceConsole
  • Select the Search.. option to find the Main Class (com.teradata.tza.insurance.console.CanaryQuotation).

Run Configuration - Main

  • Switch to the Arguments tab and add program arguments such as "92127".

Run Configuration - Arguments

Select Apply to save the changes and select Run to run the new configuration. The Console Vener will start up with Log4j and TZA-InsuranceConsole output being sent to the console screen. There will be a delay as the Connection Pool establishes a set of connections with Teradata (remember for Web based applications this happens only once at startup). Once the connection pool is established the getQuotation method of the Simple Quote Engine business process will be able to find (within the ZipCodeRiskFactors table of TZA_DB) the Insurance Risk Factors associated with the input Zip Code so it can calculate the appropriate insurance quotation for a 'Canary' Property at that location. 

Console Output

You can experiment with different Zip Codes within the Program Arguments to get different quotes from the Quotation Engine or give it zero or invalid parameters to see the Exception Reports.


So this illustrates the code and resources necessary to build the simplest possible Presentation Veneer, while still conforming to all of our Architectural Principles. We have Isolation through the use of Interfaces and Implementations, wired together through the Spring Framework and XML Configuration. We have Cohesion by placing each code or resource element in an appropriate package. We provide for Workload Management by manually establishing the Thread Local Context as soon as we enter the Thread of Execution and by enabling Query Banding within the configuration.

All of the elements and concepts necessary to provide the infrastructure for a Web, Portlet or Web services application have now been brought together so next week we will give Toto something to really chew on as we go straight to a WS-I Web service.

3 REPLIES
Teradata Employee

Re: The Friday Night Project #7 – A Console Veneer

Hi Mike,

I'm finding this series an interesting way of finding my way around eclipse and in building up some knowledge of how to build java applications in a "safe" environment so thanks for that.

I had a number of errors when running the console application which were related to the xsi:schemalocation definitions in the xml context files. The formatting doesn't look right to me but I don't have sufficient knowledge to be sure. I tried various ways of formatting this but eventually resolved the issue (with the help of the Spring reference guide) by replacing the namespace and schema definitions with the much simpler -

"http://www.springframework.org/dtd/spring-beans-2.0.dtd">

This left just the bean declarations within the tags.

I might be using slightly different versions than you while building the example which would explain the errors but I thought I'd make the comment in case anyone else finds themselves stuck.

Cheers

Mike

Teradata Employee

Re: The Friday Night Project #7 – A Console Veneer

D'Oh ! Must remember that xml tags are interpreted on web pages and are not visible.

The inserted code is -

[!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd"]

replace the [] with "<>".
Teradata Employee

Re: The Friday Night Project #7 – A Console Veneer

There appears to be a bug in the way that the Spring applicationContext.xml file is displayed (the xsi:schemaLocation is displayed with an HREF URL added).

The line should be as follows:

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">