diff --git a/financer-web-client/pom.xml b/financer-web-client/pom.xml index 9dd4dd9..f8b91e3 100644 --- a/financer-web-client/pom.xml +++ b/financer-web-client/pom.xml @@ -62,6 +62,7 @@ de.77zzcx7.push-service push-service-client-lib + true diff --git a/financer-web-client/src/main/java/de/financer/controller/AccountController.java b/financer-web-client/src/main/java/de/financer/controller/AccountController.java index 105d437..b1e6f90 100644 --- a/financer-web-client/src/main/java/de/financer/controller/AccountController.java +++ b/financer-web-client/src/main/java/de/financer/controller/AccountController.java @@ -7,13 +7,13 @@ import de.financer.dto.Order; import de.financer.dto.SearchTransactionsResponseDto; import de.financer.form.NewAccountForm; import de.financer.model.*; +import de.financer.notification.Notification; +import de.financer.notification.PushServiceProxy; +import de.financer.notification.Urgency; import de.financer.template.*; import de.financer.template.exception.FinancerRestException; import de.financer.util.ControllerUtils; import de.financer.util.TransactionUtils; -import de.pushservice.client.dto.PayloadDto; -import de.pushservice.client.model.Urgency; -import de.pushservice.client.service.SubscriptionService; import org.apache.commons.collections4.IterableUtils; import org.apache.commons.lang3.BooleanUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -209,21 +209,22 @@ public class AccountController { // --------------------------------------------- - @Autowired(required = false) - private SubscriptionService subscriptionService; + @Autowired + private PushServiceProxy pushServiceProxy; private int counter = 0; @GetMapping("/sendTestNotification") public String sendTestNotification() { - if (this.subscriptionService != null && this.subscriptionService.isInitialized()) { - PayloadDto p = new PayloadDto("Hello from Financer!"); + if (this.pushServiceProxy.isInitialized()) { + Notification notification = new Notification(); - p.setTimestamp(System.currentTimeMillis()); - p.setMessage("Test notification " + counter++); - p.setVibration(new int[] {100, 200, 300, 400, 500}); + notification.setTitle("Hello from Financer!"); + notification.setTopic("FINANCER-TEST"); + notification.setMessage("Test notification " + counter++); + notification.setUrgency(Urgency.NORMAL); try { - this.subscriptionService.notify(p, "FINANCER-TEST", Urgency.NORMAL); + this.pushServiceProxy.notify(notification); } catch(Exception e) { e.printStackTrace(); diff --git a/financer-web-client/src/main/java/de/financer/notification/Notification.java b/financer-web-client/src/main/java/de/financer/notification/Notification.java new file mode 100644 index 0000000..5ecf583 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/notification/Notification.java @@ -0,0 +1,40 @@ +package de.financer.notification; + +public class Notification { + private String title; + private String topic; + private String message; + private Urgency urgency; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getTopic() { + return topic; + } + + public void setTopic(String topic) { + this.topic = topic; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Urgency getUrgency() { + return urgency; + } + + public void setUrgency(Urgency urgency) { + this.urgency = urgency; + } +} diff --git a/financer-web-client/src/main/java/de/financer/notification/PushServiceProxy.java b/financer-web-client/src/main/java/de/financer/notification/PushServiceProxy.java new file mode 100644 index 0000000..9b457e5 --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/notification/PushServiceProxy.java @@ -0,0 +1,138 @@ +package de.financer.notification; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.AutowireCapableBeanFactory; +import org.springframework.stereotype.Component; + +/** + * Class to really loosely couple the PushService to financer. + * The PushService dependency is optional in the POM, so if it is not available instantiation would fail, + * that's why the actual classes get proxied and coupling is done via reflection. + */ +@Component +public class PushServiceProxy implements InitializingBean { + private static final Logger LOGGER = LoggerFactory.getLogger(PushServiceProxy.class); + + // #### Service constants + private static final String SERVICE_CLASS_NAME = "de.pushservice.client.service.SubscriptionService"; + private static final String SERVICE_METHOD_IS_INITIALIZED = "isInitialized"; + private static final String SERVICE_METHOD_NOTIFY = "notify"; + + // #### Payload constants + private static final String PAYLOAD_CLASS_NAME = "de.pushservice.client.dto.PayloadDto"; + private static final String PAYLOAD_METHOD_SET_TIMESTAMP = "setTimestamp"; + private static final String PAYLOAD_METHOD_SET_MESSAGE = "setMessage"; + + // #### Urgency constants + private static final String URGENCY_CLASS_NAME = "de.pushservice.client.model.Urgency"; + + private Class subscriptionServiceClass; + private Class payloadClass; + private Class urgencyClass; + private Object subscriptionServiceInstance; + + @Autowired + private AutowireCapableBeanFactory autowireCapableBeanFactory; + + // #### Public methods mimicking SubscriptionService interface + + public boolean isInitialized() { + return this.subscriptionServiceInstance != null && this.isInitializedInternal(); + } + + public void notify(Notification notification) { + if(!this.isInitialized()) { + LOGGER.warn("notify() called but not initialized!"); + } + + try { + this.subscriptionServiceClass + .getMethod(SERVICE_METHOD_NOTIFY, this.payloadClass, String.class, this.urgencyClass) + .invoke(this.subscriptionServiceInstance, toPayload(notification), notification + .getTopic(), toUrgency(notification)); + } catch (ReflectiveOperationException e) { + LOGGER.error("Error while sending notification!", e); + } + } + + // #### Initialization + + @Override + public void afterPropertiesSet() throws Exception { + try { + this.subscriptionServiceClass = Class.forName(SERVICE_CLASS_NAME); + + // Since we create the instance ourself no auto wiring by Spring + this.subscriptionServiceInstance = this.subscriptionServiceClass.getDeclaredConstructor().newInstance(); + + // Do the Spring wiring magic + this.autowireCapableBeanFactory.autowireBean(this.subscriptionServiceInstance); + + this.payloadClass = Class.forName(PAYLOAD_CLASS_NAME); + this.urgencyClass = Class.forName(URGENCY_CLASS_NAME); + } catch (ReflectiveOperationException e) { + LOGGER.error("Error while sending notification!", e); + } + } + + // #### Internal methods + + private Object toUrgency(Notification notification) { + Object urgencyInstance = null; + + try { + // Urgency is an Enum in PushClient as well + // Works by having the same name in both Urgency enums + urgencyInstance = this.urgencyClass.getDeclaredField(notification.getUrgency().name()).get(null); + } catch (ReflectiveOperationException e) { + LOGGER.error("Error while sending notification!", e); + } + + return urgencyInstance; + } + + private Object toPayload(Notification notification) { + Object payloadInstance = null; + + try { + payloadInstance = this.payloadClass.getConstructor(String.class) + .newInstance(notification.getTitle()); + + this.payloadClass.getMethod(PAYLOAD_METHOD_SET_TIMESTAMP, long.class) + .invoke(payloadInstance, System.currentTimeMillis()); + + this.payloadClass.getMethod(PAYLOAD_METHOD_SET_MESSAGE, String.class) + .invoke(payloadInstance, notification.getMessage()); + } catch (ReflectiveOperationException e) { + LOGGER.error("Error while sending notification!", e); + } + + return payloadInstance; + } + + private boolean isInitializedInternal() { + boolean retVal = false; + + try { + final Object tmpRetVal = this.subscriptionServiceClass.getMethod(SERVICE_METHOD_IS_INITIALIZED) + .invoke(this.subscriptionServiceInstance); + + if (Boolean.class.isAssignableFrom(tmpRetVal.getClass())) { + retVal = ((Boolean) tmpRetVal).booleanValue(); + } else { + LOGGER.warn("Proxied isInitialized call returned non java.lang.Boolean value"); + } + } catch (ReflectiveOperationException e) { + LOGGER.error("Error while sending notification!", e); + } + + if(LOGGER.isDebugEnabled()) { + LOGGER.debug(String.format("isInitializedInternal() returns with %s", retVal)); + } + + return retVal; + } +} diff --git a/financer-web-client/src/main/java/de/financer/notification/Urgency.java b/financer-web-client/src/main/java/de/financer/notification/Urgency.java new file mode 100644 index 0000000..441f4cc --- /dev/null +++ b/financer-web-client/src/main/java/de/financer/notification/Urgency.java @@ -0,0 +1,8 @@ +package de.financer.notification; + +public enum Urgency { + VERY_LOW, + LOW, + NORMAL, + HIGH; +}