Skip to main content

Deploy Java UDRs through Web services on Informix using Rational Application Developer

Soumita Ghosh (soumita.ghosh@in.ibm.com), System Software Engineer, IBM Software Labs, India
Soumita Ghosh photo
Soumita Ghosh worked within the Informix team as part of the Classics Development Team for a year. Now she works with the Visual Age team on XLC/XLC++ compilers.
Sobha Rani Cheruku (scheruku@in.ibm.com), Associate Software Engineer, IBM Software Labs, India
Sobha Cheruku photo
Sobha Rani Cheruku works for Lab Services and handles Informix customer calls in India.
Akhilesh K. Tiwary (aktiwary@in.ibm.com), Staff Software Engineer, IBM Software Labs, India
Akhilesh Tiwary photo
Akhilesh Kumar Tiwary is a member of the Classics Development Team, working on JDBC, C-ISAM, ESQL/COBOL, ISA and ISPY.

Summary:  Learn how to expose an IBM® Informix® user-defined routine or user-defined datatype on the Web as a Web service. You'll see how to use a JavaBean for interacting with the Informix UDR or UDT, deploying as a Web service using Rational® Application Developer.

Date:  28 Sep 2006
Level:  Introductory
Activity:  1159 views

Introduction

A common requirement these days for database application developers is to be able to expose functions that access data on the Web. In this article, we show you how to expose an Informix user-defined routine (UDR) or user-defined datatype (UDT) on the Web as a Web Service, as part of service-oriented architecture. We'll use a JavaBean for interacting with an Informix UDR or UDT, and deploy it as a Web Service using Rational Application Developer (RAD).

For our example, we have created a customer table on the Informix server, and will be accessing the table to retrieve customer details. Customer ID is used as the unique identifier for each customer record. Customer details are retrieved using a Java™ method that has been installed and registered as a UDR on the Informix server. The activity of creating and registering the UDR or UDT is done using Informix udtudrmgr classes.

We used RAD to create and deploy the Web service using a JavaBean. Internally the method which calls the UDR is exposed as a Web service method.

The front end application was designed in JSP/HTML. The customer ID is the input field for the index page, and on submission calls a results page which retrieves and displays the customer billing details.

In walking through this sample application, you will learn:

  • How to create Java UDRs and UDTs
  • How to create a Web service using Rational Application Developer
  • How to use service-oriented architecture to create better Web applications
  • How Informix Dynamic Server (IDS) can exploit the functionalities of service-oriented architecture

Basic concepts

Let's start with the fundamental concepts behind Web services.

What is service-oriented architecture?

Service-oriented architecture (SOA) is built on top of the three-tier client-server architecture composed of the client application, the Web services application, and the server or ERP layer, and addresses its shortcomings. SOA is composed of a set of services and applications. These services implement a function of some kind and are used by applications and other services. The services communicate among one other and with applications by exchanging XML data. Hence, SOA facilitates software reusability in the form of services that are actually software modules that cater to more than one application's requirements.

What is a Web service?

A Web service is basically a software system that provides interoperability between machines over a network. It has two parts: language and protocol of message transfer. The language part is called WSDL (Web service definition language). The protocol used is called SOAP (Simple Object Access Protocol). WSDL basically describes the service and XML is mainly used as the language. SOAP helps the applications to communicate over the Internet.


Figure 1. Service-oriented architecture
Service-oriented architecture

What are Java UDRs and UDTs?

A user-defined routine (UDR) is a routine that an SQL statement or another UDR can invoke. UDRs written in Java use the server-side implementation of the Informix JDBC driver to communicate with the database server.

A user-defined datatype (UDT) is the mapping between SQL data types and Java objects to be able pass parameters and retrieve results from a UDR.

There are 2 types of UDT in Java:

  • Distinct data type: CREATE DISTINCT DATATYPE
  • Opaque data type: CREATE OPAQUE DATATYPE

UDTs can be created by using CREATE TYPE SQL statement or by using UDTMANAGERs createUDT methods.


Before you get started

Software requirements

To create and use UDRs written in Java:

  • You need to install Informix Internet Foundation 2000
  • You need to install The Java Development Kit (JDK). You may also install DataBlade Developers Kit, Version 4.0 or later, to facilitate development of UDRs in Java. If you just want to run the existing Java UDRs without compiling the source code, then installing only JRE would be sufficient instead of JDK.

Server requirements

UDRs written in Java execute on specialized virtual processors , called Java virtual processors (JVPs). A JVP embeds a Java Virtual machine in its code. You need to specify some Java-specific configuration parameters in the INFORMIX ONCONFIG configuration file. They should look like this:


Listing 1. Snapshot of ONCONFIG file on UNIX
                
VPCLASS            jvp,num=1                         # Number of JVPs to start with

JVPJAVAHOME    /usr/informix/ids_10/extend/krakatoa/jre/      

JVPHOME        /usr/informix/ids_10/extend/krakatoa      # Krakatoa installation directory

JVPPROPFILE     /usr/informix/ids_10/extend/krakatoa/.jvpprops       # JVP  property file

JVPLOGFILE    /usr/informix/ids_10/jvp.log                  # JVP log file.

JDKVERSION        1.3                           # JDK version supported by this server

JVMTHREAD       native                          # Java VM thread type(green or native)

# The path to the JRE libraries relative to JVPJAVAHOME
JVPJAVALIB                      /lib/sparc/

# The JRE libraries to use for the Java VM
JVPJAVAVM                      hpi:server:verify:java:net:zip:jpeg

# use JVPARGS to change Java VM configuration
#To display jni call

#JVPARGS    -verbose:jni

# Classpath to use upon Java VM start-up (use _g version for debugging)
                                                     
JVPCLASSPATH   /usr/informix/ids_10/extend/krakatoa/krakatoa.jar:
                 /usr/informix/ids_10/extend/krakatoa/jdbc. jar                    


How to create and register UDRs in Java

Follow these steps to create and register the UDRs:

  1. Write the body of the UDR in a Java file, similar to the following example:


    Listing 2. Snapshot of UDR in Java: Circle.java
                            
    	
    public class Circle
    {
    	private static double PI = 3.14159;
    
    	public static double area(double c)
    	{
    		return PI * c*c
        	}
    }
          

  2. Before invoking the UDR in SQL statement, register the UDR in the current database using CREATE FUNCTION or CREATE PROCEDURE statement as follows:
    CREATE FUNCTION area (float) RETURNS float EXTERNAL NAME 'circle_jar:Circle.area(double)' LANGUAGE JAVA NOT VARIANT END FUNCTION You can also create a Java file and compile it (as in given sample code: Create Cust UDT.java).
  3. Use the javac command to compile the body of the UDR and create the class file.
  4. Use the jar command to create jar file, which will be installed on the server.
  5. Install the jar file:
    Install the jar files using SQLJ built-in procedure install_jar.


    Listing 3
                            
    execute procedure sqlj.install_jar('file:/work/circle_jar.jar','circle_jar',1) 

UDRs can be registered using the deployment descriptor and manifest file also. If you use deployment descriptor then create a file (deploy.txt) as follows:


Listing 4
                

SQLACtions[] = {
    "BEGIN INSTALL
CREATE FUNCTION area (float) RETURNS float 
EXTERNAL NAME 'circle_jar:Circle.area(double)' LANGUAGE 
JAVA NOT VARIANT 
	END FUNCTION
     END INSTALL"
}

Create the manifest file manifest.txt as follows:
Name: deploy.txt
SQLJDeploymentDescriptor : TRUE

Create the jar file using manifest and deployment descriptor as follows:
Jar cvfm manifest.txt Circle_jar.jar deploy.txt Circle.class

Now the install jar step will register the UDR also.

How to use or execute UDRs

After registering the UDR, UDRs can be invoked in SQL statements, for example:
select area(3) from area_table;


Introduction to Rational Application Developer

RAD for Websphere is an integrated development environment that helps developers to quickly design, develop, analyze, test, profile, and deploy high quality Web, SOA, Java, J2EE and portal applications. It has an inbuilt Eclipse editor that helps to quickly develop Java classes and compile them, after which we can deploy them as Web services using inbuilt WebSphere Application Server. RAD also provides a testing environment so we can test the Web services on a standalone system before exposing them on the Web.

We used RAD to develop the Java classes and deploy the Web Services on WAS to test its functionality. With the help of a JDBC connection we were able to connect to the Informix server through which we retrieved data from the database and also use the Java UDRs registered on the Informix server. Hence, RAD provides the ONE platform where we can run and execute our application without further assistance.

Code used in sample application

The five programs that we used in our application are:


Listing 5: Customer.java
                

package customer;
import java.sql.*;
import com.informix.jdbc.IfmxUDTSQLInput;
import com.informix.jdbc.IfmxUDTSQLOutput;
public class Customer implements SQLData
{
	private String type = "customer";
	public int id=101;
	public int tbill;
	public int ebill;
	public int mbill;
	public int monyr;
    public String getSQLTypeName() { return type; }
    public void readSQL(SQLInput stream, String typeName)
        throws SQLException
    {
        IfmxUDTSQLInput in = (IfmxUDTSQLInput) stream;
        id = in.readInt();
        tbill= in.readInt();
        ebill= in.readInt();
        mbill= in.readInt();
        monyr= in.readInt();
    }
    public void writeSQL(SQLOutput stream) throws SQLException
    {
        IfmxUDTSQLOutput out = (IfmxUDTSQLOutput) stream;
        out.writeInt(id);
        out.writeInt(tbill);
        out.writeInt(ebill);
        out.writeInt(mbill);
        out.writeInt(monyr);    
    }
	public static Customer getCustomerDetail ( int cust_id) {
		Customer cust_obj=new Customer();
		try
		{
			Connection conn = null;
			try
			{
				Class.forName("com.informix.jdbc.IfxDriver");
			}
			catch (Exception e)
			{
				System.out.println("Error: failed to load Informix JDBC driver.");
				e.printStackTrace();
				return null;
			} 
			String url="jdbc:informix-sqli://XXX.XXX.XXX.com:7005/testdb:INFORMIXSERVER=ol_ids;
                                user=XXXXX;password=XXXXX";
			try
			{
				conn=DriverManager.getConnection(url);
			}
			catch(SQLException e)
			{
				System.out.println("ERROR: Failed to connect!");
				System.out.println("ERROR:" + e.getMessage());
				e.printStackTrace();
				return null;
			} 
			PreparedStatement pstmt=conn.prepareStatement("Select * from customer where id=?");
			pstmt.setInt(1,cust_id);
			ResultSet rs=pstmt.executeQuery();
			while(rs.next())
			{
				cust_obj.id =rs.getInt(1);
				cust_obj.tbill =rs.getInt(2);
				cust_obj.ebill =rs.getInt(3);
				cust_obj.mbill =rs.getInt(4);
				cust_obj.monyr =rs.getInt(5);
			}			
			rs.close();
			pstmt.close();
		}
		catch(SQLException e)
		{
			System.out.println("ERROR:" + e.getMessage());
			e.printStackTrace();
		}
		return cust_obj;  
	}
}




Listing 6: CustSOA.java
                

package customer;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.Iterator;
import java.util.StringTokenizer;


public class CustSOA {
	public String getBillDetail(int cust_id)
	{
		Customer c_out=new Customer();
		/*===================Connection Block==========*/
		Connection conn = null;
		try
		{
			Class.forName("com.informix.jdbc.IfxDriver");
		}
		catch (Exception e)
		{
			System.out.println("Error: failed to load Informix JDBC driver.");
			e.printStackTrace();
			return null;
		} // End Driver Loading Block
		System.out.println("Informix JDBC driver loaded successfully.");
		// Connect to database
			String url="jdbc:informix-sqli://XXX.XXX.XXX.com:7005/testdb:
                         INFORMIXSERVER=ol_ids;user=XXXXX;password=XXXXX";
		//System.out.println("The url is:-"+url);
		try
		{
			conn=DriverManager.getConnection(url);
		}
		catch(SQLException e)
		{
			System.out.println("ERROR: Failed to connect!");
			System.out.println("ERROR:" + e.getMessage());
			e.printStackTrace();
			return null;
		}
		System.out.println("\nConnection established\n");
		/*=========End of connection Block=============*/
		
		/*============Call the UDR===================*/
        try {
        	 java.util.Map customtypemap = conn.getTypeMap();
             System.out.println("getTypeMap...ok");
             if (customtypemap == null)
             {
                 System.out.println("***ERROR: map is null!");
                 return null;
             }
            customtypemap.put("customer", Class.forName("customer.Customer")); 
        	String s = "select getCustomerDetail("+cust_id+") from customer";
            System.out.println(s);
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery(s);
            if (rs.next())
                {
            		c_out=(Customer) rs.getObject(1);
                    System.out.println("   ID = " + c_out.id);
                    System.out.println("   ID = " + c_out.tbill);
                }
            rs.close();
            stmt.close();
        }
	    catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	    }
		return c_out.id+":"+c_out.tbill+":"+c_out.mbill+":"+c_out.ebill+":"+c_out.monyr;
	}
}



Listing 7: CreateCust UDT.java
                

import java.sql.*;
import java.lang.reflect.*;
public class CreateCustUdt
{
    String url = null;
    Connection conn = null;
    public static void main ()
    {
        new CreateCustUdt();
    }
    CreateCustUdt() {
	  String url="jdbc:informix-sqli://XXX.XXX.XXX.com:7005/testdb:
                           INFORMIXSERVER=ol_ids;user=XXXXX;password=XXXXX";
        // --------------
        // Loading driver
        // --------------
        try {
            Class.forName("com.informix.jdbc.IfxDriver");
        }
        catch (java.lang.ClassNotFoundException e) {
            System.out.println("\n***ERROR: " + e.getMessage());
            e.printStackTrace();
            return;
        }
         try {
            conn = DriverManager.getConnection(url);
        }
        catch (SQLException e) {
            System.out.println("URL = '" + url + "'");
            System.out.println("\n***ERROR: " + e.getMessage());
            e.printStackTrace();
            return;
        }
        Method getCustomerDetailmethod = null;
        try {
            Class c = Class.forName("Customer");			
            getCustomerDetailmethod = c.getMethod("getCustomerDetail", new Class[]  
                                                             {Integer.TYPE });
        }
        catch (ClassNotFoundException e) {
            System.out.println("Cannot get Class: " + e.toString());
            return;
        }
        catch (NoSuchMethodException e) {
            System.out.println("Cannot get Method: " + e.toString());
            return;
        }
        UDTMetaData mdata = null;
        try {
            System.out.print("Setting mdata...");
            mdata = new UDTMetaData();
            mdata.setSQLName("Customer");
            mdata.setLength(24);
            mdata.setAlignment(UDTMetaData.EIGHT_BYTE);
            mdata.setUDR(getCustomerDetailmethod, "getCustomerDetail");
            mdata.setJarFileSQLName("Customer_jar");
            System.out.println("ok");
        }
        catch (SQLException e) {
            System.out.println("\n***ERROR: " + e.getMessage());
            return;
        }
        UDTManager udtmgr = null;
        try {
            udtmgr = new UDTManager(conn);   
            String jarfilename = udtmgr.createJar(mdata,
                new String[] {"Customer.class"}); // jarfilename = Customer.jar
            udtmgr.setJarTmpPath("/tmp");
            udtmgr.createUDT(mdata,
            "C:\\eclipse\\CUST_TEST\\" + jarfilename, "Customer", 0);
            System.out.println("UDT/UDR Created");
            }
        catch (SQLException e)
            {
            System.out.println("\n***ERROR: " + e.getMessage());
            return;
            }
        System.out.println();
    }
    private void executeUpdate(String s)
    {
        try
            {
            Statement stmt = conn.createStatement();
            stmt.executeUpdate(s);
            stmt.close();
            }
        catch (SQLException e)
            {
            	e.printStackTrace();
            	return;
            }
    }   
}


Listing 8: CustSOAIndex.html
                
<HTML>
<HEAD>
<TITLE>Customer Detail</TITLE>
</HEAD>
<BODY>
<H1>Inputs</H1>
<FORM METHOD="POST" ACTION="CustSOAResult.jsp">
<INPUT TYPE="HIDDEN" NAME="method" VALUE="18">
<TABLE>
<TR>
<TD COLSPAN="1" ALIGN="LEFT">Enter Customer ID:</TD>
<TD ALIGN="left"><INPUT TYPE="TEXT" NAME="cust_id" SIZE=20></TD>
</TR>
</TABLE>
<BR>
<INPUT TYPE="SUBMIT" VALUE="Invoke">
<INPUT TYPE="RESET" VALUE="Clear">
</FORM>
</BODY>
</HTML>


Listing 9: CustSOAResult.jsp
                
<HTML>
<HEAD> <TITLE>Result</TITLE> </HEAD>
<BODY>
<H1>Result</H1>
<jsp:useBean id="sampleCustSOAProxyid" scope="session" class="customer.CustSOAProxy" />
    <%  String p_id=  request.getParameter("cust_id");
  int p_idTemp  = Integer.parseInt(p_id);
  java.lang.String ret_cust = sampleCustSOAProxyid.getBillDetail(p_idTemp);
if(ret_cust == null)
{    %>
<%=ret_cust%>
<% 
  } else {
String tempResultreturn = webserviceutils.com.ibm.etools.webservice.util.JspUtils.markup
     (String.valueOf(ret_cust));
  %>
        <% StringTokenizer st=new StringTokenizer(tempResultreturn,":");%>
		<b> 	<TABLE>
        	 <tr>
        		<td> Customer ID </td>
		<td> <%= st.nextToken() %> </td>
           	</tr>
	<tr>
            	<td> Telephone Bill </td>
		<td>  	<%= st.nextToken() %> </td>
	</tr>
	<tr>
        		<td> Elect Bill </td>
		<td> <%= st.nextToken() %> </td>
	</tr>
	<tr>
            	<td> Mobile Phone Bill </td>
		<td> <%= st.nextToken() %> </td>
	</tr>
	<tr>
            	<td> Year & Month </td>
		<td> <%= st.nextToken() %> </td>
	</tr>
		</TABLE>   </b>
        <% } %>
</BODY>
</HTML>

Procedure to create the Web service used in the sample appication

Follow these steps to create the Web service and expose the method:

  1. Create a dynamic project.
    Select Launch File > New > Project to create a new project, then choose dynamic Web project:

    Figure 2. Creating dynamic project
    Creating dynamic project

  2. Create a new package, where all the source code will be created.
    Select JavaSource > New > Package:


    Figure 3. Create new package
    Create new package

  3. Create a new Java class that will store the Web service code:


    Figure 4. Create new Java class
    Create new Java class

  4. Create a Web service, using the default options. RAD provides the functionality to create Web Services using JavaBeans.
    Select File > New > Web Service:

    Figure 5. Create new Web service
    Create new Web service

  5. In the WebService explorer select Java Bean Web Service and other option shown in the figure.

    Figure 6. Select Java Beans Web service
     Select Java Beans Web service

  6. When the Object Selection Page appears, click Browse Classes..., type customer.CustSOA, and click OK.

    Figure 7. Java bean identity
    Java bean identity



    Figure 8. Web services explorer
    Web services explorer

  7. In WebService client Test Page check the methods to expose. Click Next > Finish.


    Figure 9. Web services explorer
    Web services explorer



    Figure 10. Web services explorer
    Web services explorer

  8. Invoke the method. The exposed method can be tested on this page by clicking the hyperlink.


    Figure 11. The exposed method
    The exposed method



    Figure 12. Methods in a browser
    Methods in a browser


The RAD directory structure

This screen shows the source structure of the dynamic Web project and the generated client project.


Figure 13. Directory structure
Directory structure

Here is the main screen of the application:


Figure 14. Main page
Main page

Here is the results screen of the application:


Figure 15. Result page
Result page

Acknowledgement

We would like to thank Madhusudhan Ramidi for his support and the TWISTER team for their ideas without which we would not have thought so far.


Resources

Learn

Get products and technologies

Discuss

About the authors

Soumita Ghosh photo

Soumita Ghosh worked within the Informix team as part of the Classics Development Team for a year. Now she works with the Visual Age team on XLC/XLC++ compilers.

Sobha Cheruku photo

Sobha Rani Cheruku works for Lab Services and handles Informix customer calls in India.

Akhilesh Tiwary photo

Akhilesh Kumar Tiwary is a member of the Classics Development Team, working on JDBC, C-ISAM, ESQL/COBOL, ISA and ISPY.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Information Management, SOA and Web services, Rational, Java technology
ArticleID=163865
ArticleTitle=Deploy Java UDRs through Web services on Informix using Rational Application Developer
publish-date=09282006
author1-email=soumita.ghosh@in.ibm.com
author1-email-cc=
author2-email=scheruku@in.ibm.com
author2-email-cc=
author3-email=aktiwary@in.ibm.com
author3-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers