#8 financer-web-client has a hard dependency on push-service
Introduce proxy for push service so it is completely optional
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package de.financer.notification;
|
||||
|
||||
public enum Urgency {
|
||||
VERY_LOW,
|
||||
LOW,
|
||||
NORMAL,
|
||||
HIGH;
|
||||
}
|
||||
Reference in New Issue
Block a user