4 Creating Custom Actions for Your APIs

This chapter explains how to create a custom action to make available to your APIs on the Actions tab of the Services Gatekeeper Partner and API Management Portal.

Understanding When to Create Custom Actions

Services Gatekeeper provides a set of actions that you use to manipulate requests and response messages to your APIs. These default actions listed in ”Actions Provided by Services Gatekeeper” in Services Gatekeeper API Management Guide.

Most of the default actions have specialized applications. In contrast, the Groovy action is specifically is available for you to add any level of sophistication required for manipulating request and response messages for API traffic. The drawback to using the Groovy action is that you must replicate that code for each API that requires it. To remove that restriction, you also have the option to create your own custom action code and make it available to all APIs. Once created and added to the external actions library, custom actions are available for use by all of your APIs. You can use it with the Actions Java API or by using the Partner and API Management Portal user interface. The portal is generated dynamically, so your custom actions appear automatically on the Actions tab of the portal.

You can use any of the classes in the Actions Java API Reference in the Java/Groovy code you use to create a custom action. See ”All Classes” in the Actions Java API Reference document for information.

Creating and Adding a Custom Action to Services Gatekeeper

Simply put, you create a custom action by creating and compiling it as a custom Java program, and packaging it as an .ear file. You then add the .ear file to Services Gatekeeper, and your custom action is then available to use alongside the Services Gatekeeper default actions.

The "Example Custom Actions" section also be a help to you.

During this process you can also add custom events that appear in event data records (EDRs) for debugging purposes. For details on EDRs, see ”Managing and Configuring EDRs, CDRs, and Alarms” in Services Gatekeeper System Administrator's Guide.

Creating a custom Action: 

  1. Create and compile the Java code for the functionality that your implementation requires into the MyAction (using HttpContext) and action.java files. See the "Example Black List Action" section for examples for these files, and see the ”All Classes” section of Actions Java API Reference for details on HttpContext.

    Use HttpContext for the context in your action file. Here is a Java example:

    System.out.println(context.getClientRequest().getMethod())
    

    The MyActionConfig.java file is limited to one level of properties that use the Java primitive data types. It cannot use hierarchies.

    An example MyActionConfig.java file:

    @XmlRootElement
    public final class MyActionConfig implements Serializable{
      /**
       * UUID.
       */
      private static final long serialVersionUID = 1L;
     
      private String requestUrl;
     
      public String getRequestUrl() {
        return requestUrl;
      }
     
      public void setRequestUrl(String requestUrl) {
        this.requestUrl = requestUrl;
      }
    }
    
  2. Add the DafAction class to the action file.

    DafAction uses these parameters to define how the new action (MyAction in this example) is presented and used in Services Gatekeeper:

    • configBean (Class) - Defines the Java Bean class that holds the configuration for this class. The Action class must be included the class as a Generic in the Action interface that it implements, as well as have it as the first parameter in the init() method.

    • description (String) - And informal description of the action. Can be used by PRM API clients.

    • flowRestriction (FlowRestriction) - Optional. Defines where this Action can be used:

      • NONE - The default. Does not restrict the action, so it can be used in either the request or response flow.

      • REQUEST - Restricts the action to use on the request flow.

      • RESPONSE Restricts the action to use on the response flow.

    • hidden (Boolean) - True specifies that the action be hidden. The default is false.

    • name (String) - The name that identifies the action. Must be unique.

    • flowRestriction (FlowRestriction ENUM) - Defines where this Action can be used:

    DafAction example:

    @DafAction(name = "My", hidden = false, configBean = MyActionConfig.class,
      description = "description here.")
    public final class MyAction implements Action<MyActionConfig> {
     
      private MyActionConfig configuration;
     
      /**
       * Init configuration.
       * @param pConfiguration configuration
       * @param apiConfiguration api configuration
       */
      @Override
      public void init(MyActionConfig pConfiguration, final ApiConfiguration apiConfiguration) {
        this.configuration = pConfiguration;
      }
      /**
       * Process the request.
       * @param context the context
       * @throws ActionProcessingError if an attribute using the 
       * ${x}-syntax in the url does not exist.
       */
      @Override
      public void process(HttpContext context) throws ActionProcessingError {
     // to be added
      }
    }
    

    See "Header Validation Example" and "Example Black List Action" for other examples.

  3. Register your action to use by adding it to the MyListener.java file.

    public class MyListener extends ApplicationLifecycleListener {
      public void preStart(ApplicationLifecycleEvent evt) {
        try {
          ActionRegistrationManager.getInstance().
    getActionRegistrationClientManager().registerAction(MyAction.class);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    
  4. (As needed) Add any custom events that you want included in event data records (EDRs) by:

    • Adding these classes to your action.java file:

      import com.bea.wlcp.wlng.api.plugin.context.RequestContext;
      import com.bea.wlcp.wlng.api.plugin.context.RequestContextManager;
      
    • Adding this statement to the process function of the actions class in your action.java file:

      final RequestContext reqCtx = RequestContextManager.getCurrent(); 
      reqCtx.putEdr("MYKEY", "MYVALUE");
      

      Where MYKEY and MYVALUE are the key/value pair that will appear in EDRs.

    Note:

    You also need to set server default logging priority to DEBUG to ensure that your events appear in EDRs. For details see ”Changing Log Levels in Services Gatekeeper” in the Services Gatekeeper System Administrator's Guide.
  5. Add the Gatekeeper_home/ocsg/modules/oracle.sdp.registration.prs_6.0.0.0.jar and Gatekeeper_home/ocsg/modules/oracle.sdp.daf-6.0.0.0.jar libraries to your CLASSPATH.

    Note:

    Do not add these libraries to the .ear file at run time. Load them as a system library automatically at run time.
  6. Compile your actions java code.

  7. Add this code to the weblogic-application.xml file.

      <wls:listener>
        <wls:listener-class>com.MyListener</wls:listener-class>
      </wls:listener>
    

    If weblogic-application.xml does not exist, navigate to Project Properties, then Project Facets, then Oracle WebLogic EAR Extensions, then click OK.

  8. Package the .jar file, and any other files or directories that the action requires into an .ear file.

  9. Deploy the .ear file to the network tier cluster in your implementation.

Your new custom action is displayed and available for use in the Partner and API Management Portal, or by the Actions API Management REST-based API. See "Discovering Actions Chains Schemas" for information on how to obtain the action schemas.

Managing Custom Actions

This section explains how to manage your custom actions and make them available in the Partner and API Management Portal. This section explains how to manage actions using the Administration Console. These functions are also available as MBeans so you can use them programmatically. See the "All Classes" section of the OAM Java API for details.

Note:

You can only perform these management operations on your custom actions. These operations fail and return an error if you attempt to use them on the default Services Gatekeeper actions.

You have these options for managing custom actions:

  • deprecateAction - Deprecates the action. APIs that already use the action continue to do so, but no other APIs can add the action.

  • activateAction - Reactivates a deprecated action. After using this operation to reactivate an action, you need to register the action before new APIs can use it.

  • deregisterAction - Prevents the action from being added by any API. You must remove this action from all APIs before using this operation. If any APIs are using the action when you run this operation, an error is returned with a list of those APIs.

  • isRegisteredAction - Checks whether an action with the same name has already been registered. This function prevents you from unintentionally overwriting an existing action. Be sure to use the fully qualified action class name.

To manage custom actions: 

  1. Start the Administration Console

    See ”Starting and Using the Administration Console” in Services Gatekeeper System Administrator's Guide for details.

  2. Click Lock and Edit.

  3. Navigate to OCSG, then servername, then Container Services, then DafActionRegistration.

  4. Select Operations.

  5. Select a management option from the Select an Operation menu. You have these options for managing actions:

    • activateAction

    • deprecateAction

    • deregisterAction

    • isRegisteredAction

  6. Enter the class name of the action to perform this action on in the actionClassName field.

  7. Click Invoke.

Discovering Actions Chains Schemas

Use the "loadActionSchemas" method of the API Actions Management REST-based API to return the schemas for all actions available to a Services Gatekeeper implementation. This allows you to discover action details, such as required fields, without using the Partner and API Management Portal.

Example Custom Actions

This section includes some examples to illustrate the types of custom actions that you can create.

RESTful Request for an Attribute Example

This code snippit sends a RESTful request to an external URL for value using the createCallout method of the HttpContext class, and stores it in a custom key/value pair. Add this line to a custom action early in the action chain:

context.createCallout().withRequestUrl("http://myurl.com").withRequestMethod("GET").build().send("myattribute");

Where myurl is the URL to request the attribute from, and myattribute is the name of the attribute to request. After using this line in a custom action, you can then use the value for myattribute in a subsequent action:

HttpResponse httpResponse = (HttpResponse) context.getAttribute("myattribute");

It must be in a subsequent action because action requests are asynchronous to keep from halting the action chain.

For details on HttpContext, see the ”All Classes” section of the Actions Java API Reference.

Header Validation Example

This example action allows you to add name/value pair test for a header/value as a requirement for manipulating traffic for an API. To make this work you would need to register the action with the lifestyle listener (substitute HeaderValidationAction for myAction in Step 3 above).

The HeaderValidationAction.java file:

/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */
package oracle.sdp.daf.action;
 
import oracle.sdp.daf.action.api.Action;
import oracle.sdp.daf.action.DafAction;
import oracle.sdp.daf.action.FlowRestriction;
import oracle.sdp.daf.action.api.ActionConfigurationException;
import oracle.sdp.daf.action.api.ActionProcessingError;
import oracle.sdp.daf.action.api.HttpContext;
import oracle.sdp.daf.config.ApiConfiguration;
 
/**
 * My custom action.
 */
@DafAction(name = "HeaderValidation", configBean = HeaderValidationActionConfig.class)
public final class HeaderValidationAction implements Action<HeaderValidationActionConfig> {
 
  private static final int HTTP_INTERNAL_ERROR = 500;
 
  private HeaderValidationActionConfig configuration;
 
  @Override
  public void init(HeaderValidationActionConfig pConfiguration, ApiConfiguration apiConfiguration)
    throws ActionConfigurationException {
 
    configuration = pConfiguration;
  }
 
  @Override
  public void process(HttpContext context) throws ActionProcessingError {
    if (!configuration.getHeaderValue().equals(context.getClientRequest().getHeader(configuration.getHeaderKey()))) {
      throw new ActionProcessingError(HTTP_INTERNAL_ERROR, "Required Header value not matching value");
    }
  }
 
}

The HeaderValidationActionConfig.java file:

/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */
package oracle.sdp.daf.action;
 
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
 
/**
 * The configuration file for the action.
 */
@XmlRootElement
public final class HeaderValidationActionConfig implements Serializable {
 
  /**
   * UUID.
   */
  private static final long serialVersionUID = 1L;
 
  private String headerKey;
  private String headerValue;
 
  public void setHeaderKey(String pHeaderKey) {
    headerKey = pHeaderKey;
  }
 
  public String getHeaderKey() {
    return headerKey;
  }
 
  public void setHeaderValue(String pHeaderValue) {
    headerValue = pHeaderValue;
  }
 
  public String getHeaderValue() {
    return headerValue;
  }
 
}

Example Black List Action

This example action allows you to create a list of IP addresses that are prohibited from sending requests to an API.

The BlackListAction.java file:

/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */
package oracle.sdp.daf.action;
 
import oracle.sdp.daf.action.api.Action;
import oracle.sdp.daf.action.DafAction;
import oracle.sdp.daf.action.FlowRestriction;
import oracle.sdp.daf.action.api.ActionConfigurationException;
import oracle.sdp.daf.action.api.ActionProcessingError;
import oracle.sdp.daf.action.api.HttpContext;
import oracle.sdp.daf.config.ApiConfiguration;
 
/**
 * BlackList action.
 */
@DafAction(name = "BlackList", configBean = BlackListActionConfig.class)
public final class BlackListAction implements Action<BlackListActionConfig> {
 
  private static final int HTTP_FORBIDDEN = 403;
 
  private BlackListActionConfig configuration;
 
  @Override
  public void init(BlackListActionConfig pConfiguration, ApiConfiguration apiConfiguration)
    throws ActionConfigurationException {
 
    configuration = pConfiguration;
  }
 
  @Override
  public void process(HttpContext context) throws ActionProcessingError {
    if (configuration.getAddress().equals(context.getClientRequest().getRemoteHost())) {
      throw new ActionProcessingError(HTTP_FORBIDDEN, "BlackListed!");
    }
  }
 
}

The BlacklistActionConfig.java file:

/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. */
package oracle.sdp.daf.action;
 
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
 
/**
 * The configuration file for the action.
 */
@XmlRootElement
public final class BlackListActionConfig implements Serializable {
 
  /**
   * UUID.
   */
  private static final long serialVersionUID = 1L;
 
  private String address;
 
  public void setAddress(String pAddress) {
    address = pAddress;
  }
 
  public String getAddress() {
    return address;
  }
 
}

Example Action for Adding a New Key/Value to EDRs

This code snippet for a custom action adds a new key/value pair to an EDR:

com.bea.wlcp.wlng.api.plugin.context.RequestContextManager.getCurrent().putEdr("new_key", "new_value")