Skip to content

Commit

Permalink
Feat : Implemented Virtual thread in backend
Browse files Browse the repository at this point in the history
  • Loading branch information
HarshitPachori committed Aug 3, 2024
1 parent 6ae2c4e commit 711f0b4
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 98 deletions.
25 changes: 23 additions & 2 deletions storypath_backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<url/>
</scm>
<properties>
<java.version>17</java.version>
<java.version>21</java.version>
</properties>
<dependencies>

Expand Down Expand Up @@ -100,6 +100,19 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>3.1.8</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>



<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Expand Down Expand Up @@ -128,7 +141,15 @@
</excludes>
</configuration>
</plugin>
</plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class StorypathBackendApplication {

public static void main(String[] args) {
SpringApplication.run(StorypathBackendApplication.class, args);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
package com.example.storypath_backend.config;

//@Configuration
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

@Configuration
public class CaffeineCacheConfig {
// @Bean
// public CaffeineCacheManager cacheManager() {
// CaffeineCacheManager cacheManager = new CaffeineCacheManager("users",
// "journals");
// cacheManager.setCaffeine(caffeineCacheBuilder());
// return cacheManager;
// }
//
// Caffeine<Object, Object> caffeineCacheBuilder() {
// return Caffeine.newBuilder()
// .expireAfterAccess(60, TimeUnit.MINUTES)
// .maximumSize(500);
// }
@Bean
public CaffeineCacheManager cacheManager() {
CaffeineCacheManager cacheManager = new CaffeineCacheManager("users",
"journals");
cacheManager.setCaffeine(caffeineCacheBuilder());
return cacheManager;
}

Caffeine<Object, Object> caffeineCacheBuilder() {
return Caffeine.newBuilder()
.expireAfterAccess(60, TimeUnit.MINUTES)
.maximumSize(500);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
import com.example.storypath_backend.service.UserService;
import lombok.RequiredArgsConstructor;
import org.bson.types.ObjectId;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand All @@ -21,9 +25,10 @@
public class UserController {
private final UserService userService;

@Cacheable(cacheNames = "users",key = "#principal.getName()")
@GetMapping("/profile")
public ResponseEntity<Map<String, Object>> getProfile(@RequestHeader(HttpHeaders.AUTHORIZATION) String jwtToken) {
UserDto userProfile = userService.getProfile(jwtToken);
public ResponseEntity<Map<String, Object>> getProfile(Principal principal) {
UserDto userProfile = userService.getProfile(principal.getName());
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("message", "Profile fetched successfully");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.List;

public interface UserService {
UserDto getProfile(String jwtToken);
UserDto getProfile(String username);

UserDto updateProfile(String jwtToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.example.storypath_backend.model.User;
import com.example.storypath_backend.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.bson.types.ObjectId;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

Expand All @@ -22,81 +23,89 @@
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
private final JournalEntryRepository journalEntryRepository;
private final JwtTokenHelper tokenHelper;
private final UserRepository userRepository;
private final JournalEntryRepository journalEntryRepository;
private final JwtTokenHelper tokenHelper;

@Override
public UserDto getProfile(String token) {
User userProfile = getUserFromJwtToken(token);
return UserDto.builder()
.id(userProfile.getId())
.email(userProfile.getEmail())
.name(userProfile.getUsername())
.wantsSentimentAnalysis(true)
.roles(userProfile.getRoles())
.build();
}

@Override
public UserDto updateProfile(String jwtToken) {
User user = getUserFromJwtToken(jwtToken);
user.setWantsSentimentAnalysis(!user.isWantsSentimentAnalysis());
User userProfile = userRepository.save(user);
return UserDto.builder()
.id(userProfile.getId())
.email(userProfile.getEmail())
.name(userProfile.getUsername())
.wantsSentimentAnalysis(!userProfile.isWantsSentimentAnalysis())
.roles(userProfile.getRoles())
.build();
}

public User getUserFromJwtToken(String jwtToken) {
String username = tokenHelper.getUsernameFromToken(jwtToken);
log.info("Fetching user profile from email: {}", username);
return userRepository.findByEmail(username)
.orElseThrow(() -> new ApiException(HttpStatus.NOT_FOUND, "User not found with email " + username));
}
@Override
public UserDto getProfile(String username) {
log.info("getting user from userrepo");
User userProfile = userRepository.findByEmail(username)
.orElseThrow(() -> new ApiException(HttpStatus.NOT_FOUND,
"user not found with this email"));
return UserDto.builder()
.id(userProfile.getId())
.email(userProfile.getEmail())
.name(userProfile.getUsername())
.wantsSentimentAnalysis(true)
.roles(userProfile.getRoles())
.build();
}

@Override
public List<User> getUserForSentimentAnalysis() {
return userRepository.findByWantsSentimentAnalysisTrue();
}
@Override
public UserDto updateProfile(String jwtToken) {
User user = getUserFromJwtToken(jwtToken);
user.setWantsSentimentAnalysis(!user.isWantsSentimentAnalysis());
User userProfile = userRepository.save(user);
return UserDto.builder()
.id(userProfile.getId())
.email(userProfile.getEmail())
.name(userProfile.getUsername())
.wantsSentimentAnalysis(!userProfile.isWantsSentimentAnalysis())
.roles(userProfile.getRoles())
.build();
}

@Override
public List<JournalEntryResponse> getAllJournalEntriesOfUser(String jwtToken) {
User user = getUserFromJwtToken(jwtToken);
return user.getJournalEntries().stream()
.map(journalEntry -> JournalEntryResponse.builder()
.id(journalEntry.getId())
.title(journalEntry.getTitle())
.content(journalEntry.getContent())
.date(journalEntry.getDate())
.tags(journalEntry.getTags())
.build())
.toList();
}
public User getUserFromJwtToken(String jwtToken) {
String username = tokenHelper.getUsernameFromToken(jwtToken);
log.info("Fetching user profile from email: {}", username);
return userRepository.findByEmail(username)
.orElseThrow(() -> new ApiException(HttpStatus.NOT_FOUND,
"User not found with email " + username));
}

@Override
public JournalEntryResponse updateJournalEntryOfUser(String jwtToken, ObjectId journalId,
JournalEntryRequest request) {
User user = getUserFromJwtToken(jwtToken);
JournalEntry journalByUser = journalEntryRepository.findByUserIdAndId(user.getId(), journalId);
journalByUser.setTitle(
request.title() != null && !request.title().isEmpty() ? request.title() : journalByUser.getTitle());
journalByUser.setContent(request.content() != null && !request.content().isEmpty() ? request.content()
: journalByUser.getContent());
journalByUser.setTags(
request.tags() != null && !request.tags().isEmpty() ? request.tags() : journalByUser.getTags());
JournalEntry savedJournalEntry = journalEntryRepository.save(journalByUser);
return JournalEntryResponse.builder()
.id(savedJournalEntry.getId())
.title(savedJournalEntry.getTitle())
.content(savedJournalEntry.getContent())
.tags(savedJournalEntry.getTags())
.date(savedJournalEntry.getDate())
.build();
}
@Override
public List<User> getUserForSentimentAnalysis() {
return userRepository.findByWantsSentimentAnalysisTrue();
}

@Override
public List<JournalEntryResponse> getAllJournalEntriesOfUser(String jwtToken) {
User user = getUserFromJwtToken(jwtToken);
return user.getJournalEntries().stream()
.map(journalEntry -> JournalEntryResponse.builder()
.id(journalEntry.getId())
.title(journalEntry.getTitle())
.content(journalEntry.getContent())
.date(journalEntry.getDate())
.tags(journalEntry.getTags())
.build())
.toList();
}

@Override
public JournalEntryResponse updateJournalEntryOfUser(String jwtToken, ObjectId journalId,
JournalEntryRequest request) {
User user = getUserFromJwtToken(jwtToken);
JournalEntry journalByUser = journalEntryRepository.findByUserIdAndId(user.getId(), journalId);
journalByUser.setTitle(
request.title() != null && !request.title().isEmpty() ? request.title()
: journalByUser.getTitle());
journalByUser.setContent(request.content() != null && !request.content().isEmpty() ? request.content()
: journalByUser.getContent());
journalByUser.setTags(
request.tags() != null && !request.tags().isEmpty() ? request.tags()
: journalByUser.getTags());
JournalEntry savedJournalEntry = journalEntryRepository.save(journalByUser);
return JournalEntryResponse.builder()
.id(savedJournalEntry.getId())
.title(savedJournalEntry.getTitle())
.content(savedJournalEntry.getContent())
.tags(savedJournalEntry.getTags())
.date(savedJournalEntry.getDate())
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

Expand All @@ -21,7 +22,7 @@
public class JwtTokenHelper {

public String getUsernameFromToken(String token) {
log.info("fetching username from token {}", token);
// log.info("fetching username from token {}", token);
if (token.startsWith("Bearer ")) {
token = token.substring(7);
}
Expand Down
15 changes: 8 additions & 7 deletions storypath_backend/src/main/resources/application-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ spring:
auth: true
starttls:
enable: true
# cache:
# type: caffeine
# cache-names:
# - users
# - journals
# caffeine:
# spec: maximumSize=500, expireAfterAccess=60m
cache:
type: caffeine
cache-names:
- users
- journals
caffeine:
spec: maximumSize=500, expireAfterAccess=60m

0 comments on commit 711f0b4

Please sign in to comment.