use of io.micronaut.core.annotation.AnnotationValue in project micronaut-micrometer by micronaut-projects.
the class TimedInterceptor method intercept.
@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
final AnnotationMetadata metadata = context.getAnnotationMetadata();
final AnnotationValue<TimedSet> timedSet = metadata.getAnnotation(TimedSet.class);
if (timedSet != null) {
final List<AnnotationValue<Timed>> timedAnnotations = timedSet.getAnnotations(VALUE_MEMBER, Timed.class);
if (!timedAnnotations.isEmpty()) {
String exceptionClass = "none";
List<Timer.Sample> syncInvokeSamples = null;
InterceptedMethod interceptedMethod = InterceptedMethod.of(context);
try {
InterceptedMethod.ResultType resultType = interceptedMethod.resultType();
switch(resultType) {
case PUBLISHER:
Object interceptResult = context.proceed();
if (interceptResult == null) {
return null;
}
Object result;
AtomicReference<List<Timer.Sample>> reactiveInvokeSample = new AtomicReference<>();
if (context.getReturnType().isSingleResult()) {
Mono<?> single = Mono.from(Publishers.convertPublisher(interceptResult, Publisher.class));
result = single.doOnSubscribe(d -> reactiveInvokeSample.set(initSamples(timedAnnotations))).doOnError(throwable -> finalizeSamples(timedAnnotations, throwable.getClass().getSimpleName(), reactiveInvokeSample.get())).doOnSuccess(o -> finalizeSamples(timedAnnotations, "none", reactiveInvokeSample.get()));
} else {
AtomicReference<String> exceptionClassHolder = new AtomicReference<>("none");
Flux<?> flowable = Flux.from(Publishers.convertPublisher(interceptResult, Publisher.class));
result = flowable.doOnRequest(n -> reactiveInvokeSample.set(initSamples(timedAnnotations))).doOnError(throwable -> exceptionClassHolder.set(throwable.getClass().getSimpleName())).doOnComplete(() -> finalizeSamples(timedAnnotations, exceptionClassHolder.get(), reactiveInvokeSample.get()));
}
return Publishers.convertPublisher(result, context.getReturnType().getType());
case COMPLETION_STAGE:
List<Timer.Sample> completionStageInvokeSamples = initSamples(timedAnnotations);
CompletionStage<?> completionStage = interceptedMethod.interceptResultAsCompletionStage();
CompletionStage<?> completionStageResult = completionStage.whenComplete((o, throwable) -> finalizeSamples(timedAnnotations, throwable == null ? "none" : throwable.getClass().getSimpleName(), completionStageInvokeSamples));
return interceptedMethod.handleResult(completionStageResult);
case SYNCHRONOUS:
syncInvokeSamples = initSamples(timedAnnotations);
return context.proceed();
default:
return interceptedMethod.unsupported();
}
} catch (Exception e) {
exceptionClass = e.getClass().getSimpleName();
return interceptedMethod.handleException(e);
} finally {
finalizeSamples(timedAnnotations, exceptionClass, syncInvokeSamples);
}
}
}
return context.proceed();
}
use of io.micronaut.core.annotation.AnnotationValue in project micronaut-gcp by micronaut-projects.
the class PubSubClientIntroductionAdvice method intercept.
@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
if (context.hasAnnotation(Topic.class)) {
PubSubPublisherState publisherState = publisherStateCache.computeIfAbsent(context.getExecutableMethod(), method -> {
String projectId = method.stringValue(PubSubClient.class).orElse(googleCloudConfiguration.getProjectId());
Optional<Argument> orderingArgument = Arrays.stream(method.getArguments()).filter(argument -> argument.getAnnotationMetadata().hasAnnotation(OrderingKey.class)).findFirst();
String topic = method.stringValue(Topic.class).orElse(context.getName());
String endpoint = method.stringValue(Topic.class, "endpoint").orElse("");
String configurationName = method.stringValue(Topic.class, "configuration").orElse("");
String contentType = method.stringValue(Topic.class, "contentType").orElse(MediaType.APPLICATION_JSON);
ProjectTopicName projectTopicName = PubSubTopicUtils.toProjectTopicName(topic, projectId);
Map<String, String> staticMessageAttributes = new HashMap<>();
List<AnnotationValue<MessageHeader>> headerAnnotations = context.getAnnotationValuesByType(MessageHeader.class);
headerAnnotations.forEach((header) -> {
String name = header.stringValue("name").orElse(null);
String value = header.stringValue().orElse(null);
if (StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(value)) {
staticMessageAttributes.put(name, value);
}
});
Argument<?> bodyArgument = findBodyArgument(method).orElseThrow(() -> new PubSubClientException("No valid message body argument found for method: " + context.getExecutableMethod()));
PubSubPublisherState.TopicState topicState = new PubSubPublisherState.TopicState(contentType, projectTopicName, configurationName, endpoint, orderingArgument.isPresent());
logger.debug("Created a new publisher[{}] for topic: {}", context.getExecutableMethod().getName(), topic);
PublisherInterface publisher = publisherFactory.createPublisher(new PublisherFactoryConfig(topicState, pubSubConfigurationProperties.getPublishingExecutor()));
return new PubSubPublisherState(topicState, staticMessageAttributes, bodyArgument, publisher, orderingArgument);
});
Map<String, String> messageAttributes = new HashMap<>(publisherState.getStaticMessageAttributes());
String contentType = publisherState.getTopicState().getContentType();
Argument<?> bodyArgument = publisherState.getBodyArgument();
Map<String, Object> parameterValues = context.getParameterValueMap();
final ReturnType<Object> returnTypeInfo = context.getReturnType();
ReturnType<Object> returnType = returnTypeInfo;
Class<?> javaReturnType = returnType.getType();
Argument[] arguments = context.getArguments();
for (Argument arg : arguments) {
AnnotationValue<MessageHeader> headerAnn = arg.getAnnotation(MessageHeader.class);
if (headerAnn != null) {
Map.Entry<String, String> entry = getNameAndValue(arg, headerAnn, parameterValues);
messageAttributes.put(entry.getKey(), entry.getValue());
}
}
PublisherInterface publisher = publisherState.getPublisher();
Object body = parameterValues.get(bodyArgument.getName());
PubsubMessage pubsubMessage = null;
if (body.getClass() == PubsubMessage.class) {
pubsubMessage = (PubsubMessage) body;
} else {
// if target type is byte[] we bypass serdes completely
byte[] serialized = null;
if (body.getClass() == byte[].class) {
serialized = (byte[]) body;
} else {
PubSubMessageSerDes serDes = serDesRegistry.find(contentType).orElseThrow(() -> new PubSubClientException("Could not locate a valid SerDes implementation for type: " + contentType));
serialized = serDes.serialize(body);
}
messageAttributes.put("Content-Type", contentType);
PubsubMessage.Builder messageBuilder = PubsubMessage.newBuilder();
messageBuilder.setData(ByteString.copyFrom(serialized)).putAllAttributes(messageAttributes);
if (publisherState.getOrderingArgument().isPresent()) {
String orderingKey = conversionService.convert(parameterValues.get(publisherState.getOrderingArgument().get().getName()), String.class).orElseThrow(() -> new PubSubClientException("Could not convert argument annotated with @OrderingKey to String type"));
messageBuilder.setOrderingKey(orderingKey);
}
pubsubMessage = messageBuilder.build();
}
PubsubMessage finalPubsubMessage = pubsubMessage;
Mono<String> reactiveResult = Mono.create(sink -> {
ApiFuture<String> future = publisher.publish(finalPubsubMessage);
future.addListener(() -> {
try {
final String result = future.get();
sink.success(result);
} catch (Throwable e) {
sink.error(e);
}
}, executorService);
});
if (javaReturnType == void.class || javaReturnType == Void.class) {
String result = reactiveResult.block();
return null;
} else {
if (returnTypeInfo.isReactive()) {
return Publishers.convertPublisher(reactiveResult, javaReturnType);
} else if (returnTypeInfo.isAsync()) {
return reactiveResult.toFuture();
} else {
String result = reactiveResult.block();
return conversionService.convert(result, javaReturnType).orElseThrow(() -> new PubSubClientException("Could not convert publisher result to method return type: " + javaReturnType));
}
}
} else {
return context.proceed();
}
}
use of io.micronaut.core.annotation.AnnotationValue in project micronaut-gcp by micronaut-projects.
the class PubSubConsumerAdvice method process.
@Override
public void process(BeanDefinition<?> beanDefinition, ExecutableMethod<?, ?> method) {
if (beanDefinition.hasDeclaredAnnotation(PubSubListener.class)) {
AnnotationValue<Subscription> subscriptionAnnotation = method.getAnnotation(Subscription.class);
io.micronaut.context.Qualifier<Object> qualifier = beanDefinition.getAnnotationTypeByStereotype(Qualifier.class).map(type -> Qualifiers.byAnnotation(beanDefinition, type)).orElse(null);
boolean hasAckArg = Arrays.stream(method.getArguments()).anyMatch(arg -> Acknowledgement.class.isAssignableFrom(arg.getType()));
Class<Object> beanType = (Class<Object>) beanDefinition.getBeanType();
Object bean = beanContext.findBean(beanType, qualifier).orElseThrow(() -> new MessageListenerException("Could not find the bean to execute the method " + method));
DefaultExecutableBinder<PubSubConsumerState> binder = new DefaultExecutableBinder<>();
if (subscriptionAnnotation != null) {
String subscriptionName = subscriptionAnnotation.getRequiredValue(String.class);
ProjectSubscriptionName projectSubscriptionName = PubSubSubscriptionUtils.toProjectSubscriptionName(subscriptionName, googleCloudConfiguration.getProjectId());
String defaultContentType = subscriptionAnnotation.stringValue("contentType").orElse(MediaType.APPLICATION_JSON);
String configuration = subscriptionAnnotation.stringValue("configuration").orElse("");
MessageReceiver receiver = (PubsubMessage message, AckReplyConsumer ackReplyConsumer) -> {
String messageContentType = message.getAttributesMap().getOrDefault("Content-Type", "");
String contentType = Optional.of(messageContentType).filter(StringUtils::isNotEmpty).orElse(defaultContentType);
DefaultPubSubAcknowledgement pubSubAcknowledgement = new DefaultPubSubAcknowledgement(ackReplyConsumer);
PubSubConsumerState consumerState = new PubSubConsumerState(message, ackReplyConsumer, projectSubscriptionName, contentType);
try {
BoundExecutable executable = null;
try {
executable = binder.bind(method, binderRegistry, consumerState);
} catch (Exception ex) {
handleException(new PubSubMessageReceiverException("Error binding message to the method", ex, bean, consumerState));
}
// Discard result
executable.invoke(bean);
if (!hasAckArg) {
// if manual ack is not specified we auto ack message after method execution
pubSubAcknowledgement.ack();
} else {
Optional<Object> boundAck = Arrays.stream(executable.getBoundArguments()).filter(o -> (o instanceof DefaultPubSubAcknowledgement)).findFirst();
if (boundAck.isPresent()) {
DefaultPubSubAcknowledgement manualAck = (DefaultPubSubAcknowledgement) boundAck.get();
if (!manualAck.isClientAck()) {
logger.warn("Method {} was executed and no message acknowledge detected. Did you forget to invoke ack()/nack()?", method.getName());
}
}
}
} catch (Exception e) {
handleException(new PubSubMessageReceiverException("Error handling message", e, bean, consumerState));
}
};
try {
this.subscriberFactory.createSubscriber(new SubscriberFactoryConfig(projectSubscriptionName, receiver, configuration, pubSubConfigurationProperties.getSubscribingExecutor()));
} catch (Exception e) {
throw new PubSubListenerException("Failed to create subscriber", e);
}
}
}
}
use of io.micronaut.core.annotation.AnnotationValue in project micronaut-core by micronaut-projects.
the class JsonViewServerFilter method doFilter.
@Override
public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) {
final RouteInfo<?> routeInfo = request.getAttribute(HttpAttributes.ROUTE_INFO, RouteInfo.class).orElse(null);
final Publisher<MutableHttpResponse<?>> responsePublisher = chain.proceed(request);
if (routeInfo != null) {
final Optional<Class<?>> viewClass = routeInfo.findAnnotation(JsonView.class).flatMap(AnnotationValue::classValue);
if (viewClass.isPresent()) {
return Flux.from(responsePublisher).switchMap(response -> {
final Optional<?> optionalBody = response.getBody();
if (optionalBody.isPresent()) {
Object body = optionalBody.get();
MediaTypeCodec codec = codecFactory.resolveJsonViewCodec(viewClass.get());
if (Publishers.isConvertibleToPublisher(body)) {
Publisher<?> pub = Publishers.convertPublisher(body, Publisher.class);
response.body(Flux.from(pub).map(o -> codec.encode((Argument) routeInfo.getBodyType(), o)).subscribeOn(Schedulers.fromExecutorService(executorService)));
} else {
return Mono.fromCallable(() -> {
@SuppressWarnings({ "unchecked", "rawtypes" }) final byte[] encoded = codec.encode((Argument) routeInfo.getBodyType(), body);
response.body(encoded);
return response;
}).subscribeOn(Schedulers.fromExecutorService(executorService));
}
}
return Flux.just(response);
});
}
}
return responsePublisher;
}
use of io.micronaut.core.annotation.AnnotationValue in project micronaut-core by micronaut-projects.
the class AbstractEnvironmentAnnotationMetadata method getAnnotationValuesByType.
@Override
@NonNull
public <T extends Annotation> List<AnnotationValue<T>> getAnnotationValuesByType(@NonNull Class<T> annotationType) {
ArgumentUtils.requireNonNull("annotationType", annotationType);
Environment environment = getEnvironment();
List<AnnotationValue<T>> values = environmentAnnotationMetadata.getAnnotationValuesByType(annotationType);
if (environment != null) {
return values.stream().map(entries -> new EnvironmentAnnotationValue<>(environment, entries)).collect(Collectors.toList());
}
return values;
}
Aggregations