public static MessageType of(Type t) { return new MessageType(t.getTypeName()); } }
public static Message<? extends com.google.protobuf.Message> requestFor(Topic target, Topic replyTo, String partitionKey, com.google.protobuf.Message protoPayloadMessage, OrangeContext context) { boolean wasReceived = false; String messageId = UUID.randomUUID().toString(); String correlationId = context.getCorrelationId(); MessageType type = MessageType.of(protoPayloadMessage); // Use default inbox for service. if (replyTo == null) { throw new IllegalArgumentException("replyTo required"); } String requestCorrelationId = ""; // not required Metadata meta = new Metadata(wasReceived, target, partitionKey, -1, -1, messageId, correlationId, requestCorrelationId, replyTo, type); return new Message<>(protoPayloadMessage, meta); }
public UnknownMessageHandlerException(MessageType type) { super(type.toString()); } }
@Test public void testCreateFromClasspath() { // The ReflectionTypeDictionaryFactory is robust by design, so it does not throw any Exception. // Need to check the log output for the error test cases. // Dependency injection magic ServiceProperties serviceProperites = new ServiceProperties(); Module[] modules = new Module[1]; modules[0] = new TestInjectionModule(serviceProperites); Injector injector = Guice.createInjector(modules); ReflectionTypeDictionaryFactory rtdf = new ReflectionTypeDictionaryFactory(injector); TypeDictionary dictionary = rtdf.createFromClasspath(); MessageHandler<? extends com.google.protobuf.Message> handler = dictionary.messageHandlerFor(MessageType.of(TypeDictionaryTest.class)); assertNotNull(handler); MessageHandler<? extends com.google.protobuf.Message> unknownHandler = dictionary.messageHandlerFor(MessageType.of(TestMessageWithNoHandler.class)); assertNull(unknownHandler); Parser parser = dictionary.parserFor((MessageType.of(TypeDictionaryTest.class))); assertNotNull(parser); assertNull(dictionary.parserFor(new MessageType("UnknownType"))); }
public static Message<? extends com.google.protobuf.Message> oneWayMessage(Topic target, String partitionKey, com.google.protobuf.Message protoPayloadMessage, OrangeContext context) { boolean wasReceived = false; String messageId = UUID.randomUUID().toString(); String correlationId = context.getCorrelationId(); Topic replyTo = null; // not required String requestCorrelationId = ""; // not required MessageType type = MessageType.of(protoPayloadMessage); Metadata meta = new Metadata(wasReceived, target, partitionKey, -1, -1, messageId, correlationId, requestCorrelationId, replyTo, type); return new Message<>(protoPayloadMessage, meta); }
static MessageType of(com.google.protobuf.Message protoMessage) { return new MessageType(protoMessage.getClass().getTypeName()); }
public UnknownMessageTypeException(MessageType type) { super(type.toString()); } }
public Map<MessageType, Parser<com.google.protobuf.Message>> populateParsersFromClasspath() { Map<MessageType, Parser<com.google.protobuf.Message>> parsers = new HashMap<>(); List<Class<? extends com.google.protobuf.GeneratedMessageV3>> foundProtoMessages = new ArrayList<>(); new FastClasspathScanner() .matchSubclassesOf(com.google.protobuf.GeneratedMessageV3.class, matchingClass -> foundProtoMessages.add(matchingClass)).scan(); // This algorithm adds parsers for all protobuf messages in the classpath including base types such as com.google.protobuf.DoubleValue. for (Class<? extends com.google.protobuf.GeneratedMessageV3> clazz : foundProtoMessages) { try { java.lang.reflect.Method method = clazz.getMethod("parser"); // static method, no arguments @SuppressWarnings("unchecked") Parser<com.google.protobuf.Message> parser = (Parser<com.google.protobuf.Message>) method.invoke(null, (Object[]) null); // static method, no arguments parsers.put(MessageType.of(clazz), parser); // too noisy: logger.debug("Added parser for protobuf type {}", clazz.getTypeName()); } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ignored) { // too noisy: logger.debug("Ignoring protobuf type {} as we cannot invoke static method parse().", clazz.getTypeName()); } } return parsers; }
private Message<? extends com.google.protobuf.Message> parseMessage() { Envelope envelope = null; try { envelope = Envelope.parseFrom(record.value()); } catch (InvalidProtocolBufferException parseError) { markAsConsumed(record.offset()); parsingFailed(envelope, parseError); return null; } try { MessageType type = new MessageType(envelope.getMessageType()); Parser<com.google.protobuf.Message> parser = typeDictionary.parserFor(type); if (parser == null) { throw new UnknownMessageTypeException(type); } com.google.protobuf.Message innerMessage = parser.parseFrom(envelope.getInnerMessage()); return Messages.fromKafka(innerMessage, envelope, record); } catch (InvalidProtocolBufferException | UnknownMessageTypeException unrecoverableParsingError) { markAsConsumed(record.offset()); parsingFailed(envelope, unrecoverableParsingError); return null; } }
private void deliveryFailed(Message message, Exception failure, boolean tryDeliverMessage) { logger.debug(message.getMetadata().getLoggingMarker(), "Received tryDeliverMessage={} from {}.onFailedMessage({})", tryDeliverMessage, failedMessageProcessor.getClass().getTypeName(), failure.toString()); if (metricsBuilderFactory != null) { GoCounter deliveryFailures = metricsBuilderFactory.newMetric("messaging_consumer_delivery_failures") .withTag("messageType", message.getMetadata().getType().toString()) .withTag("topic", message.getMetadata().getTopic().toString()) .buildCounter(); if(tryDeliverMessage) { deliveryFailures.incSuccess(); } else { deliveryFailures.incFailure(); } } }
MessageType type = MessageType.of(t); MessageHandler<? extends com.google.protobuf.Message> handler = null;
logger.debug(message.getMetadata().getLoggingMarker(), "Sending message {} with key {} to topic {}", message.getMetadata().getType().toString(), partitioningKey, destinationTopic);
public static Message<? extends com.google.protobuf.Message> replyTo(Message originalRequest, com.google.protobuf.Message protoPayloadMessage, OrangeContext context) { boolean wasReceived = false; // By default, return to sender topic using same partitioning scheme. Topic target = originalRequest.getMetadata().getReplyTo(); String partitionKey = originalRequest.getMetadata().getPartitioningKey(); String messageId = UUID.randomUUID().toString(); String correlationId = context.getCorrelationId(); String requestCorrelationId = originalRequest.getMetadata().getMessageId(); Topic replyTo = null; // not required MessageType type = MessageType.of(protoPayloadMessage); Metadata meta = new Metadata(wasReceived, target, partitionKey, -1, -1, messageId, correlationId, requestCorrelationId, replyTo, type); return new Message<>(protoPayloadMessage, meta); }
private void deliveryStarted(Message message, MessageHandler handler, OrangeContext context) { logger.debug(message.getMetadata().getLoggingMarker(), "Calling {}.onMessage({})", handler.getClass().getTypeName(), message.getMetadata().getType()); if (tracer != null) { span = tracer.buildSpan(message.getMetadata().getType().toString()).start(); Tags.SPAN_KIND.set(span, "consumer"); span.setTag("correlation_id", context.getCorrelationId()); context.setTracingContext(span.context()); } if (metricsBuilderFactory != null) { handlerTimer = metricsBuilderFactory.newMetric("messaging_consumer_message_handler") .withTag("messageType", message.getMetadata().getType().toString()) .withTag("topic", message.getMetadata().getTopic().toString()) .buildTimer(); startTime = handlerTimer.start(); } }
private <T extends com.google.protobuf.Message> ConsumerFactory consumerFactoryWithHandler(ServiceProperties serviceProperties, Class<T> messageType, MessageHandler<T> handler) { TypeDictionary typeDictionary = new TypeDictionary(); ReflectionTypeDictionaryFactory reflectionCruft = new ReflectionTypeDictionaryFactory(null); typeDictionary.putAllParsers(reflectionCruft.populateParsersFromClasspath()); typeDictionary.putHandler(MessageType.of(messageType), handler); ConsumerFactory consumerFactory = new ConsumerFactory(serviceProperties, typeDictionary, null, null); return consumerFactory; }
static Envelope toKafka(Message message) { Envelope.Builder envelope = Envelope.newBuilder(); Metadata meta = message.getMetadata(); envelope.setMessageId(meta.getMessageId()); // Correlation ids are set when building the message if (!Strings.isNullOrEmpty(meta.getCorrelationId())) { envelope.setCorrelationId(meta.getCorrelationId()); } // Message exchange pattern headers if (meta.getReplyTo() != null) { envelope.setReplyTo(meta.getReplyTo().toString()); } if (!Strings.isNullOrEmpty(meta.getRequestCorrelationId())) { envelope.setRequestCorrelationId(meta.getRequestCorrelationId()); } // Payload (mandatory fields!) envelope.setMessageType(meta.getType().toString()); envelope.setInnerMessage(message.getPayload().toByteString()); // Serialize the proto payload to bytes return envelope.build(); } }
private <T extends com.google.protobuf.Message> ConsumerFactory consumerFactoryWithHandler(ServiceProperties serviceProperties, Class<T> messageType, MessageHandler<T> handler) { TypeDictionary typeDictionary = new TypeDictionary(); ReflectionTypeDictionaryFactory reflectionCruft = new ReflectionTypeDictionaryFactory(null); typeDictionary.putAllParsers(reflectionCruft.populateParsersFromClasspath()); typeDictionary.putHandler(MessageType.of(messageType), handler); ConsumerFactory consumerFactory = new ConsumerFactory(serviceProperties, typeDictionary, null, null); return consumerFactory; } }
public Marker getLoggingMarker() { // If we get more optional header fields, we should probably exclude them if they are empty. Marker messageMarker = append("messageId", messageId) .and(append("partitionId", partitionId)) .and(append("partitioningKey", partitioningKey)) .and(append("offset", offset)) .and(append("messageId", messageId)) .and(append("correlationId", correlationId)) .and(append("requestCorrelationId", requestCorrelationId)); // Nota bene: without the toString the marker tries to convert the object into Json, which produces strange results if (topic != null) { messageMarker.add(append("topic", topic.toString())); } if (replyTo != null) { messageMarker.add(append("replyTo", replyTo.toString())); } if (type != null) { messageMarker.add(append("messageType", type.toString())); } return messageMarker; }
static Message<? extends com.google.protobuf.Message> fromKafka(com.google.protobuf.Message protoMessage, Envelope envelope, ConsumerRecord<String, byte[]> record) { boolean wasReceived = true; Topic topic = new Topic(record.topic()); String partitioningKey = record.key(); int partitionId = record.partition(); long offset = record.offset(); String messageId = envelope.getMessageId(); String correlationId = envelope.getCorrelationId(); MessageType type = MessageType.of(protoMessage); String requestCorrelationId = envelope.getRequestCorrelationId(); Topic replyTo = new Topic(envelope.getReplyTo()); Metadata meta = new Metadata(wasReceived, topic, partitioningKey, partitionId, offset, messageId, correlationId, requestCorrelationId, replyTo, type); return new Message<>(protoMessage, meta); }
typeDictionary.putAllParsers(typeDictionaryFactory.populateParsersFromClasspath()); typeDictionary.putHandler(MessageType.of(SayHelloToCmd.class), new MessageHandler<SayHelloToCmd>() { @Override public void onMessage(Message<SayHelloToCmd> message, OrangeContext context) { typeDictionary.putHandler(MessageType.of(SayHelloToReply.class), new MessageHandler<SayHelloToReply>() { @Override public void onMessage(Message<SayHelloToReply> message, OrangeContext context) {