Upgrading Controls

This topic gives more detail about upgrade changes noted for controls.

For other upgrade issues related to controls, see the following topics:

Replacing Callback-Enabled Controls Used in a Page Flow

For a more complete list of changes affecting applications upgraded from version 8.1, see Changes During Upgrade from WebLogic Workshop 8.1 to Version 10.x.

Enabling Automatic Transaction Support in Controls

In version 8.1, controls are automatically run within the scope of a transaction because they're run in the context of an Enterprise JavaBean. In version 10.x controls are Plain Old Java Objects (POJOs). As a result, if you want transaction support, your control interfaces must be annotated with the @TransactionAttribute annotation for transaction support.

During upgrade, upgrade tools will add an annotation for transaction support. The following version 8.1 and version 10.x examples show a very simple control interface before and after upgrade.

In version 8.1, no annotation was required:

package localControls.nestedControls; 

import com.bea.control.Control;

 * This is the public interface for the VerifyFunds control.
 * The control is implemented in VerifyFundsImpl.jcs.
public interface VerifyFunds extends Control
    interface Callback
        void onTransactionComplete(String message, boolean isBalanceAvailable, 
			boolean isInventoryAvailable);

     * @common:operation
    void submitPO(java.lang.String poNumberString, 
        java.lang.String customerIDString, int itemNumber, 
        int quantityRequested, double startingBalance);

In version 10.x, the @TransactionAttribute annotation signifies that transaction support is requested:

package localControls.nestedControls; 

import com.bea.control.annotations.TransactionAttribute;
import com.bea.control.annotations.TransactionAttributeType;
import org.apache.beehive.controls.api.bean.ControlInterface;
import org.apache.beehive.controls.api.events.EventSet;

 * Public interface for the VerifyFunds control.
public interface VerifyFunds 
    @EventSet(unicast = true)
    interface Callback
        void onTransactionComplete(String message, boolean isBalanceAvailable, 
			boolean isInventoryAvailable);

    void submitPO(java.lang.String poNumberString,
        java.lang.String customerIDString, int itemNumber, 
        int quantityRequested, double startingBalance);

Replacing Control Factory Functionality

Version 10.x does not support control factories, a version 8.1 feature in which multiple control instances could be created at run time from a single control. If your code uses control factories, you'll need to replace the functionality with an alternate solution.

You can support control factory-like functionality by using control-related APIs through which you explicitly instantiate multiple control instances. The following example illustrates by using a simplified version of the control factory example that was included with the version 8.1 samples application.

package controlfactory;

import java.util.HashMap;
import java.util.Map;
import java.io.Serializable;
import javax.jws.WebMethod;
import javax.jws.WebService;
import org.apache.beehive.controls.api.bean.ControlReferences;
import org.apache.beehive.controls.api.bean.Controls;
import weblogic.jws.Conversation;
import weblogic.jws.WLHttpTransport;
import javax.jws.soap.SOAPBinding;
import controlfactory.SlowServiceControlBean;
import controlfactory.SlowServiceControl;

 * The following code demonstrates how you can achieve version 8.1 control
 * factory functionality by using APIs associated with controls.
 * The code in this example is a somewhat simplified version of the control
 * factory example included in the version 8.1 SamplesApp application.
@WLHttpTransport(serviceUri = "controlfactory/ServiceFactoryClient.jws")
@WebService(serviceName = "ServiceFactoryClient", 
        targetNamespace = "http://workshop.bea.com/ServiceFactoryClient")
@javax.jws.soap.SOAPBinding(style = javax.jws.soap.SOAPBinding.Style.DOCUMENT, 
        use = javax.jws.soap.SOAPBinding.Use.LITERAL, 
        parameterStyle = javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED)
public class ServiceFactoryClient implements java.io.Serializable {
    static final long serialVersionUID = 3553L;

    static Map<String, Long> serviceControlsMap = new HashMap<String, Long>();

    int m_numServices;

     * This method does the work of creating a quantity of control instances
     * based on a number received in the numServices param.
    @SOAPBinding(style = javax.jws.soap.SOAPBinding.Style.DOCUMENT, 
    		use = javax.jws.soap.SOAPBinding.Use.LITERAL, 
    		parameterStyle = javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED)
    public void startServices(int numServices) {
        int i;

        if (numServices > 0) {
            try {
                for (i = 0; i < numServices; i++) {
                    m_numServices = numServices;

                    // Instead of using a control factory, instantiate separate
                    // instances of the control using the Controls.instantiate
                    // method.
                    SlowServiceControlBean bean;
                    bean = (SlowServiceControlBean) Controls.instantiate(Thread
                            "controlfactory.SlowServiceControlBean", null);

                    // Also pair an instance of the callback handler
                    // for each new control instance. This handler will listen
                    // for the service's infoReady callback.
                    SlowServiceCallbackHandler handler = new SlowServiceCallbackHandler(

                    // Call the Service control, passing a unique value to label
                    // it for identifying later.
                    String serviceName = "Service" + i;

                    // Stash the time each control is launched, indexed by
                    // instance name
                    serviceControlsMap.put(serviceName, new Long(
                            (new java.util.Date().getTime())));
            } catch (Exception e) {

     * Callback handler for the control's infoReady callback.
    public class SlowServiceCallbackHandler implements
            SlowServiceControl.Callback, Serializable {
        static final long serialVersionUID = 1L;

        private SlowServiceControlBean serviceControl;

        public SlowServiceCallbackHandler(SlowServiceControlBean control) {
            serviceControl = control;

        public void infoReady(String name) {
            // Compute how many seconds since this control was launched.
            long timeTaken = 
            	(new java.util.Date().getTime() - ((Long) serviceControlsMap
                    .get(name)).longValue()) / 1000;

            // A ControlBean instance provides many methods useful for
            // getting information about the instance.
            String controlId = serviceControl.getControlID();

            // Print the information discovered.
            printControlInfo(name, controlId, timeTaken);

        public void onAsyncFailure(String arg0, Object[] arg1) {
            // TODO Auto-generated method stub

    public String finishServices() {
        return "Finished. " + m_numServices + " services invoked.";

    public void printControlInfo(String serviceName, String controlId, long time) {
        System.out.println("Control callback received from " + serviceName
                + ":" + controlId + " after " + time + " seconds.");

This example includes the following APIs:






Xbean wrapper classes generated for a ServiceControl must not be visible to the target JWS

When generating Xbean types for a Service Control, there are a limited number of situations where the wrapper type from the WSDL is exposed as a type in the Service Control (e.g. when there are multiple occurrences of the same Document type in the same operation signature). If the generated types jar is visible to the target JWS classloader, a duplicate type error will be thrown during deployment.

In this case, place Service Controls that use wrapper types in a separate project than the Service that they call. If the SerivceControl classes are loaded from a utility project, then the Service Control and the target Service must be in separate applications.

Associating a Service Control with a WSDL

While version 8.1 allowed a service control to not be associated with a WSDL, the control must be associated with a WSDL in order for it to upgrade successfully.

You can associate the WSDL with the service control in WebLogic Workshop 8.1 before you upgrade your application. The easiest way to do this is by regenerating the Service control from the WSDL. In the Application tab, right-click the WSDL, then click Generate Service Control.

You can also associate the WSDL manually by pasting it into the Service control. Open the Service control in Source View, scroll to the end of the file and paste the WSDL's contents as the value of a @common:define annotation after all other code. Note in the following example that the value attribute encloses its value in double colons, and that the Javadoc comment continues after it.

/** @common:define name="MyServiceWsdl" value::
    ... WSDL contents ...
* ::

After adding the WSDL, add a @jc:wsdl annotation to the control declaration as follows:

 * <other annotations>
 * @jc:wsdl file="#MyServiceWsdl"
public interface MyServiceControl extends ControlExtension, ServiceControl

Note that the value of the file attribute is the same as the value of the @common:define name attribute, but with a # sign prepended.

Upgrading Service Controls that are Based on an Abstract WSDL

In version 8.1 it was possible to generate a service control from an abstract WSDL — that is, from a WSDL with no service definition. You could then configure the endpoint to call or listen on programmatically or by using annotations. However, WebLogic Server version 10.x does not support abstract WSDLs. As a result, Workshop's upgrade tools are unable to upgrade a service control with the necessary annotations, leaving compiler errors in upgraded code. Likewise, if you try to generate a service control from an abstract WSDL in 9.x, you will receive an error stating that a service is required.

One workaround is to add a <service> definition into the WSDL before using upgrade tools. That added entry will not be used in upgraded code because the endpoints will be taken from the annotations instead.

Replacing Service Control Methods getEndPoint and setEndPoint

The ServiceControl.getEndPoint() and ServiceControl.setEndPoint(URL) methods are deprecated in version 10.x and may be removed in a future version. New code requiring this kind of API should use ServiceControl.getEndpointAddress() and ServiceControl.setEndpointAddress(String), respectively.

Note that a URL instance (as used in the version 8.1 methods) isn’t required in order to support the most common usage for these methods; a String instance suffices. The get* method is useful in debugging, providing a way to retrieve and log the endpoint location. The set* method is useful for dynamically configuring the endpoint location at run time, such as when the destination is on another server/cluster.

Configuring Run-Time Message-Level Security Via the Service Control

Due to changes in the web services security model, the means for specifying security characteristics through the version 10.x service control differs from version 8.1. In version 8.1, you specified both security policies and values in a WebLogic Workshop WSSE policy file. In version 10.x, the means for specifying characteristics for these two aspects of security has been split into multiple locations.

Briefly, the model for specifying aspects of security in the version 10.x service control is as follows:

Repairing Service Control JMS URL After Upgrade

When upgrading a service control, upgrade tools do not correctly upgrade a JMS URL specified in a @jc:location annotation. You will need to manually edit the URL. For example, compare the following URLs from version 8.1 and its upgraded counterpart:

Version 8.1

@jc:location jms-url="jms://localhost:7001/weblogic.jws.jms.QueueConnectionFactory/jws.queue?URI=/services/MyService.jws&java.naming.factory.initial=com.myco.jndi.factory"

Version 10.x

@ServiceControl.Location(urls = {

To fully upgrade the URL, make the following edits:

After edits, your JMS URL might look like the following (if you elect to specify the connection factory):

@ServiceControl.Location(urls = {

Upgrade does not copy some MBCS characters in .jcx files

When upgrading some .jcx files, the upgrade process may not be able to copy some MBCS characters into the resulting upgraded file. This happens when a WSDL with UTF-8 encoding is inside a file with some other sort of MBCS encoding, like MS932 (Japanese) and MBCS characters appear in that file outside of the WSDL definition.

When this happens, the resulting file will have "????" in place of the original characters, which will not compile.

In this case, perform one of these fixes:

  1. Change the wsdl definition to VM encoding instead of UTF-8 or others, if these are different.
  2. Upgrade source
  3. Change the wsdl definition to the original like UTF-8 both within Service Control source comment and generated wsdl file.

Upgrading EJB Control getJNDIName and setJNDIName Method Invocations

Differences from the getJNDIName and setJNDIName methods exposed from the version 8.1 EJB control will cause errors in upgraded code. In version 8.1, these methods were exposed as EJBControl.getJNDIName and EJBControl.setJNDIName; in version 10.x, they are exposed from a build-time-generated control bean class as getJndiName and setJndiName (note the case difference also).

You should be able to correct upgraded code by replacing the method invocations. For example, in version 8.1 you would have call these methods from an instance of the control, as follows:

import mypackage.MyEJBControl;
private MyEJBControl ejbControl;

public String getEJBJNDIName()
    String jndiName = ejbControl.getJNDIName();

In version 10.x you will call the method from an instance of a control bean class for your EJB control. (Note that the control bean isn't generated until you are able to successfully build the project.)

import mypackage.MyEJBControlBean;
private MyEJBControlBean ejbControlBean;

public String getEJBJNDIName()
    String jndiName = ejbControlBean.getJndiName()

Upgrading Security in EJB Controls

Due to the how the EJB control works (which differs from other kinds of controls), the upgrade tools do not automatically upgrade security annotations used in an EJB control. You can work around this difference by manually editing the EJB control extension file to include the needed methods and annotations.

Security annotations on controls are no longer supported at the class level. For controls that had security annotations at the class level, the upgrader will copy the security annotation to each method defined in the control. However, in the case of the EJB control, there are no methods defined directly in the control extension (the JCX file in version 8.1). Instead, the methods are inherited from the EJB home and interface definitions. Because omitting these annotations creates a security gap, upgrade tools will generate an error for any EJB control with security annotations.

To work around this difference, you can manually copy the EJB's methods into the control extension file and add the com.bea.control.annotations.Security annotation to each method. It is important to remember that any subsequent change to the EJB itself (such as adding new methods) may require updating the control extension to ensure that the security constraint formerly defined at the class level remains in force.

The following template-style example shows the kind of changes to make:

 * @common:security [attributes here]
public class MyEjb extends EJBControl, MyHome, MyLocal [other types] {
    // Nothing; methods were derived from the home and interface definitions.

After upgrade, you should edit the upgraded control extension so that the methods are declared along with the corresponding version 10.x annotation on them:

public class MyEjb extends EJBControl, MyHome, MyLocal [other types] {

    @Security [attributes here]
    void methodFromHome()
    @Security [attributes here]
    void methodFromBean()

Replacing JMS Control Receive Functionality

In version 10.x, a JMS control can't be used to receive messages. During upgrade, if version 8.1 @jc:jms annotations include attributes that specify message receiving behavior, these attributes will be ignored. For example, the following version 8.1 annotation will be migrated to the version 10.x annotation that follows it.

Version 8.1

@jc:jms receive-type="topic" receive-jndi-name="jms.AccountUpdate"

Upgrade to version 10.x

@JMSControl.Destination(jndiConnectionFactory = "weblogic.jws.jms.QueueConnectionFactory")

Here are two suggestions for working around this in upgraded code:

If it’s possible to update the receiving application, then replacing the receiving application with a JWS that has a callback would make it possible to replace the JMS control with a Service Control. If the API (between systems) included the use of JMS or user properties, then those properties would have to be added to the definition of the message(s) or added as custom SOAP headers.

If it’s not possible to update the receiving application, then an alternative approach is to add a Timer Control to the calling application and use the Timer events to trigger polling for response messages. When a response message is present, the JMS message (and any relevant properties) would be manipulated (as needed) to match the signature of the event method. This functionality could be encapsulated in a custom control to minimize the impact on the calling application.

Upgrading JMS Control sendJMSMessage Method Invocations

Version 8.1 of the JMS control took a JMSControl.Message type as a parameter for its sendJMSMessage method; in version 10.x the method takes an instance of javax.jms.Message. For a full upgrade, you must change your code accordingly.

Note that in upgrading this code, which uses the @org.apache.beehive.controls.system.jms.JMSControl.Message annotation, you may see the type ambiguity issue described in Resolving Ambiguity Related to Annotation Types. See that section for information on resolving the issue with a fully-qualified type name.

Supporting Parameter Bindings for JMS Properties with the JMS Control

Upgrade tools do not fully upgrade JMS control support for binding control method parameters to JMS properties. In particular, the method parameters themselves must be annotated but aren't. You can ensure support for these bindings by manually adding the required annotations after upgrading your version 8.1 code.

In the following example, note that the accountID parameter is annotated with @JMSControl.Property to indicate which JMS property the parameter should be bound to.

    @JMSControl.PropertyValue(name = "transactionType",
        value = "DEPOSIT")
public void deposit(
    AccountTransaction transaction,
    @JMSControl.Property(name="accountIdentifier") String accountID);

Changes to Support Database Control Row Set Functionality

The standard JdbcControl (org.apache.beehive.controls.JdbcControl) in version 10.x, which corresponds to the version 8.1 Database control, does not support the version 8.1 "RowSet control" feature. To ensure that row set functionality is preserved during upgrade, the Database control is upgraded to the backward compatible JdbcControl (com.bea.control.JdbcControl) provided by Oracle.

If your upgraded application does not use the row set functionality, it is recommended that you update, after upgrading, from the backward compatible control to the control. To do this, modify the control to extend org.apache.beehive.controls.system.jdbc.JdbcControl if it does not use any of the version 8.1 features that are not available in the control. If your upgraded application does use the row set functionality, note that this functionality is now represented by the JbcControl.SQLRowSet annotation's rowsetSchema attribute.

If you add an upgraded 8.1 Database control into a 10.x or later application, you can do one of the following, depending on the control features your application requires:

Note that when you insert a new JdbcControl, you'll get the Beehive-based control.

Replacing "All" Requests for Database Control Results

The version 8.1 database control supported getting all rows for a query by specifying "all" as a value for the @jc:sql array-max-length attribute. The version 10.x JDBC control does not support this value; instead, specify a numerical value. This change is not automatically made by upgrade tools.

For example, you might make the following change:

Version 8.1: @jc:sql array-max-length="all" statement="SELECT * FROM Customers"

Version 10.x: @JdbcControl.SQL(arrayMaxLength = 1024, statement = "SELECT * FROM Customers")

Multiple Calls to TimerControl.start Method Have No Effect

In version 8.1 it was possible to call the timer control's start method multiple times, without error, to start the timer; however, the onTimeout callbacks did not necessarily correspond to the separate calls to the start method. The version 10.x timer control simplifies the API by disallowing multiple calls to the start method. Calls to the start method when the timer control is still running will have no effect.

Upgrading Exception Handling in Control Event Handlers

In version 8.1, control event handlers (known in that version as "callback handlers") could throw exceptions of any type. In version 10.x, if the event handler throws the caught exception, it must now throw a proper subset of the throws clause declared for the control EventSet method.

Your event handler code can work around the version 10.x requirement by modifying event handler exception handling after you have upgraded your application. Here are two suggestions:

Upgrading Custom Controls Featuring Custom Properties

Version 8.1 custom control annotation definitions are not upgraded to version 10.x. The means for defining annotations is based on the Java 5 annotations model. To upgrade controls written for version 8.1, you must rewrite the annotations definition in keeping with the new model.

For more information on upgrading your custom annotations, take a look at the Apache Beehive source code for its system controls. These provide annotations that use the new model.

For information on how the control context APIs have changed from version 8.1, see Handling Context API Changes.

Upgrading Message Buffering in Custom Controls

In version 8.1 you could apply the common:message-buffer tag to a custom control's interface or implementation code. In version 10.x this annotation's counterpart, com.bea.control.annotations.MessageBuffer, is supported only in the control interface code. To work around this change, you should remove the annotation from implementation code before upgrading the application.

Handling Context API Changes

Version 8.1 provided context APIs through which components such as web services (in version 8.1 JWS files) and custom controls could interact with their runtime environment. The following provides an overview of how support for these APIs has (or hasn't) been migrated to version 10.x.

Web Service Context Changes

In general, the role played by the com.bea.control.JwsContext interface now belongs to weblogic.wsee.jws.JwsContext, used in conjunction with the weblogic.jws.Context annotation (both are described on the edocs web site).

However, some of the version 8.1 APIs were deprecated and are unavailable in version 10.x. Examples include callback-oriented methods on com.bea.control.JwsContext such as getCallbackLocation, getCallbackPassword, and others. For counterparts to these methods useful in version 10.x, see weblogic.wsee.jws.CallbackInterface. For example, you can replace the getCallbackLocation method with the CallbackInterface.getEndpointAddress method.

Control Context Changes

Changes brought by the version 10.x control model have meant that several APIs exposed by the version 8.1 control context classes are either exposed in different ways or are no longer relevant and so not available. Note that in many cases the lack of a workaround is due to the fact the current model streamlines a control's role for interacting with aspects of its container's environment. In particular, conversation-related methods are no longer supported within a control.

The following table lists the version 8.1 control context-related classes and methods along with their version 10.x counterparts, if any.

Version 8.1 Method Version 10.x Counterpart
finishConversation() : void No workaround.
getCallerPrincipal() : Principal See com.bea.control.util.SecurityHelper.getCallerPrincipal().
getCurrentAge() : long No workaround.
getCurrentIdleTime() : long No workaround.
getLogger(String name) : Logger Use logging services provided with WebLogic Server. For more information, see Understanding WebLogic Logging Services and Configuring WebLogic Logging Services.
getMaxAge() : long No workaround.
getMaxIdleTime() : long No workaround.
getService() : ServiceHandle No workaround.
isCallerInRole(String role) : boolean See com.bea.control.util.SecurityHelper.isCallerInRole().
isFinished() : boolean No workaround.
resetIdleTime() : void No workaround.
setMaxAge(Date date) : void No workaround.
setMaxAge(String duration) : void No workaround.
setMaxIdleTime(long) : void No workaround.
setMaxIdleTime(String duraction) : void No workaround.
onAgeTimeout(long age) : void No workaround.
onAsyncFailure(String methodName, Object[] args) : void No workaround.
onCreate() : void See ControlBeanContext.LifeCycle.onCreate()
onException(Exception e, String methodName, Object[] args) : void No workaround.
onFinish(boolean expired) : void No workaround.
onIdleTimeout(long time) : void No workaround.
cancelEvents(String eventName) : void No workaround.
getCallbackInterface() : Class You can use the Java reflection API (java.lang.reflect) to retrieve the callback interface. Here's a brief example:
Class controlInterface = context.getControlInterface();
Class callbackInterface = null;
for(Class c : controlInterface.getDeclaredClasses())
    if("Callback".equals(c.getSimpleName()) && c.getAnnotation(EventSet.class) != null) 
        callbackInterface = c;
        System.out.println("Callback Interface: " + c.getName());
getControlAttribute(String tagName, String attrName) : String See ControlBeanContext.getControlPropertySet(Class<T> propSet)
getControlAttributes(String tagName) : List

No counterpart. The version 10.x annotation model is based on JSR175, which doesn't support mulitiple attributes of the same name on an annotation. To work around this change, redesign your annotation so that it is a single annotation that can contain an array of annotations with the attribute that used to be repeated. For example, with the current JMS control you can specify multiple property values by using multiple @JMSControl.PropertyValue annotations within a @JMSControl.Properties annotation:

    @JMSControl.PropertyValue(name="Property1", value="SomeValue")
    @JMSControl.PropertyValue(name="Property2", value="{arg2}")
public void sendAMessage(String arg1, String arg2)

Access to the property values would be through the JMSControl.Properties annotation rather than a context API.

getControlInterface() : Class See ControlBeanContext.getControlInterface()
getMethodArgument(String argName) : Object Use Java reflection (see java.lang.reflect at the Sun web site).
getMethodArgumentNames() : String[] See the method ControlBean.getParameterNames(Method method).
getMethodAttribute(String tagName, String attrName) : String See ControlBeanContext.getMethodPropertySet(Method m, Class<Annotation> propSet)
getMethodAttributes(String tagName) : List

No counterpart. The version 10.x annotation model is based on JSR175, which doesn't support mulitiple attributes of the same name on an annotation. To work around this change, redesign your annotation so that it is a single annotation that can contain an array of annotations with the attribute that used to be repeated. For example, with the current JMS control you can specify multiple property values by using multiple @JMSControl.PropertyValue annotations within a @JMSControl.Properties annotation:

    @JMSControl.PropertyValue(name="Property1", value="SomeValue")
    @JMSControl.PropertyValue(name="Property2", value="{arg2}")
public void sendAMessage(String arg1, String arg2)

Access to the property values would be through the JMSControl.Properties annotation rather than a context API.

raiseEvent() : Object

See the workaround for the sendEvent method below. A workaround for raiseEvent would involve executing similar code in the event handler for the event that should be raised (forwarded to the client). The code would find the current event name and arguments and forward it to the client by invoking the method through reflection.

scheduleEvent(String eventName, Object[] eventArgs, long time, boolean ignoreIfFinished) : void See the workaround for the sendEvent method below. A workaround for scheduleEvent would involve executing similar code in the onTimeout event handler for a timer control.
sendEvent(String eventName, Object args[]) : Object

You can work around the absence of sendEvent with the code below. Compare the following two code snippets.

Version 8.1

context.sendEvent("mycallback", new String[]{"Hi from the callback (sendEvent)"});

Version 10.x

try {
    Method eventMethod = 
        callback.getClass().getMethod("mycallback", new Class[] { String.class });
    if (eventMethod != null) {
        eventMethod.invoke(callback, new Object[]{"Hi from the callback (invoke)"});
} catch (Exception e) {
    System.err.println("Exception trying to 'sendEvent': " + e.getMessage());
onAcquire() : void See ResourceContext.ResourceEvents.onAcquire()
onRelease() : void See ResourceContext.ResourceEvents.onRelease()
onReset() : void No workaround.

Related Topics

Changes During Upgrade from WebLogic Workshop 8.1 to Version 10.x

Still need help? Post a question on the Workshop newsgroup.