Showing posts with label oc4j. Show all posts
Showing posts with label oc4j. Show all posts

03 September 2009

Switching Between JRockit and Sun JDK with WebLogic Server

Need to swap between JRockit and the Sun JDK when starting your WebLogic Server instance?

Looking at the start scripts $DOMAIN_HOME/bin/setDomainEnv.cmd, I just realized that this operational task is basically taken care of in the scripts we have.

To swap between the Sun JDK and JRockit to launch a WLS instance, all you need to do is set the JAVA_VENDOR environment variable to either "Sun" or "Oracle" and the scripts will take of launching WLS using the specified JDK.

Snippets from setDomainEnv.cmd:
set BEA_JAVA_HOME=d:\wls1031\jrockit_160_05_R27.6.2-20
set SUN_JAVA_HOME=d:\wls1031\jdk160_11

if "%JAVA_VENDOR%"=="Oracle" (
set JAVA_HOME=%BEA_JAVA_HOME%
) else (
if "%JAVA_VENDOR%"=="Sun" (
set JAVA_HOME=%SUN_JAVA_HOME%
) else (
set JAVA_VENDOR=Sun
set JAVA_HOME=d:\wls1031\jdk160_11
)
)

Where JAVA_HOME is then used by startWebLogic.cmd script when it launches the WLS instance to identify the JDK to use.

Snippets from startWebLogic.cmd
%JAVA_HOME%\bin\java %JAVA_VM% %MEM_ARGS% 
-Dweblogic.Name=%SERVER_NAME% 
-Djava.security.policy=%WL_HOME%\server\lib\weblogic.policy 
%JAVA_OPTIONS% 
%PROXY_SETTINGS% 
%SERVER_CLASS%

With this information at hand, then switching between the two different JDKs is as simple as setting an environment variable before launching WebLogic Server.

Using JRockit:
>set JAVA_VENDOR=Oracle
>startWebLogic.cmd
...
d:\wls1031\JROCKI~1.2-2\bin\java -jrockit -Xms512m -Xmx512m -Dweblogic.Name=AdminServer ...

And just as easy to switch back to Sun. Note here that you could just unset the JAVA_HOME environment variable, which will set the script to use whatever default was configured when the domain was created.

Using Sun JDK:
>set JAVA_VENDOR=Sun
>startWebLogic.cmd
...
d:\wls1031\JDK160~1\bin\java -client -Xms256m -Xmx512m -Dweblogic.Name=AdminServer ...

WebLogic Server Startup and Shutdown Classes

WebLogic Server supports the use of server level startup and shutdown (SU/SD) classes, which are invoked by the server when it is starting up, and conversely when it is shutting down.

The initial implementation of this functionality (not sure of the release but circa 6.x I believe) required the SU/SD classes to implement proprietary WebLogic Server interfaces:
  • weblogic.common.T3StartupDef
  • weblogic.common.T3ShutdownDef
As of WebLogic Server 9.0, these interfaces were marked as deprecated.

It appears that with the introduction of the new application lifecycle listeners feature at the same time, this has resulted in reduced visbility of the new POJO based SU/SD class approach in the documentation.

So here's a brief explanation.

With the deprecation of the earlier SU/SD interfaces, a new and simpler POJO based was introduced for SU/SD classes. This requires only that a SU/SD class only has to have a static main(String args[]) method, which the server will invoke after instantiating the class. No WLS specific interfaces are needed any longer. Any arguments that were configured for the SU/SD class configuration are passed to it via the String[] args parameter.

The POJO based SU/SD class still follows all the same deployment and configuration steps used by the previous model -- the class needs to be made available on the server classpath, the SU/SD class is configured via the console with the requisite parameters and settings, and ultimately stored as an entry in config.xml.

Startup Class:
package sab.demo.utils;

public class StartupMain {
/**
* @param args
*/
public static void main(String[] args) {

log(StartupMain.class.getName() + "::main");
log("Arguments::");
for(int i=0;args!=null && i<args.length;i++) {
log("  arg[" + i + "]: " + args[i]);
}
}

private static void log(String msg) {
System.out.printf("  --> [SAB]: %s\n", msg);
}
}


WLS Console:


config.xml:
<startup-class>
<name>StartupMain</name>
<target>AdminServer</target>
<deployment-order>1000</deployment-order>
<class-name>sab.demo.utils.StartupMain</class-name>
<arguments>arg1 arg2 arg3</arguments>
<failure-is-fatal>false</failure-is-fatal>
<load-before-app-deployments>false</load-before-app-deployments>
<load-before-app-activation>true</load-before-app-activation>
</startup-class>

28 August 2009

OC4J 10.1.3.5 Released


We published OC4J 10.1.3.5 to OTN this week.

This is a maintenance release, but it has a sprinkling of new features that had been in the works for a while and have now made it into an official OC4J release.

Download location:

http://www.oracle.com/technology/software/products/ias/htdocs/utilsoft.html

Updated Documentation:


http://download.oracle.com/docs/cd/E14101_01/index.htm


Release Notes:

http://download.oracle.com/docs/cd/E14101_01/doc.1013/e15342/oc4j.htm

New Feature List:

http://download.oracle.com/docs/cd/E14101_01/doc.1013/e15342/oc4j.htm#BDCCBAFD

I really like the small set of new features that have been added.

My pick of them, is probably the Peek utility. Peek provides a nice Web based front end for singing and dancing, all powerful, classloading functionality we've had in OC4J 10.1.3.x since its first dot zero release. Peek lets you drive easily around the classloading environment, visualizing the loader tree and letting you to drill down into it to see code-sources, packages, classes, etc. It also lets you execute the wide set of classloader queries we provide, directly from a Web browser. Really neat stuff.

There are also a set of new commands added to the admin_client utility, to support actions such as getting a listing of all deployed applications/web bindings, importing (and removing) shared libraries into applications, and a restart app command. Nice additions.

If you are still using OC4J and haven't yet moved over to the world of WebLogic Server, I reckon checking out OC4J 10.1.3.5 would be worth your time.

06 February 2009

Using Derby Network Server with OC4J

Seeing as how I spent sometime this morning on getting OC4J DataSources to work with Derby, and there wasn't much information out there in googleland on it, I thought I'd post some information.

The request, paraphrased was: "I need to use the ClientXADataSource with OC4J to connect to a remote Derby server, but it only seems to connect to localhost".

Taking a look at it, this required a few things:

1. A crash course in using Derby. Dead easy to download, unzip, run. Bit harder to work out where to specify users, properties, and how to configure datasources. There's quite a bit of information out there, but it seems to need some previous level of experience with Derby to make sense of it quickly.

2. OC4J needs to use the derbyclient.jar file to establish a JDBC connection to the Derby server. Now this is similar to the MySql situation -- the derbyclient.jar needs to be placed within OC4J where it can be found by the various classloaders that need it.

The most obvious solution is to put it in the j2ee/home/applib directory, which will make it available to the default application classloader, which should suffice for runtime.

However the thing to keep in mind here is that the applib directory is configured as part of the "global.libraries" shared-library, which is explicitly NOT imported by the ascontrol application. Thus if you want to use ascontrol to configure a DataSource for Derby, you need to make the library available to it as well.

I have a previous post on how this applied to ascontrol/DataSources and MySql, which should explain away this problem as well.

The other options are to publish derbyclient.jar as an explicit named:versioned shared-library and import it wherever its needed. This could be into the default application, a specific application, wherever.

3. Configuring a DataSource. There are several ways to configure a database connection on OC4J -- ConnectionPools with Managed DataSources, or Native DataSources. The doc explains the differences between the two.

Likewise, there are several classes in the derbyclient.jar you can use to connect to a Derby database. Most of the information in googleland shows the use of the org.apache.derby.jdbc.ClientDriver and a simple JDBC URL, and most often being done from within Java code. There are also two additional classes which implement the javax.sql.DataSource and javax.sql.XADataSource interfaces. These seem to be what we should be using for a datasource, and more particularly a datasource for use with XA.

With the classes identified, the next step is to actually create the datasource. This can be done with ascontrol or manually. I initially started using ascontrol, but I ran into some problems. The first was that when I was specifying the Derby DRIVER_URL, which includes the databasename "jdbc:derby://localhost:1521/wombat;create=true", when I tested the connection, I kept getting an error message indicating that the databaseName must be set. Looking at the org.apache.derby.jdbc.ClientDataSource implementation, there's a setter for the database name. To force the setting of the value, I used the <property> configuration setting on the datasource configuration to set the databaseName as follows:

<connection-pool name="DerbyCP">
<connection-factory
factory-class="org.apache.derby.jdbc.ClientXADataSource"
user="foo" password="bar"
url="jdbc:derby://localhost:1527/wombat">
<property name="databaseName" value="wombat"/>
<property name="createDatabase" value="true"/>
</connection-factory>
</connection-pool>


The problem I ran into then, was that with ascontrol if you "test this connection" at this point, it still throws an error saying the databaseName is not set. I don't know for sure, but I think the problem here may be that the supplied properties are not being used when this quick test is done. To get beyond this, click finish to save the connection pool, and then test it from the resulting JDBC resources page.

Another problem I ran into here is that we need a user/password to connect with. The default Derby network server runs without needing authentication. I don't know if this is the correct approach, but I ended up running Derby with a derby.properties file that specified the following:

derby.authentication.provider=BUILTIN
derby.user.foo=bar


So that a user "foo" exists and can be used to connect with.

The next issue is that once you have user foo, if you try and do the "test connection" and use the standard sql query "select * from dual" you'll get an error saying the "FOO" schema doesn't exist. I found how to create a schema from some online doc, and used the "ij" utility to create the database "wombat" and the schema "foo".

That finally allowed me to successfully execute a test to verify the connection could be established. Some further reading seemed to indicate there is a default schema called "APP" so perhaps if the test query was modified to explicitly name that schema "select * from APP.dual" maybe that would have worked too. Worth noting is that the table "dual" here does not exist, but I was considering a return error of "table does not exist" as proof that the connection was successfully created.

Once you have the connection pool connecting correctly, then you can wrap it with a datasource which is bound to the JNDI team with a specified name, and hopefully all will be good from then.

For completeness, here is the final data-sources.xml file that shows the final configuration:

<native-data-source
user="foo" password="bar"
url="jdbc:derby://localhost:1527/wombat;create=true"
data-source-class="org.apache.derby.jdbc.ClientDataSource"
jndi-name="jdbc/DerbyNDS"
name="DerbyNDS">
<property name="databaseName" value="wombat"/>
<property name="createDatabase" value="true"/>
</native-data-source>

<managed-data-source connection-pool-name="DerbyCP" jndi-name="jdbc/DerbyMDS" name="DerbyMDS"/>

<connection-pool name="DerbyCP">
<connection-factory
factory-class="org.apache.derby.jdbc.ClientXADataSource"
user="foo" password="bar"
url="jdbc:derby://localhost:1527/wombat">
<property name="databaseName" value="wombat"/>
<property name="createDatabase" value="true"/>
</connection-factory>
</connection-pool>


Note: as I have alluded to, this may not be the most appropriate way to make use of Derby so please don't read this in that way. I need have to do some more reading, thinking and a lot of testing if I had to do anything more than just prove quickly that it could work with OC4J.

09 December 2008

Replacing Oracle JAX-RPC Libraries

As of the OC4J 10.1.3.4 release, the Oracle WS JAX-RPC libraries have been isolated into their own named/versioned shared-library. This means that they can be selectively removed from the visibility of an application, allowing alternative implementations to be provided as needed:

The shared-library is defined as:
Shared Library Name:    oracle.ws.jaxrpc
Shared Library Version: 1.1
Parent Name: api
Parent Version: 1.4.0

Modifiable: no

Library Compatible: yes

Code Sources:
/D:/java/oc4j-10134-dev/webservices/lib/jaxr-api.jar
/D:/java/oc4j-10134-dev/webservices/lib/jaxrpc-api.jar
/D:/java/oc4j-10134-dev/webservices/lib/saaj-api.jar
/D:/java/oc4j-10134-dev/webservices/lib/jws-api.jar
The section in the doc that describes this is here: Using JAX-WS RI

20 November 2008

Dependency Injection in Taglibs

Helping with some migration material recently for OC4J --> WLS, a question was asked about whether OC4J 10.1.3.x supported dependency injection with its Tag library implementation.

It's known that OC4J 10.1.3.1+ supports dependency injection in the Web container as described here, but the specifics of whether that extended to tag librarieswas not mentioned.

A subsequent quick test verified that dependency injection does indeed work for tags using the  SimpleTag (SimpleTagSupport) and BodyTag (BodyTagSupport).
package sab.testdi.tag;

import java.io.*;
import java.io.PrintWriter;
import javax.ejb.EJB;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import sab.testdi.ejb.CalcLocal;

public class CalcAdd extends SimpleTagSupport {

@EJB(name="Calc")
CalcLocal calc;


int v1 = 0;
int v2 = 0;

public void setV1(int v1) {
this.v1 = v1;
}

public void setV2(int v2) {
this.v2 = v2;
}

public void doTag() throws JspException, IOException {
PrintWriter out = new PrintWriter(this.getJspContext().getOut());
out.printf("<div style='font-family: courier'>");
if(calc != null) {
out.printf("%s+%s=%s", v1, v2, calc.add(v1, v2));
} else {
out.printf("bugger, calc is null!");
}
out.println("</div>");
}
}

The taglib.tld file defines the tag:
<?xml version = '1.0' encoding = 'windows-1252'?>
<taglib 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/web-jsptaglibrary_2_0.xsd"
version="2.0"
xmlns="http://java.sun.com/xml/ns/j2ee">
<display-name>calc</display-name>
<tlib-version>1.2</tlib-version>
<short-name>calc</short-name>
<uri>/webapp/calc</uri>
<tag>
<description>A short description...</description>
<display-name>add</display-name>
<name>add</name>
<tag-class>sab.testdi.tag.CalcAdd</tag-class>
<body-content>empty</body-content>
<attribute>
<name>v1</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>v2</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<example><calc:add v1="100" v2="25"/></example>
</tag>
</taglib>
And finally, a JSP can use it by importing the JAR file containing the tag libraru into the WEB-INF/lib directory (where it is nicely auto-discovered) and making a call to the <calc:add .../> tag.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ page contentType="text/html;charset=windows-1252"%>
<%@ taglib uri="/webapp/calc" prefix="calc"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"/>
<title>Index</title>
</head>
<body style="font-family: arial">
<h2>Testing Taglib Dependency Injection</h2>
<p>
<calc:add v1="12" v2="12"/></p>
</body>
</html>

When the JSP is accessed it successfully displays 12+12=24 which is rendered by the tag library after being calculated via the injected EJB reference.

18 November 2008

Configuring shared-libraries settings post deployment

With the introduction of the shared-library mechanism in OC4J 10.1.3.x, it is possible to configure the set of libraries that an application has access to. This is done at the application level using the tag to include a named shared-library, or its counterpart, to remove a library from the view of the application.

These settings are made in the OC4J specific orion-application.xml deployment descriptor for the application, typically either as a hard-coded entry in the packaged EAR file that is being deployed, or they are set during the deployment process using the Class Loading Task in the ASC console.

In the current releases, there are no ways to easily change these settings once the application has been deployed. One approach that has been used is to perform a redeployment operation of the application and make the change via the ASC console. Obviously this requires a redeployment to be performed. While you can also manually edit the resulting orion-application.xml file to add/remove/change the settings, this provides no validation that the settings are correct.

To address this, for the next patch release of OC4J (10.1.3.5) we are looking to add a couple of new shared-library commands to the admin_client.jar utility to operate on existing, deployed applications. These commands will allow you to perform add or delete operations on either of the or configuration elements.

As an example, lets say you have an application in which you wish to use the Apache Xerces parser instead of the Oracle XML parser. This change can be performed during deployment as described here: http://www.oracle.com/technology/tech/java/oc4j/1013/how_to/how-to-swapxmlparser/doc/readme.html

But! When you test your application, it throws an Exception and you eventually realise that you forgot to make the change to the shared-libraries during the deployment of the application. The Oracle XML parser is still being used.

Using the new commands you would be able to change this on the deployed application as follows:

>java -jar admin_client.jar .... -addRemoveInheritedSharedLibrary -appName myapp -name oracle.xml


>java -jar admin_client.jar .... -addImportSharedLibrary -appName myapp -name apache.xml -minVersion 2.7 -maxVersion 2.7





14 August 2008

Formatting OC4J access logs

OC4J can be configured to log its web accesses to a specified access-log file.

The format of the log entry can be customized according to the documentation here:

http://download.oracle.com/docs/cd/B25221_04/web.1013/b14432/website.htm#BABFGJHD

Some format tokens that are mentioned, but not really called out are $cookie and $header.

Using these tokens, you can ask OC4J to inject the specified cookie/header value into the access-log.

For example, if you wanted to log the value of the JSESSIONID cookie for each request, you'd configure the format string as follows:

<access-log path="../log/default-web-access.log" format="
$ip - $user '$request' $status $cookie:JSESSIONID" />
When OC4J runs, it will log entries in default-web-access.log according to the pattern that was specified:
141.144.152.48 - 'oc4jadmin' 'GET /peek/ HTTP/1.1' 200 c2796b83b9d7a79cfa4c491792f6783fd64a00cd3a17d13548c189d8d6e6543f

05 June 2008

Classloader Loader Event Tracing

Classloader Event Tracing

If you are seeing classloader closed errors from time to time, then one really useful utility OC4J has is the ability to log the various events related to different aspects of the classloading mechanism.

So for example, lets say you are seeing errors occasionally containing this type of message: "This loader has been closed and should not be in use."

Then what you can do to help trace why this is occurring is to enable log tracing for the various loader events.

In the error message above, it should also explicitly provide the name of the loader that was being used, of the form appname.modulename[.module]:major.minor. For example myapp.webmodule.root:0.0

To observe classloading events relating to this specific loader, you configure OC4J to start as follows:

>java -Dclass.load.trace=loader:myapp.webmodule.* -Dclass.load.trace.level=all -jar oc4j.jar


That setup configures OC4J to output all the loader related classloading events, at the log level of ALL, where the loader name matches the pattern "myapp.webmodule.*".

In the output, you'll see entries such as:

ClassLoader created: myapp.webmodule.root:0.0.0 (instance 1cba87)
ClassLoader committed: myapp.webmodule.root:0.0.0 (instance 1cba87)
...
ClassLoader closing: myapp.webmodule..jsp13471351:0.0.0 (instance 14441b6)
...

That shows you where the loaders are being operated on, and confirms (one way or another) that the loader is actually being closed -- this may correlate with other actions you have performs -- say a redeployment operation.

Now to help further understand why/where the loader event occured, you can add an extra event filter. The "stack" event filter adds the associated stacktrace that caused the loader event to occur to the output -- thus for the loader closed events, you can trace back and identify the source of the loader close.

To add the stack event filter to the classloader tracing, simply concatentate it to the class.load.trace property:
>java -Dclass.load.trace=stack+loader:myapp.webmodule.* -Dclass.load.trace.level=all -jar oc4j.jar

That then causes a stacktrace to be appended to each event that is logged:

ClassLoader closing: myapp.webmodule:0.0.0 (instance 18aea9e)
at oracle.classloader.util.ClassLoadTracing$LoaderListener.loaderClosing(ClassLoadTracing.java:738)
at oracle.classloader.EventDispatcher.loaderClosing(EventDispatcher.java:232)
at oracle.classloader.PolicyClassLoader.close(PolicyClassLoader.java:1056)
at oracle.classloader.PolicyClassLoader.close(PolicyClassLoader.java:1041)
at com.evermind.server.http.HttpApplication.destroy(HttpApplication.java:5860)
at com.evermind.server.http.HttpApplication.stopCleanUp(HttpApplication.java:8437)
at com.evermind.server.http.HttpApplication.componentStop(HttpApplication.java:8383)
at com.evermind.server.Application.doStop(Application.java:2092)
at com.evermind.server.Application.stop(Application.java:2019)
at oracle.oc4j.admin.management.mbeans.J2EEStateManageableObjectBase.stop(J2EEStateManageableObjectBase.java:275)
at oracle.oc4j.admin.management.mbeans.J2EEApplication.stop(J2EEApplication.java:1542)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:36)
at sun.reflect.GeneratedMethodAccessor17.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:239)
at javax.management.modelmbean.RequiredModelMBean.invokeMethod(RequiredModelMBean.java:1071)
at javax.management.modelmbean.RequiredModelMBean.invoke(RequiredModelMBean.java:953)
at oracle.oc4j.admin.jmx.server.mbeans.model.DefaultModelMBeanImpl.invoke(DefaultModelMBeanImpl.java:700)
at com.sun.jmx.mbeanserver.DynamicMetaDataImpl.invoke(DynamicMetaDataImpl.java:213)
at com.sun.jmx.mbeanserver.MetaDataImpl.invoke(MetaDataImpl.java:220)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:815)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:784)
at oracle.oc4j.admin.jmx.server.state.ApplicationStateFilterMBeanServer.invoke(ApplicationStateFilterMBeanServer.java:572)
at oracle.oc4j.admin.jmx.shared.UserMBeanServer.invoke(UserMBeanServer.java:634)
at oracle.oc4j.admin.jmx.server.state.LocalizationFilterMBeanServer.invoke(LocalizationFilterMBeanServer.java:579)
at oracle.sysman.ias.studio.jmx.spi.JMXConnectorImpl.invoke(JMXConnectorImpl.java:389)
at oracle.sysman.ias.studio.oc4j.JMXAppAdminBean.stopApp(JMXAppAdminBean.java:276)
at oracle.sysman.ias.studio.oc4j.AppHelper.doStopAppOp(AppHelper.java:776)
at oracle.sysman.ias.studio.oc4j.AppHelper.access$600(AppHelper.java:116)
at oracle.sysman.ias.studio.oc4j.AppHelper$AppControlProcessingBean.appControlOperation(AppHelper.java:1628)
at oracle.sysman.ias.studio.oc4j.AppHelper$AppControlProcessingBean.doWork(AppHelper.java:1642)
at oracle.sysman.ias.studio.util.ProcessingBean$ProcessingThread.run(ProcessingBean.java:273)
at com.evermind.util.ReleasableResourcePooledExecutor$MyWorker.run(ReleasableResourcePooledExecutor.java:298)
at java.lang.Thread.run(Thread.java:595)


Looking at the stacktrace for the loader closing event, you can reasonably surmise that the event was caused by the application being "stopped" from ascontrol (sysman).

Now that's a contrived example, I agree! But I hope it serves in some small way to demonstrate how you can use the classloader tracing mechanism to get a handle on the different events that happen to loaders and why they have occurred.

04 June 2008

FAQ for OC4J 10.1.3. Management

A few questions I see from time to time in the OTN OC4J Forum are covered in the OC4J 10.1.3 Management/Admin FAQ

http://www.oracle.com/technology/tech/java/oc4j/1013/whitepapers/OC4J-FAQ-MGT-10131.pdf

07 November 2007

Application Supplied System Properties

We added a feature in the 10.1.3.1 release which enables an application to supply its own set of System properties, which are added and removed to the global System property set as the application is started and stopped. The documentation for it is not extensive, but there's a how-to on OTN which walks through the use of it.

Check it out on OTN.

The System properties (name, value) are defined in the orion-application.xml descriptor provided with the application.

<orion-application>
<property name="application.tax.rate" value="10" />
<property name="application.tax.code" value="AU" />
</orion-application>
During deployment with ASC, the deployment plan editor can be used to view the set of specified System properties in the application. It can also be used to add, remove, edit the defined properties so they can be tailored to the specific deployment being performed.

11 October 2007

OC4J 10.1.3.3 Ant Taskname Error

OC4J 10.1.3.x supplies a set of Ant tasks that enable operations such as application deployment, resource configuration and server lifecycle tasks to be performed.

The abridged history of the tasks is:
  • OC4J 10.1.3.0 introduced the basic tasks
  • OC4J 10.1.3.1 and later versions extends the set of tasks to support JDBC/JMS resource configuration options and server shutdown/restart tasks
The OC4J Configuration and Administration guide documents the Ant tasks.

However in the OC4J 10.1.3.3 release several of the tasks are incorrectly defined in the antlib.xml and therefore not available using the names as described in the documentation.

The documentation is correct and shows how the tasks should be named. However if you use these tasks as documented you will get errors. The screen capture below highlights the specific differences.



The workarounds are either:

1. Revert to using the names as defined in antlib.xml for these tasks:

  • addDataSourceConnectionPool == createJDBCConnectionPool
  • addManagedDataSource == createManagedDataSource
  • addNativeDataSource == createNativeDataSource
  • testDataSourceConnectionPool == testConnectionPool
2. Update the /j2ee/utilities/ant-oracle-classes.jar!/oracle/antlib.xml to change the names of the tasks so they reflect the correct names as specified in the documentation:

Change: taskdef name="createJDBCConnectionPool"
To: taskdef name="addDataSourceConnectionPool"

Change: taskdef name="createManagedDataSource"
To: taskdef name="addManagedDataSource"

Change: taskdef name="addManagedDataSource"
To: taskdef name="createNativeDataSource"

Change: taskdef name="testConnectionPool"
To: taskdef name="testDataSourceConnectionPool"

A bug has been filed for this and a patch will be released which fixes the issue along the lines of option 2 shown above.

28 September 2007

Using JAXB 2.0 with OC4J 10.1.3.x

OC4J 10.1.3.x provides a JAXB 1.0 implementation as part of its standard runtime. If you want to use JAXB 2.x then its easy to do using the shared-library mechanism of OC4J.

As a simple test of the JAXB 2.0 capabilities, a simple application can be used that makes use of the JAXB 2.0 features. In the example used herein, the application is a simple Web application that makes use of two POJOs that are annotated with JAXB 2.0 annotations.

Build a Test Application:
package sab.demo.jaxb.model;

import java.util.ArrayList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.*;

/**
*
@author sbutton
*
*/
@XmlType(propOrder = { "manufacturer", "model", "year",
"color"
, "registration", "owners" })
@XmlRootElement(name = "vehicle")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Vehicle {
long id;
String registration;
String manufacturer;
String model;
String year;
String color;
ArrayList<Owner> owners = new ArrayList<Owner>();

public Vehicle() {
// TODO Auto-generated constructor stub
}

...
...
}

Instances of the POJOS are then created from a JSP page, where they are marshalled into an XML document and then displayed by the JSP:
<%
try {
JAXBContext context = JAXBContext.newInstance(Vehicle.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

Vehicle xtrail = new Vehicle(1L, "Nissan", "X-Trail",
"2002"
, "Silver", "ABC-123");
xtrail.addOwner(new Owner(1L, "Fred", "Bloggs"));

Vehicle golf = new Vehicle(2L, "Volkswagen", "Golf",
"2002"
, "Silver", "XYZ-123");
golf.addOwner(new Owner(1L, "Fred", "Bloggs"));
golf.addOwner(new Owner(2L, "Freda", "Bloggs"));

StringWriter sw = new StringWriter();
marshaller.marshal(xtrail,sw);
out.println(escapeHtml(sw.toString()));

sw = new StringWriter();
marshaller.marshal(golf,sw);
out.println(escapeHtml(sw.toString()));

} catch (JAXBException e) {
e.printStackTrace(new PrintWriter(out));
}
%>
The application is then packaged up into a WAR and an EAR file ready for deployment.

Prepare the Server: Using ASC, publish a shared-library that contains the JAXB 2.0 JAR files.



Deploy the Application: When deploying the application, use the Classloading Task and import the "jaxb 2.0" shared-library so the application has access to the JAXB 2.0 implementation.



When the application is run, the Vehicle and Owner instances are marshalled to XML and displayed in the JSP page.



Voila.

20 September 2007

Command Line Monitoring of Thread Pool Sizes

Want to periodically view the OC4J thread pool sizes from the command line?

Using Groovy + JMX , its dead simple:
import demo.oc4j.jmx.*;
import java.text.*;

def period = 5000L
def client = new OC4JClient()
def df = DateFormat.getTimeInstance(DateFormat.LONG)

try {
client.connect("service:jmx:rmi://10.187.112.178:23791",
"oc4jadmin", "welcome1")

println "$client\n"

http = client.helper.createGroovyMBean(
"oc4j:j2eeType=ThreadPool,name=http,J2EEServer=standalone")

system = client.helper.createGroovyMBean(
"oc4j:j2eeType=ThreadPool,name=system,J2EEServer=standalone")
jca=client.helper.createGroovyMBean(
"oc4j:j2eeType=ThreadPool,name=jca,J2EEServer=standalone")


while(true) {
now = df.format(new Date(System.currentTimeMillis()));
println "$now HTTP:[$http.poolSize] JCA:[$jca.poolSize] System:[$system.poolSize]"
Thread.sleep(period)
}
} finally {
println 'Closing'
client.close()
}

This makes use of the OC4J helper library, which you can access here.

A simple script to run this would look like this:

@setlocal
set J2EE_HOME=d:\java\oc4j-10133-prod\j2ee\home
set GROOVY_HOME=d:\java\groovy-1.0
set classpath=lib\oc4jgroovy.jar;%GROOVY_HOME%\lib\commons-cli-1.0.jar;/
%GROOVY_HOME%\embeddable\groovy-all-1.0.jar;%J2EE_HOME%\admin_client.jar;%J2EE_HOME%\oc4jclient.jar

java -classpath %CLASSPATH% groovy.lang.GroovyShell src\threadlevel.groovy
@endlocal


When the script is run, it produces this sort of output:

Client is connected to: rmi://10.187.112.178:23791 oc4jadmin [connectionCaching:
true, httpTunneling:false, locale:not set]

1:03:54 HTTP:[7] JCA:[1] System:[7]
1:03:59 HTTP:[7] JCA:[1] System:[7]
1:04:06 HTTP:[7] JCA:[1] System:[7]
1:04:11 HTTP:[7] JCA:[1] System:[7]


----------------
Listening to: Ned's Atomic Dustbin - What Gives My Son?

10 September 2007

Using Shared Libraries to configure Log4j

As I was mucking around with Log4j last week, it occurred to me that I could make use of the OC4J shared-library mechanism to inject the Log4J properties files into an an application when it was being deployed -- after all the properties file is just read from the classpath.

Even better, what this enables an administrator to do is to configure a set of shared-libraries that contain different log4j properties file, say enabling different log levels, and then choose between them when the application is deployed. Or additionally, make changes to in a post-deployment manner to switch between different logging settings.

OK, enough with the banal description, here's a few screen shots to show you what I'm dribbling on about here.

First off, lets assume you have a desire to capture and route your log4j entries into the OC4J log system using the OracleAppender as described here and you have a properties file that configures the appropriate settings and the log level you want to enable.

log4j.rootLogger=INFO,OJDL
log4j.appender.OJDL=oracle.core.ojdl.log4j.OracleAppender
log4j.appender.OJDL.LogDirectory=${oracle.j2ee.home}/log/oc4j
#log4j.appender.APP1.MaxSize=1000000
#log4j.appender.APP1.MaxSegmentSize=200000
#log4j.appender.APP1.Encoding=iso-8859-1
log4j.appender.OJDL.ComponentId=OracleProd

The first thing to do is to put the log4j.properties file into a JAR file, then deploy it as a shared-library to OC4J.





Once the shared-library has been published, you will see it available on the server shared-libraries page, ready to be imported. Note that in the below, I actually have two different log4j.config shared-libraries deployed.



Once the shared-library is deployed, it is then available to be imported by applications when they are deployed. By importing the log4j.info.config shared-library, the log4j.properties file is made accessible to the application and therefore used to to configure log4j for the application.

To import the shared-library during the deployment process, use the Configure Classloading button on the Deployment Tasks page.





By selecting the desired log4j.config shared-library, it will be made available to the application, and therefore dictate how the log4j log entries for the application are handled. In this specific case, the ROOT logger is set to the INFO level, and the OracleAppender is being employed to direct the log entries into the OC4J log system.

Ultimately the customized shared-library settings for the application are written into the orion-application.xml for the deployed application.



If at some point you wanted to change this application to use a lower log level such as DEBUG or TRACE then you can easily modify the import-shared-library statement to import the shared-library that has the relevant log4j.properties configuration file.

In summary, using the Oc4J shared-library mechanism and a consistent naming convention should enable you to have as many reusable log4j configurations as you need that can be applied to your applications.

----------------
Listening to: Billy Bragg - A New England

06 September 2007

Directing Log4j logs into OC4J logging system

My last posts have focussed on using the JDK standard logging API, and directing the logs being emitted into the OC4J logging system so they can be viewed and searched using the ASC LogViewer.

The log-handler mechanism we have works with the JDK standard logging constructs. The appender mechanism used by log4j is not covered by the basic configuration option in j2ee-config.xml.

However if you are using log4j, then on the surface it looks you are apparently SOL.

But if you want to get a little dirty, here's how you can also choose to redirect log4j logs into the OC4J log files.

In the OracleAS distribution, we ship a JAR file -- $ORACLE_HOME/diagnostics/lib/ojdl-log4j.jar -- that contains an OracleAppender class. Turns out, this class is a log4j appender that transforms log4j messages into the OJDL XML form.

To use this appender, simply configure it using your preferred log4j configuration mechanism. I'll use log4j.properties as an example:

log4j.rootLogger=TRACE,OJDL
log4j.appender.OJDL=oracle.core.ojdl.log4j.OracleAppender
log4j.appender.OJDL.LogDirectory=${oracle.j2ee.home}/log/oc4j
#log4j.appender.APP1.MaxSize=1000000
#log4j.appender.APP1.MaxSegmentSize=200000
#log4j.appender.APP1.Encoding=iso-8859-1
log4j.appender.OJDL.ComponentId=OracleProd

In this configuration, the log4j messages will be directed into the $ORACLE_HOME/j2ee/home/log/oc4j/log.xml file -- which is the "Diagnostics" file read and displayed by LogViewer.

To make use of the OracleAppender, you have to ensure that you have the classes available to the application to use.

One approach it to include the libraries within the application itself -- with JEE5 applications, this is dead simple using the new <librar-directory> facility, with which you specify a directory within the EAR file to hold libaries, and then plunk the libraries into that directory. EasyPeasy!

Another approach to this is to create a shared-library containing the log4j library and the ojdl-log4j.library, and then import this into the application when it is being deployed so the libraries are available to the application.

If you have a Web application, just plunk the libraries into the WEB-INF/lib directory and go.

Something to keep in mind when you are using the ojdl-log4j library is that it has a dependency on the log4j library, so they have to both be accessible at the same classloader level.

Once you have it configured, then the one log.xml file will contain log entries from OC4J, as well as any logs from log4j.

----------------
Listening to:
Powderfinger - Love your way

05 September 2007

Capturing and viewing application log messages with LogViewer

Or put another way ... directing application log messages into the OC4J logging system and viewing them.

Lets say you are wisely using some form of logging framework within your application. And when using OC4J, you use the LogViewer functionality within Application Server Control (ASC) to view the various log messages emitted by the susbsystems of OC4J. Perhaps, you think to yourself, I'd be quite convenient to also include the log messages from my application into the general OC4J log so it can be viewed from the same LogViewer.

Here's how it can be done!

I'm not getting in the religious argument as to which logging framework you are using. For pure expediency, my example will use the JDK logging API.

OK, so in your application, you are using a logger naming hierachy of some form, and using the logger to issue log messages at different levels.
Logger logger = Logger.get("foo.bar.web.EmployeeFrontEnd");

public
void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {response.setContentType(CONTENT_TYPE);
logger.fine(
String.format("Handling web request for %s", request.getRequestURL()));

PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head><title>EmployeeFrontEnd</title></head>");
out.println("<body>");
Employee test = Employee.getTestInstance();
logger.finest(
String.format("Test Employee Instance: %s", test));
logger.finest(
String.format("Calling %s to locate office for %s",
employeeManager.toString(),
test.identifier(test.ID_SHORT)));
String location = employeeManager.locateEmployeeOffice(test);

logger.finest(
String.format("bean returned %s for %s ",
location, test.identifier(test.ID_SHORT)));
out.printf("<p>Employee: %s</br>Office: %s</p>", test.identifier(test.ID_SHORT), location);
logger.fine(String.format("Employee currently earns $%s", test.getSalary()));
test.raiseSalary(15D);
out.printf("<p>Give employee 15percent raise, now earns %s", test.getSalary());
out.println("</body></html>");
out.close();
}

Cool.

Now if you are using standard JDK logging, you can configure the logging handlers and log levels using various mechanism, to ultimately direct the log entries from the application into some form of persistent form to view at a later point.

Now this is where the intersection with the standard logging API, OC4J and the ASC LogViewer intersect.

First off, the ASC LogViewer knows about all the log files that are generated by OC4J. Among them is the big daddy of log files -- j2ee/home/log/oc4j/log.xml -- this is known as the diagnostics log file.

How this file is constructed as a log target is done in the j2ee/home/config/j2ee-config.xml file, where the oc4j-handler is configured to use the Oracle common logging mechanism:

<log_handler name="oc4j-handler" class="oracle.core.ojdl.logging.ODLHandlerFactory">
<property name="path" value="../log/oc4j"/>
<property name="maxFileSize" value="10485760"/>
<property name="maxLogSize" value="104857600"/>
<property name="encoding" value="UTF-8"/>
<property name="supplementalAttributes" value="J2EE_APP.name,J2EE_MODULE.name,WEBSERVICE.name,WEBSERVICE_PORT.name"/>
</log_handler>

Then by convention,, the oracle naming hierachy is specified as being handled by this oc4j-handler:

<logger name="oracle" level="NOTIFICATION:1" useParentHandlers="false">
<handler name="oc4j-handler"/>
<handler name="console-handler"/>
</logger>
Thus any messages written into the "oracle" root logger will be directed to the oc4j-handler, which writes them out in XML form to the j2ee/home/log/oc4j.log.xml file.

To therefore include log messages from your application in the OC4J diagnostics log file, all you need to do is to add a new <logger> entry in the j2ee-config.xml file that specifies your logger name and the level, and declares it to use the oc4j-handler.

<logger name="foo" level="FINEST">
<handler name="oc4j-handler"/>
</logger>

Now using ASC, select the logs entry at the bottom of the page to view all the logs.



By clicking on the the Diagnostics Logs file, you should see it showing both log entries for OC4J PLUS the log entries from your application.



You can see from the log messages the component where the log entry was generated. From the example above you can see log messages from the web_EmployeeFrontEnd component and the ejb_EmployeeManagerBean.

Now the really really cool thing you can do from here is to view all the log entries from the same execution path. Basically what happens is that the Oracle common logging mechanism allocates an execution context ID to every log message, which enables it to then correlate the various log entries from the different components of an execution path. By simply clicking on the Execution Context ID (ECID) link for a log entry of interest, all the log files will be searched for that ECID and each entry will then be displayed in time stamp order.

This effectively gives you the log entries, in sequence for an individual request.



How's that for a handy capability!

Once your log entries are being handled within the Oracle common logging mechanism, you can then utilize the search facilities within the LogViewer to search for items of interest. Explore away!

And for one final rabbit out of the hat for this blog entry, you can also use ASC to configure your application level loggers. On the Administration page, select the Configure Loggers link. If you application has run and your loggers have registered themselves (or you statically configured them in the j2ee-config.xml file) you will see the logger name listed, along with a select list to allow you to specify the levels for each logger. This lets you configure your custom application logging on the fly.



----------------
Listening to: Pixies - Here Comes Your Man

03 September 2007

Getting @ an EJBContext from External Interceptors

If you need to get at the EJBContext of the target bean from an external interceptor class, then one easy way to do it with OC4J is to lookup the following resource from within the interceptor:

EJBContext context = (EJBContext)new InitialContext().lookup("java:comp/EJBContext");

In OC4J 11 even this marginal piece of code won't be necessary as the EJBContext (and any other type of resource) can be injected directly into the interceptor.

Before I was made aware of the simpler solution above, I was resorting to using some reflection code to try and work out if there was an applicable way to get the EJBContext from the target bean. It uses first a direct field check and if that yields no results, it then looks for an accessible method that has returns an EJBContext class, or a derivative thereof.

// The EJBContext classes
final List contextClasses = Arrays.asList(
new Class[] {
javax.ejb.EJBContext.class,
javax.ejb.SessionContext.class });
/**
* Try and get the principal name from the target bean class
* @param target
* @return name of the principal
* @throws Exception
*/
String getPrincipalName(Object target) throws Exception {
String ret = getPrincipalNameFromField(target);
if(ret != null) {
return ret;
} else {
ret = getPrincipalNameFromMethod(target);
}
return(ret != null ? ret : "Ghost Rider");
}

private String getPrincipalNameFromField(Object target) throws Exception {
for(Field field : target.getClass().getFields()) {
if(contextClasses.contains(field.getType())) {
EJBContext ctx = (EJBContext)field.get(target);
return ctx.getCallerPrincipal().getName();
}
}
return null;
}

private String getPrincipalNameFromMethod(Object target) throws Exception {
Method[] methods = target.getClass().getMethods();
for (Method method: methods) {
if(contextClasses.contains(method.getReturnType())) {
EJBContext ret = (EJBContext)method.invoke(target, null);
return ret.getCallerPrincipal().getName();
}
}
return null;
}


This worked pretty well in my tests, but of course it needs the target bean class to be in a cooperative form -- the EJBontext either needs to be accessible as a public field, or there needs to be a public method to get the object from the target bean.

The JNDI lookup is easier and more reliable.

Accessing Return Values from EJB Interceptors

Continuing from my last posting regarding the application of EJB3 interceptors to existing applications, there's another interesting tidbit regarding how to access the return value of an EJB method call in an interceptor.

Thanks to some sage advice from members of our EJB team (who have authored a simply outstanding book in my opinion) turns out that you can use a simple pattern like this in your interceptor method:

public Object intercept(InvocationContext ctx) throws Exception {

// do stuff as pre-invoke
...

// Execute the bean method, or next interceptor in the chain
Object result = ctx.proceed();


// do stuff as post-invoke
...

// return the result from the handler
return result;
}


Using this pattern, you have access to the pre and post invoke states of the method call on the bean.

30 August 2007

EJB External Interceptors

Came across a situation quite recently which had a requirement for the invocation of various methods calls of an EJB to be able to logged for future auditing purposes.

The simplest answer is to use EJB3 and its Interceptor functionality in the guise of an @AroundInvoke method which gets called on every method invocation of the bean class.

Now this sounds OK if you are already using EJB3 and have access to the bean source code to modify it and add the interceptor method and the annotation.

If you don't have access to the original bean source code, you can still do it by using an external interceptor class. In this technique, you create an class external which contains interceptor method(s) and use the ejb-jar.xml file to declare the external interceptor class and bind it to the bean(s) and methods you want to apply it to.

By way of example, here's an external interceptor class:
package sab.demo.interceptors;

import javax.interceptor.InvocationContext;

public class AuditInterceptor {
public AuditInterceptor() {
}

/**
* Interceptor method which prints method call
*/
public Object logMethodCall(InvocationContext ic) throws Exception {

// The InvocationContext contains the context of the intercepted call

System.out.printf("ExternalInterceptor\n\tMethod: %s\n",
ic.getMethod().getName());

// Print out the parameter values if they exist
if(ic.getParameters().length!=0) {
System.out.printf("\tParameters: ");
boolean first = true;
String sep = ", ";
for(Object o : ic.getParameters()) {
System.out.printf(" %s", o.toString());
if(!first) {
System.out.printf("%c", sep);
} else {
first = false;
}
}
}
System.out.println();

// Carry on
return ic.proceed();
}
}
To apply this to an existing bean class, create a partial ejb-jar.xml file with the entries pertinent to the interceptor class:
<?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/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
xmlns="http://java.sun.com/xml/ns/javaee" version="3.0">
<interceptors>
<interceptor>
<interceptor-class>sab.demo.interceptors.AuditInterceptor</interceptor-class>
<around-invoke>
<method-name>logMethodCall</method-name>
</around-invoke>
</interceptor>
</interceptors>
<assembly-descriptor>
<interceptor-binding>
<ejb-name>SomeBusiness</ejb-name>
<interceptor-class>sab.demo.interceptors.AuditInterceptor</interceptor-class>
<method>
<method-name>*</method-name>
</method>
</interceptor-binding>
</assembly-descriptor>
</ejb-jar>
When the bean is called from a client, the external interceptor is invoked and the method calls are printed to stdout:
ExternalInterceptor
Method: someBusinessMethod
Parameters: 1188441131015
The external interceptor class can be packaged within the EJB-JAR file, or alternatively, it can be packaged in a separate JAR file and included in the EAR file as a library. Using JEE5, the library can be referenced using the new <libraries ... > tag and putting the JAR file into the specified directory in the EAR file.

<application version="5">
<library-directory>libraries</library-directory>
<module>
<ejb>ejb.modulejar</ejb>
</module>
</application>
What about EJB 2.1?

Turns out this works for EJB 2.1 applications as well with some minor tweaks to the existing descriptor file.

In this case, you only really need to alter the existing ejb-jar.xml so the version is specified as "3.0" and add the interceptors tags. Whereupon OC4J (10.1.3.x) will run the bean as EJB 3.0, and apply the interceptors as specified.

Here's an example of an EJB 2.1 being converted to EJB 3.0 and the interceptors added.


<?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"
xmlns="http://java.sun.com/xml/ns/j2ee"
version="2.1" >
-->

<ejb-jar version="3.0">
<interceptors>
<interceptor>
<interceptor-class>sab.demo.interceptors.AuditInterceptor</interceptor-class>
<around-invoke>
<method-name>logMethodCall</method-name>
</around-invoke>
</interceptor>
</interceptors>
<enterprise-beans>
<session>
<description>Session Bean ( Stateless )</description>
<display-name>SomeBusiness</display-name>
<ejb-name>SomeBusiness</ejb-name>
<home>sab.demo.ejb21.SomeBusinessHome</home>
<remote>sab.demo.ejb21.SomeBusiness</remote>
<local-home>sab.demo.ejb21.SomeBusinessLocalHome</local-home>
<local>sab.demo.ejb21.SomeBusinessLocal</local>
<ejb-class>sab.demo.ejb21.SomeBusinessBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>SomeBusiness</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
<interceptor-binding>
<ejb-name>SomeBusiness</ejb-name>
<interceptor-class>sab.demo.interceptors.AuditInterceptor</interceptor-class>
<method>
<method-name>*</method-name>
</method>
</interceptor-binding>
</assembly-descriptor>
</ejb-jar>


In this case, if you don't want to change the application.xml file to be versioned at JEE 5.0 and use its libraries inclusion facility, then to include the library containing the external interceptor class you can use the <library> element of the orion-application.xml file to specify the library to load:
<orion-application xsi="http://www.w3.org/2001/XMLSchema-instance" nonamespaceschemalocation="http://xmlns.oracle.com/oracleas/schema/orion-application-10_0.xsd">
<library path="InterceptorLibrary.jar"/>
</orion-application>