Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .gradle/8.8/checksums/checksums.lock
Binary file not shown.
Binary file removed .gradle/8.8/checksums/md5-checksums.bin
Binary file not shown.
Binary file removed .gradle/8.8/checksums/sha1-checksums.bin
Binary file not shown.
Empty file.
Binary file removed .gradle/8.8/fileChanges/last-build.bin
Binary file not shown.
Binary file removed .gradle/8.8/fileHashes/fileHashes.bin
Binary file not shown.
Binary file removed .gradle/8.8/fileHashes/fileHashes.lock
Binary file not shown.
Empty file removed .gradle/8.8/gc.properties
Empty file.
Binary file removed .gradle/8.9/checksums/checksums.lock
Binary file not shown.
Binary file removed .gradle/8.9/checksums/sha1-checksums.bin
Binary file not shown.
Empty file.
Binary file removed .gradle/8.9/executionHistory/executionHistory.lock
Binary file not shown.
Binary file removed .gradle/8.9/fileChanges/last-build.bin
Binary file not shown.
Binary file removed .gradle/8.9/fileHashes/fileHashes.lock
Binary file not shown.
Empty file removed .gradle/8.9/gc.properties
Empty file.
2 changes: 0 additions & 2 deletions .gradle/buildOutputCleanup/cache.properties

This file was deleted.

Empty file removed .gradle/vcs-1/gc.properties
Empty file.
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
package app.sportahub.eventservice.config.kafka;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.kafka.core.ProducerFactory;
import org.springframework.kafka.listener.ContainerProperties;
import org.springframework.kafka.listener.KafkaMessageListenerContainer;
import org.springframework.kafka.requestreply.ReplyingKafkaTemplate;
import org.springframework.kafka.support.serializer.JsonSerializer;

import java.util.HashMap;
import java.util.Map;
import app.sportahub.kafka.events.user.UserEvent;

@EnableKafka
@Configuration
Expand All @@ -31,7 +38,25 @@ public ProducerFactory<String, Object> producerFactory() {
}

@Bean
public KafkaTemplate<String, Object> kafkaTemplate(ProducerFactory<String, Object> producerFactory) {
return new KafkaTemplate<>(producerFactory);
public KafkaTemplate<String, Object> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}

@Bean
public ReplyingKafkaTemplate<String, Object, Object> replyingKafkaTemplate(
ProducerFactory<String, Object> producerFactory,
KafkaMessageListenerContainer<String, Object> replyContainer) {
ReplyingKafkaTemplate<String, Object, Object> template = new ReplyingKafkaTemplate<>(producerFactory,
replyContainer);
template.setDefaultReplyTimeout(Duration.ofSeconds(6));
return template;
}

@Bean
public KafkaMessageListenerContainer<String, Object> replyContainer(
ConsumerFactory<String, Object> consumerFactory) {
ContainerProperties containerProperties = new ContainerProperties(UserEvent.RESPONSE_TOPIC);
containerProperties.setGroupId("OrchestrationServiceConsumer");
return new KafkaMessageListenerContainer<>(consumerFactory, containerProperties);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
package app.sportahub.eventservice.controller.event;

import app.sportahub.eventservice.dto.request.event.EventRequest;
import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import app.sportahub.eventservice.dto.request.event.WhitelistRequest;
import app.sportahub.eventservice.dto.request.event.EventCancellationRequest;
import app.sportahub.eventservice.dto.request.event.EventRequest;
import app.sportahub.eventservice.dto.response.EventResponse;
import app.sportahub.eventservice.dto.response.ParticipantResponse;
import app.sportahub.eventservice.dto.response.ReactionResponse;
import app.sportahub.eventservice.enums.EventSortingField;
import app.sportahub.eventservice.enums.SortDirection;
import app.sportahub.eventservice.model.event.Location;
import app.sportahub.eventservice.enums.SkillLevelEnum;
import app.sportahub.eventservice.dto.response.ReactionResponse;
import app.sportahub.eventservice.enums.SortDirection;
import app.sportahub.eventservice.model.event.reactor.ReactionType;
import app.sportahub.eventservice.service.event.EventService;
import app.sportahub.eventservice.service.recommendation.RecommendationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;


@RestController
@RequestMapping("/event")
Expand All @@ -35,6 +45,7 @@
public class EventController {

private final EventService eventService;
private final RecommendationService recommendationService;

@GetMapping("/{id}")
@ResponseStatus(HttpStatus.OK)
Expand Down Expand Up @@ -201,4 +212,20 @@ public EventResponse whitelistUsers(@PathVariable String id,
@RequestBody WhitelistRequest whitelistRequest) {
return eventService.whitelistUsers(id, whitelistRequest);
}
}


@GetMapping("/recommendation")
@PreAuthorize("authentication.name == #userId || hasRole('ROLE_ADMIN')")
@ResponseStatus(HttpStatus.OK)
@Operation(summary = "Retrieve events by location",
description = "Fetches events based on the provided location.")
public Page<EventResponse> getEventRecommendations(
@RequestParam String userId,
@RequestParam double longitude,
@RequestParam double latitude,
@RequestParam(defaultValue = "30.0") double radius,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
return recommendationService.getRecommendations(userId, longitude, latitude, radius, page, size);
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package app.sportahub.eventservice.exception;

import java.util.HashMap;
import java.util.Map;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.server.ResponseStatusException;

import java.util.HashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;

@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

@ExceptionHandler(ResponseStatusException.class)
Expand All @@ -18,4 +24,13 @@ public class GlobalExceptionHandler {
response.put("message", ex.getStatusCode().value());
return ResponseEntity.status(ex.getStatusCode()).body(response);
}

@ExceptionHandler(Exception.class)
public ResponseEntity<Map<String, Object>> handleException(Exception ex) {
Map<String, Object> response = new HashMap<>();
response.put("error", "Internal Server Error");
response.put("message", ex.getMessage());
log.error(ex.getMessage(), ex);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package app.sportahub.eventservice.factory;

import java.util.List;

import app.sportahub.eventservice.mapper.user.UserProfileMapper;
import app.sportahub.eventservice.model.event.Event;
import app.sportahub.eventservice.model.user.UserProfile;
import app.sportahub.eventservice.service.kafka.producer.OrchestrationServiceProducer;
import app.sportahub.eventservice.service.recommendation.strategies.HistoryScoreStrategy;
import app.sportahub.eventservice.service.recommendation.strategies.ProfileScoreStrategy;
import app.sportahub.eventservice.service.recommendation.strategies.ScoreStrategy;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ScoringFactory {

private final UserProfileMapper userProfileMapper;
private final OrchestrationServiceProducer orchestrationServiceProducer;

public ScoringFactory(OrchestrationServiceProducer orchestrationServiceProducer) {
this.orchestrationServiceProducer = orchestrationServiceProducer;
this.userProfileMapper = new UserProfileMapper();
}

public ScoreStrategy getScoringStrategy(List<Event> userEventHistory, String userId) {
if (userEventHistory.isEmpty()) {
String userString = orchestrationServiceProducer.getUserById(userId);
UserProfile userProfile = userProfileMapper.userStringToUserProfile(userString);
log.info("ScoringFactory::getScoringStrategy: user retrieved {}", userProfile);
return new ProfileScoreStrategy(userProfile);
} else {
return new HistoryScoreStrategy(userEventHistory);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package app.sportahub.eventservice.mapper.user;

import com.fasterxml.jackson.databind.ObjectMapper;

import app.sportahub.eventservice.model.user.UserProfile;

public class UserProfileMapper {

public UserProfile userStringToUserProfile(String user) {
ObjectMapper objectMapper = new ObjectMapper();
UserProfile userProfile;
try {
userProfile = objectMapper.readValue(user, UserProfile.class);
} catch (Exception e) {
throw new RuntimeException("Error processing JSON for user data");
}
return userProfile;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package app.sportahub.eventservice.model.user;

import java.util.List;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;

import app.sportahub.eventservice.enums.SkillLevelEnum;
import lombok.Data;

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserProfile {

@JsonProperty("profile")
private Profile profile;

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public static class Profile {
@JsonProperty("sportsOfPreference")
private List<SportPreferences> sportsOfPreference;
}

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public static class SportPreferences {
@JsonProperty("name")
private String sport;

@JsonProperty("ranking")
private SkillLevelEnum ranking;

public void setRanking(String ranking) {
try {
this.ranking = SkillLevelEnum.valueOf(ranking.toUpperCase());
} catch (IllegalArgumentException | NullPointerException e) {
this.ranking = SkillLevelEnum.BEGINNER;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package app.sportahub.eventservice.repository.event;

import app.sportahub.eventservice.model.event.Event;
import app.sportahub.eventservice.repository.SearchingEventRepository;
import java.util.List;
import java.util.Optional;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.geo.Distance;
Expand All @@ -10,8 +11,8 @@
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import app.sportahub.eventservice.model.event.Event;
import app.sportahub.eventservice.repository.SearchingEventRepository;

@Repository
public interface EventRepository extends MongoRepository<Event, String>, SearchingEventRepository {
Expand All @@ -23,9 +24,9 @@ public interface EventRepository extends MongoRepository<Event, String>, Searchi
Optional<Event> findEventByEventName(String eventName);

Page<Event> findByParticipantsUserId(String userId, Pageable pageable);

List<Event> findByParticipantsUserId(String userId);

Page<Event> findByCreatedBy(String userId, Pageable pageable);

@Query("{ 'participants.userId' : ?0 }")
List<Event> findAllByParticipantUserId(String userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void handleEventsByUserRequest(

String userId = fetchEvent.getUserId();

List<String> eventIds = eventRepository.findAllByParticipantUserId(userId)
List<String> eventIds = eventRepository.findByParticipantsUserId(userId)
.stream()
.map(Event::getId)
.collect(Collectors.toList());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

import app.sportahub.kafka.events.notification.NotificationEvent;

import java.util.List;
import java.util.Map;

public interface OrchestrationServiceProducer {
void sendNotificationEvent(NotificationEvent event);
}
String getUserById(String userId);
}
Loading
Loading