Onboarding a REST API service with the Plain Java Enabler (PJE)
This article is part of a series of onboarding guides, which outline the process of onboarding REST API services to the Zowe API Mediation Layer (API ML). As a service developer, you can onboard a REST service with the API ML with the Zowe API Mediation Layer using our Plain Java Enabler (PJE). This enabler is built without a dependency on Spring Cloud, Spring Boot, or SpringFramework.
Tip: For more information about onboarding API services with the API ML, see the Onboarding Overview.
#
IntroductionZowe API ML is a lightweight API management system based on the following Netflix components:
- Eureka - a discovery service used for services registration and discovery
- Zuul - reverse proxy / API Gateway
- Ribbon - load balancer
The API ML Discovery Service component uses Netflix/Eureka as a REST services registry. Eureka endpoints are used to register a service with the API ML Discovery Service.
The API ML provides onboarding enabler libraries. The libraries are JAR artifacts available through an artifactory. Using these libraries is the recommended approach to onboard a REST service with the API ML.
The PJE library serves the needs of Java developers who are not using either Spring Boot or the Spring Framework. If Spring Boot or the Spring framework are used in the project you would like to onboard, see the Onboarding Overview for the corresponding enablers.
Additionally, this enabler is not intended for use in projects that depend on Spring Cloud Netflix components. Configuration settings in the PJE and Spring Cloud Netflix Eureka Client are different. Using the two configuration settings in combination makes the result state of the discovery registry unpredictable.
Tip: For more information about how to utilize another API ML enablers, see the documentation in the Onboarding Overview.
#
Onboarding your REST service with API MLThe following steps outline the overall process to onboard a REST service with the API ML using the PJE. Each step is described in further detail in this article.
(Optional) Validating the discoverability of your API service by the Discovery Service
(Optional) Troubleshooting
#
PrerequisitesEnsure that the prerequisites from the Onboarding Overview are met.
- The REST API service to onboard is written in Java.
- The service is enabled to communicate with API ML Discovery Service over a TLS v1.2 secured connection.
Notes:
This documentation is valid for API ML version
ZoweApimlVersion 1.3.0
and higher. We recommend that you check the Zowe Artifactory for latest stable versions.Following this guide enables REST services to be deployed on a z/OS environment. Deployment to a z/OS environment, however, is not required. As such, you can first develop on a local machine before you deploy on z/OS.
#
Configuring your projectUse either Gradle or Maven build automation systems to configure the project with service to be onboarded. Use the appropriate configuration procedure that corresponds to your build automation system.
Note: You can use either the Zowe Artifactory or an artifactory of your choice. However, if you decide to build the API ML from source, you are required to publish the enabler artifact to your artifactory. Publish the enabler artifact by using the Gradle tasks provided in the source code.
#
Gradle build automation systemUse the following procedure to use Gradle as your build automation system.
Follow these steps:
Create a
gradle.properties
file in the root of your project if one does not already exist.In the
gradle.properties
file, set the URL of the specific artifactory containing the PJE artifact. Provide the corresponding credentials to gain access to the Maven repository.Add the following Gradle code block to the
repositories
section of yourbuild.gradle
file:In the same
build.gradle
file, add the necessary dependencies for your service. If you use the Java enabler from the Zowe Artifactory, add the following code block to yourbuild.gradle
script. Replace the$zoweApimlVersion
with the proper version of the enabler, for example:1.3.0
:The published artifact from the Zowe Artifactory also contains the enabler dependencies from other software packages. If you are using an artifactory other than Zowe, add also the following dependencies in your service
build.gradle
script:Notes:
- You may need to add more dependencies as required by your service implementation.
- The information provided in this file is valid for
ZoweApimlVersion 1.3.0
and above.
In your project home directory, run the
gradle clean build
command to build your project. Alternatively, you can rungradlew
to use the specific gradle version that is working with your project.
#
Maven build automation systemUse the following procedure if you use Maven as your build automation system.
Follow these steps:
Add the following XML tags within the newly created
pom.xml
file:Tip: If you want to use snapshot version, replace libs-release with libs-snapshot in the repository url and change snapshots->enabled to true.
Add the proper dependencies:
In the directory of your project, run the
mvn clean package
command to build the project.
#
Configuring your serviceTo configure your service, provide default service configuration in the service-configuration.yml
file located in your service source tree resources directory.
Note: To externalize service onboarding configuration, see: Externalizing onboarding configuration.
The following code snippet shows an example of service-configuration.yml
. Some parameters which are specific for your service deployment
are written in ${parameterValue}
format. For your service configuration file, provide actual values or externalize your onboarding configuration.
Example:
Optional metadata section
The onboarding configuration parameters are broken down into the following groups:
- REST service identification
- Administrative endpoints
- API info
- API routing information
- API catalog information
- Authentication parameters
- API security
- SAF Keyring configuration
- Eureka Discovery Service
- Custom Metadata
- Connection Timeout
#
REST service identificationserviceId
The
serviceId
uniquely identifies one or more instance of a microservice in the API ML and is used as part of the service URL path in the API ML Gateway address space. Additionally, the API ML Gateway uses theserviceId
for routing to the API service instances. When two API services use the sameserviceId
, the API Gateway considers the services as clones of each other. An incoming API request can be routed to either of them through utilized load balancing mechanism.Important! Ensure that the
serviceId
is set properly with the following considerations:The same
servicedId
should only be set for multiple API service instances for API scalability.The
servicedId
value must only contain lowercase alphanumeric characters.The
servicedId
cannot contain more than 40 characters.Example:
If the
serviceId
issampleservice
, the service URL in the API ML Gateway address space appears as the following path:
title
This parameter specifies the human readable name of the API service instance. This value is displayed in the API Catalog when a specific API service instance is selected. This parameter can be externalized and set by the customer system administrator.
Tip: We recommend that service developer provides a default value of the
title
. Use a title that describes the service instance so that the end user knows the specific purpose of the service instance.description
This parameter is a short description of the API service. This value is displayed in the API Catalog when a specific API service instance is selected. This parameter can be externalized and set by the customer system administrator.
Tip: Describe the service so that the end user understands the function of the service.
baseUrl
This parameter specifies the base URL for the following administrative endpoints:
homePageRelativeUrl
statusPageRelativeUrl
healthCheckRelativeUrl
Use the following format to include your service name in the URL path:
protocol://host:port/servicename
Note: Do not end
baseUrl
with a trailing/
. This will cause a malformed URL if any of the above administrative endpoints begin with a/
. It is expected that each administrative endpoint begins with a/
. Warnings will be logged if this recommendation is not followed.
serviceIpAddress (Optional)
Specifies the service IP address and can be provided by a system administrator in the externalized service configuration. If this parameter is not present in the configuration file or is not set as a service context parameter, it will be resolved from the hostname part of the
baseUrl
.preferIpAddress (Optional)
Set the value of the parameter to "true" if you want to advertise a service IP address instead of its hostname.
#
Administrative endpointsThe following snippet presents the format of the administrative endpoint properties:
where:
homePageRelativeUrl
specifies the relative path to the home page of your service.
Start this path with
/
. If your service has no home page, leave this parameter blank.Examples:
homePageRelativeUrl:
This service has no home pagehomePageRelativeUrl: /
This service has a home page with URL${baseUrl}/
statusPageRelativeUrl
specifies the relative path to the status page of your service.
Start this path with
/
.Example:
statusPageRelativeUrl: /application/info
This results in the URL:
${baseUrl}/application/info
healthCheckRelativeUrl
specifies the relative path to the health check endpoint of your service.
Start this path with
/
.Example:
healthCheckRelativeUrl: /application/health
This results in the URL:
${baseUrl}/application/health
#
API infoREST services can provide multiple APIs. Add API info parameters for each API that your service wants to expose on the API ML.
The following snippet presents the information properties of a single API:
where:
apiInfo.apiId
specifies the API identifier that is registered in the API ML installation. The API ID uniquely identifies the API in the API ML. The
apiId
can be used to locate the same APIs that are provided by different service instances. The API developer defines this ID. TheapiId
must be a string of up to 64 characters that uses lowercase alphanumeric characters and a dot:.
.apiInfo.version
specifies the api
version
. This parameter is used to correctly retrieve the API documentation according to requested version of the API.apiInfo.gatewayUrl
specifies the base path at the API Gateway where the API is available. Ensure that this value is the same path as the
gatewayUrl
value in theroutes
sections that apply to this API.apiInfo.swaggerUrl (Optional)
specifies the Http or Https address where the Swagger JSON document is available.
apiInfo.documentationUrl (Optional)
specifies the link to the external documentation. A link to the external documentation can be included along with the Swagger documentation.
#
API routing informationThe API routing group provides the required routing information used by the API ML Gateway when routing incoming requests to the corresponding REST API service.
A single route can be used to direct REST calls to multiple resources or API endpoints. The route definition provides rules used by the API ML Gateway to rewrite the URL
in the Gateway address space. Currently, the routing information consists of two parameters per route: The gatewayUrl
and serviceUrl
. These two parameters together specify a rule for how the API service endpoints are mapped to the API Gateway endpoints.
The following snippet is an example of the API routing information properties.
Example:
where:
routes
specifies the container element for the routes.
routes.gatewayUrl
The gatewayUrl parameter specifies the portion of the gateway URL which is replaced by the serviceUrl path part.
routes.serviceUrl
The serviceUrl parameter provides a portion of the service instance URL path which replaces the gatewayUrl part.
Example:
will be routed to:
API major version 1:
will be routed to:
APIs docs major version 1:
will be routed to:
#
API Catalog informationThe API ML Catalog UI displays information about discoverable REST services registered with the API ML Discovery Service. Information displayed in the Catalog is defined by the metadata provided by your service during registration. The Tile will look similar to the one shown on following image.
The Catalog groups correlated services in the same tile, if these services are configured with the same catalog.tile.id
metadata parameter.
The following code block is an example of configuration of a service tile in the Catalog:
Example:
where:
catalog.tile.id
specifies the unique identifier for the product family of API services. This is a value used by the API ML to group multiple API services into a single tile. Each unique identifier represents a single API dashboard tile in the Catalog.
Tip: Specify a value that does not interfere with API services from other products. We recommend that you use your company and product name as part of the ID.
catalog.tile.title
specifies the title of the product family of the API service. This value is displayed in the API Catalog dashboard as the tile title.
catalog.tile.description
is the detailed description of the API services product family. This value is displayed in the API Catalog UI dashboard as the tile description.
catalog.tile.version
specifies the semantic version of this API Catalog tile.
Note: Ensure that you increase the version number when you introduce changes to the API service product family details.
#
Authentication parametersThese parameters are not required. When not specified, the default values are used.
Allows a service to accept the Zowe JWT token. The API Gateway translates the token to an authentication method supported by a service.
The following parameters define service authentication method:
Example:
authentication.scheme
This parameter specifies a service authentication scheme. The following schemes are supported by the API Gateway:
bypass
This value specifies the token is passed unchanged to service.
Note: This is the default scheme when no authentication parameters are specified.
zoweJwt
This value specifies that a service accepts the Zowe JWT token. No additional processing is done by the API Gateway.
httpBasicPassTicket
This value specifies that a service accepts PassTickets in the Authorization header of the HTTP requests using the basic authentication scheme. It is necessary to provide a service APPLID in
authentication.applid
parameter.For more information, see Enabling PassTicket creation for API Services that Accept PassTickets
zosmf
This value specifies that a service accepts z/OSMF LTPA (Lightweight Third-Party Authentication). This scheme should be used only for z/OSMF service used by the API Gateway Authentication Service and other z/OSMF services that are using the same LTPA key.
For more information about z/OSMF Single Sign-on, see Establishing a single sign-on environment
authentication.applid
This parameter specifies a service APPLID. This parameter is valid only for
httpBasicPassTicket
authentication scheme.
#
API SecurityREST services onboarded with the API ML act as both a client and a server. When communicating to API ML Discovery service, a REST service acts as a client. When the API ML Gateway is routing requests to a service, the REST service acts as a server. These two roles have different requirements. The Zowe API ML Discovery Service communicates with its clients in secure Https mode. As such, TLS/SSL configuration setup is required when a service is acting as a server. In this case, the system administrator decides if the service will communicate with its clients securely or not.
Client services need to configure several TLS/SSL parameters in order to communicate with the API ML Discovery service.
When an enabler is used to onboard a service, the configuration is provided in the ssl
section/group in the same YAML file that is used to configure the Eureka parameters and the service metadata.
For more information about API ML security see: API ML security
TLS/SSL configuration consists of the following parameters:
verifySslCertificatesOfServices
This parameter makes it possible to prevent server certificate validation.
Important! Ensure that this parameter is set to
true
in production environments. Setting this parameter tofalse
in production environments significantly degrades the overall security of the system.protocol
This parameter specifies the TLS protocol version currently used by Zowe API ML Discovery Service.
Tip: We recommend you use
TLSv1.2
as your security protocolkeyAlias
This parameter specifies the
alias
used to address the private key in the keystore.keyPassword
This parameter specifies the password associated with the private key.
keyStore
This parameter specifies the keystore file used to store the private key. When using keyring, this should be set to SAF keyring location. For information about required certificates, see Zowe API ML TLS requirements.
keyStorePassword
This parameter specifies the password used to unlock the keystore.
keyStoreType
This parameter specifies the type of the keystore.
trustStore
This parameter specifies the truststore file used to keep other parties public keys and certificates. When using keyring, this should be set to SAF keyring location. For information about required certificates, see Zowe API ML TLS requirements.
trustStorePassword: password
This parameter specifies the password used to unlock the truststore.
trustStoreType: PKCS12
This parameter specifies the truststore type. The default for this parameter is PKCS12.
Notes:
- Ensure that you define both the key store and the trust store even if your server is not using an Https port.
#
SAF Keyring configurationYou can choose to use SAF keyring instead of keystore and truststore for storing certificates. For information about required certificates, see Zowe API ML TLS requirements. For information about running Java on z/OS with keyring, see SAF Keyring. Make sure that the enabler can access and read the keyring. Please refer to documentation of your security system for details.
The following example shows enabler configuration with keyrings:
#
Eureka Discovery ServiceThe Eureka Discovery Service parameters group contains a single parameter used to address Eureka Discovery Service location. An example is presented in the following snippet:
Example:
where:
discoveryServiceUrls
Specifies the public URL of the Discovery Service. The system administrator at the customer site defines this parameter. It is possible to provide multiple values in order to utilize fail over and/or load balancing mechanisms.
#
Custom MetadataCustom metadata are described here.
#
Registering your service with API MLThe following steps outline the process of registering your service with API ML. Each step is described in detail in this article. The process describes the integration with the usage of the Java application server. The guideline is tested with the Tomcat application server. The specific steps that apply for other application servers may differ.
- Add a web application context listener class
- Register a web application context listener
- Load service configuration
- Register with Eureka discovery service
- Unregister your service
Follow these steps:
Implement and add a web application context listener class
implements javax.servlet.ServletContextListener
The web application context listener implements two methods to perform necessary actions at application start-up time as well as when the application context is destroyed:
- The
contextInitialized
method invokes theapiMediationClient.register(config)
method to register the application with API Mediation Layer when the application starts. - The
contextDestroyed
method invokes theapiMediationClient.unregister()
method when the application shuts down. This unregisters the application from the API Mediation Layer.
- The
Register a web application context listener.
Add the following code block to the deployment descriptor
web.xml
to register a context listener:Load the service configuration.
Load your service configuration from a file
service-configuration.yml
file. The configuration parameters are described in the preceding section, Configuring your service.Use the following code as an example of how to load the service configuration.
Example:
Note: The
ApiMediationServiceConfigReader
class also provides other methods for loading the configuration from two files,java.util.Map
instances, or directly from a string. Check theApiMediationServiceConfigReader
class JavaDoc for details.Register with Eureka Discovery Service.
Use the following call to register your service instance with Eureka Discovery Service:
Example:
Unregister your service.
Use the
contextDestroyed
method to unregister your service instance from Eureka Discovery Service in the following format:Example:
The following code block is a full example of a context listener class implementation.
Example:
#
Validating the discoverability of your API service by the Discovery ServiceOnce you are able to build and start your service successfully, you can use the option of validating that your service is registered correctly with the API ML Discovery Service.
Follow these steps:
Check that you can access your API service endpoints through the Gateway.
(Optional) Check that you can access your API service endpoints directly outside of the Gateway.
Specific addresses and user credentials for the individual API ML components depend on your target runtime environment.
Note: If you are working with local installation of API ML and you are using our dummy identity provider, enter user
for both username
and password
. If API ML was installed by system administrators, ask them to provide you
with actual addresses of API ML components and the respective user credentials.
Tip: Wait for the Discovery Service to discover your service. This process may take a few minutes after your service was successfully started.
#
Troubleshooting#
Log messages during registration problemsWhen an Enabler connects to the Discovery service and fails, an error message prints to the Enabler log. The default setting does not suppress these messages as they are useful to resolve problems during the Enabler registration. Possible reasons for failure include the location of Discovery service is not correct, the Discovery Service is down, or the TLS certificate is invalid.
These messages continue to print to the Enabler log, while the Enabler retries to connect to the Discovery Service.
To fully suppress these messages in your logging framework, set the log levels to OFF
on the following loggers:
Some logging frameworks provide other tools to suppress repeated messages. Consult the documentation of the logging framework you use to find out what tools are available. The following example demonstrates how the Logback framework can be used to suppress repeated messages.
Example:
The Logback framework provides a filter tool, DuplicateMessageFilter.
Add the following code to your configuration file if you use XML configuration:
Note: For more information, see the full configuration used in the Core Services in GitHub.