Java tutorial
/* * Copyright 2013 ZANOX AG * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.zanox.vertx.mods; import com.amazonaws.ClientConfiguration; import com.amazonaws.auth.AWSCredentialsProvider; import com.amazonaws.auth.ClasspathPropertiesFileCredentialsProvider; import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; import com.amazonaws.handlers.AsyncHandler; import com.amazonaws.regions.Region; import com.amazonaws.regions.RegionUtils; import com.amazonaws.retry.RetryPolicy; import com.amazonaws.services.kinesis.AmazonKinesisAsyncClient; import com.amazonaws.services.kinesis.model.PutRecordRequest; import com.amazonaws.services.kinesis.model.PutRecordResult; import com.zanox.vertx.mods.exception.KinesisException; import org.vertx.java.busmods.BusModBase; import org.vertx.java.core.Context; import org.vertx.java.core.Handler; import org.vertx.java.core.eventbus.Message; import org.vertx.java.core.json.JsonObject; import java.nio.ByteBuffer; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import static com.zanox.vertx.mods.internal.EventProperties.PAYLOAD; import static com.zanox.vertx.mods.internal.KinesisProperties.*; /** * This verticle is responsible for processing messages. * It subscribes to Vert.x's specific EventBus address to handle messages published by other verticles * and sends messages to Kinesis. */ public class KinesisMessageProcessor extends BusModBase implements Handler<Message<JsonObject>> { private AmazonKinesisAsyncClient kinesisAsyncClient; private String streamName, partitionKey, region; @Override public void handle(Message<JsonObject> jsonObjectMessage) { try { sendMessageToKinesis(jsonObjectMessage); } catch (KinesisException exc) { logger.error(exc); } } @Override public void start() { super.start(); kinesisAsyncClient = createClient(); // Get the address of EventBus where the message was published final String address = getMandatoryStringConfig("address"); vertx.eventBus().registerHandler(address, this); } @Override public void stop() { if (kinesisAsyncClient != null) { kinesisAsyncClient.shutdown(); } } private AmazonKinesisAsyncClient createClient() { // Building Kinesis configuration int connectionTimeout = getOptionalIntConfig(CONNECTION_TIMEOUT, ClientConfiguration.DEFAULT_CONNECTION_TIMEOUT); int maxConnection = getOptionalIntConfig(MAX_CONNECTION, ClientConfiguration.DEFAULT_MAX_CONNECTIONS); // TODO: replace default retry policy RetryPolicy retryPolicy = ClientConfiguration.DEFAULT_RETRY_POLICY; int socketTimeout = getOptionalIntConfig(SOCKET_TIMEOUT, ClientConfiguration.DEFAULT_SOCKET_TIMEOUT); boolean useReaper = getOptionalBooleanConfig(USE_REAPER, ClientConfiguration.DEFAULT_USE_REAPER); String userAgent = getOptionalStringConfig(USER_AGENT, ClientConfiguration.DEFAULT_USER_AGENT); streamName = getMandatoryStringConfig(STREAM_NAME); partitionKey = getMandatoryStringConfig(PARTITION_KEY); region = getMandatoryStringConfig(REGION); logger.info(" --- Stream name: " + streamName); logger.info(" --- Partition key: " + partitionKey); logger.info(" --- Region: " + region); ClientConfiguration clientConfiguration = new ClientConfiguration(); clientConfiguration.setConnectionTimeout(connectionTimeout); clientConfiguration.setMaxConnections(maxConnection); clientConfiguration.setRetryPolicy(retryPolicy); clientConfiguration.setSocketTimeout(socketTimeout); clientConfiguration.setUseReaper(useReaper); clientConfiguration.setUserAgent(userAgent); /* AWS credentials provider chain that looks for credentials in this order: Environment Variables - AWS_ACCESS_KEY_ID and AWS_SECRET_KEY Java System Properties - aws.accessKeyId and aws.secretKey Credential profiles file at the default location (~/.aws/credentials) shared by all AWS SDKs and the AWS CLI Instance profile credentials delivered through the Amazon EC2 metadata service */ AWSCredentialsProvider awsCredentialsProvider = new DefaultAWSCredentialsProviderChain(); // Configuring Kinesis-client with configuration AmazonKinesisAsyncClient kinesisAsyncClient = new AmazonKinesisAsyncClient(awsCredentialsProvider, clientConfiguration); Region awsRegion = RegionUtils.getRegion(region); kinesisAsyncClient.setRegion(awsRegion); return kinesisAsyncClient; } protected void sendMessageToKinesis(final Message<JsonObject> event) throws KinesisException { if (kinesisAsyncClient == null) { throw new KinesisException("AmazonKinesisAsyncClient is not initialized"); } if (!isValid(event.body().getString(PAYLOAD))) { logger.error("Invalid message provided."); return; } JsonObject object = event.body(); logger.debug(" --- Got event " + event.toString()); logger.debug(" --- Got body + " + object.toString()); byte[] payload = object.getBinary(PAYLOAD); if (payload == null) { logger.debug(" --- Payload is null, trying to get the payload as String"); payload = object.getString(PAYLOAD).getBytes(); } logger.debug("Binary payload size: " + payload.length); String msgPartitionKey = object.getString(PARTITION_KEY); String requestPartitionKey = msgPartitionKey != null ? msgPartitionKey : partitionKey; PutRecordRequest putRecordRequest = new PutRecordRequest(); putRecordRequest.setStreamName(streamName); putRecordRequest.setPartitionKey(requestPartitionKey); logger.info("Writing to streamName " + streamName + " using partitionkey " + requestPartitionKey); putRecordRequest.setData(ByteBuffer.wrap(payload)); final Context ctx = vertx.currentContext(); kinesisAsyncClient.putRecordAsync(putRecordRequest, new AsyncHandler<PutRecordRequest, PutRecordResult>() { public void onSuccess(PutRecordRequest request, final PutRecordResult recordResult) { ctx.runOnContext(v -> { logger.info("Sent message to Kinesis: " + recordResult.toString()); sendOK(event); }); } public void onError(final java.lang.Exception iexc) { ctx.runOnContext(v -> { logger.error(iexc); sendError(event, "Failed sending message to Kinesis", iexc); }); } }); } private boolean isValid(String str) { return str != null && !str.isEmpty(); } }