« August 2009 | Main | October 2009 »

September 2009 Archives

September 10, 2009

Message Driven Bean Migration from OC4J to WebLogic

Both OC4J and WebLogic have a provider specific descriptor that, in conjunction with the standard ejb-jar.xml descriptor, integrates MDBs with the container and provides inbound configuration that identifies the source destination and related information.  This source destination may share the same instance as the MDB, be from a different instance, or even a different JMS provider.    This discussion will focus on the configuration approaches of OC4J and WebLogic and offer what needs to be considered when migrating an existing MDB deployed to OC4J to a WebLogic server.

OC4J and WebLogic MDB Configuration Approaches

Each OC4J JMS MDB endpoint is associated with a set of configuration properties (referred to as ActivationSpec properties).    These properties are typically set in the orion-ejb-jar.xml, however, the properties can also be set in the ejb-jar.xml file if the JMS connector is included in an application's .ear file.   The syntax for each file is different.

<orion-ejb-jar>
    <enterprise-beans>
       <message-driven-deployment name="simpleMdb" resource-adapter="tibcojms">
        <config-property>
            <config-property-name>ExamplePropertyName</config-property-name>
            <config-property-value>ExampleValue</config-property-value>
        </config-property>
        ...

When using the ejb-jar.xml file, the properties are added to each <message-driven> node, using the following syntax:

<ejb-jar>
    <enterprise-beans>
       <message-driven>
          <ejb-name>simpleMdb</ejb-name>
          <activation-config
        <activation-config-property>
            <activation-config-property-name>ExamplePropertyName
            </activation-config-property-name>
            <activation-config-property-value>ExampleValue
            </activation-config-property-value>
        </activation-config-property>
       ...

A complete listing of OC4J JMS ActivationSpec properties and their usage can be found in chapter four of the OC4J Services Guide, fine tuning MDB endpoints.

For WebLogic, Message Driven Beans can be integrated into the server through the use of the <message-driven-descriptor> stanza within the weblogic-ejb-jar.xml file.

<weblogic-ejb-jar>
  <weblogic-enterprise-bean>
    <ejb-name>SimpleMdb</ejb-name>

    <message-driven-descriptor>
       <destination-jndi-name>...</destination-jndi-name>
       <initial-context-factory>...</initial-context-factory>
       <connection-factory-jndi-name>...</connection-factory-jndi-name>
       <jms-client-id>...</jms-client-id>
       <generate-unique-jms-client-id>...</generate-unique-jms-client-id>
       <durable-subscription-deletion>...</durable-subscription-deletion>
       ...
    </message-driven-descriptor>

  </weblogic-enterprise-bean>
</weblogic-ejb-jar>


A complete description for developing MDBs in WebLogic can be found in the Design Message-Driven Beans guide.

MDB Migration Considerations

Resource References

It's very common for MDB applications to leverage resource references for forwarding/response purposes.  Like OC4J, WebLogic provides an element in its proprietary weblogic-ejb-jar.xml to map a logical resource reference to a JNDI location.   This element is named <resource-description>.   Enhanced Support for Using WebLogic JMS with EJBs and Servlets steps through its usage step-by-step and also describes how WebLogic automatically wraps and pools resource references.

XA Support

Both OC4J and WebLogic utilize the standard JEE ejb-jar.xml descriptor to identify if the inbound MDB participates in an XA transaction.  
<ejb-jar>
<enterprise-beans>
<message-driven>
<transaction-type>Container</transaction-type>

<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>...</ejb-name>
<method-name>onMessage()</method-name>
</method>
<trans-attribute>Required</trans-attribute>

Users must then specify a JMS connection factory that implements the XA for the inbound MDB and for any connection factories configured as resource-references used within the MDB.

Translating OC4J JMS MDB ActivationSpec Properties

Migrating the MDB involves understanding which ActivationSpec properties are defined for the MDB in OC4J, then utilize the WebLogic MDB descriptor elements to configure similar behavior.   Furthermore, any ActivationSpec properties defined within the standard ejb-jar.xml descriptor should either be commented out or removed.   WebLogic will not process OC4J specific activation-config-properties.

A listing of OC4J JMS MDB ActivationSpec properties and how they may be translated to the descriptors for WebLogic's MDB implementation is a follows:

OC4J JMS MDB
ActivationSpec Property
Purpose
How to define in WebLogic
ConnectionFactoryJndiName,
Destination Name,
DestinationType
MDB inbound configuration including the JNDI names for the connection factory and destination and the destination type.
The inbound JNDI names for the MDB are configured as connection-factory-jndi-name and destination-jndi-name elements in the message-driven-subscription section of weblogic-ejb-jar.xml.
The destination type is specified using the destination-type element in the message-driven section of ejb-jar.xml.
SubscriptionDurability,
SubscriptionName
Identifies if an MDB's topic subscription is durable or non-durable and the subscription name.
The subscription durability is configured as subscription-durability element in the message-driven section of ejb-jar.xml.  Subscription name can not be specified in WebLogic.
ClientID If set, connections used by the inbound MDB connection will set this clientID Set by the jms-client-id element in the message-driven section of weblogic-ejb-jar.xml.   Additionally, a generate-unique-jms-client-id element in the same descriptor may be used in some cases.
AcknowledgeMode
Controls quality of service for MDB's onMessage
Configured as acknowledge-mode element in the message-driven section of the ejb.jar.xml.
MessageSelector
Selector expression to filter inbound messages
Configured as message-selector element in the message-driven section of the ejb-jar.xml.
UseExceptionQueue,
ExceptionQueueName,
IncludeBodiesInExceptionQueue
Specifies how to handle problem messages (if they should be saved to an exception queue and in what format)
WebLogic does not handle problem messages on an MDB by MDB basis.   User needing such features may consider configuring an error destination if the JMS provider is WebLogic.
MaxDeliveryCnt The number of times an MDB will attempt to process the same message before it is discarded. WebLogic MDBs do not supply this capability directly.
If the source destination is a WebLogic JMS destination, users can configure a delivery limit in the JMS destination configuration.    Also, if the source is a WebLogic JMS destination you can configure redelivery delay.
MaxListenerThreads,
MinListenerThreads,
ReceiverThreads
Controls the maximum and minimum number of receiver threads to create for the endpoint.  (RecieverThreads was depricated in OC4J 10.1.3.4 in favor of Min/MaxListenerThreads) This is configured by the max-beans-in-free-pool and dispatch-policy element values in the message-driven-descriptor element of weblogic-ejb-jar.xml.
ListenerThreadMaxPollInterval,
ListenerThreadMaxIdleDuration,
ListenerThreadMinBusyDuration
Controls the throttling of the number of MDB threads, how fast should they ramp up or down (works in conjunction with MaxListenerThreads and MinListenerThreads).
No action required.  WebLogic MDB thread throttling is either automatic or is delegated to the source JMS server's built in asynchronous consumer capability, depending on the use case
EndpointFailureRetryInterval
If endpoint can not be processed, how long until it will be scheduled to be retried

The init-suspend-seconds element Allows an MDB to suspend it's JMS connection when the EJB container detects a JMS resource outage.

The max-suspend-seconds element provides the maximum number of seconds to suspend an MDB's JMS connection when the EJB container detects a JMS resource outage.

Additionally, the jms-polling-interval-seconds element sets the number of seconds between attempts by the EJB container to reconnect to a JMS destination that has become unavailable.
ResUser,
ResPassword
Allow a pre-defined username/password to be specified for the MDB's JMS connection.
Users may utilize the JMS Foreign Server (even for the local WebLogic JMS server) to specify pre-defined username/passwords for the MDB's inbound connection.

Configuring a Security Identity for a Message-Driven Bean is another approach available in WebLogic.


When the Destination is Remote

When a destination is remote, both WebLogic and OC4J require further configuration.

OC4J requires that remote destinations and connection factories be configured as part of a JMS Connector.  The JMS connector will use an OC4J resource-provider to access a foreign server's context.  The connector includes entries in oc4j-connectors.xml to map foreign destinations and the resource adapter's oc4j-ra.xml descriptor for mapping connection factories.   OC4J utilizes the same JMS Connector approach when accessing JMS objects for the local OC4J instance's JMS server objects.

For WebLogic, remote destinations are preferably accessed via Foreign Server Context, Foreign Connection Factory, and Foreign Destination mappings that are configured in a JMS configuration system module.

In WebLogic, a destination is known to be "local" to a WebLogic MDB when the MDB and destination both run on the same server or cluster. In cases where the destination is deployed on a different server or cluster, it is referred to as a "remote" destination to the MDB.  

A remote destination also includes those defined in the Oracle AQ JMS provider and non-Oracle JMS providers..   Integrating AQ JMS with WebLogic 10.3.1 is discussed in Interoperating with Oracle AQ JMS.   Information for integrating AQ JMS with earlier WebLogic releases can be found in AQ - Weblogic JMS Connectivity using Weblogic JMS Bridge.   Integrating WebLogic with non-Oracle providers is discussed in
Configuring Foreign Server Resources to Access Third-Party JMS Providers

The nature of a destination--local versus remote--dictates to some extent how the following key elements in the message-destination-descriptor for the MDB in weblogic-ejb-jar.xml are configured, as shown in the table below:

WebLogic message-driven-description Attribute
Value
Destination is Local
Destination is Remote
Not using Foreign Server (not the preferred method)
Using Foreign Server (preferred method)
provider-url
Do not specify
Specify remote/foreign provider-url
Do not specify provider-url.  The URL is implicitly encoded in the Foreign Server configuration.
initial-context-factory
Do not specify
Specify the initial context factory class name used by the JMS provider except when the remote provider is WebLogic JMS, in which case, do not specify this value (use the default)
do not specify initial-context-factory
destination-jndi-name
Specify the name bound in the local JNDI tree for the destination
Specify the name of the destination, as bound in the remote provider's JNDI tree
Specify the name of the Foreign Destination you set up in your local JNDI tree that corresponds to the remote or foreign destination.
connection-factory-jndi-name
Do not specify connection-factory-jndi-name unless a custom connection factory is configured to be used with the MDB.
Specify the name of the connection fatory used by the JMS provider, as bound in the remote JNDI tree, except when the remote provider is WebLogic JMS in which case it is okay to use the default.
Specify the Foreign Connection Factory you set up in your local JNDI tree that corresponds to the remote JMS provider's connection factory.

For more information regarding WebLogic and MDB Integration





Application Client Upgrades from OC4J to WLS

Summary

Upgrading an OC4J Java EE application in order to deploy to Weblogic server may require one of several upgrade paths, depending upon the component being upgraded.  Remote clients that rely on the Application Client Container will require deployment changes in order to access resources on Weblogic Server.  One use case for remote clients will require some extra steps in order to upgrade successfully.  That case is the subject of this blog posting. 

 

OC4J's JNDI implementation allows a standalone client to take advantage of some features of the application client in Java EE without running in a Java EE Application Client Container.  A client can use the

 

"oracle.j2ee.naming.ApplicationClientInitialContextFactory"

 

InitialContextFactory implementation in order to access this functionality.  As long as the client includes a "META-INF/application-client.xml" deployment descriptor in the client jar, this initial context factory will create a JNDI context that can support Java EE resources that are typically used in an application client (EJB references, Resource References, Environment entries, etc).  This context factory will use the application-client.xml and the proprietary orion-application-client.xml in order to map JNDI bindings to logical Java EE reference names.  This level of application client support does not include Java EE 1.5-style annotations/dependency injection. 

 

Please refer to the following for more information on OC4J's Application Client support:

 

Looking Up Objects from J2EE Application Clients

 

While not required by the Java EE specification, this type of remote client can be very useful when a customer wishes to use the Java EE standard resource mapping types in order to use logical names for resources such as EJBs, Datasources, and JMS destinations.  Using an application client deployment descriptor has the advantage of allowing resources to change without having to change the client code itself, and can be considered useful even if not running in the Application Client Container. 

 

Customers using this feature of the ApplicationClientInitialContextFactory in OC4J will need to port their application client to run in the Weblogic Server Application Client Container. 

 

Upgrade Steps

The steps required to upgrade an OC4J application client to run in the Weblogic Application Client Container are as follows:

 

  1. Add a "Main-Class" entry to the client jar's manifest.  This entry should specify the entry point class for the application client.  This class, according to the Java EE standard, must include a "public static void main(String[] args)" method, and also include a no-arguments constructor. 

 

An example of the proper manifest entry would look as follows:

            Manifest-Version: 1.0

     Ant-Version: Apache Ant 1.6.5

     Created-By: 1.5.0_06-b05 (Sun Microsystems Inc.)

     Main-Class: oracle.ejb30.HelloWorldClient

 

      

 

  1. Modify the jndi.properties file in this client (or the source code that sets the JNDI properties directly) to refer to the Oracle WebLogic Server JNDI Provider.

 

An example of the jndi.properties file would look as follows:

 

            java.naming.factory.initial=weblogic.jndi.WLInitialContextFactory

java.naming.provider.url=t3://localhost:7001

 

    

The jndi.properties file may also require a username/password.  These JNDI properties should be modified to use the principal and credentials created on the Weblogic Server. 

           

 

  1. For every element in orion-application-client.xml, create a corresponding element in weblogic-application-client.xml to map any Java EE references to the resources bound in Oracle WebLogic Server.

 

  1. Modify the classpath of the client to include the Oracle WebLogic Server client jars.  The jars required for the classpath are determined by the protocol that the customer wishes to use for this client. 

 

Please refer to the following Weblogic Server documentation to determine the appropriate client jar to use:

 

Client Types and Features

 

 

  1. Modify any application client startup scripts to use the Oracle WebLogic Server application client launcher.

 

The following is an example of a typical command line for launching a Weblogic Application Client:

java weblogic.demo.DemoClient myclient.jar t3://localhost:7001

 

 

The following links will be helpful when attempting to upgrade an application client from OC4J to Weblogic Server:

 

"WLS - Programming Standalone Clients"

Programming Stand-alone Clients

 

"Oracle Fusion Middleware Upgrade"

Oracle Fusion Middleware Upgrade

 

September 14, 2009

Migrating OC4J 10.1.3 Stateful Web Services to WebLogic

Consider migrating an OC4J 10.1.3 web service to WebLogic. If the migration preserves the service WSDL description, the original client for that OC4J 10.1.3 web service will work with the migrated service. However, if the service is stateful, the original client will no longer work. OC4J 10.1.3 stateful web service uses HTTP session to track the web service session. WebLogic, on the other hand, does not support such http session-based stateful web service. One way to allow the original client to work with the migrated service is to modify the migrated service implementation to map http session into the web service session. Below is a modified service implementation.

package cyclecounter.test.oracle;
import java.net.URI;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;
import javax.jws.WebService;
import javax.xml.rpc.server.ServiceLifecycle;
import javax.xml.rpc.server.ServletEndpointContext;
import weblogic.jws.WLHttpTransport;

@WebService(serviceName = "testsfWS-serssion", portName = "HttpSoap11", endpointInterface = "cyclecounter.test.oracle.CycleCounterInterface") @WLHttpTransport(serviceUri = "/HttpSoap11", portName = "HttpSoap11")
public class CycleCounterInterfaceImpl implements ServiceLifecycle {
  private ServletEndpointContext context;
  public void init(Object context){
    this.context = ((ServletEndpointContext)context);
  }
  public void destroy() {
  }

  public int getCurrentCounter() {
    CycleCounterImpl impl = SessionManager.getImpl(context);
    return impl.getCurrentCounter();
  }
}

The
CycleCounterInterfaceImpl class serves as a wrapper around the actual service implementation. The SessionManager class maps JSESSIONID cookie to its corresponding service implementation instance.

package cyclecounter.test.oracle;
import java.util.HashMap;
import javax.servlet.http.HttpSession;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.server.ServletEndpointContext;
import weblogic.wsee.connection.transport.servlet.HttpTransportUtils;

public class SessionManager {
// timeout in 15 seconds
private final static long timeout = 15 * 1000l;
private final static HashMap<HttpSession, Long> timeoutMap = new HashMap<HttpSession, Long>();
private final static HashMap<HttpSession, CycleCounterImpl> implMap = new HashMap<HttpSession, CycleCounterImpl>();
public static synchronized CycleCounterImpl getImpl(ServletEndpointContext context) {
MessageContext mc = context.getMessageContext();
HttpSession session = HttpTransportUtils.getHttpServletRequest(mc).getSession(true);
CycleCounterImpl impl=implMap.get(session);
if (impl!=null) {
long time = timeoutMap.get(session);
if (System.currentTimeMillis()>time+timeout) {
// session timed out
implMap.remove(session);
}
}
if (impl==null) {
// new session
impl = new CycleCounterImpl();
implMap.put(session, impl);
timeoutMap.put(session, System.currentTimeMillis());
}
return impl;
}
}
The SessionManager class could be enhanced for better session management, particularly configuring timeout, and pooling service implementation instances.

September 22, 2009

Sample WebLogic JMX Client

Our goal is to implement a simple WebLogic JMX client that can be used as a starting point to write any WebLogic JMX client. We will look at the client's code. The classpath used to compile and run the code. The different WebLogic MBeanServers and associated JMX URI's the JMX Client can connect to.

Let's directly dive in the client's code below:

package blog.wls.jmx.client;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.JMXConnectorFactory;
import java.util.Hashtable;
import java.util.Set;

public class JMXClient {

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

        JMXConnector jmxCon = null;
 
        try {
            JMXServiceURL serviceUrl = 
                new JMXServiceURL(
         "service:jmx:iiop://127.0.0.1:7001/jndi/weblogic.management.mbeanservers.runtime");

            System.out.println("Connecting to: " + serviceUrl);
 
            Hashtable env = new Hashtable();
            env.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, 
                         "weblogic.management.remote");
            env.put(javax.naming.Context.SECURITY_PRINCIPAL, "weblogic");
            env.put(javax.naming.Context.SECURITY_CREDENTIALS, "welcome1");

            jmxCon = JMXConnectorFactory.newJMXConnector(serviceUrl, env);
            jmxCon.connect();
            MBeanServerConnection con = jmxCon.getMBeanServerConnection();
 
            Set<ObjectName> mbeans = con.queryNames(null, null);
            for (ObjectName mbeanName : mbeans) {
                System.out.println(mbeanName);
            }
        }
        finally {
            if (jmxCon != null)
                jmxCon.close();
        }
    }
}

Let's take a quick look at the above code.

JMXServiceURL serviceUrl = 
                new JMXServiceURL(
      "service:jmx:iiop://127.0.0.1:7001/jndi/weblogic.management.mbeanservers.runtime");

The JMX service URI identifies the following:

  • The protocol used to communicate with the remote WebLogic process. "iiop" in the above example. WebLogic supports "t3", "iiop" and "rmi". We won't touch further on this topic here.
  • The WebLogic process to connect to (host & port ). "127.0.0.1:7001" in the above example.

    The port value is available from the <WLS_INSTANCE_HOME>/config/config.xml file:

     <server>
        <name>myServer</name>
        <listen-port>7001</listen-port>
        <listen-address>myhost</listen-address>
      </server>
    
    Make sure you look under the correct server if several servers are defined as part of your config.xml. For instance in the above case we are connecting to the server identified as "myServer".

    The same information is also available from the server log at <WLS_INSTANCE_HOME>/servers/myServer/logs/myServer.log:

    <Sep 22, 2009 12:05:23 PM PDT> <Notice> <Server> <localhost><myServer>
    <[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'> 
    <<WLS Kernel>> <> <> <1253585123268> <BEA-002613> <Channel "Default" is now
    listening on myhost:7001 for protocols iiop, t3, ldap, snmp, http.> 
    
  • The MBeanServer to connect to: " weblogic.management.mbeanservers.runtime". This identifies WebLogic's "Runtime" MBeanServer. This is the MBeanServer available from any WebLogic process, and that contains both WebLogic and user MBeans.
            Hashtable env = new Hashtable();
            env.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,
                    "weblogic.management.remote");
            env.put(javax.naming.Context.SECURITY_PRINCIPAL, "weblogic");
            env.put(javax.naming.Context.SECURITY_CREDENTIALS, "welcome1");

The above code specifies properties associated with the connection. "weblogic.management.remote" identifies the package implementing WebLogic's client side connector code. For instance the 't3' or 'iiop' client connector.

"weblogic" and "welcome1" are the login/password associated with the user originating the JMX connection.

In the rest of the code we establish the JMX connection, and then retrieve the ObjectNames for all the MBeans registered in the "Runtime" MBeanServer. The ObjectNames are then displayed on the console. We also make sure we release the connection in a finally block to avoid leaking any resource.

The code doesn't contain any WebLogic specific classes, and can be compiled as follow:

javac -d . blog/wls/jmx/client/JMXClient.java

Executing the code requires to add WebLogic client side classes to the execution ClassPath. We need to include the WebLogic JMX connector client side classes. Remember we specified those in the environment properties passed to the JMXConnectorFactory. Below is the command I used:

java -classpath .:$WL_HOME/server/lib/wljmxclient.jar blog/wls/jmx/client/JMXClient

WL_HOME points to the WebLogic binary install.

The above uses WebLogic's thin client classes. In some cases when you access server side classes, or you want to take full advantage of the t3 protocol, you are required to use WebLogic's thick client classes. To do so, you first need to build wlfullclient.jar as follow:

cd $WL_HOME/server/lib
java -jar wljarbuilder.jar

You can then execute the JMX Client as follow:

java -classpath .:$WL_HOME/server/lib/wlfullclient.jar  blog/wls/jmx/client/JMXClient

You can also bundle wlfulclient.jar with your client code. When using the thin client you cannot just bundle wljmxclient.jar with you client code, as this jar references other jars as part of its manifest Class-Path entry. At the time of this writing, you also need to bundle wlclient.jar

At this point we are now able to connect to WebLogic's "Runtime" MBeanServer. Each WebLogic process contains a "Runtime" MBeanServer in which local WebLogic MBeans and user-defined application MBeans are registered. WebLogic also offers two other MBeanServers that are only available from the Domain "AdminServer" process:

  • The "Domain Runtime" MBeanServer. It aggregates the MBeans registered on the domain's "Runtime" MBeanServers. So as long as a managed server is up, its MBeans can be accessed through the "Domain Runtime" MBeanServer. To connect to that MBeanServer, just use the following JMX URI:

    service:jmx:iiop://127.0.0.1:7002/jndi/
    weblogic.management.mbeanservers.domainruntime
    

    "7002" is the iiop port for my "AdminServer" install. Replace with your AdminServer's port as previously explained. Remember; only the AdminServer process runs the "Domain Runtime" MBeanServer.

  • The "Edit" MBeanServer. It contains the WebLogic Config MBeans that are used to configure the Domain. To connect to that MBeanServer, just use the following JMX URI:

    service:jmx:iiop://127.0.0.1:7002/jndi/weblogic.management.mbeanservers.edit 
    

    "7002" is the iiop port for my "AdminServer" install. Replace with your AdminServer's port as previously explained. Remember; only the AdminServer process runs the "Domain Runtime" MBeanServer.

Note: One can also use "t3" or "rmi" as protocol in place of "iiop"

The rest of the client's code remains unchanged. Only the JMX URI needs to be changed to connect to different MBeanServers.

About September 2009

This page contains all entries posted to WebLogic Server in September 2009. They are listed from oldest to newest.

August 2009 is the previous archive.

October 2009 is the next archive.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type and Oracle