Using jpub to create webserivce proxy for callouts.

Posted by Steve Racanovic | Posted in , | Posted on 11:58 AM

2

Im my preivous blog I created a simple webservice and used plsql to call the webservice from the database. Here I will use jpub to generate my java proxy and use that to call my webservice without the need to code any plsql. Note all of these steps are done upon the previous blog beginning completed.

1. Download and unzip jpub. You can get it from http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/index.html
Im using JPublisher 10g Release 10.2


C:\Documents and Settings\stever\Desktop> set_database.bat
C:\Documents and Settings\stever\Desktop> oracle_home
D:\Oracle\product\10.2.0\db_1
C:\Documents and Settings\stever\Desktop> unzip jpub_102.zip -d %oracle_home%
Archive: jpub_102.zip
inflating: D:/Oracle/product/10.2.0/db_1/sqlj/lib/sqljutl.sql
inflating: D:/Oracle/product/10.2.0/db_1/sqlj/lib/translator.jar
...


2. Set the classpath and run jpub.


C:\Documents and Settings\stever\Desktop>cdo

D:\Oracle\product\10.2.0\db_1

D:\Oracle\product\10.2.0\db_1>cd sqlj\bin

D:\Oracle\product\10.2.0\db_1\sqlj\bin>ll
Volume in drive D is ACERDATA
Volume Serial Number is 4059-B823

Directory of D:\Oracle\product\10.2.0\db_1\sqlj\bin

07/21/2005 03:34 AM <DIR> .
07/21/2005 03:34 AM <DIR> ..
07/21/2005 03:34 AM 1,376 jpub
07/21/2005 03:34 AM 2,834 jpub.c
07/21/2005 03:34 AM 50,619 jpub.exe
07/21/2005 03:34 AM 267 README.txt
4 File(s) 55,096 bytes
2 Dir(s) 8,243,344,384 bytes free

D:\Oracle\product\10.2.0\db_1\sqlj\bin> cd ..
D:\Oracle\product\10.2.0\db_1\sqlj>java_home
D:\Oracle\product\10.2.0\db_1\jdk

D:\Oracle\product\10.2.0\db_1\sqlj>classpath
.;D:\Oracle\product\10.2.0\db_1\sqlj\lib\translator.jar;
D:\Oracle\product\10.2.0\db_1\sqlj\lib\runtime12.jar;
D:\Oracle\product\10.2.0\db_1\sqlj\lib\dbwsa.jar;D:\Oracle\product\10.2
.0\db_1\javavm\lib\aurora.zip;
D:\Oracle\product\10.2.0\db_1\jdbc\lib\ojdbc14.jar;

D:\Oracle\product\10.2.0\db_1\sqlj>jpub -u wsuser/wsuser -sysuser sys/welcome1
-proxywsdl=http://stever-5670:8988/DatabaseWSDemo-WS-context-root/MyWebService1SoapHttpPort?WSDL
-endpoint=http://stever-5670:8988/DatabaseWSDemo-WS-context-root/MyWebService1SoapHttpPort
tmp\src\genproxy\MyWebService1SoapHttpPortClientJPub.java
plsql_wrapper.sql
plsql_dropper.sql
plsql_grant.sql
plsql_revoke.sql
Executing plsql_dropper.sql
Executing plsql_wrapper.sql
Executing plsql_grant.sql
Loading plsql_proxy.jar


3. Call the webservice.


D:\Oracle\product\10.2.0\db_1\sqlj>sqlplus wsuser/wsuser

SQL*Plus: Release 10.2.0.3.0 - Production on Mon Nov 10 19:36:58 2008

Copyright (c) 1982, 2006, Oracle. All Rights Reserved.

Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> select jpub_plsql_wrapper.sayhelloworld from dual;

SAYHELLOWORLD
--------------------------------------------------------------------------------
Hello World

SQL> select jpub_plsql_wrapper.sayhelloname('Steve') from dual;

JPUB_PLSQL_WRAPPER.SAYHELLONAME('STEVE')
--------------------------------------------------------------------------------
Hello Steve

SQL>

NOTE: My set_database.bat file simply has my environment settings in there.
This is where I set the classpath. It looks like:

set ORACLE_HOME=D:\Oracle\product\10.2.0\db_1
set ORACLE_SID=ORCL
set JAVA_HOME=%ORACLE_HOME%\jdk
set PATH=%ORACLE_HOME%\bin;%TT_HOME%\bin;%JAVA_HOME%\bin;%ORACLE_HOME%\sqlj\bin;%PATH%
set TNS_ADMIN=D:\Oracle\product\10.2.0\db_1\NETWORK\ADMIN
set CLASSPATH=.;%ORACLE_HOME%\sqlj\lib\translator.jar;
%ORACLE_HOME%\sqlj\lib\runtime12.jar;%ORACLE_HOME%\sqlj\lib\dbwsa.jar;
%ORACLE_HOME%\javavm\lib\aurora.zip;%ORACLE_HOME%\jdbc\lib\ojdbc14.jar;

Using UTL_DBWS Package To Call A Web Service From PL/SQL Code.

Posted by Steve Racanovic | Posted in | Posted on 3:12 PM

2

I am going to show a simple example that will call my web service from my database. I will be using JDev 10.1.3.x to create and run my web service. My database and web service will all be running from my local machine.

1. My first step is to upgrade my database to 10.2.0.2 or later. UTL_DBWS will not work on 10.2.0.1. While its upgrading, I need to download the latest UTL_DBWS from
http://www.oracle.com/technology/sample_code/tech/java/jsp/dbwebservices.html

* I am going to use 10.1.3.1 Callout Utility for 10g and 11g RDBMS (ZIP, ~13MB)

Extract the downloaded file like:

unzip dbws-callout-utility-10131.zip sqlj/* -d $ORACLE_HOME
unzip dbws-callout-utility-10131.zip samples/* -d $ORACLE_HOME/sqlj
unzip dbws-callout-utility-10131.zip *.htm -d $ORACLE_HOME/sqlj

2. Ensure that I have $ORACLE_HOME/bin in my path. First, I need to run the following command to load the libraries (run this from the $ORACLE_HOME/sqlj/lib folder).

loadjava -u username/password -r -v -f -s -grant public -genmissing dbwsclientws.jar dbwsclientdb102.jar

The username and password is this example will be the sys user.


Check my database is upgraded/correct and load the jar files.

NOTE: This may take a while to run.

3. Create a new user to use web services utl_dbws package and give grant privileges.

create user wsuser identified by wsuser
default tablespace users
temporary tablespace temp
/

grant connect, resource to wsuser;



4. Once the packages had been loaded (step 2), the next step is to provide grants from the schema where the jar files have been loaded to our 'WSUSER'. These grants will have to run from where the libraries are installed. 'SYS' user.


execute dbms_java.grant_permission('<user schema>','SYS:java.lang.RuntimePermission', 

'accessClassInPackage.sun.util.calendar','');



execute dbms_java.grant_permission('<user schema>','SYS:java.lang.RuntimePermission',

'getClassLoader','');



execute dbms_java.grant_permission('<user schema>','SYS:java.net.SocketPermission','*',

'connect,resolve');



execute dbms_java.grant_permission('<user schema>','SYS:java.util.PropertyPermission','*',

'read,write');



execute dbms_java.grant_permission('<user schema>','SYS:java.lang.RuntimePermission',

'setFactory','');






5. Now using Jdev, I create my java class as follows.


package ws;

public class HelloWorld {
public HelloWorld() {
}

public String sayHelloWorld(){
return "Hello World";
}

public String sayHelloName(String n){
return "Hello " + n;
}
}


6. I then create a web service from this class.



* Select "J2EE 1.4 (JAX-RPC) Web Service"

I then click on finished at Step 1 of 8 of the 'Create Java J2EE 1.4 Web Service' wizard so it uses all the default setting.

7. Then I ran the web service in the embedded server.



And checked my WS WSDL to ensure it is running.

http://stever-5670:8988/DatabaseWSDemo-WS-context-root/MyWebService1SoapHttpPort
http://stever-5670:8988/DatabaseWSDemo-WS-context-root/MyWebService1SoapHttpPort?WSDL



This is how my deployed WSDL looks like:

This XML file does not appear to have any style information associated with it. The document tree is shown below.


-<definitions name="MyWebService1" targetNamespace="http://ws/">
-<types>
-<schema targetNamespace="http://ws/types/" elementFormDefault="qualified">
-<element name="sayHelloNameElement">
-<complexType>
-<sequence>
<element name="n" type="string" nillable="true"/>
-</sequence>
</complexType>
</element>
-<element name="sayHelloNameResponseElement">
-<complexType>
-<sequence>
<element name="result" type="string" nillable="true"/>
</sequence>
</complexType>
</element>
-<element name="sayHelloWorldElement">
-<complexType>
<sequence/>
</complexType>
</element>
-<element name="sayHelloWorldResponseElement">
-<complexType>
-<sequence>
<element name="result" type="string" nillable="true"/>
</sequence>
</complexType>
</element>
</schema>
</types>
-<message name="MyWebService1_sayHelloName">
<part name="parameters" element="tns0:sayHelloNameElement"/>
</message>
-<message name="MyWebService1_sayHelloNameResponse">
<part name="parameters" element="tns0:sayHelloNameResponseElement"/>
</message>
-<message name="MyWebService1_sayHelloWorld">
<part name="parameters" element="tns0:sayHelloWorldElement"/>
</message>
-<message name="MyWebService1_sayHelloWorldResponse">
<part name="parameters" element="tns0:sayHelloWorldResponseElement"/>
</message>
-<portType name="MyWebService1">
-<operation name="sayHelloName">
<input message="tns:MyWebService1_sayHelloName"/>
<output message="tns:MyWebService1_sayHelloNameResponse"/>
</operation>
<operation name="sayHelloWorld">
<input message="tns:MyWebService1_sayHelloWorld"/>
<output message="tns:MyWebService1_sayHelloWorldResponse"/>
</operation>
</portType>
-<binding name="MyWebService1SoapHttp" type="tns:MyWebService1">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
-<operation name="sayHelloName">
<soap:operation soapAction="http://ws//sayHelloName"/>
-<input>
<soap:body use="literal"/>
</input>
-<output>
<soap:body use="literal"/>
</output>
</operation>
-<operation name="sayHelloWorld">
<soap:operation soapAction="http://ws//sayHelloWorld"/>
-<input>
<soap:body use="literal"/>
</input>
-<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
-<service name="MyWebService1">
-<port name="MyWebService1SoapHttpPort" binding="tns:MyWebService1SoapHttp">
<soap:address
location="http://stever-5670:8988/DatabaseWSDemo-WS-context-root/MyWebService1SoapHttpPort"/>
</port>
</service>
</definitions>


8. Now using the UTL_DBWS package, I will create my PL/SQL code.


CREATE OR REPLACE PACKAGE HelloWorld
AS

FUNCTION SayHelloWorld RETURN VARCHAR2;
FUNCTION sayHelloName(yourname IN VARCHAR2) RETURN VARCHAR2;

END HelloWorld;
/

CREATE OR REPLACE PACKAGE BODY HelloWorld AS

FUNCTION SayHelloWorld
RETURN VARCHAR2
IS

service_ sys.utl_dbws.SERVICE;
call_ sys.utl_dbws.CALL;
service_qname sys.utl_dbws.QNAME;
port_qname sys.utl_dbws.QNAME;
xoperation_qname sys.utl_dbws.QNAME;
xstring_type_qname sys.utl_dbws.QNAME;
response sys.XMLTYPE;
request sys.XMLTYPE;

BEGIN
service_qname := sys.utl_dbws.to_qname(null, 'SayHelloWorld');
service_ := sys.utl_dbws.create_service(service_qname);
call_ := sys.utl_dbws.create_call(service_);
sys.utl_dbws.set_target_endpoint_address(call_
, 'http://stever-5670:8988/DatabaseWSDemo-WS-context-root/MyWebService1SoapHttpPort');

sys.utl_dbws.set_property( call_
, 'SOAPACTION_USE'
, 'TRUE'
);

sys.utl_dbws.set_property( call_
, 'SOAPACTION_URI'
, 'http://ws//sayHelloWorld'
);

sys.utl_dbws.set_property( call_
, 'OPERATION_STYLE'
, 'document'
);

request := sys.XMLTYPE('<sayHelloWorldElement xmlns="http://ws/types/" />');

response :=sys. utl_dbws.invoke(call_, request);
return response.extract('//child::text()'
, 'xmlns="http://stever-5670:8988/DatabaseWSDemo-WS-context-root/
MyWebService1SoapHttpPort"'
).getstringval();

END SayHelloWorld;

FUNCTION sayHelloName(yourname IN VARCHAR2) RETURN VARCHAR2 AS

service_ sys.utl_dbws.SERVICE;
call_ sys.utl_dbws.CALL;
service_qname sys.utl_dbws.QNAME;
port_qname sys.utl_dbws.QNAME;
xoperation_qname sys.utl_dbws.QNAME;
xstring_type_qname sys.utl_dbws.QNAME;
response sys.XMLTYPE;
request sys.XMLTYPE;

BEGIN
service_qname := sys.utl_dbws.to_qname(null, 'SayHelloName');
service_ := sys.utl_dbws.create_service(service_qname);
call_ := sys.utl_dbws.create_call(service_);
sys.utl_dbws.set_target_endpoint_address(call_
, 'http://stever-5670:8988/DatabaseWSDemo-WS-context-root/MyWebService1SoapHttpPort');

sys.utl_dbws.set_property( call_
, 'SOAPACTION_USE'
, 'TRUE'
);

sys.utl_dbws.set_property( call_
, 'SOAPACTION_URI'
, 'http://ws//sayHelloName'
);

sys.utl_dbws.set_property( call_
, 'OPERATION_STYLE'
, 'document'
);

request := sys.XMLTYPE('<sayHelloNameElement xmlns="http://ws/types/">'
||'<n>' || yourname || '</n> </sayHelloNameElement>');

response :=sys. utl_dbws.invoke(call_, request);
return response.extract('//child::text()'
, 'xmlns="http://stever-5670:8988/DatabaseWSDemo-WS-context-root/
MyWebService1SoapHttpPort"'
).getstringval();

END SayHelloName;

END HelloWorld;
/


9. I then ran my package:

select helloworld.sayhelloworld from dual;

select helloworld.sayhelloname('Steve') from dual;

Performance using Bind Variables in Java Application

Posted by Steve Racanovic | Posted in , | Posted on 1:03 PM

1

The advantage of using bind variables within your Java application, it that provides greater application performance and uses less of the shared pool from the database.

This is illustrated in the following 2 examples.

Example 1: Using Bind variables.


package bindvariables;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import bindvariables.JDBCUtil;

public class Bind {

public static void main(String[] args) throws SQLException {

ResultSet rs = null;
Connection conn = null;
PreparedStatement pstmt = null;

try {
// Get Connection
conn = JDBCUtil.getConnection();
// Create statement
pstmt = conn.prepareStatement("SELECT ? FROM dual");
System.out.println("Start: " + new Date());
for (int i = 1; i < 100000; i++) {
// Use bind variable for subsitution
pstmt.setString(1, String.valueOf(i));
// Execute the query
rs = pstmt.executeQuery();
//if (i % 1000 == 1)
// System.out.println("Print: " + i);
}
System.out.println("End: " + new Date());

} catch (SQLException se) {
System.out.println("SQL Exception:");
se.printStackTrace();
}
finally {
// Close the result set, statement and the connection
JDBCUtil.close(rs,pstmt,conn);
}
}
}


Running this application returns the following:

Start: Mon Mar 31 11:36:04 EST 2008
End: Mon Mar 31 11:36:51 EST 2008

It shows the application being executed within less than a minute.

Now the second example does not use bind variables and force the use of Hard Parse on the database.

Example 2: Not using bind variables.


package bindvariables;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;

public class NonBind {

public static void main(String[] args) throws SQLException {

ResultSet rs = null;
Connection conn = null;
Statement stmt = null;

try {
// Get Connection
stmt = (JDBCUtil.getConnection()).createStatement();
System.out.println("Start: " + new Date());
for (int i = 0; i < 100000; i++) {
// Execute Statement
rs = stmt.executeQuery("SELECT " + i + " FROM dual");
//if (i % 1000 == 1)
// System.out.println("Print: " + i);
}
System.out.println("End: " + new Date());
} catch (SQLException se) {
System.out.println("SQL Exception:");
se.printStackTrace();
}
finally {
// Close the result set, pstatement and the connection
JDBCUtil.close(rs,stmt,conn);
}
}
}


Running this application returns the following:

Start: Mon Mar 31 11:31:45 EST 2008
End: Mon Mar 31 11:35:34 EST 2008

It shows the application being executed over 4 minutes.

As you can see, ensure you use bind variables for performance when coding your application.

My JDBCUtil class method look like:

...

public static void close(ResultSet resultSet, Statement statement,
Connection connection) {
try {
if (resultSet != null)
close(resultSet);
if (statement != null)
close(statement);
if (connection != null)
close(connection);
} catch (Exception e) {
e.printStackTrace();
}
}

public static void close(ResultSet resultSet, PreparedStatement pstatement,
Connection connection) {
try {
if (resultSet != null)
close(resultSet);
if (pstatement != null)
close(pstatement);
if (connection != null)
close(connection);
} catch (Exception e) {
e.printStackTrace();
}
}

public static Connection getConnection() throws SQLException {
String username = "scott";
String password = "tiger";
String thinConn =
"jdbc:oracle:thin:@sracanov-au2.au.oracle.com:1522:orcl";
DriverManager.registerDriver(new OracleDriver());
Connection conn =
DriverManager.getConnection(thinConn, username, password);
conn.setAutoCommit(false);
return conn;
}
}


...

Database (Web Services Call-Out) class error

Posted by Steve Racanovic | Posted in , | Posted on 11:28 AM

2

When receiving the following error:

ERROR at line 1:
ORA-29540: class oracle/jpub/runtime/dbws/DbwsProxy does not exist

ORA-06512: at "SYS.UTL_DBWS", line 195

ORA-06512: at "INTERFACE.GET_JOKE", line 13

The java classes are not installed in the database user schema.

Logout of sqlplus and run:
loadjava -u / -r -v -f -s -grant public -genmissing  dbwsclientws.jar dbwsclientdb102.jar

Where user/password are the details of the database user using the database web service callout.

Further details can be found here:
http://www.oracle.com/technology/sample_code/tech/java/jsp/callout_users_guide.htm
http://www.oracle.com/technology/tech/java/oc4j/1003/how_to/how-to-ws-db-javacallout.html

How to configure an Oracle J2CA JMS RA and use it with a java client

Posted by Steve Racanovic | Posted in , , | Posted on 2:20 PM

0

This article explain’s in point form to create a java client that excesses a resource adapter, from an oc4j instance that is configure with fast connection failover to RAC database. It extends from my previous JMS posts.

I am using:
OAS 10.1.3.2.0
RAC DB 10.2.0.3.0
Jdev 10.1.3.2

1. First logged in the database as “sys” user and created the queue.

I ran the following script:


------------------------------------------------------------
drop user jmsuser cascade;
------------------------------------------------------------
create user jmsuser identified by jmsuser;

grant create database link, create sequence, create session,
create synonym, create public synonym, drop public synonym,
create table, create view, create indextype,
create procedure, create trigger, create type,
unlimited tablespace
to jmsuser;

grant aq_administrator_role to jmsuser;
grant execute on sys.dbms_aqadm to jmsuser;
grant execute on sys.dbms_aq to jmsuser;

grant execute on sys.dbms_aqin to jmsuser;
grant execute on sys.dbms_aqjms to jmsuser;

grant force any transaction to jmsuser;

------------------------------------------------------------
connect jmsuser/jmsuser@judd;
------------------------------------------------------------
create or replace package ROUTERAdmin
AUTHID DEFINER as

procedure createQueueTable(qtablename IN VARCHAR2);
procedure createTopicTable(ttablename IN VARCHAR2);

procedure createQueue(
qname IN VARCHAR2,
qtablename IN VARCHAR2);

procedure createTopic(
tname IN VARCHAR2,
ttablename IN VARCHAR2);

end ROUTERAdmin;
/
show errors;
------------------------------------------------------------
------------------------------------------------------------
create or replace package body ROUTERAdmin as

---------------------------------
---------------------------------
procedure createQueue(
qname IN VARCHAR2,
qtablename IN VARCHAR2) is
begin
--
createQueueTable(qtablename);

--
DBMS_AQADM.CREATE_QUEUE(
Queue_name => qname,
Queue_table => qtablename,
max_retries => '2');

--
DBMS_AQADM.START_QUEUE(
queue_name => qname);
end;
---------------------------------
procedure createTopic(
tname IN VARCHAR2,
ttablename IN VARCHAR2) is
begin
--
createTopicTable(ttablename);

--
DBMS_AQADM.CREATE_QUEUE(
Queue_name => tname,
Queue_table => ttablename,
max_retries => '2');

--
DBMS_AQADM.START_QUEUE(
queue_name => tname);
end;

---------------------------------
procedure createQueueTable(qtablename IN VARCHAR2) is
begin
DBMS_AQADM.CREATE_QUEUE_TABLE(
Queue_table => qtablename,
Queue_payload_type => 'SYS.AQ$_JMS_MESSAGE',
sort_list => 'PRIORITY,ENQ_TIME',
multiple_consumers => false,
compatible => '9.2');
exception
when others then
dbms_output.put_line('EXC: createQueueTable');
return;
end;
---------------------------------
procedure createTopicTable(ttablename IN VARCHAR2) is
begin
DBMS_AQADM.CREATE_QUEUE_TABLE(
Queue_table => ttablename,
Queue_payload_type => 'SYS.AQ$_JMS_MESSAGE',
sort_list => 'PRIORITY,ENQ_TIME',
multiple_consumers => TRUE,
compatible => '9.2');
exception
when others then
dbms_output.put_line('EXC: createTopicTable');
return;
end;
---------------------------------

end ROUTERAdmin;
/
show errors;


------------------------------------------------
----- create topics and queues for jmsrouteruser
------------------------------------------------
connect jmsuser/jmsuser@judd;

begin
---- Queues ----
ROUTERAdmin.createQueue('RPQueue','RPTABLE');
ROUTERAdmin.createQueue('RPLogQ','RPQLOGTABLE');
end;
/

2. I am using the oc4j instance “OC4J_Apps”

Created a connection pool called “fcfConnPoolJMS”

ULR: jdbc:oracle:thin:@(DESCRIPTION=(LOAD_BALANCE=on)(...))

Username: jmsuser
Password: jmsuser

Connection Factory Properites:
connectionCachingEnabled = true
fastConnectionFailoverEnabled =true

Initial size of Connection Cache = 10
Minimum Number of Connections = 10
Maximum Number of Connections = 20





Save

3. Create a data source

Name: fcfDSJMS
JNDI Location: jdbc/fcfDSJMS
Connection Pool: fcfConnPoolJMS



Save

4. Create a Database Persistence.

OC4J_Apps -> Administration -> Database Persistence -> Deploy

Resource Adapter Module Name = mySimpleTestRA

Add new Resource Provider
Resource Provider Name = mySimpleTestRP
Datasource JNDI Location = jdbc/fcfDSJMS



Saved and then restarted OC4J instance “OC4J_Apps”.

5. Created Connection Factory.

OC4J_Apps -> Applications -> Standalone Resource Adapters (select from combo box) -> mySimpleTestRA (Resource Adapter Module)



Connection Factories -> Create

Connection Factory Interface = javax.jms.QueueConnectionFactory
JNDI Location = mySimpleTestRA



Save.

6. Create Administration Objects

Administration Objects -> create

Object Class = oracle.j2ee.ra.jms.generic.AdminObjectQueueImpl

JNDI Location = mySimpleTestRA/AutoWrap

Configuration Properties
ResourceProviderName = mySimpleTestRP



Save.

7. Create my java test client in Jdev.

package jmsracclient;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import javax.jms.*;

public class JMSClient {

public static void main(String[] args) {
final String queueName =
"java:comp/resource/mySimpleTestRP/Queues/RPQueue";
final String queueConnectionFactoryName =
"java:comp/resource/mySimpleTestRP/QueueConnectionFactories/QCF";
final String oc4juser = "oc4jadmin";
final String oc4juserpassword = "welcome1";
final String urlProvider = "opmn:ormi://";
final String jmsProviderHost = "sracanov-au2.au.oracle.com";
final String colon = ":";
final String opmnPort = "6005";
final String oc4jinstance = "OC4J_Apps";
final int NUMBER_OF_MESSAGES = 5;
Context jndiContext = null;
QueueConnectionFactory queueConnectionFactory = null;
QueueConnection queueConnection = null;
QueueSession queueSession = null;
Queue queue = null;
QueueSender queueSender = null;
TextMessage message = null;

/*
* Set the environment for a connection to the OC4J instance
*/
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"oracle.j2ee.rmi.RMIInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, oc4juser);
env.put(Context.SECURITY_CREDENTIALS, oc4juserpassword);
env.put(Context.PROVIDER_URL,
urlProvider + jmsProviderHost + colon + opmnPort + colon +
oc4jinstance + "/default");

/*
* Set the Context Object.
* Lookup the Queue Connection Factory.
* Lookup the JMS Destination.
*/
try {
jndiContext = new InitialContext(env);
System.out.println("Env set");
queueConnectionFactory =
(QueueConnectionFactory)jndiContext.lookup(queueConnectionFactoryName);
System.out.println("Got QCF");
queue = (Queue)jndiContext.lookup(queueName);
System.out.println("Got Q");
} catch (NamingException e) {
System.out.println("JNDI lookup failed: " + e.toString());
System.exit(1);
}
System.out.println("End of test client");
/*
* Create connection.
* Create session from connection.
* Create sender.
* Create text message.
* Send messages.
* Send non text message to end text messages.
* Close connection.
*/
try {
queueConnection = queueConnectionFactory.createQueueConnection();
queueSession =
queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queueSender = queueSession.createSender(queue);
message = queueSession.createTextMessage();
for (int i = 0; i < NUMBER_OF_MESSAGES; i++) {
message.setText("Message " + (i + 1));
System.out.println("Producing message: " + message.getText());
queueSender.send(message);
}
queueSender.send(queueSession.createBytesMessage());
} catch (JMSException e) {
System.out.println("Exception occurred: " + e.toString());
} finally {
if (queueConnection != null) {
try {
queueConnection.close();
} catch (JMSException e) {
System.out.println("Closing error: " + e.toString());
}
}
}
}
}


8. Ensure the project properties java options are set correctly for -Doracle.ons.oraclehome



This directory must contain opmn\conf\ons.config file. My ons.config file looks like:

localport=6100
remoteport=6202
nodes=aulnx11-vip.au.oracle.com:6202,aulnx12-vip.au.oracle.com:6202

9. The project should have the following libraries (in this order)

* JDBC Driver 10.2.0.3
* Apache Ant
* JSP Runtime
* Ons.jar
* J2EE



10. Run the java client. Received the following result:

Env set
Got QCF
Got Q
End of test client
Producing message: Message 1
Producing message: Message 2
Producing message: Message 3
Producing message: Message 4
Producing message: Message 5



Note: I didn’t explain the ons configuration on the oc4j server side for my OC4J_Apps instance.

If you have applied any patches to your Application Server, then use all the libraries from the server (step 9).

How to create a simple JMS topic, publisher and subscriber in Oracle 10g

Posted by Steve Racanovic | Posted in , | Posted on 2:48 PM

1

In continuing from my previous updates about jms, this time I am writing a simple file persistence jms topic.

I am still using the same version OracleAS 10.1.3.2.0 as the JMS Provider.

1. Create the JMS destination. Run the following from $OH\j2ee\home:

java -jar admin_client.jar deployer:oc4j:opmn://sracanov-au.au.oracle.com:6007/JMS oc4jadmin welcome1 -addDestination -domain topic -name jmstopic -jndiLocation jms/MyJMSTopic -persistenceFile myjmstopic.txt

This will create a presistence file “myjmstopic.txt” to store the message. You can see the file by navigating to

$OH\j2ee\<instance_name>\persistence\<instance_name>_<group_name>_1

[sracanov@sracanov-au D]$ java -jar admin_client.jar deployer:oc4j:opmn://sracanov-au.au.oracle.com:6007/JMS oc4jadmin welcome1 -addDestination -domain topic -name jmstopic -jndiLocation jms/MyJMSTopic -persistenceFile myjmstopic.txt
Command was successful

2. Create the JMS connection factory. Run the following from $OH\j2ee\home:

java -jar admin_client.jar deployer:oc4j:opmn://sracanov-au.au.oracle.com:6007/JMS oc4jadmin welcome1 -addJMSConnectionFactory -domain topic -jndiLocation jms/MyJMSTCF

[sracanov@sracanov-au D]$ java -jar admin_client.jar deployer:oc4j:opmn://sracanov-au.au.oracle.com:6007/JMS oc4jadmin welcome1 -addJMSConnectionFactory -domain topic -jndiLocation jms/MyJMSTCF

3. We need to create 3 java classes. Once again, I am using Jdev to create my classes. So first I will create a new application and project.

I will need to make sure the follow libraries are including in the project:
· J2EE
· Apache Ant

4. Now create the publisher client:

package project1;

import java.util.Hashtable;

import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Session;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;


public class MyTopicPublisher {

public static void main(String[] args) {
final String topicName = "jms/MyJMSTopic";
final String topicConnectionFactoryName = "jms/MyJMSTCF";
final String oc4juser = "oc4jadmin";
final String oc4juserpassword = "welcome1";
final String urlProvider = "opmn:ormi://";
final String jmsProviderHost = "sracanov-au.au.oracle.com";
final String colon = ":";
final String opmnPort = "6007";
final String oc4jinstance = "OC4J_JMS";
final int NUMBER_OF_MESSAGES = 5;
TopicConnection topicConnection = null;
TopicConnectionFactory topicConnectionFactory = null;
Context jndiContext = null;
TopicSession topicSession = null;
Topic topic = null;
TopicPublisher topicPublisher = null;
MapMessage message = null;

/*
* Set the environment for a connection to the OC4J instance
*/
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"oracle.j2ee.rmi.RMIInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, oc4juser);
env.put(Context.SECURITY_CREDENTIALS, oc4juserpassword);
env.put(Context.PROVIDER_URL,
urlProvider + jmsProviderHost + colon + opmnPort + colon +
oc4jinstance + "/default");

/*
* Set the Context Object.
* Lookup the Topic Connection Factory.
* Lookup the JMS Destination.
*/
try {
jndiContext = new InitialContext(env);
topicConnectionFactory =
(TopicConnectionFactory)jndiContext.lookup(topicConnectionFactoryName);
topic = (Topic)jndiContext.lookup(topicName);
} catch (NamingException e) {
System.out.println("Lookup failed: " + e.toString());
System.exit(1);
}

/*
* Create connection.
* Create session from connection.
* Create publisher.
* Create text message.
* Send messages.
* Close connection.
*/
try {
topicConnection = topicConnectionFactory.createTopicConnection();
topicSession =
topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
topicPublisher = topicSession.createPublisher(topic);
message = topicSession.createMapMessage();
for (int i = 0; i < NUMBER_OF_MESSAGES; i++) {
message.setStringProperty("from", "from@" + jmsProviderHost);
message.setStringProperty("to", "to@" + jmsProviderHost);
message.setStringProperty("subject",
"Topic Message " + (i + 1));
message.setStringProperty("content",
"Message " + (i + 1) + " in Topic: \"" +
topicName + "\"");
System.out.println("Publishing message: " +
message.getStringProperty("from"));
System.out.println("Publishing message: " +
message.getStringProperty("to"));
System.out.println("Publishing message: " +
message.getStringProperty("subject"));
System.out.println("Publishing message: " +
message.getStringProperty("content"));
topicPublisher.publish(message);
}
} catch (JMSException e) {
System.out.println("Exception occurred: " + e.toString());
} finally {
if (topicConnection != null) {
try {
topicConnection.close();
} catch (JMSException e) {
System.out.println("Closing error: " + e.toString());
}
}
}
}
}

5. Now we need to create the message listener that will listen to meesages on map types:

package project1;

import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;

public class JMSTopicMapListener implements MessageListener {

public void onMessage(Message message) {
MapMessage msg = null;

try {
if (message instanceof MapMessage) {
msg = (MapMessage)message;
String from = msg.getStringProperty("from");
String to = msg.getStringProperty("to");
String subject = msg.getStringProperty("subject");
String content = msg.getStringProperty("content");
System.out.println("READING MESSAGE \n=============== \nFrom: " +
from + "\nTo: " + to + "\nSubject: " +
subject + "\nContent: " + content);
} else {
System.out.println("Wrong type");
}
} catch (JMSException e) {
System.out.println("JMSException in onMessage(): " + e.toString());
} catch (Throwable t) {
System.out.println("Exception in onMessage():" + t.getMessage());
}
}
}

6. Create the subscriber client:

package project1;

import javax.jms.*;

import javax.naming.*;

import java.util.Hashtable;

public class MyTopicSubscriber {

public static void main(String[] args) {
final String topicName = "jms/MyJMSTopic";
final String topicConnectionFactoryName = "jms/MyJMSTCF";
final String oc4juser = "oc4jadmin";
final String oc4juserpassword = "welcome1";
final String urlProvider = "opmn:ormi://";
final String jmsProviderHost = "sracanov-au.au.oracle.com";
final String colon = ":";
final String opmnPort = "6007";
final String oc4jinstance = "OC4J_JMS";
Context jndiContext = null;
TopicConnectionFactory topicConnectionFactory = null;
TopicConnection topicConnection = null;
TopicSession topicSession = null;
Topic topic = null;
TopicSubscriber topicSubscriber = null;
JMSTopicMapListener topicListener = null;

/*
* Set the environment for a connection to the OC4J instance
*/
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"oracle.j2ee.rmi.RMIInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, oc4juser);
env.put(Context.SECURITY_CREDENTIALS, oc4juserpassword);
env.put(Context.PROVIDER_URL,
urlProvider + jmsProviderHost + colon + opmnPort + colon +
oc4jinstance + "/default");

/*
* Set the Context Object.
* Lookup the Topic Connection Factory.
* Lookup the JMS Destination.
*/
try {
jndiContext = new InitialContext(env);
topicConnectionFactory =
(TopicConnectionFactory)jndiContext.lookup(topicConnectionFactoryName);
topic = (Topic)jndiContext.lookup(topicName);
} catch (NamingException e) {
System.out.println("Lookup failed: " + e.toString());
System.exit(1);
}

/*
* Create connection.
* Create session from connection; false means session is
* not transacted.
* Create subscriber.
* Register message listener (TextListener).
* Receive text messages from topic.
* Close connection.
*/
try {
topicConnection = topicConnectionFactory.createTopicConnection();
topicSession =
topicConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
topicSubscriber = topicSession.createSubscriber(topic);
topicListener = new JMSTopicMapListener();
topicSubscriber.setMessageListener(topicListener);
topicConnection.start();
System.out.println("Subscripted to topic: \"" + topicName + "\"");
while (true) {
}
} catch (JMSException e) {
System.out.println("Exception occurred: " + e.toString());
} finally {
if (topicConnection != null) {
try {
topicConnection.close();
} catch (JMSException e) {
System.out.println("Closing error: " + e.toString());
}
}
}
}
}

7. Ensure the follow Strings in the publisher and subcriber java class are set according to your environment:

final String topicName = "jms/MyJMSTopic";
final String topicConnectionFactoryName = "jms/MyJMSTCF";
final String oc4juser = "oc4jadmin";
final String oc4juserpassword = "welcome1";
final String urlProvider = "opmn:ormi://";
final String jmsProviderHost = "sracanov-au.au.oracle.com";
final String colon = ":";
final String opmnPort = "6007";
final String oc4jinstance = "JMS";

8. Run the subcriber class. The subscriber is waiting for message to be sent by the publisher. You will see the following message in the console.

Subscripted to topic: "jms/MyJMSTopic"


9. Run the publisher class. The following results in displayed in the publisher console:

Publishing message: from@sracanov-au.au.oracle.com
Publishing message: to@sracanov-au.au.oracle.com
Publishing message: Topic Message 1
Publishing message: Message 1 in Topic: "jms/MyJMSTopic"
Publishing message: from@sracanov-au.au.oracle.com
Publishing message: to@sracanov-au.au.oracle.com
Publishing message: Topic Message 2
Publishing message: Message 2 in Topic: "jms/MyJMSTopic"
Publishing message: from@sracanov-au.au.oracle.com
Publishing message: to@sracanov-au.au.oracle.com
Publishing message: Topic Message 3
Publishing message: Message 3 in Topic: "jms/MyJMSTopic"
Publishing message: from@sracanov-au.au.oracle.com
Publishing message: to@sracanov-au.au.oracle.com
Publishing message: Topic Message 4
Publishing message: Message 4 in Topic: "jms/MyJMSTopic"
Publishing message: from@sracanov-au.au.oracle.com
Publishing message: to@sracanov-au.au.oracle.com
Publishing message: Topic Message 5
Publishing message: Message 5 in Topic: "jms/MyJMSTopic"
Process exited with exit code 0.

10. Back in the subscriber console, the following message is displayed:

READING MESSAGE
===============
From: from@sracanov-au.au.oracle.com
To: to@sracanov-au.au.oracle.com
Subject: Topic Message 1
Content: Message 1 in Topic: "jms/MyJMSTopic"
READING MESSAGE
===============
From: from@sracanov-au.au.oracle.com
To: to@sracanov-au.au.oracle.com
Subject: Topic Message 2
Content: Message 2 in Topic: "jms/MyJMSTopic"
READING MESSAGE
===============
From: from@sracanov-au.au.oracle.com
To: to@sracanov-au.au.oracle.com
Subject: Topic Message 3
Content: Message 3 in Topic: "jms/MyJMSTopic"
READING MESSAGE
===============
From: from@sracanov-au.au.oracle.com
To: to@sracanov-au.au.oracle.com
Subject: Topic Message 4
Content: Message 4 in Topic: "jms/MyJMSTopic"
READING MESSAGE
===============
From: from@sracanov-au.au.oracle.com
To: to@sracanov-au.au.oracle.com
Subject: Topic Message 5
Content: Message 5 in Topic: "jms/MyJMSTopic"

Ensure you stop the subscriber client when done.

How to Send JMS Messages to one Oracle Application Server while reading it from another.

Posted by Steve Racanovic | Posted in , | Posted on 2:01 PM

2

The example demonstrates a queue on one server (Server A), while having an MDB on another server (Server B) that listens to the queue. It also includes a client that connects to Server B and reads the messages.

The example involves having 2 Oracle Application Server. I'm using Oracle AS 10.1.3.2.0.

The following outline the tasks to be complete:
a) Server A is used to send the message to.
Need to create a JMS destination and queue connection factory
The queue on Server A will be called jms/MyJMSQueue.
The queue connection factory Server A will be called jms/MyJMSQCF.
The client will connect to server A and send a message to the queue.

b) Server B is used to read the messages.
Need to create a queue connection factory destination that point to Server A and the JMS destination as in Server A.
The queue on Server B is the same as Server A.
The queue connection factory Server B will be called jms/MyRemoteQCF.
The MDB will be deployed to Server B. The MDB will listen to messages on Server A.
The client will connect to server B and read messages from the queue.

1. On Server A, create a JMS Destination.

[sracanov@sracanov-au2 JMS_SR]$ cd $ORACLE_HOME\j2ee\JMS

[sracanov@sracanov-au2]$ java -jar admin_client.jar deployer:oc4j:opmn://sracanov-au2.au.oracle.com:6005/JMS_SR oc4jadmin welcome1 -addDestination -domain queue -name jmsqueue -jndiLocation jms/MyJMSQueue

2. On Server B, create a JMS Destination. Same as in step 1.

[sracanov@sracanov-au2]$ java -jar admin_client.jar deployer:oc4j:opmn://sracanov-au.au.oracle.com:6007/JMS oc4jadmin welcome1 -addDestination -domain queue -name jmsqueue -jndiLocation jms/MyJMSQueue

3. On Server A, create a Connection Factory.

[sracanov@sracanov-au2 JMS_SR]$ java -jar admin_client.jar deployer:oc4j:opmn:// sracanov-au2.au.oracle.com:6005/JMS_SR oc4jadmin welcome1 -addJMSConnectionFactory -domain queue -jndiLocation jms/MyJMSQCF

4. On Server B, create a Connection Factory.

First determine the jms port for the OC4J instance you are using on Server A.

[oracle@sracanov-au2 JMS_SR]$ opmnctl status -l


OC4JGroup:default_group | OC4J:JMS_SR | 11196 | Alive | 857355163 | 253252 | 23:27:49 | jms:12604,ajp:12504,rmis:12704,rmi:12404


The instance in the example is using port 12604.

On Server B, run the following:

[sracanov@sracanov-au D]$ java -jar admin_client.jar deployer:oc4j:opmn:// sracanov-au.au.oracle.com:6007/JMS oc4jadmin welcome1 -addJMSConnectionFactory -jndiLocation jms/MyRemoteQCF -domain queue -host sracanov-au2.au.oracle.com -username oc4jadmin -password welcome1 -port 12604

5. Create the QueueProducer.

Use the example code from the previous blog to create the QueueProducer class. The QueueProducer will connection to Server A and send messages to the queue. You will need to make the following changes to the class.


String queueName = "jms/MyJMSQueue";
String queueConnectionFactoryName = "jms/MyJMSQCF";

And

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, “oracle.j2ee.rmi.RMIInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, "oc4jadmin");
env.put(Context.SECURITY_CREDENTIALS, "welcome1");
env.put(Context.PROVIDER_URL, "opmn:ormi://sracanov-au2.au.oracle.com:6005:JMS_SR/default");


Ensure you have set this to your Server A details, including opmn port, and oc4j instance.Use ‘opmnctl status –port’ to find your opmn port.

6) Run the QueueProducer class to send the message to the queue.

The is result:
Producing message: Message 1
Producing message: Message 2
Producing message: Message 3
Producing message: Message 4
Producing message: Message 5

7) From the Oracle EM, select your instance (in this example, ‘JMS_SR’) -> Administration -> JMS Destinations -> Memory Performance (on ‘jmsqueue’ in this example). Here you will see you messages in the queue.



8) Create the QueueConsumer.

Use the example code from the previous blog to create the QueueConsumer class. The QueueConsumer will connection to Server B and read messages from the queue on Server A. You will need to make the following changes to the class.


String queueName = "jms/MyJMSQueue";
String queueConnectionFactoryName = " jms/MyRemoteQCF";

And

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, “oracle.j2ee.rmi.RMIInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, "oc4jadmin");
env.put(Context.SECURITY_CREDENTIALS, "welcome1");
env.put(Context.PROVIDER_URL, opmn:ormi:// sracanov-au.au.oracle.com:6007:JMS/default");


Ensure you have set this to your Server B details, including opmn port, and oc4j instance.

9) Now run the QueueConsumer class that will connect to Server B and receive the messages from the queue on Server A.

This is the result:

Consuming message: Message 1
Consuming message: Message 2
Consuming message: Message 3
Consuming message: Message 4
Consuming message: Message 5

10) Create an MBD and deploy to Server B that will listen and print the messages in the queue on Server A.

a.Create the MessageDrivenEJBBean as follows:


package project3;

import javax.ejb.EJBException;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;

public class MessageDrivenEJBBean implements MessageDrivenBean,
MessageListener {
private MessageDrivenContext _context;

public void ejbCreate() {
}

public void setMessageDrivenContext(MessageDrivenContext context) throws EJBException {
_context = context;
}

public void ejbRemove() throws EJBException {
}

public void onMessage(Message message) {
TextMessage msg = null;

try {
if (message instanceof TextMessage) {
msg = (TextMessage)message;
System.out.println("Reading message: " + msg.getText());
} else {
System.out.println("Wrong Message type");
}
} catch (JMSException e) {
System.out.println("JMSException in onMessage(): " + e.toString());
} catch (Throwable t) {
System.out.println("Exception in onMessage():" + t.getMessage());
}
}
}


b.Edit the ejb-jar.xml as follows:

<?xml version = '1.0' encoding = 'windows-1252'?>
<ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" version="2.1"
xmlns="http://java.sun.com/xml/ns/j2ee">
<enterprise-beans>
<message-driven>
<description>Message Driven Bean</description>
<display-name>MessageDrivenEJB</display-name>
<ejb-name>MessageDrivenEJB</ejb-name>
<ejb-class>project3.MessageDrivenEJBBean</ejb-class>
<messaging-type>javax.jms.MessageListener</messaging-type>
<transaction-type>Container
<message-destination-type>javax.jms.Queue</message-destination-type>
<activation-config>
<activation-config-property>
<activation-config-property-name>destinationType</activation-config-property-name>
<activation-config-property-value>javax.jms.Queue</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>acknowledgeMode</activation-config-property-name>
<activation-config-property-value>Auto-acknowledge</activation-config-property-value>
</activation-config-property>
<activation-config-property>
<activation-config-property-name>subscriptionDurability</activation-config-property-name>
<activation-config-property-value>NonDurable</activation-config-property-value>
</activation-config-property>
</activation-config>
</message-driven>
</enterprise-beans>
</ejb-jar>

c.Edit the orion-ejb-jar.xml as follows:

<?xml version = '1.0' encoding = 'windows-1252'?>
<orion-ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/orion-ejb-jar-10_0.xsd"
schema-major-version="10" schema-minor-version="0">
<enterprise-beans>
<message-driven-deployment name="MessageDrivenEJB"
connection-factory-location="jms/MyRemoteQCF"
destination-location="jms/MyJMSQueue"/>
</enterprise-beans>
<assembly-descriptor>
<default-method-access>
<security-role-mapping/>
</default-method-access>
</assembly-descriptor>
</orion-ejb-jar>

d.Deploy MDB to Server B.

e.Run the QueueProduce to send some messages to the queue.

f.Open the file $ORACLE_HOME\opmn\log\default_group~~default_group~1.log

To view the result:

07/10/02 08:52:24 Reading message: Message 1
07/10/02 08:52:24 Reading message: Message 2
07/10/02 08:52:24 Reading message: Message 3
07/10/02 08:52:24 Reading message: Message 4
07/10/02 08:52:24 Reading message: Message 5
07/10/02 08:52:24 Wrong Message type