Accessing Databases with Services
Overview
All types of services can access databases, including flow services, Java service, and C/C++ services. You can create:
- Flow services using the Integration Server Administrator. When you create a flow service that accesses a database, you make selections from Integration Server Administrator screens to describe the function that you want the service to perform. The webMethods Integration Server generates the flow service for you based on your selections.
- Java and C/C++ services using webMethods Integration Server or your own development environment. Integration Server provides built-in services that perform basic database operations, such as connecting to a database, selecting rows, inserting rows, and deleting rows. Your services can access these built-in services to perform database operations. Your services can also use other database APIs (for example, JDBC) to access databases.
This chapter describes how to decide which type of service to create, how to create database flow services, how to create database services with Java or C/C++, and how to create clients that access databases.
Deciding Which Type of Service to Create
Use the information in the following table to decide which type of service you should create.
| Type of Service | Advantages | Disadvantages |
|---|---|---|
| Flow services created with the Integration Server Administrator |
|
|
| Java or C/C++ Services |
|
You must code and compile the service. |
Creating Database Flow Services
About this task
The resulting flow service invokes the same built-in services that you can invoke from Java or C/C++. For more information about these services, see Built-in Database Services.
Using the Integration Server Administrator, you can create a flow service in one of the following ways:
- Generate from tables. You select the table that you want the service to access. Then, you select the database operation you want your service to perform (Select, Insert, Delete, or Update). The server displays the columns in the table that you can use to indicate the input that the service expects. When you use this option, the server automatically generates the required SQL statements. For more information, see Generating a Database Flow Service from a Table.
- Generate from an SQL statement. You specify the SQL statement that you want the service to perform. The SQL statement you specify can be more complex than the SQL statements the server generates when it generates a service from tables. In addition, you can specify database-specific SQL. Use this option if you want to use database-specific SQL that requires the fully qualified table names. For more information, see Generating a Database Flow Service from an SQL Statement.
Regardless of how you generate them, database flow services are all standard flow services. After a service is created, you can edit it using Designer in the same way you edit any other flow service. You can invoke the resulting database flow service from other services.
Generating a Database Flow Service from an SQL Statement
About this task
Specifying a Dynamic SQL Statement
About this task
Using Question Marks (?) in SQL Statements
About this task
Example 1
To select all rows from the Names table that match the values specified for the Last_Name column, specify the following SQL statement:
select * from Names where Last_Name=?
The service expects an input value to use
to match rows in the
Last_Name
column.
Example 2
To add a new row to the Addresses table and populate it with specified values, specify the following SQL statement:
insert into Addresses (name,street,city,state,zip)
values (?,?,?,?,?)
The service expects input values to use to populate the new row.
Using Template Tags in SQL Statements
About this task
When you use template tags in an SQL statement, you cannot test the statement with the Integration Server Administrator; (the Integration Server Administrator does not recognize template tags and will not prompt you for input when you execute the service). To test a service that uses template tags, you must open that service in Designer and add to its input parameters any variables that are referenced in a tag. You can then test the service with Designer and it will prompt you for each input variable you defined. For information about declaring input parameters for a service, see the webMethods Service Development Help.
Example 1
The following shows an SQL statement that selects all rows satisfying the criteria that will be specified in a variable named condition at run time:
select * from Names where %value condition%
At run time, the server will substitute the
value of
condition for the
%value% tag.
The following shows examples of what you might use as the value of
condition:
name = 'Steve'
name like 'Jim%'
Example 2
To delete all rows from the Music table that meet a specified condition, specify the following SQL statement:
delete from Music where %value outdated%
The service expects input for an input variable named outdated that it uses to replace the entire token. Following is an example of what a user can specify for %value outdated%:
ReleaseDate < '1950'
Format = '8-track'
Steps for Generating a Flow Service from an SQL Statement
About this task
To generate a flow service from an SQL statement
Procedure
Generating a Database Flow Service from a Table
About this task
Restricting the List of Database Tables
About this task
-
Catalog.
You specify the name of the catalog whose tables you want to use.
- If you are not working with a distributed database, do not restrict by catalog.
- If you are working with a distributed database, you can specify the name of the database with which you want to work. If you are using DB2, use this field to specify the name of a DB2 location.
-
Schema
pattern. You specify the schemas whose tables you want to work with (if
you are using DB2, use this field to specify an AuthID).
- If you want tables for all schemas in the selected database, do not restrict by schema pattern.
- If you want to restrict your search to tables by selected schemas, specify the schema name. You can specify a pattern-matching string if your JDBC supports it. Most drivers support the pattern-matching characters described for Table name pattern below; however, check your driver’s documentation for information about its pattern-matching capabilities.
-
Table name
pattern. You specify the names of the tables with which you want to work.
Specify a table name or a pattern-matching string that specifies the names of
the tables. Most drivers support the following pattern-matching characters;
however, check your driver’s documentation for information about its
pattern-matching capabilities.
Use To match For example % Any string of characters HR% matches: HR30all, HR15mgmt, HR01payroll, and so forth. _ A single character HR3_mgmt matches: HR30mgmt, HR31mgmt, HR3Amgmt, and so forth. - Table type. The type of the tables for which you want information. You can choose from the following common JDBC table types: Table, View, System Table, Global Temporary, Local Temporary, Alias, and Synonym.
Steps for Generating the Flow Service from a Table
About this task
To generate a flow service from a table
Procedure
Output from the Flow Service
| Database Operation | Output |
|---|---|
| Select | Number of rows that the service retrieved and the columns from those rows that the service requested |
| Insert | Update count that the database returned in response to the SQL command |
| Delete | Update count that the database returned in response to the SQL command |
| Update | Update count that the database returned in response to the SQL command |
Creating Database Services with Java or C/C++
About this task
To assist you in coding database services, you can use the built-in database services to perform basic database operations and test SQL statements before you add them to your services.
If you want your service to access a database that has nonstandard features (for example, data types that are not supported by SQL), use other database connection APIs. For example, you can make direct calls to JDBC or use other connection libraries, such as ADO.
Built-in Database Services
webMethods Integration Server provides several built-in database services that perform basic database operations. These services use JDBC to connect to the database to perform the specific database operation. You can invoke the built-in database services from:
- Java and C/C++ services
- Any flow service that you create in Designer by using the INVOKE flow step
- Clients
The webMethods Integration Server Built-In Services Reference contains a list of built-in database services and shows input and output information for each. Your service or client must invoke the built-in database service that opens a connection to a database before it can invoke any of the other built-in database services.
Testing SQL Statements
About this task
Before you can use the Integration Server Administrator to test an SQL statement, the server must have a configured database alias for the database that you want to access. For more information about how to configure a database alias, see Identifying Database Aliases.
To test an SQL statement
Procedure
Error Handling
Some database services return a $dbMessage output value which contains a text message that describes the results of the service. If the service results in an error, the service also returns standard error output values.
Creating Clients that Access Databases
About this task
Invoking a Database Service from a Browser-based Client
About this task
For example, suppose a browser user submits the following name-value pairs:
| Variable Name | Contents |
|---|---|
| $dbTable |
Table Name
|
| Name |
Joe B
|
| Company |
Widgets,
Inc.
|
The pub.db:insert service converts the inputs as follows:
| Variable Name | Contents | |
|---|---|---|
| $dbTable | Table Name | |
| $data | Variable Name | Contents |
| Name |
Joe B
|
|
| Company |
Widgets,
Inc.
|
|
Invoking a Built-in Service from a Java, C/C++, or VB Client
About this task
If you want your client to access a database that has nonstandard features (for example, data types that are not supported by SQL), you use other database APIs. For example, you can make direct calls to JDBC or use other connection libraries, such as ADO.
Sample Code - IData
The following shows a sample Java client that accesses a database using an IData object to pass and receive data from the database service.
import com.wm.data.*;
import com.wm.app.b2b.client.Context;
public class DBClient
{
public static void main (String [] args) throws Exception
{
IData in = null;
IData out = null;
IData criteria = null;
IData set = null;
//
// connect to your integration server using an appropriate user
// name and password (doesn't have to be Administrator)
//
Context ctx = new Context();
ctx.connect ("localhost:5555", "Administrator", "manage");
//
// (1) request a DB connection by DB alias (if the DB
// changes location or something, we won't have to change
// this client code)
//
in = IDataFactory.create();
IDataCursor inCursor = in.getCursor();
inCursor.insertAfter ("$dbAlias", "Employees");
inCursor.destroy();
out = ctx.invoke ("wm.util.db", "connect", in);
//
// (2) update the Identification table to set Fonz's ID
// to 6500. note that we couldn't do this from a Web
// browser because we couldn't build up the complex
// nested data structures
in = IDataFactory.create();
inCursor = in.getCursor();
inCursor.insertAfter ("$dbAlias", "Employees");
inCursor.insertAfter ("$dbTable", "Identification");
criteria = IDataFactory.create();
IDataCursor criteriaCursor = criteria.getCursor();
criteriaCursor.insertAfter ("name", "fonzie");
criteriaCursor.destroy();
inCursor.insertAfter ("$criteria", criteria);
set = IDataFactory.create();
IDataCursor setCursor = set.getCursor();
setCursor.insertAfter ("ID", "6500");
setCursor.destroy();
inCursor.insertAfter ("$set", set);
inCursor.destroy();
try {
out = ctx.invoke ("wm.util.db", "update", in);
//
// (3) look at the return values (updateCount is the
// most important in this case)
//
IDataCursor outCursor = out.getCursor();
if (outCursor.first("updateCount"))
{
int uc = Integer.parseInt ((String)outCursor.getValue());
System.err.println ("Update count: "+uc);
}
else
System.err.println ("Error: no update count returned");
outCursor.destroy();
} catch (Exception e) {
// maybe something went wrong with the DB access; we
// can get more information here
if (outCursor.first("$error")) {
System.err.println ("Error: "+outCursor.getValue());
}
if (outCursor.first("$errorType")) {
System.err.println ("Error type: "+outCursor.getValue());
}
outCursor.destroy();
}
}
}