Skip to content

Commit

Permalink
Merge pull request #18 from rajumb0232/implementing/caching
Browse files Browse the repository at this point in the history
Replaced Guava from EhCache for Caching
  • Loading branch information
rajumb0232 authored Nov 6, 2024
2 parents caffff9 + 92d5522 commit c4c7d3a
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 77 deletions.
13 changes: 10 additions & 3 deletions E-Stores-API/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,16 @@

<!-- CACHE PROVIDER DEPENDENCIES -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.2-jre</version>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
</dependency>

<!-- API DOCUMENTATION LIBRARY -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.devb.estores.cache;

import com.devb.estores.model.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;

@Configuration
public class CacheBeanConfig {

private <K, V> CacheConfigurer<K, V> configure(String cacheName, Class<K> keyType, Class<V> valueType, int heap, int offHeap, Duration ttl) {
return CacheConfigurer.<K, V>builder()
.cacheName(cacheName)
.keyType(keyType)
.valueType(valueType)
.heap(heap)
.offHeap(offHeap)
.ttl(ttl)
.build();
}

@Bean
CacheConfigurer<String, Integer> OtpCache() {
return this.configure(CacheName.OTP_CACHE, String.class, Integer.class, 10000, 1, Duration.ofMinutes(5));
}

@Bean
CacheConfigurer<String, User> userCache() {
return this.configure(CacheName.USER_CACHE, String.class, User.class, 20000, 10, Duration.ofDays(1));
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.devb.estores.cache;

import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.ExpiryPolicyBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.jsr107.Eh107Configuration;

import javax.cache.configuration.Configuration;
import java.time.Duration;

@Getter
@Builder
@Slf4j
public class CacheConfigurer<K, V> {
private String cacheName;
private Class<K> keyType;
private Class<V> valueType;
private int heap;
private int offHeap;
private Duration ttl;

public Configuration<K, V> getEhCacheConfiguration() {
log.info("Configuring Cache with name: {}, heap: {}, offHeap: {}, TTL: {}", this.cacheName, this.heap, this.offHeap, this.ttl.toMinutes() + " Minutes");
ResourcePoolsBuilder resourcePoolsBuilder = ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(this.heap, EntryUnit.ENTRIES).offheap(this.offHeap > 0 ? this.offHeap : 10, MemoryUnit.MB);

CacheConfiguration<K, V> cacheConfiguration = CacheConfigurationBuilder
.newCacheConfigurationBuilder(
this.keyType,
this.valueType,
resourcePoolsBuilder)
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(this.ttl))
.build();

return Eh107Configuration.fromEhcacheCacheConfiguration(cacheConfiguration);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.devb.estores.cache;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.spi.CachingProvider;
import java.util.List;

@Configuration
@EnableCaching
@Slf4j
public class CacheInitializer {

@Bean
JCacheCacheManager cacheManager(List<CacheConfigurer<?,?>> cacheConfigurers) {
log.info("Configuring CacheManger, {} cache configurations found", cacheConfigurers.size());
CachingProvider provider = Caching.getCachingProvider();
CacheManager manager = provider.getCacheManager();

cacheConfigurers.forEach(cacheConfigurer -> {
manager.createCache(cacheConfigurer.getCacheName(), cacheConfigurer.getEhCacheConfiguration());
});

return new JCacheCacheManager(manager);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.devb.estores.cache;

public class CacheName {
public static final String OTP_CACHE = "otp-cache";
public static final String USER_CACHE = "user-cache";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.devb.estores.cache;

import lombok.AllArgsConstructor;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;

@Service
@AllArgsConstructor
public class CacheService {

private final CacheManager cacheManager;

public <K, V> boolean doEntry(String cacheName, K key, V value) {
Cache cache = cacheManager.getCache(cacheName);
if(cache != null) {
cache.put(key, value);
return true;
} else return false;
}

public <K, V> V getEntry(String cacheName, K key, Class<V> type) {
Cache cache = cacheManager.getCache(cacheName);
if(cache != null)
return cache.get(key, type);
else return null;
}

public <K> boolean evictEntry(String cacheName, K key) {
Cache cache = cacheManager.getCache(cacheName);
if(cache != null) {
cache.evict(key);
return true;
} else return false;
}

public boolean clearCache(String cacheName) {
Cache cache = cacheManager.getCache(cacheName);
if (cache != null) {
cache.clear();
return true;
}
return false;
}
}
31 changes: 0 additions & 31 deletions E-Stores-API/src/main/java/com/devb/estores/cache/CacheStore.java

This file was deleted.

3 changes: 2 additions & 1 deletion E-Stores-API/src/main/java/com/devb/estores/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import lombok.*;
import org.hibernate.annotations.GenericGenerator;

import java.io.Serializable;
import java.util.List;

@Entity
Expand All @@ -17,7 +18,7 @@
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
public class User implements Serializable {
@Id
@GeneratedValue(generator = "custom")
@GenericGenerator(name = "custom", type = IdGenerator.class)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.devb.estores.serviceimpl;

import com.devb.estores.cache.CacheStore;
import com.devb.estores.cache.CacheName;
import com.devb.estores.cache.CacheService;
import com.devb.estores.config.AppEnv;
import com.devb.estores.dto.MessageData;
import com.devb.estores.dto.OtpModel;
Expand Down Expand Up @@ -41,13 +42,12 @@ public class AuthServiceImpl implements AuthService {
private final UserRepo userRepo;
private final PasswordEncoder passwordEncoder;
private final MailService mailService;
private final CacheStore<OtpModel> otpCache;
private final CacheStore<User> userCacheStore;
private final JwtService jwtService;
private final AuthenticationManager authenticationManager;
private final CookieManager cookieManager;
private final Random random;
private final AppEnv appEnv;
private final CacheService cacheService;

public static final String FAILED_REFRESH = "Failed to refresh login";
public static final String FAILED_OTP_VERIFICATION = "Failed to verify OTP";
Expand All @@ -61,16 +61,14 @@ public String registerUser(UserRequest userRequest, UserRole role) {
User user = mapToUserEntity(userRequest, role);

// caching user data
userCacheStore.add(user.getEmail(), user);
cacheService.doEntry(CacheName.USER_CACHE, user.getEmail(), user);

// Generate the OTP and provide the ID of the OTP as a path variable to the confirmation link.
OtpModel otp = OtpModel.builder()
.otp(random.nextInt(100000, 999999))
.email(user.getEmail()).build();
otpCache.add(otp.getEmail(), otp);
// Generating OTP and caching to otp-cache
int otp = random.nextInt(100000, 999999);
cacheService.doEntry(CacheName.OTP_CACHE, user.getEmail(), otp);

try {
sendOTPToMailId(user, otp.getOtp());
sendOTPToMailId(user, otp);
return "Verify Email using the OTP sent to " + user.getEmail();
} catch (MessagingException e) {
throw new EmailNotFoundException("Failed to verify the email ID");
Expand All @@ -79,17 +77,19 @@ public String registerUser(UserRequest userRequest, UserRole role) {

@Override
public UserResponse verifyUserEmail(OtpModel otpModel) {
OtpModel otp = otpCache.get(otpModel.getEmail());
User user = userCacheStore.get(otpModel.getEmail());
Integer otp = cacheService.getEntry(CacheName.OTP_CACHE, otpModel.getEmail(), Integer.class);
User user = cacheService.getEntry(CacheName.USER_CACHE, otpModel.getEmail(), User.class);

if (otp == null) throw new OtpExpiredException(FAILED_OTP_VERIFICATION);
if (user == null) throw new RegistrationSessionExpiredException(FAILED_OTP_VERIFICATION);
if (otp.getOtp() != otpModel.getOtp()) throw new IncorrectOTPException(FAILED_OTP_VERIFICATION);
if (otp != otpModel.getOtp()) throw new IncorrectOTPException(FAILED_OTP_VERIFICATION);

user.setEmailVerified(true);
user = userRepo.save(user);

otpCache.remove(otpModel.getEmail());
cacheService.evictEntry(CacheName.USER_CACHE, user.getEmail());
cacheService.evictEntry(CacheName.OTP_CACHE, user.getEmail());

try {
sendConfirmationMail(user);
return mapToUserResponse(user);
Expand Down

0 comments on commit c4c7d3a

Please sign in to comment.