Hiển thị các bài đăng có nhãn Oracle. Hiển thị tất cả bài đăng
Hiển thị các bài đăng có nhãn Oracle. Hiển thị tất cả bài đăng

Thứ Hai, 22 tháng 7, 2013

Groovy Sql and Oracle 'Invalid column index' SQLException

There are some minor potential dangers associated with Groovy's def keyword. The Groovy style and language feature guidelines for Java developers provides some warnings about use of def. In this blog post, I demonstrate an advantage of being more explicit in typing when using Groovy SQL with an Oracle database to avoid a potential "Invalid column index" SQLException because I've run into this issue a few times.

The following Groovy script provides comments on Oracle database tables matching a provided search string. In this case, what the script does is not as important as look at the code that defines the SQL query string (lines 18-21).

searchDbComments.groovy (using def without String typing or as String)

#!/usr/bin/env groovy
// searchDbComments.groovy

this.class.classLoader.rootLoader.addURL(
new URL("file:///C:/oraclexe/app/oracle/product/11.2.0/server/jdbc/lib/ojdbc6.jar"))

if (args.length < 1)
{
println "USAGE: searchDbComments.groovy <searchString>"
System.exit(-1)
}

def searchString = args[0].toUpperCase()

import groovy.sql.Sql
def sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:xe", "hr", "hr",
"oracle.jdbc.pool.OracleDataSource")
def dbTableCommentsQry = """
SELECT table_name, table_type, comments
FROM user_tab_comments
WHERE UPPER(comments) LIKE '%${searchString}%'"""

sql.eachRow(dbTableCommentsQry)
{
println "${it.table_name} (${it.table_type}): ${it.comments}"
}

When the above code is executed, the following error is generated:


WARNING: Failed to execute:
SELECT table_name, table_type, comments
FROM user_tab_comments
WHERE UPPER(comments) LIKE '%?%' because: Invalid column index

Caught: java.sql.SQLException: Invalid column index

java.sql.SQLException: Invalid column index
at oracle.jdbc.driver.OraclePreparedStatement.setStringInternal(OraclePreparedStatement.java:5303)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:8323)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8259)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:9012)
at oracle.jdbc.driver.OraclePreparedStatement.setObject(OraclePreparedStatement.java:8993)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:230)
at searchDbComments.run(searchDbComments.groovy:23)

Addressing the "invalid column index" SQLException is easy. One solution is to change the "def" on lines 18-21 to an explicit "String" type. Another solution, shown in the next code listing, is to use Groovy's "as" coercion keyword to explicitly allow the "def" to be used and have the dbTableCommentsQry variable be typed as a String.

searchDbComments.groovy (using as String)

#!/usr/bin/env groovy
// searchDbComments.groovy

this.class.classLoader.rootLoader.addURL(
new URL("file:///C:/oraclexe/app/oracle/product/11.2.0/server/jdbc/lib/ojdbc6.jar"))

if (args.length < 1)
{
println "USAGE: searchDbComments.groovy <searchString>"
System.exit(-1)
}

def searchString = args[0].toUpperCase()

import groovy.sql.Sql
def sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:xe", "hr", "hr",
"oracle.jdbc.pool.OracleDataSource")
def dbTableCommentsQry = """
SELECT table_name, table_type, comments
FROM user_tab_comments
WHERE UPPER(comments) LIKE '%${searchString}%'""" as String

sql.eachRow(dbTableCommentsQry)
{
println "${it.table_name} (${it.table_type}): ${it.comments}"
}

Using "def" only or no "def" with no type at all leads to the above error. Explicitly defining the String variable used in the query either via static typing or via use of "as" keyword allows the code to execute properly. One could use a static typing with "def", but that is thought to be redundant.

There is nothing necessarily wrong about using "def," but one does need to be careful with its application. Guillaume Laforge has written that "def is fine in method bodies or for particular dynamic aspects, but for everything that is a 'contract' (method signatures, properties, etc), it's better to use explicit types."

Thứ Năm, 14 tháng 2, 2013

Miscellaneous Musings about RMOUG Training Days 2013

I was only able to attend a portion of Rocky Mountain Oracle Users Group (RMOUG) Training Days 2013, but this was my 13th year to attend all or part of this conference (and my 11th year presenting). I have always enjoyed meeting and talking to the people who attend even as my interests have diverged somewhat from the database-focus that formerly aligned so well for me with the conference. As I have posted on before, this year's conference had a lot of focus on mobile application development in addition to the normal breadth and depth of database-oriented topics. In this post, I look at some of the excellent questions (and my responses) I was asked at my presentation on JavaFX and Groovy and look at some other things I learned while attending.

RMOUG Training Days 2013

JavaFX and Groovy

I started my session at 2:45 pm with about 10 people in attendance, but the audience reached about 25 people in size by the end. It was another good RMOUG Training Days audience with good questions that made me think they were understanding what I was trying to convey. I'll address some of those questions with my responses now.

One audience member asked how it worked in the JavaFX example that the overridden start method was never called from the static main function of the application. I explained that the same application class extends javafx.application.Application and, thanks to that inheritance, the start(Stage) method is invoked automatically as part of the JavaFX application lifecycle. That start(Stage) method is declared abstract in Application so concrete child implementations must inherit it. Only a call to one of the Application.launch methods was seen in my example, but the start(Stage) method overridden in the child class gets called via polymorphism during the application's execution.

Another question asked in my presentation had to deal with Oracle's use of JavaFX in their own tooling options such as JDeveloper, Oracle ADF, and the like. I obviously do not know the extent of this, but I was happy to speculate that Oracle would like to use JavaFX in more internal tools to leverage their investment in it. One attendee wondered if some of the Oracle ADF-based mobile applications shown in other sessions of this conference used JavaFX underneath. I don't know enough about that to confirm that.

Although I did not demonstrate it in my presentation, I did mention the availability of SceneBuilder. I also mentioned that while other IDEs such as JDeveloper can support JavaFX, NetBeans appears to be the current leader in JavaFX support.

One or two questions surrounded JavaFX's place in the competitive landscape. I attempted to contrast it with Flex, Silverlight, HTML5, Swing, other languages' graphics libraries, and other native mobile development platforms. In some ways, the determination of what JavaFX is competing against is based on how one wants to use it. In desktop applications, the most common "competitors" are pure Swing (without JavaFX), pure SWT (without JavaFX), Adobe AIR, and other languages' graphical libraries. In web application, obvious "competitors" are HTML5/jQuery and Flex. On mobile applications, obvious competitors include the web stack as well as native languages such as Objective-C for the iOS devices. It could be argued that it's a good thing that JavaFX has or soon will have so many different platforms to compete on, giving JavaFX developers flexibility to apply their skills easily to multiple platforms.

I talked about GroovyFX's support for concurrency as provided in the javafx.concurrent package and I referenced the Concurrency in JavaFX article. An audience member asked about Groovy's support for concurrency. I responded to this by briefly discussing gpars and explaining that gpars (Groovy Parallel Systems) is now bundled with Groovy (since Groovy 1.8).

Additional questions were asked that were, I thought, insightful, but I am not talented enough to write them down and respond to them at the same time and have now temporarily forgotten some of the others.

Before leaving coverage of my own presentation, I want to include two slides that I showed in the presentation and in a "slide show" that I had running while waiting for the start time to arrive. These slides summarize some key moments in the history of JavaFX and history of Groovy.

Thinking back upon the history of JavaFX and Groovy, it is easy to see some similarities between the two. Both started with significant enthusiasm that then seemed to wane for a while before resurgent interest and coming back stronger than ever. It seems to me that SpringSource has been a pivotal player in providing stability to Groovy and making it more popular than ever and Oracle has done the same for JavaFX (deprecating JavaFX Script and embracing standard Java APIs was bold but well played).

Oracle Fusion Application Development

I was able to attend Ann Horton's presentation "Web Development Techniques from an Oracle Fusion Applications Developer." Ann's presentation was filled with screen snapshots, making it easy to see how to use the graphical-based tools to build Oracle Fusion Applications and use Oracle Fusion Middleware. I don't have any experience with Oracle Applications, but a lot of people do. Although I probably won't have the opportunity to work with them anytime soon, I like to see what other technologies are out there and enjoyed seeing a different way of developing applications. As is the case with much of the software development that occurs, Oracle provides tools that make much of the creation drag-and-drop and selecting things with the mouse.

Ann described "Oracle Fusion Applications Suite" as the "next generation of Oracle Applications" and added that "Fusion" implies integration of multiple products "under a common umbrella and one look and feel." Ann showed via numerous screen captures (often annotated with arrows, underlines, or other markings to provide focus) how to build up an application using Oracle Fusion Applications Suite.

One of the things I like to do at a technical conference is find out what others are using for tooling. Ann mentioned that thousands of developers have worked on Oracle Fusion Applications Suite and that they have used tools such as ade (Application Development Environment), JUnit, Selenium, OATS, and JAudit in their work. I thought it was interesting that JSP and JSF fragments (.jspx and .jsff files) were shown in the presentation.

Ann talked about Fusion developers using and providing "Fusion Guidelines, Standards, and Patterns" (GPS). More details about the Oracle Fusion Applications can be found in Oracle Fusion Applications Developer's Guide.

Oracle ADF and Mobile Development

Until I read the abstracts for this conference, I had not even realized that Oracle ADF can be used to develop applications for iOS and Android devices, but the subject of Oracle ADF Mobile was a popular one at the conference. The main page for Oracle ADF Mobile describes it like this:

Oracle ADF Mobile is an HTML5 and Java mobile development framework that enables developers to build and extend enterprise applications for iOS and Android from a single code base. Based on a hybrid mobile architecture, ADF Mobile supports access to native device services, enables offline applications and protects enterprise investments from future technology shifts.

The Oracle ADF Mobile FAQ states that Oracle ADF Mobile is licensed "as part of the Oracle Application Development Framework (ADF)" and adds that "Oracle ADF can be licensed either as 'Oracle Application Development Framework and TopLink' item on the technology price list, or as part of the Oracle WebLogic licenses." The FAQ also addresses device support: "Both iOS (5.x and above) and Android (2.3.x and above) devices are supported. Furthermore, both the tablet and smart phones running these mobile operating systems are supported."

One of the audience members asked me how using JavaFX differed from using Oracle ADF Mobile and licensing is obviously one of the major differences.

Other Blog Posts on RMOUG Training Days 2013 Conclusion

I would have liked to attend more sessions at RMOUG Training Days 2013, but enjoyed the brief time I was able to spend there this year. It was good to see people I've known for a number of years and to meet new people. It is always good to remember that there is much more to software development than the relatively narrow view one can get when working in the same circles and communities all the time.

Thứ Bảy, 24 tháng 11, 2012

Scripted Reports with Groovy

Groovy has become my favorite scripting language and in this blog I look at some of Groovy's features that make it particularly attractive for presenting text-based reports. The post will show how custom text-based reports of data stored in the database can be easily presented with Groovy. I will highlight several attractive features of Groovy along the way.

I use the Oracle Database 11g Express Edition (XE) for the data source in my example in this post, but any data source could be used. This example does make use of Groovy's excellent SQL/JDBC support and uses the Oracle sample schema (HR). A visual depiction of that sample schema is available in the sample schema documentation.

My example of using Groovy to write a reporting script involves retrieving data from the Oracle HR sample schema and presenting that data via a text-based report. One portion of the script needs to acquire this data from the database and Groovy adds only minimal ceremony to the SQL statement needed to do this. The following code snippet from the script shows use of Groovy's multi-line GString to specify the SQL query string in a user-friendly format and to process the results of that query.


def employeeQueryStr =
"""SELECT e.employee_id, e.first_name, e.last_name,
e.email, e.phone_number,
e.hire_date, e.job_id, j.job_title,
e.salary, e.commission_pct, e.manager_id,
e.department_id, d.department_name,
m.first_name AS mgr_first_name, m.last_name AS mgr_last_name
FROM employees e, departments d, jobs j, employees m
WHERE e.department_id = d.department_id
AND e.job_id = j.job_id
AND e.manager_id = m.employee_id(+)"""

def employees = new TreeMap<Long, Employee>()
import groovy.sql.Sql
def sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:xe", "hr", "hr",
"oracle.jdbc.pool.OracleDataSource")
sql.eachRow(employeeQueryStr)
{
def employeeId = it.employee_id as Long
def employee = new Employee(employeeId, it.first_name, it.last_name,
it.email, it.phone_number,
it.hire_date, it.job_id, it.job_title,
it.salary, it.commission_pct, it.manager_id as Long,
it.department_id as Long, it.department_name,
it.mgr_first_name, it.mgr_last_name)
employees.put(employeeId, employee)
}

The Groovy code above only adds a small amount of code on top of the Oracle SQL statement. The specified SELECT statement joins multiple tables and includes an outer join as well (outer join needed to include the President in the query results despite that position not having a manager). The vast majority of the first part of the code is the SQL statement that could be run as-is in SQL*Plus or SQL Developer. No need for verbose exception catching and result set handling with Groovy's SQL support!

There are more Groovy-specific advantages to point out in the code snippet above. Note that the import statement to import groovy.sql.Sql was allowed when needed and did not need to be at the top of the script file. The example also used Sql.newInstance and Sql.eachRow(GString,Closure). The latter method allows for easy application of a closure to the results of the query. The it special word is the default name for items being processed in the closure. In this case,it can be thought of a a row in the result set. Values in each row are accessed by the underlying database columns' names (or aliases in the case of mgr_first_name and mgr_last_name).

One of the advantages of Groovy is its seamless integration with Java. The above code snippet also demonstrated this via Groovy's use of TreeMap, which is advantageous because it means that the new Employee instances placed in the map based on data retrieved from the database will always be available in order of employee ID.

In the code above, the information retrieved from the database and processed via the closure is stored for each row in a newly instantiated Employee object. This Employee object provides another place to show off Groovy's brevity and is shown next.

Employee.groovy

@groovy.transform.Canonical
class Employee
{
Long employeeId
String firstName
String lastName
String emailAddress
String phone_number
Date hireDate
String jobId
String jobTitle
BigDecimal salary
BigDecimal commissionPercentage
Long managerId
Long departmentId
String departmentName
String managerFirstName
String managerLastName
}

The code listing just shown is the entire class! Groovy's property supports makes getter/setter methods automatically available for all the defined class attributes. As I discussed in a previous blog post, the @Canonical annotation is a Groovy AST (transformation) that automatically creates several useful common methods for this class [equals(Object), hashCode(), and toString()]. There is no explicit constructor because @Canonical also handles this, providing a constructor that accepts that class's arguments in the order they are specified in their declarations. It is difficult to image a scenario in which it would be easier to easily and quickly create an object to store retrieved data values in a script.

A JDBC driver is needed for this script to retrieve this data from the Oracle Database XE and the JAR for that driver could be specified on the classpath when running the Groovy script. However, I like my scripts to be as self-contained as possible and this makes Groovy's classpath root loading mechanism attractive. This can be used within this script (rather than specifying it externally when invoking the script) as shown next:


this.class.classLoader.rootLoader.addURL(
new URL("file:///C:/oraclexe/app/oracle/product/11.2.0/server/jdbc/lib/ojdbc6.jar"))

Side Note: Another nifty approach for accessing the appropriate dependent JAR or library is use of Groovy's Grape-provided @Grab annotation. I didn't use that here because Oracle's JDBC JAR is not available in any legitimate Maven central repositories that I am aware of. An example of using this approach when a dependency is available in the Maven public repository is shown in my blog post Easy Groovy Logger Injection and Log Guarding.

With the data retrieved from the database and placed in a collection of simple Groovy objects built for holding this data and providing easy access to it, it is almost time to start presenting this data in a text report. Some constants defined in the script are shown in the next excerpt from the script code.


int TOTAL_WIDTH = 120
String HEADER_ROW_SEPARATOR = "=".multiply(TOTAL_WIDTH)
String ROW_SEPARATOR = "-".multiply(TOTAL_WIDTH)
String COLUMN_SEPARATOR = "|"
int COLUMN_SEPARATOR_SIZE = COLUMN_SEPARATOR.size()
int COLUMN_WIDTH = 22
int TOTAL_NUM_COLUMNS = 5
int BALANCE_COLUMN_WIDTH = TOTAL_WIDTH-(TOTAL_NUM_COLUMNS-1)*COLUMN_WIDTH-COLUMN_SEPARATOR_SIZE*(TOTAL_NUM_COLUMNS-1)-2

The declaration of constants just shown exemplify more advantages of Groovy. For one, the constants are statically typed, demonstrating Groovy's flexibility to specifying types statically as well as dynamically. Another feature of Groovy worth special note in the last code snippet is the use of the String.multiply(Number) method on the literal Strings. Everything, even Strings and numerics, are objects in Groovy. The multiply method makes it easy to create a String of that number of the same repeating character.

The first part of the text output is the header. The following lines of the Groovy script write this header information to standard output.


println "\n\n${HEADER_ROW_SEPARATOR}"
println "${COLUMN_SEPARATOR}${'HR SCHEMA EMPLOYEES'.center(TOTAL_WIDTH-2*COLUMN_SEPARATOR_SIZE)}${COLUMN_SEPARATOR}"
println HEADER_ROW_SEPARATOR
print "${COLUMN_SEPARATOR}${'EMPLOYEE ID/HIRE DATE'.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
print "${'EMPLOYEE NAME'.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
print "${'TITLE/DEPARTMENT'.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
print "${'SALARY INFO'.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
println "${'CONTACT INFO'.center(BALANCE_COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
println HEADER_ROW_SEPARATOR

The code above shows some more addictive features of Groovy. One of my favorite aspects of Groovy's GString support is the ability to use Ant-like ${} expressions to provide executable code inline with the String. The code above also shows off Groovy's GDK String's support for the center(Number) method that automatically centers the given String withing the specified number of characters. This is a powerful feature for easily writing attractive text output.

With the data retrieved and available in our data structure and with the constants defined, the output portion can begin. The next code snippet shows use of Groovy's standard collections each method to allow iteration over the previously populated TreeMap with a closure applied to each iteration.


employees.each
{ id, employee ->
// first line in each output row
def idStr = id as String
print "${COLUMN_SEPARATOR}${idStr.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
def employeeName = employee.firstName + " " + employee.lastName
print "${employeeName.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
def jobTitle = employee.jobTitle.replace("Vice President", "VP").replace("Assistant", "Asst").replace("Representative", "Rep")
print "${jobTitle.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
def salary = '$' + (employee.salary as String)
print "${salary.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
println "${employee.phone_number.center(BALANCE_COLUMN_WIDTH)}${COLUMN_SEPARATOR}"

// second line in each output row
print "${COLUMN_SEPARATOR}${employee.hireDate.getDateString().center(COLUMN_WIDTH)}"
def managerName = employee.managerFirstName ? "Mgr: ${employee.managerFirstName[0]}. ${employee.managerLastName}" : "Answers to No One"
print "${COLUMN_SEPARATOR}${managerName.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
print "${employee.departmentName.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
String commissionPercentage = employee.commissionPercentage ?: "No Commission"
print "${commissionPercentage.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
println "${employee.emailAddress.center(BALANCE_COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
println ROW_SEPARATOR
}

The last code snippet is where the data retrieved from the database is output in a relatively attractive text format. The example shows how handles in a closure can be named to be more meaningful. In this case, they are named id and employee and represent the key (Long) and value (Employee) of each entry in the TreeMap.

There are other Groovy features in the last code snippet worth special mention. The presentation of commission uses Groovy's Elvis operator (?:), which makes even Java's conditional ternary look verbose. In this example, if the employee's commission percentage meets Groovy truth standards, that percentage is used; otherwise, "No Commission" is printed.

The handling of the hire date provides another opportunity to tout Groovy's GDK benefits. In this case, Groovy GDK Date.getDateString() is used to easily access the date-only portion of the Date class (time not desired for hire date) without explicit use of a String formatter. Nice!

The last code example also demonstrates use of the as keyword to coerce (cast) variables in a more readable way and also demonstrates more leverage of Java features, in this case taking advantage of Java String's replace(CharSequence, CharSequence) method. Groovy adds some more goodness to String again in this example, however. The example demonstrates Groovy's supporting extracting the first letter only of the manager's first name using subscript (array) notation ([0]) to get only the first character out of the string.

So far in this post, I've shown snippets of the overall script as I explained the various features of Groovy that are demonstrated in each snippet. The entire script is shown next and that code listing is followed by a screen snapshot of how the output appears when the script is executed. The complete code for the Groovy Employee class was shown previously.

generateReport.groovy: The Complete Script

#!/usr/bin/env groovy

// Add JDBC driver to classpath as part of this script's bootstrapping.
// See http://marxsoftware.blogspot.com/2011/02/groovy-scripts-master-their-own.html.
// WARNING: This location needs to be adjusted for specific user environment.
this.class.classLoader.rootLoader.addURL(
new URL("file:///C:/oraclexe/app/oracle/product/11.2.0/server/jdbc/lib/ojdbc6.jar"))


int TOTAL_WIDTH = 120
String HEADER_ROW_SEPARATOR = "=".multiply(TOTAL_WIDTH)
String ROW_SEPARATOR = "-".multiply(TOTAL_WIDTH)
String COLUMN_SEPARATOR = "|"
int COLUMN_SEPARATOR_SIZE = COLUMN_SEPARATOR.size()
int COLUMN_WIDTH = 22
int TOTAL_NUM_COLUMNS = 5
int BALANCE_COLUMN_WIDTH = TOTAL_WIDTH-(TOTAL_NUM_COLUMNS-1)*COLUMN_WIDTH-COLUMN_SEPARATOR_SIZE*(TOTAL_NUM_COLUMNS-1)-2



// Get instance of Groovy's Sql class
// See http://marxsoftware.blogspot.com/2009/05/groovysql-groovy-jdbc.html
import groovy.sql.Sql
def sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:xe", "hr", "hr",
"oracle.jdbc.pool.OracleDataSource")

def employeeQueryStr =
"""SELECT e.employee_id, e.first_name, e.last_name,
e.email, e.phone_number,
e.hire_date, e.job_id, j.job_title,
e.salary, e.commission_pct, e.manager_id,
e.department_id, d.department_name,
m.first_name AS mgr_first_name, m.last_name AS mgr_last_name
FROM employees e, departments d, jobs j, employees m
WHERE e.department_id = d.department_id
AND e.job_id = j.job_id
AND e.manager_id = m.employee_id(+)"""

def employees = new TreeMap<Long, Employee>()
sql.eachRow(employeeQueryStr)
{
def employeeId = it.employee_id as Long
def employee = new Employee(employeeId, it.first_name, it.last_name,
it.email, it.phone_number,
it.hire_date, it.job_id, it.job_title,
it.salary, it.commission_pct, it.manager_id as Long,
it.department_id as Long, it.department_name,
it.mgr_first_name, it.mgr_last_name)
employees.put(employeeId, employee)
}

println "\n\n${HEADER_ROW_SEPARATOR}"
println "${COLUMN_SEPARATOR}${'HR SCHEMA EMPLOYEES'.center(TOTAL_WIDTH-2*COLUMN_SEPARATOR_SIZE)}${COLUMN_SEPARATOR}"
println HEADER_ROW_SEPARATOR
print "${COLUMN_SEPARATOR}${'EMPLOYEE ID/HIRE DATE'.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
print "${'EMPLOYEE NAME'.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
print "${'TITLE/DEPARTMENT'.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
print "${'SALARY INFO'.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
println "${'CONTACT INFO'.center(BALANCE_COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
println HEADER_ROW_SEPARATOR

employees.each
{ id, employee ->
// first line in each row
def idStr = id as String
print "${COLUMN_SEPARATOR}${idStr.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
def employeeName = employee.firstName + " " + employee.lastName
print "${employeeName.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
def jobTitle = employee.jobTitle.replace("Vice President", "VP").replace("Assistant", "Asst").replace("Representative", "Rep")
print "${jobTitle.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
def salary = '$' + (employee.salary as String)
print "${salary.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
println "${employee.phone_number.center(BALANCE_COLUMN_WIDTH)}${COLUMN_SEPARATOR}"

// second line in each row
print "${COLUMN_SEPARATOR}${employee.hireDate.getDateString().center(COLUMN_WIDTH)}"
def managerName = employee.managerFirstName ? "Mgr: ${employee.managerFirstName[0]}. ${employee.managerLastName}" : "Answers to No One"
print "${COLUMN_SEPARATOR}${managerName.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
print "${employee.departmentName.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
String commissionPercentage = employee.commissionPercentage ?: "No Commission"
print "${commissionPercentage.center(COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
println "${employee.emailAddress.center(BALANCE_COLUMN_WIDTH)}${COLUMN_SEPARATOR}"
println ROW_SEPARATOR
}

In this blog post, I've attempted to show how Groovy provides numerous features and other syntax support that make it easier to write scripts for generating readable and relatively attractive output. For more general Groovy scripts that provide text output support, see Formatting simple tabular text data. Although these are nice general solutions, an objective of my post has been to show that it is easy and does not take much time to write customized scripts for generating custom text output with Groovy. Small Groovy-isms such as easily centering a String, easily converting a Date to a String, extracting any desired character from a string based on array position notation, and easily accessing database data make Groovy a powerful tool in generating text-based reports.

Thứ Ba, 12 tháng 6, 2012

Quickly Viewing Oracle Database Constraints

When I am working with an Oracle database, I still find myself using SQL*Plus for many quick and dirty database queries. In particular, I often look up constraints in SQL*Plus. In this post, I look at the Oracle database views and queries that I use most to get an idea what constraints I am dealing with.

I have found the two most important views for determining basic database constraints are ALL_CONSTRAINTS (USER_CONSTRAINTS) and ALL_CONS_COLUMNS (or USER_CONS_COLUMNS). In this post, I look at some queries I like to use that take advantage of these views from the Oracle Data Dictionary.

The ALL_CONSTRAINTS view is great for finding basic constraint details. The next SQL*Plus snippet demonstrates this in use.

displayConstraintInfo.sql

set linesize 180
set verify off
accept constraintName prompt "Constraint Name: "
SELECT constraint_name, constraint_type, r_constraint_name, table_name,
search_condition
FROM all_constraints
WHERE constraint_name = '&constraintName';

The above snippet will prompt for a constraint name and then provide some fundamental characteristics of that constraint provided by the ALL_CONSTRAINTS view. One of these characteristics is CONSTRAINT_TYPE, which is one of the following values: 'C' (Check Constraint), 'P' (Primary Key), 'R' (Referential/Foreign Key), 'U' (Unique), 'V' (with check option on a view), 'O' (with read only on a view). The above query requires one to know the constraint name. The next query will show similar information for constraints on a given table.

displayConstraintsOnTable.sql

set linesize 180
set verify off
accept tableName prompt "Table Name: "
SELECT constraint_name, constraint_type, r_constraint_name, table_name,
search_condition
FROM all_constraints
WHERE table_name = '&tableName';

The above query provides the constraints on a given table, but it is often useful to know which columns in particular on the table have constraints. This is easily done by joining the ALL_CONS_COLUMNS view to the ALL_CONSTRAINTS view.

displayConstraintsOnTableColumns.sql

set linesize 180
set verify off
accept tableName prompt "Table Name: "
SELECT c.constraint_name, c.constraint_type, c.r_constraint_name,
c.table_name, cc.column_name, cc.position, c.search_condition
FROM all_constraints c, all_cons_columns cc
WHERE c.table_name = '&tableName'
AND c.constraint_name = cc.constraint_name;

Other useful queries using these two constraints-related views are those that provide information on referential integrity constraints (CONSTRAINT_TYPE of R). In particular, the new two simple queries show the constraints for a given table that are foreign key constraints and which primary key constraints they depend on. The scripts only differ in substance in which version of the table_name is provided to the script (the primary or the referencing table). The majority of these scripts are exactly the same other than the comment, the prompt for the table name, and the all_constraints.table_name that is joined to the provided table name. I also use the UPPER() function in this example so that the input table_name could be provided in any case. Because I always have my tables in all uppercase, this will always work for me. Anyone who uses case sensitivity with their table names should not do this. I could have used UPPER() in my above examples as well.

displayForeignKeyConstraintsForPrimaryTable.sql

-- displayForeignKeyConstraintsForPrimaryTable.sql
--
-- Display the foreign key dependencies on a provided
-- PRIMARY table. In other words, show tables and their
-- foreign key constraints that reference the table whose
-- name is provided to the script.
--
set linesize 180
set verify off
column "PRIMARY COLUMN" format a25
accept tableName prompt "PRIMARY Table Name: "
SELECT cf.table_name "FK TABLE",
cf.constraint_name "FOREIGN KEY",
cp.constraint_name "DEPENDS ON",
cp.table_name "PK TABLE",
ccp.column_name "PRIMARY COLUMN",
ccp.position
FROM all_constraints cp, all_cons_columns ccp, all_constraints cf
WHERE cp.table_name = UPPER('&tableName')
AND cp.constraint_name = ccp.constraint_name
AND cf.r_constraint_name = cp.constraint_name
AND cf.r_constraint_name = ccp.constraint_name;
displayForeignKeyConstraintsForReferencingTable.sql

-- displayForeignKeyConstraintsForReferencingTable.sql
--
-- Display the foreign key dependencies of a provided
-- table on other tables. In other words, show tables
-- upon which the provided table has foreign key
-- constraints.
--
set linesize 180
set verify off
column "REFERENCING COLUMN" format a25
accept tableName prompt "REFERENCING Table Name: "
SELECT cf.table_name "FK TABLE",
cf.constraint_name "FOREIGN KEY",
cp.constraint_name "DEPENDS ON",
cp.table_name "PK TABLE",
ccp.column_name "PRIMARY COLUMN",
ccp.position
FROM all_constraints cp, all_cons_columns ccp, all_constraints cf
WHERE cf.table_name = UPPER('&tableName')
AND cp.constraint_name = ccp.constraint_name
AND cf.r_constraint_name = cp.constraint_name
AND cf.r_constraint_name = ccp.constraint_name;

In this post I've summarized some of the useful queries one can construct from the Oracle Data Dictionary views ALL_CONSTRAINTS and ALL_USER_CONS_COLUMNS.

Thứ Năm, 8 tháng 12, 2011

Recent Software Development Posts of Interest - Early December 2011

I have run into several software development blog posts over recent weeks that I think are worth reading or keeping links to for future reference. I collect some of these in this post.

An apt Ending

In Java 8 news, Joseph D. Darcy's post An apt ending draws nigh reports that "after being deprecated in JDK 7, the apt command line tool and the entirely of its associated API is on track to be removed from JDK 8 within the next few months." I wrote about the apt tool in a Java SE 6 context in the article Better JPA, Better JAXB, and Better Annotations Processing with Java SE 6.

Devops

I'm still somewhat skeptical of the concept of devops (not the issues the movement is trying to resolve, but rather the movement itself and what it actually is and involves), but I also realize that I still understand very little about it. Neil McAllister is critical of the devops movement in the post Devops: IT's latest paper tiger, but I tend to agree with the majority of the sentiments he expresses in the post.

Matthias Marschall's post DevOps is NOT a Job Description states that "The DevOps hype produces some strange effects." Marschall states that DevOps is not about job ads and then goes on to describe what he believes DevOps is about (culture, automation, measurements, and sharing).

Oracle's Top Ten 2011 Java Moves and the Acquisition of Sun

The post Enterprise Applications: Oracle`s Top 10 Java Moves of 2011 outlines "some of the top Java moves Oracle has made in 2011." This is in slideshow format and includes the list and brief description of each item on the list. Some of the items include JDK 7, OpenJDK, JavaFX 2.0, NetBeans, Java EE 7, and Java/HTML 5 integration.

In How Oracle made the Sun deal work: a lesson for CFOs, Elizabeth Heichler quotes Oracle Chairman Jeff Henley describing Oracle's acquisition of Sun as "unequivocally the finest acquisition we've ever done."

Is 15 Years The Half Life of a Software Development Career?

Matt Heusser's post What I learned from Google - You Get Fifteen Years maintains that "your half-life as a worker in corporate America is about age thirty-five." He explains some reasons for this: "Around that time, interviews get tougher. Your obligations make you less open to relocation, the technologies on your resume seem less-current, and your ability find that next gig begins to decrease." Heusser states in this post that more experienced technology workers do have an advantage in that their experience gives them more opportunities to do a wider variety of work.

I have written previously about older software developers in the post My Thoughts on Thoughts on Developer Longevity I thought that Seth made good points in his feedback to that post. He pointed out that many more experienced developers have stopped job hopping and found deep niches to work in.

HTML5 Continues Its Winning Streak

In mid-November, Adobe announced its intent to attempt to give Flex to the Apache Software Foundation. This move, following Adobe's announcement to abandon future versions of the Flash Player for mobile devices, implies what Adone has explicitly stated: "In the long-term, we believe HTML5 will be the best technology for enterprise application development." Of course, Flash is not completely gone and HTML5 is not completely here yet as we're reminded by the post Five Things You Can’t Do With HTML5 (yet).

Gradle Links

I recently wrote that I'm starting to get very interested in Gradle for building Java projects. As I've looked at Gradle a little more closely since my interest started at JavaOne 2011, I have found several useful resources on Gradle that I list here for future reference. It is likely that I'll reference many of these posts again in future posts I write on Gradle, but here they are in one location.

More Groovy

Several recent posts have provided different perspectives on use of Groovy. Neal Ford's Functional thinking: Functional features in Groovy, Part 1 discusses "how some functional programming has already crept into Groovy." Jakub Holý writes about use of Groovy in Java unit testing in his post Only a Masochist Would Write Unit Tests in Java. Be Smarter, Use Groovy (or Scala…). Tim Myer's post Programming with Groovy: Trampoline and Memoize point out that "Trampolining and memoization are two powerful new features in Groovy 1.8, but the combination of the two is not always straightforward." The post describes with descriptive text and code examples how to use these new Groovy 1.8 closure enhancements.

GroovyMag's News Roundup: Links for December 6 features a link to my post Compressing JPG Images with Groovy. There are several other interesting Groovy posts highlighted there as well, including Five Cool Things You Can Do With Groovy Scripts.

Reading List for JVM Developers

Thomas Lockney's post A Reading List for JVM-based Developers provides a "recommended reading list for developers who find themselves working in a JVM-based environment who need to understand the characteristics of that environment, particularly as it pertains to performance and concurrency issues." The list includes books and online sites. Some of the online resources include JSR-133 (Java Memory Model) FAQ and What Every Programmer Should Know About Memory.

"Lesser-known" Java Libraries

The reddit/java thread Nice lesser-known Java libraries provides several developers' opinions on "nice, lighweight and lesser known libraries solving various problems." Some of the referenced libraries include jcommander, FEST-Assert, jsoup, Project Lombok, and Guava. There is also a reference to the presentation Java Boilerplate Busters.

Thứ Năm, 23 tháng 6, 2011

Java at Oracle OpenWorld 2011

JavaOne 2011 and Oracle OpenWorld 2011 are being held at the same time (2-6 October 2011) in San Francisco again this year, but are considered completely separate conferences in 2011. However, this does not mean that Oracle OpenWorld won't have Java-related presentations. Instead, it seems that Oracle OpenWorld will focus more on Java topics in relation to Oracle products while JavaOne is likely to focus more on "pure Java." In this post, I look at some of the Oracle OpenWorld 2011 abstracts that reference the Java ecosystem.


From Java SE, 2012, to Java 12: Java SE Roadmap (15902)

The one-hour presentation "From Java SE, 2012, to Java 12: Java SE Roadmap" is to be presented by Oracle employees Adam Messinger, Peter Utzschneider, and Henrik Stahl. The title alone makes it obvious why this presentation is likely of great interest to Java developers.


Java EE 7 Overview and Oracle GlassFish Server Update (15597)

Oracle employees Adam Leftik and John Clingan plan to "cover the current status of Java EE 7, presenting an overview of new and updated specifications" and discuss how future GlassFish releases will provide these new features in their presentation "Java EE 7 Overview and Oracle GlassFish Server Update."


Diagnosing Scalability Issues in Java Applications on MySQL (15742)

This presentation, "Diagnosing Scalability Issues in Java Applications on MySQL," is by Oracle employees Todd Farmer and Mark Matthews. The abstract states that attendees will "learn how to diagnose and fix database- and application-level deadlocks and concurrency issues for Java applications deployed against MySQL."


Cloud-Enabled Java Persistence with Oracle TopLink (15615)

The abstract for "Cloud-Enabled Java Persistence with Oracle TopLink" states that the session will "examine the persistence requirements of Java applications in the cloud and introduces the features of Oracle TopLink that address them to simplify cloud application development." This presentation is by Shaun Smith and Doug Clarke, both of Oracle.


Optimize Java Persistence/Scale Database Access with JDBC and Oracle Universal Connection Pool (13360)

The presentation "Optimize Java Persistence/Scale Database Access with JDBC and Oracle Universal Connection Pool" is to be presented by three Oracle employees: Kuassi Mensah, Tong zhou, and Ashok Shivarudraiah. The session will focus on the "wealth of enterprise functionality" that Oracle Database 11g provides for "Java developers [to build] fast, scalable, reliable Java applications."


A Change Is as Good as a REST: Oracle JDeveloper 11g's REST Web Services (2241)

Chris Muir of Sage Computing Services is going to present "A Change Is as Good as a REST: Oracle JDeveloper 11g's REST Web Services" and the abstract states that JDeveloper support of REST and JAX-RS will be covered.


Java in the Database—The Sky's the Limit: Lessons from the Largest Deployment (14702)

Rune Lilleng of Norwegian Labour and Welfare Administration and Paul Lo and Kuassi Mensah of Oracle are presenting "Java in the Database - The Sky's the Limit: Lessons from the Largest Deployment." The abstract states that this session will begin by covering background and basics of the JVM embedded within Oracle databases and will then move onto coverage of lessons learned from a large deployment using this DB-embedded JVM.


On the Road to Java EE 6 with Oracle WebLogic and Eclipse (15276)

Oracle's Erik Bergenholtz and Pieter Humphrey will present "On the Road to Java EE 6 with Oracle WebLogic and Eclipse." Their abstract is shown here:
The developer Web profile is a key improvement in Java EE 6 servers, and Eclipse developers will want to work with it. This session demonstrates some aspects of the progress of Oracle WebLogic server on its road to Java EE 6 compliance and gives Eclipse developers a sneak peek at using Java Persistence API Release 2.0 and JavaServer Faces Release 2.0 with Oracle WebLogic's Web profile.


Production Java Diagnostics: Visibility Even Your Developer Does Not Have (14380)

The session "Production Java Diagnostics: Visibility Even Your Developer Does Not Have" by Oracle employees Neelima Bawa and Glen Hawkins "focuses on Oracle Enterprise Manager's ability to provide deep Java Virtual Machine diagnostics to quickly identify the root cause of problems within the JVM through heap stack and thread analysis as well as other detailed performance analytics based on real-time as well as historical details."


Speed Up XML Processing with Oracle XDK, XQJ, and XQuery (15714)

Oracle's Mark Drake is going to present "Speed Up XML Processing with Oracle XDK, XQJ, and XQuery." This session will demonstrate "how to build scalable XML processing systems with Oracle XML DB and Oracle XML Developer's Kit" and will provide "an introduction to using the XQuery API for Java (XQJ)." I have posted a few blog posts on XQuery previously.


Conclusion: JavaOne-less Oracle OpenWorld is not Java-less

I only listed a subset of the presentations at Oracle OpenWorld 2011 that are relevant to Java developers. When I use the keyword "Java" in the keyword search in the Oracle OpenWorld Content Catalog, there are 42 sessions returned as matches for that keyword.

Thứ Hai, 18 tháng 4, 2011

Software Development Posts of Interest - 18 April 2011

There have been numerous insightful blogs and articles on Java and other software development in recent days. I reference and summarize some of these in this post because I think they're worth a look.


Tips for Making a Developer's Life Easier

In the post Some tips to make a developer’s life easier, Bob Belderbos writes about "best practices of development" he has gained from "experience I gained building apps." He outlines six tips that I'd categorize as "general development tips" that apply to various types of software development.


Oracle Open Office and Oracle Cloud Office

Gavin Clarke's Ellison's Oracle washes hands of OpenOffice is interesting for a variety of reasons. An obvious reason for reading this post is provided in the first sentence: "Oracle is turning OpenOffice into a purely community project, and no longer plans to offer a commercial version of the collaboration suite loved by many." Another point of interest is Clarke's mention of the seeming abandonment of Oracle Cloud Office. Finally, Clark's statement about JavaFX is interesting:
Among the ideas Oracle had lined up for OpenOffice under its control: a call to rewrite it using the closed-source JavaFX language for interface development that nobody cares about but Oracle.


To Do or Not To Do for a New JVM Language

Sven Efftinge addresses those thinking about designing JVM languages in a post called Dear Java Killers and discusses "seven most important Dos and Don'ts you should consider when developing a language for the Java community". As is often the case with the best blog posts, the feedback comments add significantly to the discussion.


Ceylon

Gavin King's "Introducing the Ceylon Project" presentation was highlighted in Marc Richard's post Gavin King unveils Red Hat's Java killer: The Ceylon Project. Richard analyzes what he likes about what he has seen related to Ceylon. Ceylon has already been the subject of significant discussion.

In the post The rationale for Ceylon, Red Hat's new programming language, Ryan Paul examines the reasons for King and Redhat to pursue a successor to Java. He also points out that many in the Scala community wonder why they don't simply use Scala instead of developing yet another new language for the JVM.

Gavin King has commented on the surging interest in Ceylon in the posts Ceylon and Ceylon presentation: a clarification. He also answers questions about Ceylon in Alex Blewitt's interview post Ceylon JVM Language.

Several in the Scala community seem at least a little put off by the idea of Redhat working on a new JVM language instead of using Scala. An example is the post Ceylon: Interesting for the Wrong Reasons. Post author Lachlan O'Dea argues that he'd be likely to pick Ceylon over Java, he thinks Scala is superior to what Ceylon will offer. Toward the end of his post, he states:
You may wonder, "if you think Scala is so good, then use it and be happy, why worry about Ceylon?" Well, I worry because I think Ceylon is worse than Scala, but it could win anyway. That actually seems to be the more common outcome in these situations. I would much prefer a world with Scala jobs in demand than one with Ceylon jobs in demand. So, yes, it’s all about me being selfish. I would say to all Scala fans: don’t be afraid to be a little selfish and evangelise for the better outcome.

I'm not the only one who has noted that the Scala enthusiasts seem more concerned about Ceylon than they have been about other alternative JVM languages that have come about since Scala. The only reasonable explanations for this different reaction must have to do with the major player involved with Ceylon (Redhat).


Devops

The term "devops" has started gaining some traction recently. I ran across two posts this week that provide nice introductory overviews of the "devops" concept. In What Is This Devops Thing, Anyway?, Stephen Nelson-Smith (guest blogging on Patrick Debois's blog) describes the devops movement as a "multi-disciplinary approach" and states:
The Devops movement is built around a group of people who believe that the application of a combination of appropriate technology and attitude can revolutionize the world of software development and delivery. The demographic seems to be experienced, talented 30-something sysadmin coders with a clear understanding that writing software is about making money and shipping product.

Nelson-Smith also focuses on the idea of "sysadmin coders" and states that the concept is an acknowledgement that "there is no one IT skill that is more useful or more powerful than another." He adds, "To solve problems well you need all the skills. When you build teams around people who can be developers, testers, and sysadmins, you build remarkable teams."

Dan Ackerson's post DevOps Entrenched – Tide Begins to Turn references a description of devops stating that devops helps "improve cooperation between developers and sysadmins." The concepts of devops may be best summarized in a sentence in this post: "Developers and Sysadmins are joining forces and forming 'Delivery Teams' – working together to ship high quality products to customers faster than ever."


JVM Interaction via File Locking and Groovy

Brock Heinz's blog is named in Groovy closure style as "thoughts.each { println it }". His post Inter JVM Communication demonstrates using Groovy in conjunction with Groovy GDK's version of java.net.Socket to determine if two instances of the same application are running. Kovica left a comment stating that use of FileChannel would be effective for this situation and pointing to Kovica's post on that very subject. I took concepts from both to come up with this marriage of Groovy and FileChannel use:

#!/usr/bin/env groovy
def timeoutMs = args ? args[0] as Integer : 10000
def lockFile = new File("dustin.lock")
def fileChannel = new RandomAccessFile(lockFile, "rw").getChannel()
def fileLock = fileChannel.tryLock()
if (fileLock) // non-null (Groovy Truth) means not locked by another instance
{
println "Busy working ..."
Thread.sleep(timeoutMs)
}
else
{
println "This application is already running!"
}

The following snapshot shows how the lock works when the script is run separately and nearly at the same time.



Conclusion

In this post, I referenced and briefly summarized posts that I found to be particularly interesting in recent days. I am especially interested to see what the future holds for Ceylon and for the devops movement.

Thứ Ba, 8 tháng 2, 2011

Java and Oracle, One Year Later

It's been just over a year since Oracle closed the deal to purchase Sun. With that in mind, the forthcoming Oracle Technology Network (OTN) TechCast "Java and Oracle, One Year Later," is aptly named. It is scheduled for 10 am (Pacific Time) on Tuesday, February 15, 2011. Ajay Patel, VP of Product Development for Application Grid Products, presents a "special live conversation" regarding "changes that have come to Java and Oracle since the Sun acquisition."

Additional information on this TechCast can be found online, but I also received an e-mail message with additional details on this TechCast. The e-mail message adds more details on what will be discussed:
  • "Highlights, challenges and what we learned over the past year"
  • "The Future of Java and its importance to Oracle and the community"
  • "Oracle’s Application Grid product portfolio today"
The e-mail message states that Justin Kestelyn (Director of OTN) will also be involved and that "attendees" will be able to ask questions. There is encouragement to register even if the currently scheduled time does not work "so we can send you the replay information."

Thứ Hai, 10 tháng 1, 2011

MySQL and Other Topics in RMOUG SQL>Update Winter 2010 Edition

The Winter 2010 edition of RMOUG SQL>Update (the newsletter of the Rocky Mountain Oracle Users Group) arrived this week. It had several interesting articles that I'll reference here. As usual, the newsletter was largely oriented toward database administration, but I still found some things of interest to developers.

Peggy King's "From the President" column provided a summary of RMOUG happenings in 2010. About Training Days 2010, King states, "Over eighty speakers from RMOUG and around the world came together to present what has become known as one of the top Oracle conferences." I presented at RMOUG Training Days 2010 on REST and Groovy and will be presenting on Groovy and HTML5 at RMOUG Training Days 2011 next month.

King also states in her column that over 25 Oracle Aces/Ace Directors attended Training Days 2010 and that 2010's edition was the first to feature an Oracle Ace Panel. Peggy also highlighted RMOUG's three quarterly training meetings, the RMOUG newsletter SQL>Update, and other RMOUG events in 2010.

Technical articles featured in the Winter 2010 edition of RMOUG SQL>Update include Steven Feuerstein's "Guarantee Application Success." A "PL/SQL Evangelist for Quest Software since January 2001," Feuerstein starts his article with these two sentences:

The lawyers at Quest Software asked me to clarify something right up front: using our software will not guarantee that you will be successful. Having said that, I do believe that if you follow the ideas in this paper and my presentation you are likely to improve the chances of delivering a successful application.

The presentation referenced in that quote is probably the Oracle OpenWorld 2010 presentation Guarantee Application Success and is probably related to Guarantee Application Success with the Toad Development Suite. In the article, Feuerstein sets up criteria that an application must be correct, fast enough, and maintainable and then goes into the general high-level approaches he believes should be followed to achieve these desirable criteria. Although PL/SQL is mentioned specifically, most of these ideas apply to development in any language.

John Krahulec's "Enterprise Social Networking: It's Now Ready for the Workplace" begins with an introduction to "Enterprise Social Networking." Krahulec states that "Enterprise Social Networking connects People to People and People to Information." He writes about the merits of social networking and how to deliver those merits to the enterprise. He also discusses the obstacles to adoption of enterprise social networking and discusses use of an Oracle database in application of an enterprise social network. I am interested to see if Enterprise Social Networking continues to grow or if it will fizzle out because of various issues and concerns.

In "ASM - The Next Generation," Tim Mishek looks at the current state of Automatic Storage Management. After describing ASM Dynamic Volume Manager, ASM Clustered File System, ASM Configuration Assistant (asmca), ASM Command Line Interface (ASMCMD), and other issues related to ASM, Mishek concludes, "Oracle has really done it right. Not only is ASM an absolute necessity for database clustering technologies, but is now a better option for general database storage. ... ASM has become a full featured storage solution."

The most interesting article in this edition of the newsletter for me is the single page article "Four Things to Know about MySQL" by Benjamin Wood. During Oracle's acquisition of Sun and its MySQL assets, some were concerned that Oracle only wanted MySQL to kill it. Several Oracle actions since the acquisition have proven otherwise. This article on MySQL by an Oracle Sales Consultant in a magazine heavily targeted at Oracle database administrators is further evidence that Oracle plans to continue supporting and providing MySQL. Wood provides explanation for his "four things," but I only list the four items here (see page 20 of the newsletter for the explanations). The four things Wood states we should know about MySQL follow:

1. MySQL is Now an Oracle Product
2. MySQL Powers the High Volume Web
3. MySQL Powers Critical Infrastructure
4. Oracle 11g and MySQL Work Together

Wood ends his article by explaining how to acquire MySQL from edelivery.oracle.com. He concludes, "Leverage your Oracle knowledge and get started with the world's most popular open source database -- now an Oracle product!"

Dan Hotka is the subject of the "RMOUG Member Focus" column. It is interesting to read about the technology advancements he has seen in his career. It is also interesting to read about the various twists in his career that I believe most of us experience if we stay in the technology-oriented careers long enough.

Heidi Kuhn is the subject of the "RMOUG Board Focus" column. As the RMOUG Administrative Assistant, Kuhn has access to interesting statistical information about RMOUG. Her column includes pie charts indicating the membership types in RMOUG ("Individuals" dominate with 77% of the memberships) and the percentage of RMOUG members associated with a company (67% associated with a company, 32% individual, and 1% students). Perhaps most interesting of all is the line chart showing RMOUG membership from 1998 through 2010. Current numbers (less than 1000 members) are the lowest on the chart and the peak was in the early 2000s (~2000 members).

Although Oracle now owns many products outside of the Oracle database, I don't think there's any question that RMOUG is still primarily made up of database administrators and focused on database administration. That being stated, RMOUG does work to have presentations at Training Days that are not database related (mine are typically good examples of this) and to address other technology areas as well. Although I'm not a DBA and have no desire to become one, I do find it advantageous to know at least a little about the database.

Thứ Bảy, 10 tháng 7, 2010

RMOUG SQL>Update Spring 2010 Highlights

The attractive full-color Spring 2010 edition of the RMOUG SQL>Update newsletter arrived this week and I read several things in it that I felt were worth mentioning in this blog post.  The three technical articles featured in this edition are the second part of Mark Molnar’s “Oracle & Excel – Why Fight It?”, Mark Rittman’s “Integrating Oracle GoldenGate and Oracle Data Integrator for Change Data Capture”, and Dan Hotka’s “Index Quality.”  Besides these three technical articles this edition also features RMOUG
member Bern Bray and RMOUG Board Member Carolyn Fryc.  In the remainder of this post, I highlight some of the things I found most generally interesting in these articles and member highlights.

As is usual with these RMOUG newsletters, the cover of this edition features a photograph of a beautiful Rocky Mountain area scene.  In this case it is a Bern Bray photograph of Rock Cut Bloom in Rocky Mountain National Park.  My family and I try to get to Estes Park, Grand Lake, and Rocky Mountain National Park often and the scene in this photograph is very familiar.  Unfortunately, this beautiful cover does have a typo: it indicates that the GoldenGate/Data Integrator article is by Mark Ritter instead of Mark Rittman.  With all the Marks in this issue, this typo is more understandable.

From a technical standpoint, the articles focusing on RMOUG members are intentionally and not surprisingly typically far less interesting than the technical articles.  Their focus, after all, is more on the “soft skills” than on technical insight.  That being stated, I particularly enjoyed reading a couple of Bern Bray’s comments in his self-written “Member Focus.”  In that, Bray writes, “Like many younger engineers, my early days found me doing technical stuff on my own at night.  It paid off, as I was able to advance my career and choose what I liked to work on.  Several years ago, I started to feel that my life was out of balance.”

Later, in concluding, Bray states his “little nugget of wisdom”: “Work hard during working hours, but at quitting time, put the keyboard down and walk away… You will be a fresher and better worker when you come back in the morning.  Besides, everyone knows that you get your best ideas in the shower.”  I liked these statements because they reflect that there are career advantages to technical work done on one’s own time, but that it is also useful to take a break.  This is my excuse for the less frequent and more intermittent blog posts this summer!

In the second (of two) part of his “Oracle & Excel – Why Fight It?” series, Mark Molnar demonstrates with extensive code samples and screen snapshots how to create flat files of usefully formatted data via Excel and an Oracle database.  In his words, his examples show “how to take data out of the database, via Excel, and produce flat files in the format desired.”  At first reading this, I wondered why one would do such a thing when it is easy to read from a database in a language like Java or Groovy using JDBC and write out flat files.  However, I found the article informative because of its extensive coverage of using Visual Basic with Excel and use of 7-Zip from the command line.  Even if I’d probably solve the problem of the example in this article with a Java-based approach, I enjoyed learning some details of using Visual Basic with Excel and Molnar’s coverage of some low-level details involved in that.  He specifically references the URL
http://en.wikibooks.org/wiki/Visual_Basic/External_Processes as a source of useful details regarding use of Visual Basic with external processes.

Dan Hotka provides a code listing in his article “Index Quality” that contains the source code for a script he calls Index_Info.sql.  According to the “description” included in the script’s comments, this script is an “SQL*Plus script to display Index Statistics in relation to the clustering factor.”  Hotka writes that this script is available on his website and discusses background details of the script and why it’s useful in this article.

I’m significantly more developer-oriented than DBA-oriented, so Rittman’s article on integrating GoldenGate and Data Integrator was largely outside of my core areas of interest.  However, it also meant that I learned plenty from reading the article, even though it was more difficult because I lacked the requisite knowledge in the two products he was demonstrating integrating.  At the end of this article, Rittman states, “For a more
detailed, step-by-step version of this article that also describes the process to set up Oracle GoldenGate on the Microsoft Windows platform, an article is available on my website at: http://www.rittmanmead.com/2010/03/22/configuring-odi-10-1-3-6-to-use-oracle-golden-gate-for-changed-data-capture/

Oracle OpenWorld (OOW) is mentioned more than once in this edition of the newsletter.  In “RMOUG Board Focus,” Carolyn Fryc writes about her first Oracle OpenWorld (2005) and talks about the focus of that OOW being Fusion (likely a major theme every year since then as well).  Dan Hotka’s training advertisement also mentions that he will be at Oracle OpenWorld September 19-23.  I’ve never attended Oracle OpenWorld, but will likely attend at least portions of it this year when I attend JavaOne 2010 and Oracle Develop 2010 which are being held simultaneously in the same city.

In this blog post, I’ve attempted to outline some facets of the Spring 2010 edition of the RMOUG SQL>Update newsletter that I thought had some general interest.  According to RMOUG President Peggy King’s “From the President” column, RMOUG Training Days 2011 is scheduled for 15-17 February 2011 at the Colorado Convention Center.