diff --git a/src/main/java/com/kms/handler/CacheHandler.java b/src/main/java/com/kms/handler/CacheHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..9ffb74ee88c10d58ae3c2eed0b524cec935f4e4c --- /dev/null +++ b/src/main/java/com/kms/handler/CacheHandler.java @@ -0,0 +1,91 @@ +package com.kms.handler; + +import com.kms.handler.helper.SoapFaultHelper; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; + +import javax.xml.namespace.QName; +import javax.xml.soap.MessageFactory; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPMessage; +import javax.xml.transform.stream.StreamSource; +import javax.xml.ws.handler.MessageContext; +import javax.xml.ws.handler.soap.SOAPHandler; +import javax.xml.ws.handler.soap.SOAPMessageContext; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Set; + +public class CacheHandler implements SOAPHandler<SOAPMessageContext> { + + private static final JedisPool jedisPool = new JedisPool("localhost", 6379); + private static final int DEFAULT_CACHE_TTL = 300; + + @Override + public Set<QName> getHeaders() { + return null; + } + + @Override + public boolean handleMessage(SOAPMessageContext context) { + final boolean messageHandled = + (boolean) context.getOrDefault("messageHandled", false); + + if (!messageHandled) + return true; + + final boolean cacheResponse = + (boolean) context.getOrDefault("cacheResponse", false); + if (cacheResponse) { + final String cacheKey = (String) context.getOrDefault("cacheKey", null); + if (cacheKey == null) + return true; + + try (Jedis jedis = jedisPool.getResource()) { + OutputStream responseTextOStream = new ByteArrayOutputStream(); + context.getMessage().writeTo(responseTextOStream); + + jedis.set(cacheKey, responseTextOStream.toString()); + jedis.expire(cacheKey, DEFAULT_CACHE_TTL); + + System.out.println("Response cached with key: " + cacheKey); + } catch (SOAPException | IOException ignored) { + } + + return true; + } + + final boolean returnFromCache = + (boolean) context.getOrDefault("returnFromCache", false); + if (!returnFromCache) + return true; + + final String cacheKey = (String) context.getOrDefault("cacheKey", null); + if (cacheKey == null) { + SoapFaultHelper.throwFault("Error", "Unexpected error has happened."); + } + try (Jedis jedis = jedisPool.getResource()) { + String response = jedis.get(cacheKey); + SOAPMessage soapMessage = MessageFactory.newInstance().createMessage(); + soapMessage.getSOAPPart().setContent(new StreamSource(new java.io.StringReader(response))); + + context.setMessage(soapMessage); + + System.out.println("Return from cache with key: "+cacheKey); + } catch (SOAPException ignored) { + } + + return true; + } + + @Override + public boolean handleFault(SOAPMessageContext context) { + return false; + } + + @Override + public void close(MessageContext context) { + + } +} diff --git a/src/main/java/com/kms/service/PaymentHistoryService.java b/src/main/java/com/kms/service/PaymentHistoryService.java index b29db99e5aa23c9586618e0e2e15ed6788a6f180..54c79cdb0d64ef765e5de07565fe5da6c29a81f6 100644 --- a/src/main/java/com/kms/service/PaymentHistoryService.java +++ b/src/main/java/com/kms/service/PaymentHistoryService.java @@ -2,25 +2,32 @@ package com.kms.service; import com.j256.ormlite.dao.Dao; import com.kms.dto.EmailReq; -import com.kms.dto.PaymentHistoryResp; +import com.kms.dto.payment.PaymentHistoryResp; import com.kms.model.Payment; +import com.kms.service.helper.PaymentHistoryCacheHelper; +import com.kms.util.PdfUtil; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import freemarker.template.TemplateExceptionHandler; import lombok.RequiredArgsConstructor; +import javax.annotation.Resource; import javax.jws.HandlerChain; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebService; +import javax.xml.ws.WebServiceContext; +import javax.xml.ws.handler.MessageContext; import java.io.IOException; import java.io.StringWriter; import java.sql.SQLException; +import java.sql.Timestamp; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; @WebService @@ -28,6 +35,9 @@ import java.util.stream.Collectors; @HandlerChain(file = "handlers.xml") public class PaymentHistoryService { + @Resource + private WebServiceContext context; + private final Dao<Payment,Integer> paymentDao; private static final Configuration cfg = new Configuration(Configuration.VERSION_2_3_30); @@ -38,10 +48,24 @@ public class PaymentHistoryService { cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); } + @WebMethod public List<PaymentHistoryResp> getPaymentHistory(@WebParam(name = "initiatorId") String initiatorId, @WebParam(name = "sendMail") boolean sendMail, @WebParam(name = "mailData") EmailReq emailReq) { + MessageContext messageContext = context.getMessageContext(); + + String cacheKey = PaymentHistoryCacheHelper.checkForHistoryCacheAvailability(initiatorId); + if (!cacheKey.isEmpty()) { + messageContext.put("returnFromCache", true); + messageContext.put("cacheKey", cacheKey); + + if (sendMail && emailReq != null) + EmailService.send(emailReq.getRecipient(), emailReq.getCc(), + "Cache: KMS Payment History", "sda"); + return null; + } + try { Payment filter = Payment.builder() .initiatorId(initiatorId) @@ -50,21 +74,35 @@ public class PaymentHistoryService { List<Payment> payments = paymentDao.queryForMatching(filter); if (sendMail && emailReq != null) { - EmailService.send(emailReq.getRecipient(), emailReq.getCc(), - "KMS Payment History", formHistoryMailBody(payments)); + String html = constructHistoryHtml(payments); + EmailService.send(emailReq.getRecipient(), emailReq.getCc(), + "KMS Payment History", html); } + cacheKey = PaymentHistoryCacheHelper.formHistoryCacheKey(initiatorId); + messageContext.put("cacheResponse", true); + messageContext.put("cacheKey", cacheKey); + return payments.stream() - .map(el -> new PaymentHistoryResp(el.getPaymentInitTime().toString(), el.getPaymentPaidTime().toString(), - el.getAmount(), el.getDescription())) + .filter(el -> !(el.getPaymentInitTime() == null || el.getPaymentPaidTime() == null)) + .map(el -> { + String initTime = Optional.of(el.getPaymentInitTime()) + .orElseGet(() -> new Timestamp(0)) + .toString(), + paidTime = Optional.of(el.getPaymentPaidTime()) + .orElseGet(() -> new Timestamp(0)) + .toString(); + + return new PaymentHistoryResp(initTime, paidTime, el.getAmount(), el.getDescription()); + }) .collect(Collectors.toList()); } catch (SQLException | TemplateException | IOException e) { - throw new RuntimeException(e); + return null; } } - private String formHistoryMailBody(List<Payment> payments) throws IOException, TemplateException { + private String constructHistoryHtml(List<Payment> payments) throws IOException, TemplateException { Template template = cfg.getTemplate("history.ftl"); Map<String, Object> dataModel = new HashMap<>(); dataModel.put("payments", payments); diff --git a/src/main/java/com/kms/service/helper/PaymentHistoryCacheHelper.java b/src/main/java/com/kms/service/helper/PaymentHistoryCacheHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..f58013a74f4a6b38bf222cc9cdc759f2c8546479 --- /dev/null +++ b/src/main/java/com/kms/service/helper/PaymentHistoryCacheHelper.java @@ -0,0 +1,35 @@ +package com.kms.service.helper; + +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; + +public class PaymentHistoryCacheHelper { + + private static final JedisPool jedisPool = new JedisPool("localhost", 6379); + + /** + * + * @param initiatorId initiator id for cache key + * @return cache key, empty if cache is not available + */ + public static String checkForHistoryCacheAvailability(String initiatorId) { + String cacheKey = formHistoryCacheKey(initiatorId); + try (Jedis jedis = jedisPool.getResource()) { + boolean keyExists = jedis.exists(cacheKey); + if (!keyExists) + return ""; + + long ttlSeconds = jedis.ttl(cacheKey); + if (ttlSeconds < 3) { + jedis.expire(cacheKey, 3); + } + return cacheKey; + } + } + + public static String formHistoryCacheKey(String initiatorId) { + System.out.println("CACHE KEY: " + "payment-history:"+initiatorId); + return "payment-history:"+initiatorId; + } + +}