Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature improve notification service generics #70

Merged
merged 5 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
package net.croz.nrich.notification.api.response;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.croz.nrich.notification.api.model.Notification;

/**
* Wrapper around response data that allows for sending notification with original response data.
*
* @param <T> type of response data
*/
@RequiredArgsConstructor
@Getter
public class ResponseWithNotification<T> {
public class NotificationDataResponse<T> extends NotificationResponse {

/**
* Response data
*/
private final T data;

/**
* Notification
*/
private final Notification notification;

public NotificationDataResponse(Notification notification, T data) {
super(notification);
this.data = data;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.croz.nrich.notification.api.response;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.croz.nrich.notification.api.model.Notification;

/**
* Response that hold notification.
*/
@RequiredArgsConstructor
@Getter
public class NotificationResponse {

/**
* Notification
*/
private final Notification notification;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package net.croz.nrich.notification.api.service;

import net.croz.nrich.notification.api.model.AdditionalNotificationData;
import net.croz.nrich.notification.api.response.NotificationDataResponse;
import org.springframework.validation.Errors;

import javax.validation.ConstraintViolationException;


/**
* Helper service that helps creation response with notification.
*
* @param <T> Type of response with notification i.e. {@link NotificationDataResponse}
*/
public interface BaseNotificationResponseService<T> {

/**
* Returns response with {@link net.croz.nrich.notification.api.model.ValidationFailureNotification} instance.
*
* @param errors Springs {@link Errors} that will be used to resolve validation notification messages.
* @param validationFailedOwningType class on which validation errors were found
* @param additionalNotificationData additional notification data to add to notification
* @return response with validation failure notification
*/
T responseWithValidationFailureNotification(Errors errors, Class<?> validationFailedOwningType, AdditionalNotificationData additionalNotificationData);

/**
* Returns response with {@link net.croz.nrich.notification.api.model.ValidationFailureNotification} instance.
*
* @param exception validation exception that will be used to resolve validation notification messages.
* @param additionalNotificationData additional notification data to add to notification
* @return response with validation failure notification
*/
T responseWithValidationFailureNotification(ConstraintViolationException exception, AdditionalNotificationData additionalNotificationData);

/**
* Returns response with {@link net.croz.nrich.notification.api.model.Notification} instance.
*
* @param throwable exception for which to resolve notification
* @param additionalNotificationData additional notification data to add to notification
* @param exceptionMessageArgumentList optional exception argument list, will be used when resolving exception message
* @return response with notification
*/
T responseWithExceptionNotification(Throwable throwable, AdditionalNotificationData additionalNotificationData, Object... exceptionMessageArgumentList);

/**
* Returns response with {@link net.croz.nrich.notification.api.model.Notification} instance.
*
* @param actionName name of the action for which to resolve notification
* @param additionalNotificationData additional notification data to add to notification
* @return response with notification
*/
T responseWithNotification(String actionName, AdditionalNotificationData additionalNotificationData);

/**
* Returns response with {@link net.croz.nrich.notification.api.model.Notification} instance.
*
* @param additionalNotificationData additional notification data to add to notification
* @return response with notification
*/
T responseWithNotificationActionResolvedFromRequest(AdditionalNotificationData additionalNotificationData);

NotificationResolverService notificationResolverService();

default T responseWithValidationFailureNotification(Errors errors, Class<?> validationFailedOwningType) {
return responseWithValidationFailureNotification(errors, validationFailedOwningType, AdditionalNotificationData.empty());
}

default T responseWithValidationFailureNotification(ConstraintViolationException exception) {
return responseWithValidationFailureNotification(exception, AdditionalNotificationData.empty());
}

default T responseWithExceptionNotification(Throwable throwable, Object... additionalMessageArgumentList) {
return responseWithExceptionNotification(throwable, AdditionalNotificationData.empty(), additionalMessageArgumentList);
}

default T responseWithNotificationActionResolvedFromRequest() {
return responseWithNotificationActionResolvedFromRequest(AdditionalNotificationData.empty());
}

default T responseWithNotification(String actionName) {
return responseWithNotification(actionName, AdditionalNotificationData.empty());
}
}
Original file line number Diff line number Diff line change
@@ -1,47 +1,10 @@
package net.croz.nrich.notification.api.service;

import net.croz.nrich.notification.api.model.AdditionalNotificationData;
import org.springframework.validation.Errors;
import net.croz.nrich.notification.api.response.NotificationDataResponse;
import net.croz.nrich.notification.api.response.NotificationResponse;

import javax.validation.ConstraintViolationException;

// TODO maybe reduce number of methods, this seems a bit complicated?

/**
* Helper service that helps creation response with notification.
*
* @param <T> Type of response with notification i.e. {@link net.croz.nrich.notification.api.response.ResponseWithNotification}
*/
public interface NotificationResponseService<T> {

/**
* Returns response with {@link net.croz.nrich.notification.api.model.ValidationFailureNotification} instance.
*
* @param errors Springs {@link Errors} that will be used to resolve validation notification messages.
* @param validationFailedOwningType class on which validation errors were found
* @param additionalNotificationData additional notification data to add to notification
* @return response with validation failure notification
*/
T responseWithValidationFailureNotification(Errors errors, Class<?> validationFailedOwningType, AdditionalNotificationData additionalNotificationData);

/**
* Returns response with {@link net.croz.nrich.notification.api.model.ValidationFailureNotification} instance.
*
* @param exception validation exception that will be used to resolve validation notification messages.
* @param additionalNotificationData additional notification data to add to notification
* @return response with validation failure notification
*/
T responseWithValidationFailureNotification(ConstraintViolationException exception, AdditionalNotificationData additionalNotificationData);

/**
* Returns response with {@link net.croz.nrich.notification.api.model.Notification} instance.
*
* @param throwable exception for which to resolve notification
* @param additionalNotificationData additional notification data to add to notification
* @param exceptionMessageArgumentList optional exception argument list, will be used when resolving exception message
* @return response with notification
*/
T responseWithExceptionNotification(Throwable throwable, AdditionalNotificationData additionalNotificationData, Object... exceptionMessageArgumentList);
public interface NotificationResponseService extends BaseNotificationResponseService<NotificationResponse> {

/**
* Returns response with {@link net.croz.nrich.notification.api.model.Notification} instance.
Expand All @@ -51,7 +14,7 @@ public interface NotificationResponseService<T> {
* @param <D> type of data
* @return response with notification
*/
<D> T responseWithNotificationActionResolvedFromRequest(D data, AdditionalNotificationData additionalNotificationData);
<D> NotificationDataResponse<D> responseWithNotificationActionResolvedFromRequest(D data, AdditionalNotificationData additionalNotificationData);

/**
* Returns response with {@link net.croz.nrich.notification.api.model.Notification} instance.
Expand All @@ -62,35 +25,13 @@ public interface NotificationResponseService<T> {
* @param <D> type of data
* @return response with notification
*/
<D> T responseWithNotification(D data, String actionName, AdditionalNotificationData additionalNotificationData);

NotificationResolverService notificationResolverService();

default T responseWithValidationFailureNotification(Errors errors, Class<?> validationFailedOwningType) {
return responseWithValidationFailureNotification(errors, validationFailedOwningType, AdditionalNotificationData.empty());
}

default T responseWithValidationFailureNotification(ConstraintViolationException exception) {
return responseWithValidationFailureNotification(exception, AdditionalNotificationData.empty());
}

default T responseWithExceptionNotification(Throwable throwable, Object... additionalMessageArgumentList) {
return responseWithExceptionNotification(throwable, AdditionalNotificationData.empty(), additionalMessageArgumentList);
}
<D> NotificationDataResponse<D> responseWithNotification(D data, String actionName, AdditionalNotificationData additionalNotificationData);

default <D> T responseWithNotificationActionResolvedFromRequest(D data) {
default <D> NotificationDataResponse<D> responseWithNotificationActionResolvedFromRequest(D data) {
return responseWithNotificationActionResolvedFromRequest(data, AdditionalNotificationData.empty());
}

default <D> T responseWithNotification(D data, String actionName) {
default <D> NotificationDataResponse<D> responseWithNotification(D data, String actionName) {
return responseWithNotification(data, actionName, AdditionalNotificationData.empty());
}

default T responseWithNotificationActionResolvedFromRequest() {
return responseWithNotificationActionResolvedFromRequest(null, AdditionalNotificationData.empty());
}

default T responseWithNotification(String actionName) {
return responseWithNotification(null, actionName, AdditionalNotificationData.empty());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import lombok.RequiredArgsConstructor;
import net.croz.nrich.notification.api.service.NotificationMessageResolverService;
import net.croz.nrich.notification.api.service.NotificationResolverService;
import net.croz.nrich.notification.api.service.BaseNotificationResponseService;
import net.croz.nrich.notification.api.service.NotificationResponseService;
import net.croz.nrich.notification.service.ConstraintConversionService;
import net.croz.nrich.notification.service.DefaultConstraintConversionService;
Expand Down Expand Up @@ -42,9 +43,9 @@ public NotificationResolverService notificationResolverService(NotificationMessa
}

@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnMissingBean(NotificationResponseService.class)
@ConditionalOnMissingBean(BaseNotificationResponseService.class)
@Bean
public WebMvcNotificationResponseService notificationResponseService(NotificationResolverService notificationResolverService) {
public NotificationResponseService notificationResponseService(NotificationResolverService notificationResolverService) {
return new WebMvcNotificationResponseService(notificationResolverService);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package net.croz.nrich.notification.starter;

import net.croz.nrich.notification.api.service.NotificationResolverService;
import net.croz.nrich.notification.api.service.NotificationResponseService;
import net.croz.nrich.notification.api.service.BaseNotificationResponseService;
import net.croz.nrich.notification.service.ConstraintConversionService;
import net.croz.nrich.notification.starter.configuration.NrichNotificationAutoConfiguration;
import org.junit.jupiter.api.Test;
Expand All @@ -27,7 +27,7 @@ void shouldConfigureDefaultConfiguration() {
contextRunner.run(context -> {
assertThat(context).hasSingleBean(ConstraintConversionService.class);
assertThat(context).hasSingleBean(NotificationResolverService.class);
assertThat(context).doesNotHaveBean(NotificationResponseService.class);
assertThat(context).doesNotHaveBean(BaseNotificationResponseService.class);
assertThat(context).hasSingleBean(NrichNotificationAutoConfiguration.NotificationMessageSourceRegistrar.class);
});
}
Expand All @@ -44,7 +44,7 @@ void shouldNotRegisterMessagesWhenExplicitlyDisalbed() {
void shouldIncludeNotificationResponseServiceWhenRunningInWebEnvironment() {
// expect
webContextRunner.run(context ->
assertThat(context).hasSingleBean(NotificationResponseService.class)
assertThat(context).hasSingleBean(BaseNotificationResponseService.class)
);
}

Expand Down
6 changes: 3 additions & 3 deletions nrich-notification/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ To be able to use this library following configuration is required:
}

@Bean
public NotificationResponseService<?> notificationResponseService(NotificationResolverService notificationResolverService) {
public NotificationResponseService notificationResponseService(NotificationResolverService notificationResolverService) {
return new WebMvcNotificationResponseService(notificationResolverService);
}

Expand Down Expand Up @@ -62,7 +62,7 @@ advice would look something like this:
@RequiredArgsConstructor
public class NotificationErrorHandlingRestControllerAdvice {

private NotificationResponseService<?> notificationResponseService;
private NotificationResponseService notificationResponseService;

@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleException(Exception exception, HttpServletRequest request) {
Expand Down Expand Up @@ -93,7 +93,7 @@ Users can also use `NotificationResponseService` to return notifications with re
@RequiredArgsConstructor
public class NotificationTestController {

private NotificationResponseService<ResponseWithNotification<?>> notificationResponseService;
private NotificationResponseService notificationResponseService;

private ExampleService exampleService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import lombok.RequiredArgsConstructor;
import net.croz.nrich.notification.api.model.AdditionalNotificationData;
import net.croz.nrich.notification.api.model.Notification;
import net.croz.nrich.notification.api.response.ResponseWithNotification;
import net.croz.nrich.notification.api.response.NotificationDataResponse;
import net.croz.nrich.notification.api.response.NotificationResponse;
import net.croz.nrich.notification.api.service.NotificationResolverService;
import net.croz.nrich.notification.api.service.NotificationResponseService;
import net.croz.nrich.notification.constant.NotificationConstants;
Expand All @@ -17,43 +18,57 @@
import java.util.Objects;

@RequiredArgsConstructor
public class WebMvcNotificationResponseService implements NotificationResponseService<ResponseWithNotification<?>> {
public class WebMvcNotificationResponseService implements NotificationResponseService {

private final NotificationResolverService notificationResolverService;

@Override
public ResponseWithNotification<?> responseWithValidationFailureNotification(Errors errors, Class<?> validationFailedOwningType, AdditionalNotificationData additionalNotificationData) {
public NotificationResponse responseWithValidationFailureNotification(Errors errors, Class<?> validationFailedOwningType, AdditionalNotificationData additionalNotificationData) {
Notification notification = notificationResolverService.createNotificationForValidationFailure(errors, validationFailedOwningType, additionalNotificationData);

return new ResponseWithNotification<>(null, notification);
return new NotificationResponse(notification);
}

@Override
public ResponseWithNotification<?> responseWithValidationFailureNotification(ConstraintViolationException exception, AdditionalNotificationData additionalNotificationData) {
public NotificationResponse responseWithValidationFailureNotification(ConstraintViolationException exception, AdditionalNotificationData additionalNotificationData) {
Notification notification = notificationResolverService.createNotificationForValidationFailure(exception, additionalNotificationData);

return new ResponseWithNotification<>(null, notification);
return new NotificationResponse(notification);
}

@Override
public ResponseWithNotification<?> responseWithExceptionNotification(Throwable throwable, AdditionalNotificationData additionalNotificationData, Object... exceptionMessageArgumentList) {
public NotificationResponse responseWithExceptionNotification(Throwable throwable, AdditionalNotificationData additionalNotificationData, Object... exceptionMessageArgumentList) {
Notification notification = notificationResolverService.createNotificationForException(throwable, additionalNotificationData, exceptionMessageArgumentList);

return new ResponseWithNotification<>(null, notification);
return new NotificationResponse(notification);
}

@Override
public <D> ResponseWithNotification<D> responseWithNotificationActionResolvedFromRequest(D data, AdditionalNotificationData additionalNotificationData) {
public NotificationResponse responseWithNotificationActionResolvedFromRequest(AdditionalNotificationData additionalNotificationData) {
String actionName = extractActionNameFromCurrentRequest();

return responseWithNotification(actionName, additionalNotificationData);
}

@Override
public NotificationResponse responseWithNotification(String actionName, AdditionalNotificationData additionalNotificationData) {
Notification notification = notificationResolverService.createNotificationForAction(actionName, additionalNotificationData);

return new NotificationResponse(notification);
}

@Override
public <D> NotificationDataResponse<D> responseWithNotificationActionResolvedFromRequest(D data, AdditionalNotificationData additionalNotificationData) {
String actionName = extractActionNameFromCurrentRequest();

return responseWithNotification(data, actionName, additionalNotificationData);
}

@Override
public <D> ResponseWithNotification<D> responseWithNotification(D data, String actionName, AdditionalNotificationData additionalNotificationData) {
public <D> NotificationDataResponse<D> responseWithNotification(D data, String actionName, AdditionalNotificationData additionalNotificationData) {
Notification notification = notificationResolverService.createNotificationForAction(actionName, additionalNotificationData);

return new ResponseWithNotification<>(data, notification);
return new NotificationDataResponse<>(notification, data);
}

@Override
Expand Down
Loading