#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:
@@ -62,6 +62,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>de.77zzcx7.push-service</groupId>
|
<groupId>de.77zzcx7.push-service</groupId>
|
||||||
<artifactId>push-service-client-lib</artifactId>
|
<artifactId>push-service-client-lib</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Financer dependencies -->
|
<!-- Financer dependencies -->
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import de.financer.dto.Order;
|
|||||||
import de.financer.dto.SearchTransactionsResponseDto;
|
import de.financer.dto.SearchTransactionsResponseDto;
|
||||||
import de.financer.form.NewAccountForm;
|
import de.financer.form.NewAccountForm;
|
||||||
import de.financer.model.*;
|
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.*;
|
||||||
import de.financer.template.exception.FinancerRestException;
|
import de.financer.template.exception.FinancerRestException;
|
||||||
import de.financer.util.ControllerUtils;
|
import de.financer.util.ControllerUtils;
|
||||||
import de.financer.util.TransactionUtils;
|
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.collections4.IterableUtils;
|
||||||
import org.apache.commons.lang3.BooleanUtils;
|
import org.apache.commons.lang3.BooleanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -209,21 +209,22 @@ public class AccountController {
|
|||||||
|
|
||||||
// ---------------------------------------------
|
// ---------------------------------------------
|
||||||
|
|
||||||
@Autowired(required = false)
|
@Autowired
|
||||||
private SubscriptionService subscriptionService;
|
private PushServiceProxy pushServiceProxy;
|
||||||
private int counter = 0;
|
private int counter = 0;
|
||||||
|
|
||||||
@GetMapping("/sendTestNotification")
|
@GetMapping("/sendTestNotification")
|
||||||
public String sendTestNotification() {
|
public String sendTestNotification() {
|
||||||
if (this.subscriptionService != null && this.subscriptionService.isInitialized()) {
|
if (this.pushServiceProxy.isInitialized()) {
|
||||||
PayloadDto p = new PayloadDto("Hello from Financer!");
|
Notification notification = new Notification();
|
||||||
|
|
||||||
p.setTimestamp(System.currentTimeMillis());
|
notification.setTitle("Hello from Financer!");
|
||||||
p.setMessage("Test notification " + counter++);
|
notification.setTopic("FINANCER-TEST");
|
||||||
p.setVibration(new int[] {100, 200, 300, 400, 500});
|
notification.setMessage("Test notification " + counter++);
|
||||||
|
notification.setUrgency(Urgency.NORMAL);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.subscriptionService.notify(p, "FINANCER-TEST", Urgency.NORMAL);
|
this.pushServiceProxy.notify(notification);
|
||||||
}
|
}
|
||||||
catch(Exception e) {
|
catch(Exception e) {
|
||||||
e.printStackTrace();
|
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