updated code
This commit is contained in:
@@ -1,116 +0,0 @@
|
||||
package com.billpaymentservice.bbps.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import com.billpaymentservice.bbps.util.BBPSConstant;
|
||||
import com.billpaymentservice.bbps.dto.ResponseModel;
|
||||
|
||||
import io.github.resilience4j.ratelimiter.RateLimiter;
|
||||
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@Component
|
||||
@Order(1)
|
||||
public class RateLimitingFilter extends OncePerRequestFilter {
|
||||
|
||||
private final RateLimiterRegistry rateLimiterRegistry;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RateLimitingFilter.class);
|
||||
|
||||
// Har MID ke liye alag limiter
|
||||
private final Map<String, RateLimiter> limiterCache = new ConcurrentHashMap<>();
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
public RateLimitingFilter(RateLimiterRegistry rateLimiterRegistry) {
|
||||
this.rateLimiterRegistry = rateLimiterRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
String mid = request.getHeader("mid");
|
||||
if(mid == null) {
|
||||
mid = "GLOBAL";
|
||||
}
|
||||
|
||||
// Validate MID
|
||||
if (mid == null || mid.isBlank()) {
|
||||
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
|
||||
response.setContentType("application/json");
|
||||
|
||||
ResponseModel<Object> apiResponse = new ResponseModel<>("mid cannot be null or blank", "FAILURE", HttpServletResponse.SC_BAD_REQUEST, null);
|
||||
response.getWriter().write(OBJECT_MAPPER.writeValueAsString(apiResponse));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
RateLimiter rateLimiter = limiterCache.computeIfAbsent(
|
||||
mid,
|
||||
key -> rateLimiterRegistry.rateLimiter("default")
|
||||
);
|
||||
|
||||
// Rate limit check
|
||||
if (!rateLimiter.acquirePermission()) {
|
||||
|
||||
// Prefer existing constant if it maps to 429, otherwise fallback to literal 429
|
||||
int tooManyRequestsStatus =429;
|
||||
|
||||
response.setStatus(tooManyRequestsStatus);
|
||||
response.setContentType("application/json");
|
||||
|
||||
ResponseModel<Object> apiResponse = new ResponseModel<>("Rate limit exceeded for MID: " + mid, "FAILURE", tooManyRequestsStatus, null);
|
||||
response.getWriter().write(OBJECT_MAPPER.writeValueAsString(apiResponse));
|
||||
return;
|
||||
}
|
||||
|
||||
// Proceed with the chain and catch downstream exceptions to return consistent model
|
||||
try {
|
||||
filterChain.doFilter(request, response);
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("Unhandled exception in filter chain for MID: {}", mid, ex);
|
||||
if (!response.isCommitted()) {
|
||||
response.reset();
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
response.setContentType("application/json");
|
||||
ResponseModel<Object> apiResponse = new ResponseModel<>("Internal server error", "FAILURE", HttpServletResponse.SC_INTERNAL_SERVER_ERROR, null);
|
||||
response.getWriter().write(OBJECT_MAPPER.writeValueAsString(apiResponse));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Error while rate limiting request", e);
|
||||
if (!response.isCommitted()) {
|
||||
response.reset();
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
response.setContentType("application/json");
|
||||
ResponseModel<Object> apiResponse = new ResponseModel<>("Internal server error", "FAILURE", HttpServletResponse.SC_INTERNAL_SERVER_ERROR, null);
|
||||
response.getWriter().write(OBJECT_MAPPER.writeValueAsString(apiResponse));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldNotFilter(HttpServletRequest request) {
|
||||
|
||||
String path = request.getRequestURI();
|
||||
|
||||
return path.startsWith("/swagger")
|
||||
|| path.startsWith("/v3/api-docs")
|
||||
|| path.startsWith("/actuator");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.billpaymentservice.bbps.entites;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
@@ -9,33 +10,34 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* Base mapped superclass for audit fields. All JPA entities should extend this to
|
||||
* get automatic population of createdAt/updatedAt/isDeleted via AuditListener.
|
||||
* Base mapped superclass for audit fields. All JPA entities should extend this
|
||||
* to get automatic population of createdAt/updatedAt/isDeleted via
|
||||
* AuditListener.
|
||||
*/
|
||||
@MappedSuperclass
|
||||
@EntityListeners(AuditListener.class)
|
||||
@Getter
|
||||
@Setter
|
||||
public abstract class Auditable {
|
||||
@Column(name = "create_date_time")
|
||||
private LocalDateTime createDateTime;
|
||||
public abstract class Auditable implements Serializable {
|
||||
@Column(name = "create_date_time")
|
||||
private Date createDateTime;
|
||||
|
||||
@Column(name = "updated_date_time")
|
||||
private LocalDateTime updatedDateTime;
|
||||
@Column(name = "updated_date_time")
|
||||
private Date updatedDateTime;
|
||||
|
||||
@Column(name = "create_by")
|
||||
private LocalDateTime createdBy;
|
||||
@Column(name = "create_by")
|
||||
private String createdBy;
|
||||
|
||||
@Column(name = "updated_by")
|
||||
private LocalDateTime updatedBy;
|
||||
@Column(name = "updated_by")
|
||||
private String updatedBy;
|
||||
|
||||
@Column(name = "created_epoch_date")
|
||||
private Long createdEpochDate;
|
||||
@Column(name = "created_epoch_date")
|
||||
private Long createdEpochDate;
|
||||
|
||||
@Column(name = "modified_epoch_date")
|
||||
private Long modifiedEpochDate;
|
||||
@Column(name = "modified_epoch_date")
|
||||
private Long modifiedEpochDate;
|
||||
|
||||
@Column(name = "is_deleted")
|
||||
private Boolean isDeleted = Boolean.FALSE;
|
||||
|
||||
@Column(name = "is_deleted")
|
||||
private Boolean isDeleted = Boolean.FALSE;
|
||||
|
||||
}
|
||||
@@ -77,6 +77,9 @@ public class ComplaintResponseEntity extends Auditable {
|
||||
@Column(name = "user_id")
|
||||
private String userId;
|
||||
|
||||
@Column(name = "mid")
|
||||
private String mid;
|
||||
|
||||
@OneToMany(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "ticket_id", referencedColumnName = "ticket_id", insertable = false, updatable = false)
|
||||
private Set<ComplainStatus> complaintStatusList = new HashSet<>();
|
||||
|
||||
@@ -197,7 +197,7 @@ public class ComplainServiceImpl implements ComplainService {
|
||||
ComplaintResponse responseWrapper = objectMapper.convertValue(dataMap, ComplaintResponse.class);
|
||||
|
||||
String saveComplaintResponseEntity = mapperHelper.saveComplaintResponseEntity(responseWrapper, requestId,
|
||||
txnId, userId, requestTxnId);
|
||||
txnId, userId, requestTxnId, mid);
|
||||
LOGGER.info("Save Complaint Response Count" + saveComplaintResponseEntity);
|
||||
ResponseModel responseModel = new ResponseModel(responseWrapper.getMessage(), responseWrapper.getStatus(),
|
||||
Integer.parseInt(responseWrapper.getStatusCode()), responseWrapper);
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -528,6 +529,7 @@ public class BillerMapperHelper {
|
||||
entity.setNpciTicketStatus(dto.getNpciTicketStatus());
|
||||
entity.setCreatedTime(dto.getCreatedTime());
|
||||
entity.setUserId(userId);
|
||||
entity.setCreateDateTime(new Date());
|
||||
|
||||
try {
|
||||
ComplainStatus saved = complaintStatusRepository.save(entity);
|
||||
@@ -558,7 +560,7 @@ public class BillerMapperHelper {
|
||||
entity.setReqId(reqId);
|
||||
entity.setTxnId(txnId);
|
||||
entity.setUserId(userId);
|
||||
|
||||
entity.setCreateDateTime(new Date());
|
||||
complaintHistoryRepository.save(entity);
|
||||
savedCount++;
|
||||
}
|
||||
@@ -673,6 +675,7 @@ public class BillerMapperHelper {
|
||||
entity.setPage(String.valueOf(responseWrapper.getPage()));
|
||||
entity.setPageSize(String.valueOf(responseWrapper.getPageSize()));
|
||||
entity.setUserId(userId);
|
||||
entity.setCreateDateTime(new Date());
|
||||
|
||||
}
|
||||
|
||||
@@ -852,6 +855,7 @@ public class BillerMapperHelper {
|
||||
entity.setTotalPages(String.valueOf(responseWrapper.getTotalPages()));
|
||||
entity.setTotalElements(String.valueOf(responseWrapper.getTotalElements()));
|
||||
entity.setUserId(userId);
|
||||
entity.setCreateDateTime(new Date());
|
||||
|
||||
}
|
||||
|
||||
@@ -962,9 +966,9 @@ public class BillerMapperHelper {
|
||||
LocalDateTime bmCreatedOn = parseToLocalDateTime(responseWrapper.getCreationDate());
|
||||
|
||||
LocalDateTime bmUpdatedOn = parseToLocalDateTime(responseWrapper.getModifiedDate());
|
||||
if (bmUpdatedOn != null) {
|
||||
billMaster.setUpdatedDateTime(bmUpdatedOn);
|
||||
}
|
||||
// if (bmUpdatedOn != null) {
|
||||
// billMaster.setUpdatedDateTime(bmUpdatedOn);
|
||||
// }
|
||||
billMaster.setCreatedEpochDate(responseWrapper.getCreatedEpochDate());
|
||||
billMaster.setModifiedEpochDate(responseWrapper.getModifiedEpochDate());
|
||||
|
||||
@@ -1091,21 +1095,27 @@ public class BillerMapperHelper {
|
||||
record.setClientUserId(request.getClientUserId());
|
||||
record.setInternalTxnId(txnId);
|
||||
|
||||
if (apiResponse != null &&
|
||||
apiResponse.getResponseData() != null) {
|
||||
record.setAmount(Optional.ofNullable(apiResponse.getResponseData().getAmount(
|
||||
)).orElse("0.00"));
|
||||
|
||||
record.setTxnId(Optional.ofNullable(apiResponse.getResponseData().getTxnId())
|
||||
.orElse("DUMMY_TXN"));
|
||||
record.setQrString(Optional.ofNullable(apiResponse.getResponseData().
|
||||
getQrString()).orElse("NO_QR")); // parse createdOn string into LocalDateTime and set on Auditable
|
||||
LocalDateTime createdOn =parseToLocalDateTime(apiResponse.getResponseData().getCreatedOn());
|
||||
|
||||
record.setTxnStatus("PENDING"); } else { record.setAmount("0.00");
|
||||
record.setTxnStatus("PENDING"); }
|
||||
|
||||
|
||||
if (apiResponse != null && apiResponse.getResponseData() != null) {
|
||||
record.setAmount(Optional.ofNullable(apiResponse.getResponseData().getAmount()).orElse("0.00"));
|
||||
|
||||
record.setTxnId(Optional.ofNullable(apiResponse.getResponseData().getTxnId()).orElse("DUMMY_TXN"));
|
||||
record.setQrString(Optional.ofNullable(apiResponse.getResponseData().getQrString()).orElse("NO_QR")); // parse
|
||||
// createdOn
|
||||
// string
|
||||
// into
|
||||
// LocalDateTime
|
||||
// and
|
||||
// set
|
||||
// on
|
||||
// Auditable
|
||||
LocalDateTime createdOn = parseToLocalDateTime(apiResponse.getResponseData().getCreatedOn());
|
||||
|
||||
record.setTxnStatus("PENDING");
|
||||
} else {
|
||||
record.setAmount("0.00");
|
||||
record.setTxnStatus("PENDING");
|
||||
}
|
||||
|
||||
// store the original request body and raw response
|
||||
record.setRequestBody(requestJson);
|
||||
record.setResponseBody(rawResponse);
|
||||
@@ -1151,7 +1161,7 @@ public class BillerMapperHelper {
|
||||
|
||||
// Persist complaint response entity
|
||||
public String saveComplaintResponseEntity(ComplaintResponse responseWrapper, String requestId, String txnId,
|
||||
String userId, String requestTxnId) {
|
||||
String userId, String requestTxnId, String mid) {
|
||||
if (responseWrapper == null || responseWrapper.getTicketDetails() == null) {
|
||||
return "No data";
|
||||
}
|
||||
@@ -1164,6 +1174,8 @@ public class BillerMapperHelper {
|
||||
complaintResponseEntity.setTicketDesp(responseWrapper.getTicketDetails().getTicketDesp());
|
||||
complaintResponseEntity.setTicketDesr(responseWrapper.getTicketDetails().getTicketDesr());
|
||||
complaintResponseEntity.setRequestTxnId(requestTxnId);
|
||||
complaintResponseEntity.setMid(mid);
|
||||
complaintResponseEntity.setCreateDateTime(new Date());
|
||||
|
||||
complaintResponseEntity.setMessage(responseWrapper.getMessage());
|
||||
complaintResponseEntity.setRemarks(responseWrapper.getRemarks());
|
||||
@@ -1273,7 +1285,7 @@ public class BillerMapperHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public ComplaintResponseDto toDto(ComplaintResponseEntity e) {
|
||||
public ComplaintResponseDto toDto(ComplaintResponseEntity e) {
|
||||
|
||||
ComplaintResponseDto dto = new ComplaintResponseDto();
|
||||
dto.setTicketId(e.getTicketId());
|
||||
|
||||
Reference in New Issue
Block a user