package eu.europeana.cloud.service.dps.storm.kafka;
import java.util.Map;
import java.util.Properties;
import kafka.javaapi.producer.Producer;
import kafka.producer.KeyedMessage;
import kafka.producer.ProducerConfig;
import eu.europeana.cloud.service.dps.DpsTask;
import eu.europeana.cloud.service.dps.PluginParameterKeys;
import eu.europeana.cloud.service.dps.storm.AbstractDpsBolt;
import eu.europeana.cloud.service.dps.storm.StormTaskTuple;
/**
* Create and send {@link DpsTask} to Kafka topic.
*
* @author Pavel Kefurt <Pavel.Kefurt@gmail.com>
*/
public class KafkaProducerBolt extends AbstractDpsBolt
{
private final String topic;
private final String taskName;
private final String brokerList;
private final String serializer = "eu.europeana.cloud.service.dps.storm.kafka.JsonEncoder";
private final Map<String, String> parameters;
private Producer<String, DpsTask> producer;
/**
* Constructor of Kafka producer bolt without additional parameters.
* @param brokerList broker addresses separated by comma (e.g. localhost:9093,192.168.47.129:9093)
* @param topic topic name
* @param taskName new task name
*/
public KafkaProducerBolt(String brokerList, String topic, String taskName)
{
this.brokerList = brokerList;
this.topic = topic;
this.taskName = taskName;
this.parameters = null;
}
/**
* Constructor of Kafka producer bolt with additional parameters.
* @param brokerList broker addresses separated by comma (e.g. localhost:9093,192.168.47.129:9093)
* @param topic topic name
* @param taskName new task name
* @param parameters additional parameters
* if value == null: use value from StormTaskTuple
*/
public KafkaProducerBolt(String brokerList, String topic, String taskName, Map<String, String> parameters)
{
this.brokerList = brokerList;
this.topic = topic;
this.taskName = taskName;
this.parameters = parameters;
}
@Override
protected void finalize() throws Throwable
{
if(producer != null)
{
producer.close();
}
super.finalize();
}
@Override
public void execute(StormTaskTuple t)
{
DpsTask msg = new DpsTask();
msg.setTaskName(taskName);
msg.addParameter(PluginParameterKeys.FILE_URL, t.getFileUrl());
msg.addParameter(PluginParameterKeys.FILE_DATA, new String(t.getFileData()));
//add extension parameters (optional)
if(parameters != null)
{
for(Map.Entry<String, String> parameter : parameters.entrySet())
{
//if value is null it means that value is in received parameters
if(parameter.getValue() == null)
{
String val = t.getParameter(parameter.getKey());
if(val != null)
{
msg.addParameter(parameter.getKey(), val);
}
}
else
{
msg.addParameter(parameter.getKey(), parameter.getValue());
}
}
}
KeyedMessage<String, DpsTask> data = new KeyedMessage<>(topic, msg);
producer.send(data);
outputCollector.emit(inputTuple, t.toStormTuple());
outputCollector.ack(inputTuple);
}
@Override
public void prepare()
{
Properties props = new Properties();
props.put("metadata.broker.list", brokerList);
props.put("serializer.class", serializer);
props.put("request.required.acks", "1"); //waiting for acknowledgement
ProducerConfig config = new ProducerConfig(props);
producer = new Producer<>(config);
}
}