Search This Blog

Tuesday, 24 February 2009

How to Create a JDBC/OCI Connection Pool For Stand Alone OC4J 10.1.3.x

Recently I had to setup JDBC/OCI connection pool in stand alone OC4J 10.1.3.x using an oracle client 10.2.0.3. The problem here is OC4J 10.1.3.x comes with JDBC driver 10.1.0.5 of ojdbc14.jar. Which means you will have issues using the 10.2.0.3 oracle client libraries.

As a result of that you must upgrade the driver to use the client version JDBC driver as well as set various environment variables before starting stand alone OC4J. The steps are as follows.

Note: This is based on OC4J 10.1.3.4 and on a windows environment, using instant client 10.2.0.3

1. Download 10.2.0.3 instant client as follows, in my case installed in directory as follows

D:\jdev\instant-clients\10203

You can download the 10.2.0.3 version from here.

http://www.oracle.com/technology/software/tech/oci/instantclient/

2. Open up command window and set environment variables as follows

set PATH=D:\jdev\instant-clients\10203;%PATH%
set TNS_ADMIN=D:\jdev\instant-clients\10203

Note: A tnsnames.ora exists in the directory D:\jdev\instant-clients\10203 and has the following entry which I will use in stand alone OC4J shortly.

LINUX10G =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = xxxx.au.oracle.com)(PORT = 1522))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = linux10g)
)
)

3. Start stand alone OC4J as follows, ensuring you use the same commend window from step 2 above.

set ORACLE_HOME=D:\jdev\stand-alone-oc4j\10134
set JAVA_HOME=D:\jdev\jdevprod\10134\jdk

D:\jdev\stand-alone-oc4j\10134\bin>oc4j -start
Starting OC4J from D:\jdev\stand-alone-oc4j\10134\j2ee\home ...
09/02/23 13:42:29 Oracle Containers for J2EE 10g (10.1.3.4.0) initialized

4. OC4J 10.1.3.x is using 10.1.0.5 JDBC driver which means it will have issues connecting using 10.2.0.3 instant client so we have to upgrade the JDBC driver to 10.2.0.3 as shown below for the whole container. Follow this metalink note to fix that so it matches the same version of instant client which would mean you use ojdbc14.jar from 10.2.0.3 jar file of ojdbc14.jar.

Note 420303.1 - How to Use The Latest Thin JDBC Driver Across All Applications For a 10.1.3.x OAS Container

You can download the 10.2.0.3 JDBC driver jar file from this link, but it should be available in your oracle client install.

http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/index.html

5. Stop stand alone OC4J to pick up the shared library change.
6. Start stand alone OC4J.
7. Create a data source as follows.


<connection-pool name="ocitest-pool">
<connection-factory factory-class="oracle.jdbc.pool.OracleDataSource"
user="scott" password="tiger" url="jdbc:oracle:oci:@LINUX10G"/>
</connection-pool>


For more information on data sources refer to the following documentation.

Oracle® Containers for J2EE Services Guide
10g (10.1.3.1.0)
Part Number B28958-01
http://download-uk.oracle.com/docs/cd/B31017_01/web.1013/b28958/datasrc.htm#BABIDCBJ

Thursday, 19 February 2009

OC4J 10.1.3.x start order of Resource Adapters

In order to control the start order of Resource Adapters for an application you can use the start-order tag as described here in the docs within your oc4j-connectors.xml

Oracle® Containers for J2EE Resource Adapter Administrator's Guide
10g (10.1.3.1.0)
Part Number B28956-01
http://download.oracle.com/docs/cd/B32110_01/web.1013/b28956/xmlcnfg.htm#sthref532

Thursday, 12 February 2009

Determine the Security Providers for the JVM

Note for myself: While working with Oracle's JDBC/THIN driver with SSL this comes in handy

package pas.test;

import java.security.Provider;
import java.security.Security;

public class GetProviders
{
public GetProviders()
{
}

public static void main(String[] args)
{
Provider[] pl = Security.getProviders();
System.out.println("Printing Available Security.getProviders()");
for (int i=0; i < pl.length; i++)
{
System.out.println("\n" + i + ". " + pl[i].toString());
System.out.println("Name: " + pl[i].getName());
System.out.println("Version: " + pl[i].getVersion());
System.out.println("Info: " + pl[i].getInfo());
}
}
}

Output:

Printing Available Security.getProviders()

0. SUN version 1.5
Name: SUN
Version: 1.5
Info: SUN (DSA key/parameter generation; DSA signing; SHA-1, MD5 digests; SecureRandom; X.509 certificates; JKS keystore; PKIX CertPathValidator; PKIX CertPathBuilder; LDAP, Collection CertStores)

1. SunRsaSign version 1.5
Name: SunRsaSign
Version: 1.5
Info: Sun RSA signature provider

2. SunJSSE version 1.5
Name: SunJSSE
Version: 1.5
Info: Sun JSSE provider(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)

3. SunJCE version 1.5
Name: SunJCE
Version: 1.5
Info: SunJCE Provider (implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, Diffie-Hellman, HMAC)

4. SunJGSS version 1.0
Name: SunJGSS
Version: 1.0
Info: Sun (Kerberos v5)

5. SunSASL version 1.5
Name: SunSASL
Version: 1.5
Info: Sun SASL provider(implements client mechanisms for: DIGEST-MD5, GSSAPI, EXTERNAL, PLAIN, CRAM-MD5; server mechanisms for: DIGEST-MD5, GSSAPI, CRAM-MD5)

Thursday, 5 February 2009

Oracle Weblogic 10.3 / RAC 11g Integration How To

I worked with product management to create a how to for Oracle Weblogic 10.3 / RAC 11g Integration. The URL is on OTN now as follows. It comes with a sample web application to test your configuration out as well.

http://www.oracle.com/technology/products/weblogic/howto/rac/index.html

It comes with a white paper as well created by a product manager

http://www.oracle.com/technology/products/weblogic/OracleWLS_RAC.pdf

Monday, 2 February 2009

Using Log4J with Jdeveloper 11g / Integrated Weblogic Server

A quick demo on how to use Log4j within a JDeveloper workspace for 11g when running web projects. In this example we are using a simple HTTP servlet with just a doGet method defined

1. Create the default "log4j.properties" file within the root src folder of your web project.

# **Set root logger level to DEBUG and its only appender to A.
log4j.rootLogger=DEBUG, A
# ***** A is set to be a ConsoleAppender.
log4j.appender.A=org.apache.log4j.ConsoleAppender
# ***** A uses PatternLayout.

log4j.appender.A.layout=org.apache.log4j.PatternLayout
log4j.appender.A.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

Eg:




2. Add the log4j JAR file to the project's web-inf/lib directory for runtime and as a project library JAR file for compile time. In my case I used the JAR file as follows

> log4j-1.2.15.jar

3. Here is the servlet code which will then use log4j at runtime.


package pas.au.log4j;

import java.io.IOException;
import java.io.PrintWriter;
import org.apache.log4j.Category;
import org.apache.log4j.PropertyConfigurator;
import java.util.Properties;
import java.io.FileInputStream;

import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.log4j.Logger;

public class Log4JServletDemo
extends HttpServlet
{
Logger log = Logger.getLogger(this.getClass().getSimpleName());
private static final String CONTENT_TYPE = "text/html; charset=windows-1252";

public void init(ServletConfig config)
throws ServletException
{
super.init(config);
log.info("init() method of servlet Log4JServletDemo");
}

public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>Log4JServletDemo</title></head>");
out.println("<body>");
out.println("<h2>Log4j demo</h2>");

log.info("init() doGet method of servlet Log4JServletDemo");

out.println("</body></html>");
out.close();
}
}



4. When run within the "Integrated Weblogic Server" verify runtime output as follows within JDeveloper's log window.

Target URL -- http://127.0.0.1:7101/Log4JTest-ServletDemo-context-root/log4jservletdemo
0 [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] INFO Log4JServletDemo - init() method of servlet Log4JServletDemo
63 [[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'] INFO Log4JServletDemo - init() doGet method of servlet Log4JServletDemo


When your ready to create a WAR file for deployment to an External Weblogic 10.3 server then the log4j.properties file should be added to the web-inf/classes folder automatically with this setup.

Tuesday, 20 January 2009

JDBC THIN / SSL 11g Runtime Issue - java.security.InvalidAlgorithmParameterException

I have been working on setting up JDBC THIN /SSL 11g (ojdbc6.jar) with JDK 1.6 against an 11g database. Previously I only ever done this with 10g, so here is a common runtime issue I run into while setting this up from the client side.

Runtime excepotion as follows:

java.sql.SQLRecoverableException: Io exception: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParame
terException: the trustAnchors parameter must be non-empty

Due to the fact I was using (PKCS12) wallets (ewallet.p12) I needed place Oracle PKI provider in java.security for my JDK 1.6 runtime environment as shown below.

File : D:\jdev\jdk16\jre\lib\security\java.security

security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
security.provider.3=oracle.security.pki.OraclePKIProvider
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
security.provider.5=com.sun.crypto.provider.SunJCE
security.provider.6=sun.security.jgss.SunProvider
security.provider.7=com.sun.security.sasl.Provider
security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.9=sun.security.smartcardio.SunPCSC
security.provider.10=sun.security.mscapi.SunMSCAPI

Once that was done the error dissapeared I was able to run my client side JDBC THIN/ SSL demo.

D:\temp\pas-ssl>java -classpath ./classes;.;D:\temp\pas-ssl\lib\ojdbc6.jar;D:\temp\pas-ssl\lib\oraclepki.jar support.au.jdbc.ssl.J
DBCSSLWalletTrustore
Start: Tue Jan 20 09:16:20 EST 2009
Conncted as DATABASE USER SCOTT
Ended: Tue Jan 20 09:16:21 EST 2009

D:\temp\pas-ssl>

So the code for this was as follows :


/*
* Author: Pas Apicella
*/

package support.au.jdbc.ssl;

import java.security.Security;

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

import java.util.Date;
import java.util.Properties;

import oracle.jdbc.pool.OracleDataSource;


public class JDBCSSLWalletTrustore
{
private static OracleDataSource ods = null;
private static final String TRUSTSTORE =
"D:/jdev11g-boxer/jdeveloper/jdev/mywork/JDBCSSL11g/wallets/client/ewallet.p12";
private static final String TRUSTSTORETYPE = "PKCS12";
private static final String TRUSTSTOREPASSWORD = "myclient123";
private static final String DBURL =
"jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)" +
"(HOST=beast.au.oracle.com)(PORT=2484))" +
"(CONNECT_DATA=(SERVICE_NAME=linux11g)))";

private static final String DBUSER = "scott";
private static final String DBPASSWD = "tiger";

public JDBCSSLWalletTrustore()
{
Security.addProvider(new oracle.security.pki.OraclePKIProvider());
}

public void run () throws SQLException
{
String sql = "select user from dual";
Statement stmt = null;
ResultSet rset = null;
Connection conn = null;

try
{
conn = getConnection();
stmt = conn.createStatement();
rset = stmt.executeQuery(sql);
rset.next();

if (rset != null)
{
System.out.println
(String.format("Conncted as DATABASE USER %s",
rset.getString(1)));
}
}
finally
{
if (stmt != null)
{
stmt.close();
}

if (rset != null)
{
rset.close();
}

if (conn != null)
{
conn.close();
}
}
}

public static Connection getConnection() throws SQLException
{
Properties props = new Properties();

props.setProperty("javax.net.ssl.trustStore",
TRUSTSTORE);
props.setProperty("javax.net.ssl.trustStoreType", TRUSTSTORETYPE);
props.setProperty("javax.net.ssl.trustStorePassword", TRUSTSTOREPASSWORD);

ods = new OracleDataSource();
ods.setUser(DBUSER);
ods.setPassword(DBPASSWD);
ods.setURL(DBURL);
ods.setConnectionProperties(props);

Connection conn = ods.getConnection();

return conn;
}

public static void main(String[] args)
{
System.out.println("Start: " + new Date());
JDBCSSLWalletTrustore testssl = new JDBCSSLWalletTrustore();

try
{
testssl.run();
}
catch (SQLException se)
{
System.out.println("SQL Exception occurred: ");
se.printStackTrace();
}
catch (Exception e)
{
System.out.println("Exception occurred: ");
e.printStackTrace();
}

System.out.println("Ended: " + new Date());
}


}

If you have trouble getting a JDBC THIN / SSL demo to work , it's worth tuning on this java option at run time to get more detailed information, here is what we get when we turn it on with the same code above, the output is far more detailed to enable you to debug why it may not be working for you.

-Djavax.net.debug=ssl

Output
-------

Start: Tue Jan 20 11:10:05 EST 2009
adding as trusted cert:
Subject: OU=Class 3 Public Primary Certification Authority, O="VeriSign, Inc.", C=US
Issuer: OU=Class 3 Public Primary Certification Authority, O="VeriSign, Inc.", C=US
Algorithm: RSA; Serial number: 0x70bae41d10d92934b638ca7b03ccbabf
Valid from Mon Jan 29 11:00:00 EST 1996 until Wed Aug 02 09:59:59 EST 2028

adding as trusted cert:
Subject: CN=Entrust.net Certification Authority (2048), OU=(c) 1999 Entrust.net Limited, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), O=Entrust.net
Issuer: CN=Entrust.net Certification Authority (2048), OU=(c) 1999 Entrust.net Limited, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), O=Entrust.net
Algorithm: RSA; Serial number: 0x3863b966
Valid from Sat Dec 25 04:50:51 EST 1999 until Wed Dec 25 05:20:51 EST 2019

.....

.....

*** Finished
verify_data: { 196, 181, 216, 111, 12, 62, 126, 237, 120, 137, 1, 126 }
***
main, WRITE: TLSv1 Handshake, length = 48
main, READ: TLSv1 Change Cipher Spec, length = 1
main, READ: TLSv1 Handshake, length = 48
*** Finished
verify_data: { 50, 203, 187, 227, 95, 124, 39, 44, 151, 160, 209, 59 }
***
%% Didn't cache non-resumable client session: [Session-2, TLS_RSA_WITH_AES_128_CBC_SHA]
main, WRITE: TLSv1 Application Data, length = 224
main, READ: TLSv1 Application Data, length = 48
main, WRITE: TLSv1 Application Data, length = 192
main, READ: TLSv1 Application Data, length = 160
main, WRITE: TLSv1 Application Data, length = 64
main, READ: TLSv1 Application Data, length = 208
main, WRITE: TLSv1 Application Data, length = 2080
main, WRITE: TLSv1 Application Data, length = 176
main, READ: TLSv1 Application Data, length = 2032
main, READ: TLSv1 Application Data, length = 288
main, WRITE: TLSv1 Application Data, length = 192
main, READ: TLSv1 Application Data, length = 224
main, WRITE: TLSv1 Application Data, length = 1056
main, READ: TLSv1 Application Data, length = 1360
main, WRITE: TLSv1 Application Data, length = 48
main, READ: TLSv1 Application Data, length = 208
main, WRITE: TLSv1 Application Data, length = 112
main, READ: TLSv1 Application Data, length = 512
Conncted as DATABASE USER SCOTT
main, WRITE: TLSv1 Application Data, length = 48
main, READ: TLSv1 Application Data, length = 48
main, WRITE: TLSv1 Application Data, length = 32
main, called close()
main, called closeInternal(true)
main, SEND TLSv1 ALERT: warning, description = close_notify
main, WRITE: TLSv1 Alert, length = 32
Ended: Tue Jan 20 11:10:07 EST 2009

Tuesday, 30 December 2008

Creating a READ ONLY user for Application Server Control 10.1.3.x

Today I was asked how to create a user with a read-only user for access to the Application Server Control pages. I always use oc4jadmin and obviously that built in account has full rights, but it turns out the easiest way to create a new user with READ ONLY access is as follows

1. Log into ASC
2. Click on the link "Setup" at the top of the page.
3. Click on "Users"
4. Click on the "Create" button.
5. Enter new username/password and press OK

By default the user you create here will be one with read-only access which by default will be assigned the role "
ascontrol_monitor".

Now you can login with this new user with
read-only user access to the Application Server Control pages.

The administration roles are documented here.

http://otndnld.oracle.co.jp/document/products/as10g/101300/B25221_03/core.1013/b25209/tools.htm
Table 2-2 Administrative Roles That You Can Assign to Application Server Control Administrators

Monday, 15 December 2008

Associate an IDE DB Connection to a Workspace for Web projects in JDeveloper 11g

In JDeveloper 10g you could easily deploy all database connections when running a web project in the embedded OC4J server thus allowing each connection to be represented as a data source at runtime. Turns out the same can be done in JDeveloper 11g and Weblogic Integrated server however the steps are a little different.

1. View -> Database Navigator
2. Drag the IDE connection you wish to use in your workspace. The end result is as follows for the Workspace "WebLogicStuff"





3. Now whenever you run any web project from WebLogicStuff workspace then the database connection "scott" will automatically be deployed as an application level data source.

4. In order to access the connection "scott" we should use a JNDI location as follows within our code.

java:comp/env/jdbc/scottDS

The format would be as follows, depending on the connection name.

java:comp/env/jdbc/{jdevide-connection-name}DS

Here is some java code we can then use to perform a JNDI lookup of the data source via a simple method which requires the location above to be passed to the method.

private Connection getConnection (String dataSourceLocation)
throws NamingException, SQLException
{
Connection conn = null;

// Get a context for the JNDI look up
Context ctx = new InitialContext();

// Look up a data source
javax.sql.DataSource ds
= (javax.sql.DataSource) ctx.lookup (dataSourceLocation);

// Create a connection object
conn = ds.getConnection();

return conn;
}

Thursday, 13 November 2008

Simple Example of Memory Profiling in JDeveloper 11g

In the 11g JDBC Developer's guide below it clearly specifies the following.

http://download.oracle.com/docs/cd/B28359_01/java.111/b31224/oraint.htm#i1058743

Important: The cursor associated with a REF CURSOR is closed whenever the statement object that produced the REF CURSOR is closed. Unlike in past releases, the cursor associated with a REF CURSOR is not closed when the result set object in which the REF CURSOR was materialized is closed.

So here is how I used JDeveloper memory profiler to verify that this indeed was the case.

1. new java class as follows


package pas.jdbc.refcursor;
import java.sql.*;

import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleDriver;
import oracle.jdbc.OracleTypes;

public class RefCursorExample
{
private boolean detailsDisplayed = false;
private Connection conn = null;

public RefCursorExample() throws SQLException
{
conn = getConnection();
}

public void run () throws SQLException
{
CallableStatement cstmt = null;
ResultSet cursor = null;

try
{
if (!detailsDisplayed)
{
displayDeatils(conn);
detailsDisplayed = true;
}

// Use a PL/SQL block to open the cursor
cstmt = conn.prepareCall
("begin open ? for select ename from emp; end;");

cstmt.registerOutParameter(1, OracleTypes.CURSOR);
cstmt.execute();
cursor = ((OracleCallableStatement)cstmt).getCursor(1);

// Use the cursor like a standard ResultSet
while (cursor.next ())
{
System.out.println (cursor.getString(1));
}
System.out.println("\n");
}
catch (Exception ex)
{
ex.printStackTrace();
}
finally
{
if (cursor != null)
{
cursor.close();
}
}


}

public void displayDeatils (Connection conn) throws SQLException
{
// Create Oracle DatabaseMetaData object
DatabaseMetaData meta = conn.getMetaData ();

// gets driver info:

System.out.println("\n=============\nDatabase Product Name is ... " +
meta.getDatabaseProductName());
System.out.println("\nDatabase Product Version is " +
meta.getDatabaseProductVersion());
System.out.println("\n=============\nJDBC Driver Name is ........ " +
meta.getDriverName());
System.out.println("\nJDBC Driver Version is ..... " +
meta.getDriverVersion());
System.out.println("\nJDBC Driver Major Version is " +
meta.getDriverMajorVersion());
System.out.println("\nJDBC Driver Minor Version is " +
meta.getDriverMinorVersion());
System.out.println("\n=============");
}

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

public static void main(String[] args) throws Exception
{
RefCursorExample refCursorExample = new RefCursorExample();
refCursorExample.run();

for (int i = 1; i <= 5; i++)
{
System.out.println("Run #" + i + "\n");
refCursorExample.run();
}

Thread.sleep(30000);

System.out.println("finished");
}
}



You can see in the run() method we don't call close on the statement itself which leads to a code leak.


finally
{
if (cursor != null)
{
cursor.close();
}
}


2. In the project edit the default profile by double clicking on the project and selecting "Run/Deug/Profile" and then select "Edit" for default profile, then select "Tools Settings/Profiler" and select the checkbox "Begin Use Case on application Startup"

3. Press Ok twice

Now we are ready to memory profile the application. As ou can see from the code we call the method run() 5 times so lets see if we can see the Statement leak.

4. Select Run -> Memory profile

A snapshot is taken as soon as the program runs, and then it sleeps for 30 seconds before finally completing. Click on the icon "End task" and set the class filter to "T4CStatement"






5. You will see 2 columns , one called "New" the other one called "Final Num"

Both are 6 which shows that we have 6 "T4CStatement" classes still in the heap.

Now lets fix the code to actually call close() on the statement in the finally block of the run() mnethod as the 11g JDBC Developer's guide suggests to.

if (cstmt != null)
{
cstmt.close();
}

6. Now profile the class "RefCursorExample" again and you will see that we no longer have a build up of "T4CStatement" as previously examined, when the statement was closed as well.

We have "New" as 6 and "Final Num" as 1 as expected.

Monday, 13 October 2008

JDeveloper 11g deploying a web project to WLS 10.3 using JSTL 1.2 tag library fails

When you create a web project using JSP and add the JSTL 1.2 core library to the project and eventually go to deploy your project as a WAR to an external WLS 10.3 server you may end up with the following exception and it fails to deploy.

weblogic.management.DeploymentException: [J2EE:160149]Error while processing library references. Unresolved Webapp Library references for "weblogic.servlet.internal.WebAppServletContext@17409f8 - appName: 'jstl12demo', name: 'jstl12demo.war', context-path: '/jstl12demo', spec-version: '2.5'", defined in weblogic.xml [Extension-Name: jstl, Specification-Version: 1.2, exact-match: false].

What's odd is the integrated server works fine no issue there. The reason for this is the integrated server has the JSTL 1.2 library already defined. So the way to get around this in an external WLS 10.3 server is to do it one of 2 ways.

Option 1 - Deploy JSTL 1.2 libraries with the archive itself

1. Edit your deployment profile.
2. Select File Groups - WEB-INF/Lib - Contributors
3. Check the following to include the JSTL 1.2 libraries
  • JSTL 1.2
  • JSTL 1.2 Tags
4. Press OK
5. Redeploy and this time you get a successfull deployment.

---- Deployment started. ---- 13/10/2008 13:47:12
Target platform is (Weblogic 10.3).
Running dependency analysis...
Building...
2008-10-13 13:47:16.921: Writing WAR file to D:\jdev11gbea\jdeveloper\jdev\mywork\JSTL12\Project1\deploy\jstl12demo.war
2008-10-13 13:47:16.937: Wrote WAR file to D:\jdev11gbea\jdeveloper\jdev\mywork\JSTL12\Project1\deploy\jstl12demo.war
Deploying Application...
Application Deployed Successfully.
Elapsed time for deployment: 7 seconds
---- Deployment finished. ---- 13/10/2008 13:47:19


Option 2 - Setup WLS 10.3 to include a library for the JSTL 1.2 tags

1. Log into WLS 10.3 administration console
2. Click on deployments
3. Press the install button
4. Navigate to the following directory and select "jstl-1.2.war"

/u01/bea103/wlserver_10.3/common/deployable-libraries

5. Click next
6. Select the radio option to install this as a library
7. Select the target server for this library
8. Click next
9. Click finish

Now attempt to deploy your project which includes JSTL 1.2 tag references and it should deploy fine.

---- Deployment started. ---- 13/10/2008 13:55:03
Target platform is (Weblogic 10.3).
Running dependency analysis...
Building...
2008-10-13 13:55:07.625: Writing WAR file to D:\jdev11gbea\jdeveloper\jdev\mywork\JSTL12\Project1\deploy\jstl12demo.war
2008-10-13 13:55:07.64: Wrote WAR file to D:\jdev11gbea\jdeveloper\jdev\mywork\JSTL12\Project1\deploy\jstl12demo.war
Deploying Application...
Application Deployed Successfully.
Elapsed time for deployment: 7 seconds
---- Deployment finished. ---- 13/10/2008 13:55:10

By default due to using the JSTL 1.2 tag library when your deploying to WLS 10.3 the WAR file includes a file called weblogic.xml with contents as follows. As you can see the library reference we created is automatically used as per your project requirements to use JSTL 1.2. Once this is done all deployments targeted to the server using the JSTL 1.2 library you created will work as long as they use this in there deployment descriptor.

weblogic.xml


<?xml version = '1.0' encoding = 'windows-1252'?>
<weblogic-web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app.xsd"
xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
<library-ref>
<library-name>jstl</library-name>
<specification-version>1.2</specification-version>
</library-ref>
</weblogic-web-app>


Wednesday, 8 October 2008

JDeveloper 11g JAX-WS proxy cannot read WSDL

JDeveloper 11g (BOXER) was released today, and if your using web services it's worth reading the release notes as follows.

http://www.oracle.com/technology/products/jdev/htdocs/11/knownissues.html#wsd

When creating a JAX-WS proxy for a external web service you may get an error as follows

Exception in thread "main" javax.xml.ws.WebServiceException: weblogic.wsee.wsdl.WsdlException: Failed to read wsdl file from url due to -- java.io.FileNotFoundException: D:\jdev11gbea\jdeveloper\jdev\mywork\WebServiceProxy\Project1\classes\SimpleWS.wsdl (The system cannot find the file specified)
at weblogic.wsee.jaxws.spi.WLSProvider.readWSDL(WLSProvider.java:306)

The easiest way to avoid this is on page 3 of 8 of the JAX-WS Proxy wizard uncheck "Copy WSDL into project"

The issue is release noted as follows.

http://www.oracle.com/technology/products/jdev/htdocs/11/knownissues.html#wsd12

Thursday, 4 September 2008

Displaying OC4J JVM MBean Statistics from a JMX Client

The JVM Mbean within an OC4J 10.1.3.x container has some useful statistic which are displayed in ASC MBean browser. Here is some code which shows how to obtain those from a JMX client.

So the MBean we want to access is as follows:

oc4j:j2eeType=JVM,name=single,J2EEServer=standalone

And the statistics we want to display which ASC shows for us are as follows:
  • FreeHeapSize
  • ActiveThreads
  • HeapSize
So here is the code we will use from a JMX Client. The method which obtains the statistics we need is called "showStats(ObjectName)"


package oracle.support.oc4j.standalone;

import java.text.DateFormat;

import java.util.Date;
import java.util.logging.Logger;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.j2ee.statistics.JVMStats;
import javax.management.j2ee.statistics.Statistic;
import javax.management.j2ee.statistics.BoundedRangeStatistic;

public class JVMMonitor implements Runnable
{
private final Logger logger = Logger.getLogger(this.getClass().getName());
private static final DateFormat DATEFORMAT = DateFormat.getInstance();
private OC4JConnection con = null;
private MBeanServerConnection mbs = null;
private String targetMBean = "oc4j:j2eeType=JVM,name=single,J2EEServer=standalone";
private ObjectName mbean = null;

public JVMMonitor() throws Exception
{
// retrieve an OC4JConnection object this is a singleton class
con = OC4JConnection.getInstance();
mbs = con.getConnection();
mbean = new ObjectName(targetMBean);
System.out.println("** JVM Details **");
System.out.printf("Opmn Managed: %s\n",
mbs.getAttribute(mbean, "opmnEnabled"));
System.out.printf("Java Version: %s\n",
mbs.getAttribute(mbean, "javaVersion"));
System.out.printf("Java Vendor: %s\n",
mbs.getAttribute(mbean, "javaVendor"));
System.out.printf("Host Node: %s\n",
mbs.getAttribute(mbean, "node"));
System.out.printf("RMI Port: %s\n",
mbs.getAttribute(mbean, "rmiPort"));
System.out.printf("RMIS Port: %s\n",
mbs.getAttribute(mbean, "rmisPort"));
System.out.printf("RMI IP: %s\n",
mbs.getAttribute(mbean, "rmiServerAddress"));

}

public void run ()
{

System.out.println("\n");
try
{
System.out.printf("--> Current JVM Details [%s]\n\n",
DATEFORMAT.format(new Date()));


showStats(mbean);
System.out.printf("\n<-- End...\n");
}
catch (Exception e)
{
System.out.println("Error in run()");
e.printStackTrace();
}
finally
{
//con.close();
}
}

private void showStats(ObjectName cp) throws Exception
{

JVMStats stats =
(JVMStats) mbs.getAttribute(cp, "stats");

Object mem = null;
mem = mbs.getAttribute(cp, "totalMemory");
Long memLong = null;
memLong = (Long) mem;

System.out.printf("Total Memory: %s\n", memLong.intValue()/1024/1024 + "M");

mem = mbs.getAttribute(cp, "freeMemory");
memLong = (Long) mem;
System.out.printf("Free Memory: %s\n",
memLong.intValue()/1024/1024 + "M");

System.out.printf("HeapSize: %s\n",
stats.getHeapSize().getCurrent()/1024 + "M");
System.out.printf("HighWaterMark: %s\n",
stats.getHeapSize().getHighWaterMark()/1024 + "M");
System.out.printf("LowWaterMark: %s\n",
stats.getHeapSize().getLowWaterMark()/1024 + "M");

Statistic[] allStats = stats.getStatistics();

for (Statistic s: allStats)
{
if (!s.getName().equalsIgnoreCase("UpTime"))
{
System.out.println("\n--");
System.out.printf("JVM Statistic [%s]\n", s.getName());
System.out.printf("Description : %s\n", s.getDescription());
System.out.printf("Unit : %s\n", s.getUnit());
System.out.printf("Last Sample Time : %s\n", new Date(s.getLastSampleTime()));

BoundedRangeStatistic brs = (BoundedRangeStatistic) s;

if (s.getUnit().equals("THREADS"))
{
System.out.printf("High WaterMark : %s\n", brs.getHighWaterMark());
System.out.printf("Low WaterMark : %s\n", brs.getLowWaterMark());
System.out.printf("Current : %s\n", brs.getCurrent());
}
else
{
System.out.printf("High WaterMark : %s\n", brs.getHighWaterMark()/1024 + "M");
System.out.printf("Low WaterMark : %s\n", brs.getLowWaterMark()/1024 + "M");
System.out.printf("Current : %s\n", brs.getCurrent()/1024 + "M");
}

}
}


}

}



So the output would then be as follows:

** JVM Details **
Opmn Managed: true
Java Version: 1.5.0_06
Java Vendor: Sun Microsystems Inc.
Host Node: beast.au.oracle.com
RMI Port: 12406
RMIS Port: 12706
RMI IP: 10.187.80.70

JVMMonitor
Period to report results in seconds is : 5

** Started [4/09/08 11:29] with 5(sec) interval between reports **


--> Current JVM Details [4/09/08 11:29]

Total Memory: 515M
Free Memory: 453M
HeapSize: 515M
HighWaterMark: 550M
LowWaterMark: 504M

--
JVM Statistic [FreeHeapSize]
Description : The amount of free heap memory
Unit : KILO BYTES
Last Sample Time : Thu Sep 04 11:06:44 EST 2008
High WaterMark : 515M
Low WaterMark : 433M
Current : 453M

--
JVM Statistic [ActiveThreads]
Description : The number of active thread(s)
Unit : THREADS
Last Sample Time : Thu Sep 04 11:06:44 EST 2008
High WaterMark : 64
Low WaterMark : 4
Current : 64

--
JVM Statistic [HeapSize]
Description : The size of the JVM's heap
Unit : KILO BYTES
Last Sample Time : Thu Sep 04 11:06:44 EST 2008
High WaterMark : 550M
Low WaterMark : 504M
Current : 515M

<-- End...

Few people asked for this class itself.

OC4JConnection.java


  
package oracle.support.oc4j.standalone;

import java.io.FileInputStream;

import java.util.Hashtable;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import oracle.oc4j.admin.jmx.remote.api.JMXConnectorConstant;

public class OC4JConnection
{
private static Properties myProperties = new Properties();
private JMXConnector jmxCon = null;
private static OC4JConnection instance = null;
private final Logger logger = Logger.getLogger(this.getClass().getName());
private String username = null;
private String password = null;
private String url = null;

private OC4JConnection
(Properties inProps) throws Exception
{

try
{
processProps(inProps);

logger.log
(Level.INFO, "Username = " + username);
logger.log
(Level.INFO, "Service URL = " + url);

// Define the connection target
JMXServiceURL serviceUrl = new JMXServiceURL(url);

Hashtable env = new Hashtable();

env.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
"oracle.oc4j.admin.jmx.remote");

Hashtable credentials = new Hashtable();

credentials.put
(JMXConnectorConstant.CREDENTIALS_LOGIN_KEY, username);
credentials.put(JMXConnectorConstant.CREDENTIALS_PASSWORD_KEY,
password);

env.put(JMXConnector.CREDENTIALS, credentials);

jmxCon = JMXConnectorFactory.newJMXConnector(serviceUrl, env);
// Connect to the target OC4J instance defined in the JMXServiceURL
jmxCon.connect();
logger.log
(Level.INFO, "Connected to OC4J");
}
catch (Exception e)
{
logger.log
(Level.SEVERE,
"** [OC4JConnection()] : Unable to obtain Stand Alone Connection",
e);
e.printStackTrace();
}
}

public static OC4JConnection getInstance() throws Exception
{
if(instance == null)
{
myProperties.load(new FileInputStream("build.properties"));
instance = new OC4JConnection(myProperties);
}

return instance;
}

private void processProps(Properties inProps)
{
username = inProps.getProperty("username");
password = inProps.getProperty("password");
url = inProps.getProperty("serviceurl");

}

public MBeanServerConnection getConnection ()
{
MBeanServerConnection mbs = null;

if (jmxCon != null)
{
try
{
mbs = jmxCon.getMBeanServerConnection();
}
catch (Throwable t)
{
logger.log
(Level.SEVERE,
"**[getConnection] : Unable to retrieve MBeanServerConnection");
}
}

return mbs;
}

/**
* Determine if the client is currently connected
* @return true if connected
*/
public boolean isConnected ()
{
boolean ret = false;
if (jmxCon == null)
{
return false;
}
else
{
try
{
jmxCon.getConnectionId();
return true;
}
catch (Throwable t)
{
//
}
}

return ret;
}

/**
* Close the JMXConnector.
*/
public void close ()
{
if (jmxCon != null)
{
try
{
jmxCon.close();
jmxCon = null;
logger.log
(Level.INFO, "Closed Connection to OC4J");
}
catch (Throwable t)
{
}
}
}
}