Java Adapters

Overview

Java adapters are based on the JAX-RS 2.0 specification. In other words, a Java adapter is a JAX-RS 2.0 service that can easily be deployed to a PMF instance and has access to PMF APIs and other 3rd party APIs.

Prerequisite: Make sure to read the Creating Java and JavaScript Adapters tutorial first.

Jump to

File structure

mvn-adapter

The adapter-resources folder

The adapter-resources folder contains an XML configuration file (adapter.xml). In this configuration file you configure the class name of the JAX-RS 2.0 application for this adapter. For example: com.sample.JavaAdapterApplication.

<?xml version="1.0" encoding="UTF-8"?>
<mfp:adapter name="JavaAdapter"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mfp="http://www.ibm.com/mfp/integration"
	xmlns:http="http://www.ibm.com/mfp/integration/http">

	<displayName>JavaAdapter</displayName>
	<description>JavaAdapter</description>

	<JAXRSApplicationClass>com.sample.JavaAdapterApplication</JAXRSApplicationClass>

	<property name="DB_url" displayName="Database URL" defaultValue="jdbc:mysql://localhost:3306/mydb"  />
	<property name="DB_username" displayName="Database username" defaultValue="myUsername"  />
	<property name="DB_password" displayName="Database password" defaultValue="myPassword"  />

	<securityCheckDefinition name="sample" class="com.sample.sampleSecurityCheck">
    	<property name="maxAttempts" defaultValue="3"/>
	</securityCheckDefinition>
</mfp:adapter>
  • name: Mandatory. The name of the adapter. This name must be unique within the PMF. It can contain alphanumeric characters and underscores, and must start with a letter. After you define and deploy an adapter, you cannot modify its name.
  • displayName: Optional. The name of the adapter that is displayed in the PMF Operations Console. If this element is not specified, the value of the name attribute is used instead.
  • description: Optional. Additional information about the adapter. Displayed in the PMF Operations Console.
  • JAXRSApplicationClass: Mandatory for exposing an /adapter endpoint. Defines the class name of the JAX-RS application of this adapter. In the example, it is com.sample.JavaAdapterApplication.
  • securityCheckDefinition: Optional. Defines a security-check object. Learn more about security checks in the Creating a Security Checks tutorial.
  • property: Optional. Declares a user-defined property. Learn more in the Custom properties topic below.

.

Custom properties

The adapter.xml file can also contain user-defined custom properties. The values that developers assign to them during the creation of the adapter can be overridden in the PMF Operations Console → [your adapter] → Configurations tab, without redeploying the adapter. User-defined properties can be read using the ConfigurationAPI interface and then further customized at run time.

Note: The configuration properties elements must be located below the JAXRSApplicationClass element.
In the example above we defined the connection settings and gave them default values, so they could be used later in the AdapterApplication class.

The <property> element takes the following attributes:

  • name: The name of the property, as defined in the configuration class.
  • defaultValue: Overrides the default value defined in the configuration class.
  • displayName: optional, a friendly name to be displayed in the console.
  • description: optional, a description to be displayed in the console.
  • type: optional, ensures that the property is of a specific type such as integer, string, boolean or a list of valid values (for example type="['1','2','3']").

Console properties

Pull and Push Configurations

Customized adapter properties can be shared using the adapter configuration file found in the Configuration files tab.
To do so, use the pull and push commands described below using either Maven or the PMF CLI. For the properties to be shared, you need to change the default values given to the properties.

Run the commands from the root folder of the adapter Maven project:

Maven

  • To pull the configurations file
    mvn adapter:configpull -DmfpfConfigFile=config.json
    
  • To push the configurations file
    mvn adapter:configpush -DmfpfConfigFile=config.json
    

PMF CLI

  • To pull the configurations file
    pmfdev adapter pull
    
  • To push the configurations file
    pmfdev adapter push
    

Pushing configurations to multiple servers

The pull and push commands can help to create various DevOps flows, where different values are required in adapters depending on the environment you’re at (DEV, QA, UAT, PRODUCTION).

Maven
Note above how by default you specify a config.json file. Create files with different names to address different targets.

PMF CLI
Use the –configFile or -c flag to specify a different configuration file than the default one:

pmfdev adapter pull -c [adapterProject]/alternate_config.json

Learn more in by using pmfdev help adapter pull/push.

The java folder

the Java sources of the JAX-RS 2.0 service are placed in this folder. JAX-RS 2.0 services are composed of an application class (which extends com.ibm.mfp.adapter.api.MFPJAXRSApplication) and the resources classes.

The JAX-RS 2.0 application and resources classes define the Java methods and their mapping to URLs.
com.sample.JavaAdapterApplication is the JAX-RS 2.0 application class and com.sample.JavaAdapterResource is a JAX-RS 2.0 resource included in the application.

JAX-RS 2.0 application class

The JAX-RS 2.0 application class tells the JAX-RS 2.0 framework which resources are included in the application.

package com.sample.adapter;

import java.util.logging.Logger;
import com.ibm.mfp.adapter.api.MFPJAXRSApplication;

public class JavaAdapterApplication extends MFPJAXRSApplication{

    static Logger logger = Logger.getLogger(JavaAdapterApplication.class.getName());

    @Override
    protected void init() throws Exception {
        logger.info("Adapter initialized!");
    }

    @Override
    protected String getPackageToScan() {
        //The package of this class will be scanned (recursively) to find JAX-RS 2.0 resources.
        return getClass().getPackage().getName();
    }
}

The MFPJAXRSApplication class scans the package for JAX-RS 2.0 resources and automatically creates a list. Additionally, its init method is called by PMF as soon as the adapter is deployed (before it starts serving) and when the PMF runtime starts up.

Implementing a JAX-RS 2.0 resource

JAX-RS 2.0 resource is a POJO (Plain Old Java Object) which is mapped to a root URL and has Java methods for serving requests to this root URL and its child URLs. Any resource can have a separate set of URLs.

package com.sample.adapter;

import java.util.logging.Logger;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path("/")
public class JavaAdapterResource {

    //Define logger (Standard java.util.Logger)
    static Logger logger = Logger.getLogger(JavaAdapterResource.class.getName());

    //Path for method: "<server address>/Adapters/adapters/JavaAdapter/{username}"
    @GET
    @Path("/{username}")
    public String helloUser(@PathParam("username") String name){
        return "Hello " + name;
    }
}
  • @Path("/") before the class definition determines the root path of this resource. If you have multiple resource classes, you should set each resource a different path.

    For example, if you have a UserResource with @Path("/users") to manage users of a blog, that resource is accessible via http(s)://host:port/ProjectName/adapters/AdapterName/users/.

    That same adapter may contain another resource PostResource with @Path("/posts") to manage posts of a blog. It is accessible via the http(s)://host:port/ProjectName/adapters/AdapterName/posts/ URL.

    In the example above, because there it has only one resource class, it is set to @Path("/") so that it is accessible via http(s)://host:port/Adapters/adapters/JavaAdapter/.

  • Each method is preceded by one or more JAX-RS 2.0 annotations, for example an annotation of type “HTTP request” such as @GET, @PUT, @POST, @DELETE, or @HEAD. Such annotations define how the method can be accessed.

  • Another example is @Path("/{username}"), which defines the path to access this procedure (in addition to the resource-level path). As you can see, this path can include a variable part. This variable is then used as a parameter of the method, as defined @PathParam("username") String name.

You can use many other annotations. See Annotation Types Summary here: https://jax-rs-spec.java.net/nonav/2.0-rev-a/apidocs/javax/ws/rs/package-summary.html

Important: When you use static references to classes from javax.ws.rs.* or javax.servlet.*, within your adapter implementation, then you should ensure to configure the RuntimeDelegate using one of the options below:

  • Set -Djavax.ws.rs.ext.RuntimeDelegate=org.apache.cxf.jaxrs.impl.RuntimeDelegateImpl in Liberty jvm.options OR
  • Set the system property or JVM custom property javax.ws.rs.ext.RuntimeDelegate=org.apache.cxf.jaxrs.impl.RuntimeDelegateImpl

HTTP Session

The PMF does not rely on HTTP sessions and each request may reach a different node. You should not rely on HTTP sessions to keep data from one request to the next.

Server-side APIs

Java adapters can use server-side Java APIs to perform operations that are related to PMF, such as calling other adapters, logging to the server log, getting values of configuration properties, reporting activities to Analytics and getting the identity of the request issuer.

Configuration API

The ConfigurationAPI class provides an API to retrieve properties defined in the adapter.xml or in the PMF Operations Console.

Inside your Java class, add the following at the class level:

@Context
ConfigurationAPI configurationAPI;

Then you can use the configurationAPI instance to get properties:

configurationAPI.getPropertyValue("DB_url");

When the adapter configuration is modified from the PMF Operations Console, the JAX-RS application class is reloaded and its init method is called again.

The getServerJNDIProperty method can also be used to retrieve a JNDI property from your server configuration.

You can see usage examples on the Java SQL Adapter tutorial.

Adapters API

The AdaptersAPI class provides an API to retrieve information about the current adapter and send REST requests to other adapters.

Inside your Java class, add the following at the class level:

@Context
AdaptersAPI adaptersAPI;

You can see usage examples on the advanced adapter usage mashup tutorial.

Analytics API

The AnalyticsAPI class provides an API for reporting information to analytics.

Inside your Java class, add the following at the class level:

@Context
AnalyticsAPI analyticsAPI;

You can see usage examples on the Analytics API tutorial.

Security API

The AdapterSecurityContext class provides the security context of an adapter REST call.

Inside your Java class, add the following at the class level:

@Context
AdapterSecurityContext securityContext;

You can then, for example, get the current AuthenticatedUser using:

AuthenticatedUser currentUser = securityContext.getAuthenticatedUser();

Java adapter examples

For examples of Java adapters communicating with an HTTP or SQL back end, see:

Last modified on