Develop and Deploy the Event Relay
Create an Oracle Functions application that consumes blockchain events and relays them to Oracle Streaming Service.
The event relay application needs credentials for connecting to the streaming service. The credentials are kept in Oracle Cloud Infrastructure Vault. The credentials are stored in Vault when you run the Terraform code. The credentials are generated when you do the initial configuration of your OCI environment.
The Function provides the following services:
- Retrieve Streaming Service credentials from Vault.
- Decrypt the credentials (Vault stores encrypted values).
- Decode from base64 encoded string.
- Use the decoded credentials to connect to Streaming Service using Kafka-compatible API.
- Create and populate a Java object called event from the JSON event message.
- Use Kafka API to send the event message.
Create the Event Relay
You can create the relay in any programming language, but because Kafka APIs are documented in Java it's best to use Java.
The EventProducer class will have the following methods:
@FnConfiguration
public void config(RuntimeContext ctx) { ... }
private String decryptData(String cipherText) { ... }
public String handleRequest(Event event) { ... }
The following dependencies are also needed in the pom.xml
file:
<dependencies>
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-java-sdk-keymanagement</artifactId>
<version>1.12.5</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>javax.activation-api</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>com.fnproject.fn</groupId>
<artifactId>api</artifactId>
<version>${fdk.version}</version>
</dependency>
.
.
.
Make sure that you have the fn CLI tool installed. See https://github.com/fnproject/fn#quickstart for more information.
Build the Event Relay
Before you can push an image, you must first use the docker tag
command to create a copy of the local source image as a new image (the new image is actually just a reference to the existing source image). As a name for the new image, specify the fully qualified path to the target location in Oracle Cloud Infrastructure
Registry where you want to push the image.
You need the following information for the tag:
- The Docker registry endpoint for your region
- Your Object Storage namespace
To get the endpoint for your region, look up your region in the table on Availability by Region. For example, the registry endpoint for US East (Ashburn) is https://iad.ocir.io
.
To find your Object Storage namespace:
- In the navigation menu, click Administration and then click Tenancy Details.
- The Obect Storage Namespace is in the Object Storage Settings section
Push the Event Relay to the Registry
After the event relay is built and has the proper tag, you can push it to Oracle Cloud Infrastructure Registry.
- API endpoint for your region: For example,
iad.ocir.io
. It's the same value that you used earlier to tag the Docker image. - Tenancy Namespace: the auto-generated Object Storage namespace string of your tenancy (as shown on the Tenancy Information page).
- Username: Your user name in Oracle Cloud Infrastructure.
- Auth Token: The token that you created earlier in the Plan section.
Create an API Key
Generate a key pair and upload the public key to your Oracle Cloud Infrastructure user profile.
You can do this in couple of ways, but here we'll use the Cloud Shell because you can securely upload the generated key directly to your account.
Apply the Terraform Configuration
Download the Terraform configuration from the GitHub repository, update the Terraform variables file, then apply the configuration.
terraform.tvars
file.
- Region - the Region Identifier for the region. You can extract this from the URL of your Oracle Cloud
Infrastructure Console. For example, if the URL is
https://console.us-ashburn-1.oraclecloud.com/compute/instances
, the your Region Identifier is us-ashburn-1. If your URL ishttps://cloud.oracle.com/compute/instances
, then you have to look up your Region Identifier in https://docs.oracle.com/iaas/Content/General/Concepts/regions.htm - Compartment OCID - the OCID of the compartment that contains the resources for the project. If you followed the instructions in the Plan section, you need the OCID for the OBP_Events compartment.
- Fingerprint - the fingerprint of the public API Key that you generated and uploaded to your profile previously.
- Private key - the full path and filename of the private API Key that you generated previously. For example,
/home/opc/oci_api_key.pem
. Do not use~
in the path. - User OCID - You can obtain this from the User Details page. Open the Console menu, goto Identity and click Users. Click your user name in the list.
- Tenancy OCID - You can obtain this from the Tenancy Details page. Open the Console menu, goto Administration and click Tenancy Details.
When you have the information, download and apply the Terraform configuration.
Subscribe to Blockchain Events
Register a callback URL so that API Gateway can receive blockchain events.
https://joh5rb...fuxy.apigateway.us-ashburn-1.oci.customer-oci.com/obpevents/callback
. You'll also need the API Gateway deployment endpoint, which was displayed as use_to_extract_ssl_certificate when the Terraform process completed. It's of the form joh5rb...fuxy.apigateway.us-ashburn-1.oci.customer-oci.com:443
You also need the Oracle Blockchain Platform REST API endpoint for subscribing to chaincode events. It has the following form:
https://<rest_server_url:port/restproxy#>/bcsgw/rest/v1/event/subscribe
<rest_server_url:port/restproxy#>
is the URL for the REST proxy which is listed in the Oracle Blockchain Platform console. In the console, open the Nodes page and look for the REST proxy node. In the Route column, a URL including port and a REST proxy number is listed.
To subscribe to blockchain events:
Create and Test the Event Consumer
The event consumer uses Kafka APIs to authenticate and retrieve blockchain messages from Oracle Cloud Infrastructure Streaming.
To create a consumer, you need information for the following Strings:
- USER-NAME: Your user name.
- AUTH-TOKEN: This is the token that you generated and copied earlier.
- TENANCY-NAME: You can find this value on the Tenancy Details page of the OCI console. To open the Tenancy Details page, in the Console navigation menu select Administration then click Tenancy Details.
- STREAM-POOL-OCID: This is the OCID of the stream pool that was created when you ran the Terraform script. To find this value, open the Console navigation menu and go to Administration and click Streaming. Select the stream pool and in the page that opens copy the OCID.
- REGION: "us-ashburn-1". Your region might be different.
- EVENT-NAME: This is the same event name that you used earlier when you registered the callback URL to receive blockchain events.
Use the following example to test and validate that the system is working as expected.
import java.util.Properties;
import java.util.Arrays;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.ConsumerRecord;
public class Consumer {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
props.put("bootstrap.servers", "streaming.REGION.oci.oraclecloud.com:9092");
props.put("security.protocol", "SASL_SSL");
props.put("sasl.mechanism", "PLAIN");
props.put("sasl.jaas.config", "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"TENANCY-NAME/USER-NAME/STREAM-POOL-OCID\" password=\"AUTH-TOKEN\";");
props.put("group.id", "group-0");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
props.put("session.timeout.ms", "30000");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
// Create a consumer and subscribe to it
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("EVENT-NAME"));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(100);
for (ConsumerRecord<String, String> record : records)
System.out.printf("offset = %d, key = %s, value = %s\n",
record.offset(), record.key(), record.value());
}
}
}
When you start the consumer, it consumes any existing events that were already pushed into the stream.
After the example is working and it demonstrates that the solution works, you're ready to create one or more production-level consumer apps. The apps can be written in JavaScript, Python, or another language.