Wednesday Dec 11, 2013

Disable JDBC object wrapping in GlassFish

As outlined in my previous blog entry, if you run CMSDK 9.0.4.6 on middleware such as Oracle WebLogic Sever or Oracle GlassFish, you need to disable the JDBC object wrapping first. Otherwise you might be seeing this exception during the startup of a CMSDK Node in GlassFish:

...
oracle.ifs.core.agents.InboundQueueListenerAgent [39] WARNING: Error while processing incoming message.
oracle.ifs.common.IfsException: IFS-13001: Unable to dequeue message
java.lang.ClassCastException: com.sun.gjc.spi.jdbc40.ConnectionWrapper40 cannot be cast to oracle.jdbc.OracleConnection
    at
oracle.ifs.server.S_Queue.dequeue(S_Queue.java:342)
...

How to Disable JDBC Object Wrapping in GlassFish

It is required to disable JDBC object wrapping when using a data source for CMSDK 9.0.4.6. These instructions are for GlassFish 3.1.1 or above, as we don’t support earlier versions of GlassFish with CMSDK.

To disable wrapping of JDBC objects using the Administration Console:

  1. In the Domain Structure tree, expand Resources, then expand JDBC.
  2. Select JDBC Connection Pool in the tree structure.
  3. On the Summary of JDBC Connection Pool page, click the connection pool name that your data source is based on.
  4. Select the Advanced: Edit JDBC Connection Pool Advanced Attributes tab.
  5. In Wrap JDBC Objects, deselect the checkbox to disable wrapping.
  6. Click Save.

    This change does not take effect immediately—it requires that the data source be redeployed or the server be restarted.

In Oracle GlassFish Server this property can also be modified in the domain.xml file or via asadmin command.

Friday Dec 06, 2013

Disable JDBC data type wrapping in WLS

I've now seen this problem several times in customer environments. During startup of a CMSDK Node you see a ClassCastExceptions related to weblogic.jdbc.wrapper.

If something like this shows up in your log file:

...
oracle.ifs.common.IfsException: IFS-45206: Unable to get credential
oracle.ifs.common.IfsException: IFS-10184: Unable to get token
oracle.ifs.common.IfsException: IFS-10191: Unable to make token credential persistent
java.lang.ClassCastException: weblogic.jdbc.wrapper.Blob_oracle_sql_BLOB
    at oracle.ifs.server.S_LibrarySession.getTokenCredentialBlob(S_LibrarySession.java:23888)
...

you have probably not disabled the JDBC data type object wrapping that is enabled by default in WebLogic Server (WLS).

Background

Some JDBC objects from a driver that are returned from WLS are wrapped by default. Wrapping data source objects provides WLS the ability to:

  • Generate debugging output from all method calls.
  • Track connection utilization so that connections can be timed out appropriately.
  • Provide transparent automatic transaction enlistment and security authorization.

WLS provides the ability to disable wrapping which provides the following benefits:

  • Although WLS generates a dynamic proxy for vendor methods that implement an interface to show through the wrapper, some data types do not implement an interface. For example, Oracle data types Array, Blob, Clob, NClob, Ref, SQLXML, and Struct are classes that do not implement interfaces. Disabling wrapping allows applications to use native driver objects directly.
  • Eliminating wrapping overhead can provide a significant performance improvement.

When wrapping is disabled (the wrap-types element is false), the following data types are not wrapped:

  • Array
  • Blob
  • Clob
  • NClob
  • Ref
  • SQLXML
  • Struct
  • ParameterMetaData
    • No connection testing performed.
  • ResultSetMetaData
    • No connection testing performed.
    • No result set testing performed.
    • No JDBC MT profiling performed.

How to Disable Wrapping

It is required to disable JDBC data type wrapping when using a data source with CMSDK 9.0.4.6. This only works in WLS 10.3.4 or above. Since there is no way to change it for WLS versions earlier than 10.3.4, we don’t support those WLS versions with CMSDK.

To disable wrapping of JDBC data type objects using the Administration Console:

  1. If you have not already done so, in the Change Center of the Administration Console, click Lock & Edit.
  2. In the Domain Structure tree, expand Services, then select Data Sources.
  3. On the Summary of Data Sources page, click the data source name.
  4. Select the Configuration: Connection Pool tab.
  5. Scroll down and click Advanced to show the advanced connection pool options.
  6. In Wrap Data Types, deselect the checkbox to disable wrapping.
  7. Click Save.
  8. To activate these changes, in the Change Center of the Administration Console, click Activate Changes.

    This change does not take effect immediately—it requires that the data source be redeployed or the server be restarted.

After that you should not see the ClassCastException anymore and your CMSDK Node should start without errors.

Wednesday Nov 20, 2013

How-To: Deploy CMSDK on Tomcat

Although there are ways to run CMSDK 9.0.4.6 in a standalone JVM, when you need to use the WebDAV protocol to access documents in the CMSDK repository you can’t avoid deploying it into at least a web container.

WebLogic Server or GlassFish Server are one choice, but even Tomcat can be used to host the CMSDK Node that provides the CMSDK protocol servers along with other processes.

When you need to set up a data source on Tomcat the official documentation gives an example like this:


<Resource name="jdbc/OracleDS" auth="Container"
  type="javax.sql.DataSource"  
  driverClassName="oracle.jdbc.OracleDriver"
  url="jdbc:oracle:thin:@myhost.oracle.com:1521:orcl"
  username="cmsdk" password="****" maxActive="20" maxIdle="10"
  maxWait="-1"/>

Unfortunately, when using this data source definition you will see the following exception and the Node won’t come up.

java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.DelegatingCallableStatement cannot be cast to oracle.jdbc.OracleCallableStatement

Whereas in other container configurations (such as in WLS and GlassFish) we can specifically disable the JDBC data type wrapping, this isn’t the case in Tomcat. In Tomcat we need to change the definition of the data source to this, to get the Node started and the defaults overwritten:

<Resource name="jdbc/OracleDS" auth="Container"
  type="oracle.jdbc.pool.OracleDataSource"
  factory="oracle.jdbc.pool.OracleDataSourceFactory"
  connectionCachingEnabled="true"
  user="cmsdk" password="****"
  driverClassName="oracle.jdbc.OracleDriver"
  url="jdbc:oracle:thin:@myhost.oracle.com:1521:orcl"
  removeAbandoned="true"
  removeAbandonedTimeout="30"
  maxActive="20"
  maxIdle="10" maxwait="-1"/>


In addition to the above, you need to change the data source name attribute in the web.xml of the cmsdk.ear file, as Tomcat places all configured entries and resources in the java:comp/env portion of the JNDI namespace which is different from what most other containers are doing.
The modified data source name in the CMSDK web.xml for Tomcat should look like this:


<context-param>
  <description>The name of the DataSource for the CMSDK repository</description>
  <param-name>IFS.NODE.DataSourceName</param-name>
  <param-value>java:/comp/env/jdbc/OracleDS</param-value>
</context-param>


Thursday Sep 26, 2013

How-To: Start a CMSDK Node in a custom application

With the removal of the DomainController concept in CMSDK 9.0.4.6, it is important to know that the CMSDK Node itself now manages the Service, Servers and possible failovers to another Node.

Recently I have encountered a number of customers that have never ran a CMSDK Node in the past. That is somehow worrisome, as a CMSDK Node plays a key role in the whole CMSDK architecture. Although CMSDK is an SDK, there are some required background processes running as Agents, Servers and Handlers. These Agents and Handlers are responsible for cleanup tasks, lifecycle management, and among others, the underlying event system.

The whole Node management in CMSDK 9.0.4.6 might be a blog topic of its own, but I would like to give at least an example of how to run a CMSDK Node within your own custom application, so you can take advantage of a real managed CMSDK environment.

This custom Node does not replace the CMSDK Node that you create when you deploy the cmsdk.ear file, which is mandatory. It furthermore extends the environment and helps your application to take advantage of the built-in Node management.

  1. First create a custom NodeConfiguration, as we don't want to run all servers and agents by default in our custom Node. This can be done by executing a script. An example can be found at $CMSDK_HOME/install/config/CreateNodeConfiguration.def.
    The minimum required agents needed to run inside any custom Node are:
    • EventHandlerAgent using IFS.SERVER.EventHandlerAgentConfiguration
    • StatisticsAgent using IFS.SERVER.StatisticsAgentConfiguration

    To only inherit those from the SuperNodeConfiguration you can insert the following line after line

    ; inherit all the servers

    m += addDefinitionStringArrayProperty  defTag  IFS.NODE.EnabledInheritedServerNames "{EventHandlerAgent, StatisticsAgent}"

    You should create your own .def that contains the custom NodeConfiguration. To execute that script run the
    following command:

    $CMSDK_HOME/bin/scriptrunner.sh CustomNodeConfiguration.def

  2. Make sure that your custom application contains a web.xml. This is required for the following instructions.
    If a web.xml is not possible to add, you need to follow different instructions. Let me know if this is the case and I will publish the other instructions as well (might be a rare case, though).

  3. Register a new Servlet Context Listener to your custom application, by adding the following entries to the web.xml. If listeners are already part of the web.xml make sure that the new one will be listed first.

    <listener>
      <description>Starts and Stops the Node in this JVM</description>
      <display-name>NodeManager</display-name>
      <listener-class>oracle.ifs.core.runtime.NodeManager</listener-class>
    </listener>

  4. The new Servlet Context Listener makes use of several configuration parameters that you need to specify in the web.xml as well. You can use the defaults for most of them, but should make sure that the corresponding param-values for

    • IFS.NODE.DataSourceName
    • IFS.NODE.Service
    • IFS.NODE.NodeConfigurationName
    • IFS.NODE.ServiceConfigurationName

    match your specific configuration.

    Add the following context-params to your web.xml:

    <context-param>
      <description>The name of the DataSource for the CMSDK repository</description>
      <param-name>IFS.NODE.DataSourceName</param-name>
      <param-value>jdbc/OracleDS</param-value>
    </context-param>

    <context-param>
      <description>The class name of CMSDK Node instance running in this JVM</description>
      <param-name>IFS.NODE.Class</param-name>
      <param-value>oracle.ifs.core.runtime.Node</param-value>
    </context-param>

    <context-param>
      <description>The unique name of CMSDK Node running in this JVM</description>
      <param-name>IFS.NODE.NodeName</param-name>
      <param-value>DefaultNode</param-value>
    </context-param>

    <context-param>
      <description>The name of the Service this Node is running with</description>
      <param-name>IFS.NODE.Service</param-name>
      <param-value>DefaultService</param-value>
    </context-param>

    <context-param>
      <description>The name of the node configuration for this CMSDK Node</description>
      <param-name>IFS.NODE.NodeConfigurationName</param-name>
      <param-value>IFS.NODE.DefaultNodeConfiguration</param-value>
    </context-param>

    <context-param>
      <description>The name of the service configuration the service is running with</description>
      <param-name>IFS.NODE.ServiceConfigurationName</param-name>
      <param-value>IFS.SERVICE.SmallServiceConfiguration</param-value>
    </context-param>

    <context-param>
      <description>Time in seconds the shutdown process should wait for the service to disappear.</description>
      <param-name>IFS.NODE.ShutdownWaitTime</param-name>
      <param-value>30</param-value>
    </context-param>

    <context-param>
      <!-- Options: OFF, SEVERE, WARNING, INFO (default), CONFIG, FINE, FINER, FINEST, ALL -->
      <description>The overall LogLevel of the Node.</description>
      <param-name>LogLevel</param-name>
      <param-value>INFO</param-value>
    </context-param>

    <context-param>
      <description>The filename of the logfile for this Node.</description>
      <param-name>LogFileName</param-name>
      <param-value>DefaultNode.log</param-value>
    </context-param>

    <!-- Optional, per default the logfile will be written to your runtime directory
    <context-param>
      <description>The absolute path of the logfile location for this Node.</description>
      <param-name>LogFilePath</param-name>
      <param-value>/tmp</param-value>
    </context-param>
    -->

    <context-param>
      <!-- Options: Defines the top level package name for logging  -->
      <description>The name of the root logger.</description>
      <param-name>RootLoggerName</param-name>
      <param-value>oracle.ifs</param-value>
    </context-param>

    <context-param>
      <!-- Options: text (default), xml -->
      <description>The format of the logfile for this Node.</description>
      <param-name>LogFileFormat</param-name>
      <param-value>text</param-value>
    </context-param>

    <context-param>
      <!-- Options: true, false (default) -->
      <description>Routes logging to console (stdout) AND to a logfile.</description>
      <param-name>LogToConsole</param-name>
      <param-value>false</param-value>
    </context-param>

    <context-param>
      <!-- Options: 5MB (default), 0 means no limit, other number in bytes -->
      <description>Defines the maximum size in bytes of a logfile before creating the next one.</description>
      <param-name>MaxLogFileSize</param-name>
      <param-value>5242880</param-value>
    </context-param>

    <context-param>
      <description>Defines the maximum number of logfiles to keep before overwriting the oldest one.</description>
      <param-name>MaxLogFileCount</param-name>
      <param-value>30</param-value>
    </context-param>

    <context-param>
      <!-- Options: 1d (default), 0 indicates no time based rotation
       Allowed values are a number followed by either D (days), H (hours), M (minutes) and S (seconds)
       If no postfix is specified the provided number is assumed to be in milliseconds.
       Examples are: 12H = 12 hours; 3D = 3 days; 35M = 35 minutes; 86400000 = 86,400,000 milliseconds
      -->
      <description>Defines the log period in milliseconds before rotating the logfile.</description>
      <param-name>LogFileRotationPeriod</param-name>
      <param-value>1d</param-value>
    </context-param>

    <context-param>
      <!--
       Syntax: oracle.ifs.examples : FINE, oracle.ifs.core.runtime.NodeManager : INFO
       The list of overrides should be seperated by a comma ','
       The override is defined as 'class/package : LogLevel'
      -->
      <description>Implements LogLevel overrides at class or package level</description>
      <param-name>LogLevelOverrides</param-name>
      <param-value></param-value>
    </context-param>

    NOTE: Each CMSDK should have a unique name. So make sure that the param-value for IFS.NODE.NodeName is different in each web.xml if you are planning to run a multi-Node environment.

  5. In your code you can now use the following way of connecting to CMSDK via a managed service:

    if(LibraryService.isServiceStarted(SERVICE_NAME))
    {
      service = LibraryService.findService(SERVICE_NAME);
    }
    else
    {
      // This should not be necessary, as the Node should have already started the Service by now.
      // Just in case he didn't, we can start a Service the old fashion way as unmanaged. The Node will
      // find it later and manage it from then on.
      service = LibraryService.startService(SERVICE_NAME, CMSDK_SCHEMA_PWD, SERVICE_CONFIG_NAME, DOMAIN_URL);
    }
    ...
    LibrarySession session = service.connect(credentials, null);
About

My name is Frank Closheim. I lead Development for CMSDK at Oracle and want to share the latest news, best practices, examples and product updates about CMSDK with the Blogsphere.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today