` to any timeseries scraped from this config.
+ - job_name: 'prometheus'
+
+ # Override the global default and scrape targets from this job every 5 seconds.
+ scrape_interval: 5s
+
+ # scheme defaults to 'http' enable https in case your application is server via https
+ #scheme: https
+ # basic auth is not needed by default. See https://www.jhipster.tech/monitoring/#configuring-metrics-forwarding for details
+ #basic_auth:
+ # username: admin
+ # password: admin
+ metrics_path: /management/prometheus
+ static_configs:
+ - targets:
+ # On MacOS, replace localhost by host.docker.internal
+ - localhost:8080
diff --git a/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/docker/sonar.yml b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/docker/sonar.yml
new file mode 100644
index 0000000..35b4c83
--- /dev/null
+++ b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/docker/sonar.yml
@@ -0,0 +1,13 @@
+# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
+version: '3.8'
+services:
+ finalfreebiesalerts-sonar:
+ image: sonarqube:9.6.0-community
+ # Authentication is turned off for out of the box experience while trying out SonarQube
+ # For real use cases delete sonar.forceAuthentication variable or set sonar.forceAuthentication=true
+ environment:
+ - sonar.forceAuthentication=false
+ # If you want to expose these ports outside your dev PC,
+ # remove the "127.0.0.1:" prefix
+ ports:
+ - 127.0.0.1:9001:9000
diff --git a/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/docker/zipkin.yml b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/docker/zipkin.yml
new file mode 100644
index 0000000..07938b9
--- /dev/null
+++ b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/docker/zipkin.yml
@@ -0,0 +1,7 @@
+# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
+version: '3.8'
+services:
+ zipkin:
+ image: openzipkin/zipkin:2.23
+ ports:
+ - 127.0.0.1:9411:9411
diff --git a/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/ApplicationWebXml.java b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/ApplicationWebXml.java
new file mode 100644
index 0000000..d1367c1
--- /dev/null
+++ b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/ApplicationWebXml.java
@@ -0,0 +1,19 @@
+package com.freebies.app;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import tech.jhipster.config.DefaultProfileUtil;
+
+/**
+ * This is a helper Java class that provides an alternative to creating a {@code web.xml}.
+ * This will be invoked only when the application is deployed to a Servlet container like Tomcat, JBoss etc.
+ */
+public class ApplicationWebXml extends SpringBootServletInitializer {
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ // set a default to use when no profile is configured.
+ DefaultProfileUtil.addDefaultProfile(application.application());
+ return application.sources(FinalFreebiesAlertsApp.class);
+ }
+}
diff --git a/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/FinalFreebiesAlertsApp.java b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/FinalFreebiesAlertsApp.java
new file mode 100644
index 0000000..6e105d3
--- /dev/null
+++ b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/FinalFreebiesAlertsApp.java
@@ -0,0 +1,105 @@
+package com.freebies.app;
+
+import com.freebies.app.config.ApplicationProperties;
+import com.freebies.app.config.CRLFLogConverter;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Optional;
+import javax.annotation.PostConstruct;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.core.env.Environment;
+import tech.jhipster.config.DefaultProfileUtil;
+import tech.jhipster.config.JHipsterConstants;
+
+@SpringBootApplication
+@EnableConfigurationProperties({ LiquibaseProperties.class, ApplicationProperties.class })
+public class FinalFreebiesAlertsApp {
+
+ private static final Logger log = LoggerFactory.getLogger(FinalFreebiesAlertsApp.class);
+
+ private final Environment env;
+
+ public FinalFreebiesAlertsApp(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ * Initializes FinalFreebiesAlerts.
+ *
+ * Spring profiles can be configured with a program argument --spring.profiles.active=your-active-profile
+ *
+ * You can find more information on how profiles work with JHipster on https://www.jhipster.tech/profiles/.
+ */
+ @PostConstruct
+ public void initApplication() {
+ Collection activeProfiles = Arrays.asList(env.getActiveProfiles());
+ if (
+ activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) &&
+ activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)
+ ) {
+ log.error(
+ "You have misconfigured your application! It should not run " + "with both the 'dev' and 'prod' profiles at the same time."
+ );
+ }
+ if (
+ activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) &&
+ activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_CLOUD)
+ ) {
+ log.error(
+ "You have misconfigured your application! It should not " + "run with both the 'dev' and 'cloud' profiles at the same time."
+ );
+ }
+ }
+
+ /**
+ * Main method, used to run the application.
+ *
+ * @param args the command line arguments.
+ */
+ public static void main(String[] args) {
+ SpringApplication app = new SpringApplication(FinalFreebiesAlertsApp.class);
+ DefaultProfileUtil.addDefaultProfile(app);
+ Environment env = app.run(args).getEnvironment();
+ logApplicationStartup(env);
+ }
+
+ private static void logApplicationStartup(Environment env) {
+ String protocol = Optional.ofNullable(env.getProperty("server.ssl.key-store")).map(key -> "https").orElse("http");
+ String serverPort = env.getProperty("server.port");
+ String contextPath = Optional
+ .ofNullable(env.getProperty("server.servlet.context-path"))
+ .filter(StringUtils::isNotBlank)
+ .orElse("/");
+ String hostAddress = "localhost";
+ try {
+ hostAddress = InetAddress.getLocalHost().getHostAddress();
+ } catch (UnknownHostException e) {
+ log.warn("The host name could not be determined, using `localhost` as fallback");
+ }
+ log.info(
+ CRLFLogConverter.CRLF_SAFE_MARKER,
+ "\n----------------------------------------------------------\n\t" +
+ "Application '{}' is running! Access URLs:\n\t" +
+ "Local: \t\t{}://localhost:{}{}\n\t" +
+ "External: \t{}://{}:{}{}\n\t" +
+ "Profile(s): \t{}\n----------------------------------------------------------",
+ env.getProperty("spring.application.name"),
+ protocol,
+ serverPort,
+ contextPath,
+ protocol,
+ hostAddress,
+ serverPort,
+ contextPath,
+ env.getActiveProfiles().length == 0 ? env.getDefaultProfiles() : env.getActiveProfiles()
+ );
+ }
+}
diff --git a/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/GeneratedByJHipster.java b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/GeneratedByJHipster.java
new file mode 100644
index 0000000..f5f0120
--- /dev/null
+++ b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/GeneratedByJHipster.java
@@ -0,0 +1,13 @@
+package com.freebies.app;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.annotation.Generated;
+
+@Generated(value = "JHipster", comments = "Generated by JHipster 7.9.3")
+@Retention(RetentionPolicy.SOURCE)
+@Target({ ElementType.TYPE })
+public @interface GeneratedByJHipster {
+}
diff --git a/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/aop/logging/LoggingAspect.java b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/aop/logging/LoggingAspect.java
new file mode 100644
index 0000000..0bbf6d6
--- /dev/null
+++ b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/aop/logging/LoggingAspect.java
@@ -0,0 +1,113 @@
+package com.freebies.app.aop.logging;
+
+import java.util.Arrays;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.env.Environment;
+import org.springframework.core.env.Profiles;
+import tech.jhipster.config.JHipsterConstants;
+
+/**
+ * Aspect for logging execution of service and repository Spring components.
+ *
+ * By default, it only runs with the "dev" profile.
+ */
+@Aspect
+public class LoggingAspect {
+
+ private final Environment env;
+
+ public LoggingAspect(Environment env) {
+ this.env = env;
+ }
+
+ /**
+ * Pointcut that matches all repositories, services and Web REST endpoints.
+ */
+ @Pointcut(
+ "within(@org.springframework.stereotype.Repository *)" +
+ " || within(@org.springframework.stereotype.Service *)" +
+ " || within(@org.springframework.web.bind.annotation.RestController *)"
+ )
+ public void springBeanPointcut() {
+ // Method is empty as this is just a Pointcut, the implementations are in the advices.
+ }
+
+ /**
+ * Pointcut that matches all Spring beans in the application's main packages.
+ */
+ @Pointcut(
+ "within(com.freebies.app.repository..*)" + " || within(com.freebies.app.service..*)" + " || within(com.freebies.app.web.rest..*)"
+ )
+ public void applicationPackagePointcut() {
+ // Method is empty as this is just a Pointcut, the implementations are in the advices.
+ }
+
+ /**
+ * Retrieves the {@link Logger} associated to the given {@link JoinPoint}.
+ *
+ * @param joinPoint join point we want the logger for.
+ * @return {@link Logger} associated to the given {@link JoinPoint}.
+ */
+ private Logger logger(JoinPoint joinPoint) {
+ return LoggerFactory.getLogger(joinPoint.getSignature().getDeclaringTypeName());
+ }
+
+ /**
+ * Advice that logs methods throwing exceptions.
+ *
+ * @param joinPoint join point for advice.
+ * @param e exception.
+ */
+ @AfterThrowing(pointcut = "applicationPackagePointcut() && springBeanPointcut()", throwing = "e")
+ public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
+ if (env.acceptsProfiles(Profiles.of(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT))) {
+ logger(joinPoint)
+ .error(
+ "Exception in {}() with cause = '{}' and exception = '{}'",
+ joinPoint.getSignature().getName(),
+ e.getCause() != null ? e.getCause() : "NULL",
+ e.getMessage(),
+ e
+ );
+ } else {
+ logger(joinPoint)
+ .error(
+ "Exception in {}() with cause = {}",
+ joinPoint.getSignature().getName(),
+ e.getCause() != null ? e.getCause() : "NULL"
+ );
+ }
+ }
+
+ /**
+ * Advice that logs when a method is entered and exited.
+ *
+ * @param joinPoint join point for advice.
+ * @return result.
+ * @throws Throwable throws {@link IllegalArgumentException}.
+ */
+ @Around("applicationPackagePointcut() && springBeanPointcut()")
+ public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
+ Logger log = logger(joinPoint);
+ if (log.isDebugEnabled()) {
+ log.debug("Enter: {}() with argument[s] = {}", joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
+ }
+ try {
+ Object result = joinPoint.proceed();
+ if (log.isDebugEnabled()) {
+ log.debug("Exit: {}() with result = {}", joinPoint.getSignature().getName(), result);
+ }
+ return result;
+ } catch (IllegalArgumentException e) {
+ log.error("Illegal argument: {} in {}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature().getName());
+ throw e;
+ }
+ }
+}
diff --git a/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/ApplicationProperties.java b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/ApplicationProperties.java
new file mode 100644
index 0000000..9633c88
--- /dev/null
+++ b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/ApplicationProperties.java
@@ -0,0 +1,16 @@
+package com.freebies.app.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Properties specific to Final Freebies Alerts.
+ *
+ * Properties are configured in the {@code application.yml} file.
+ * See {@link tech.jhipster.config.JHipsterProperties} for a good example.
+ */
+@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
+public class ApplicationProperties {
+ // jhipster-needle-application-properties-property
+ // jhipster-needle-application-properties-property-getter
+ // jhipster-needle-application-properties-property-class
+}
diff --git a/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/AsyncConfiguration.java b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/AsyncConfiguration.java
new file mode 100644
index 0000000..cf25f43
--- /dev/null
+++ b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/AsyncConfiguration.java
@@ -0,0 +1,48 @@
+package com.freebies.app.config;
+
+import java.util.concurrent.Executor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
+import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
+import org.springframework.boot.autoconfigure.task.TaskExecutionProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.AsyncConfigurer;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import tech.jhipster.async.ExceptionHandlingAsyncTaskExecutor;
+
+@Configuration
+@EnableAsync
+@EnableScheduling
+@Profile("!testdev & !testprod")
+public class AsyncConfiguration implements AsyncConfigurer {
+
+ private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);
+
+ private final TaskExecutionProperties taskExecutionProperties;
+
+ public AsyncConfiguration(TaskExecutionProperties taskExecutionProperties) {
+ this.taskExecutionProperties = taskExecutionProperties;
+ }
+
+ @Override
+ @Bean(name = "taskExecutor")
+ public Executor getAsyncExecutor() {
+ log.debug("Creating Async Task Executor");
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(taskExecutionProperties.getPool().getCoreSize());
+ executor.setMaxPoolSize(taskExecutionProperties.getPool().getMaxSize());
+ executor.setQueueCapacity(taskExecutionProperties.getPool().getQueueCapacity());
+ executor.setThreadNamePrefix(taskExecutionProperties.getThreadNamePrefix());
+ return new ExceptionHandlingAsyncTaskExecutor(executor);
+ }
+
+ @Override
+ public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
+ return new SimpleAsyncUncaughtExceptionHandler();
+ }
+}
diff --git a/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/CRLFLogConverter.java b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/CRLFLogConverter.java
new file mode 100644
index 0000000..75d7dbd
--- /dev/null
+++ b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/CRLFLogConverter.java
@@ -0,0 +1,56 @@
+package com.freebies.app.config;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.pattern.CompositeConverter;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+import org.springframework.boot.ansi.AnsiColor;
+import org.springframework.boot.ansi.AnsiElement;
+import org.springframework.boot.ansi.AnsiOutput;
+import org.springframework.boot.ansi.AnsiStyle;
+
+public class CRLFLogConverter extends CompositeConverter {
+
+ public static final Marker CRLF_SAFE_MARKER = MarkerFactory.getMarker("CRLF_SAFE");
+
+ private static final String[] SAFE_LOGGERS = { "org.hibernate" };
+ private static final Map ELEMENTS;
+
+ static {
+ Map ansiElements = new HashMap<>();
+ ansiElements.put("faint", AnsiStyle.FAINT);
+ ansiElements.put("red", AnsiColor.RED);
+ ansiElements.put("green", AnsiColor.GREEN);
+ ansiElements.put("yellow", AnsiColor.YELLOW);
+ ansiElements.put("blue", AnsiColor.BLUE);
+ ansiElements.put("magenta", AnsiColor.MAGENTA);
+ ansiElements.put("cyan", AnsiColor.CYAN);
+ ELEMENTS = Collections.unmodifiableMap(ansiElements);
+ }
+
+ @Override
+ protected String transform(ILoggingEvent event, String in) {
+ AnsiElement element = ELEMENTS.get(getFirstOption());
+ if ((event.getMarker() != null && event.getMarker().contains(CRLF_SAFE_MARKER)) || isLoggerSafe(event)) {
+ return in;
+ }
+ String replacement = element == null ? "_" : toAnsiString("_", element);
+ return in.replaceAll("[\n\r\t]", replacement);
+ }
+
+ protected boolean isLoggerSafe(ILoggingEvent event) {
+ for (String safeLogger : SAFE_LOGGERS) {
+ if (event.getLoggerName().startsWith(safeLogger)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected String toAnsiString(String in, AnsiElement element) {
+ return AnsiOutput.toString(element, in);
+ }
+}
diff --git a/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/CacheConfiguration.java b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/CacheConfiguration.java
new file mode 100644
index 0000000..201f54f
--- /dev/null
+++ b/SantosHerrera-FreebiesAlert/FinalFreebiesAlerts/src/main/java/com/freebies/app/config/CacheConfiguration.java
@@ -0,0 +1,82 @@
+package com.freebies.app.config;
+
+import java.time.Duration;
+import org.ehcache.config.builders.*;
+import org.ehcache.jsr107.Eh107Configuration;
+import org.hibernate.cache.jcache.ConfigSettings;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
+import org.springframework.boot.info.BuildProperties;
+import org.springframework.boot.info.GitProperties;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.interceptor.KeyGenerator;
+import org.springframework.context.annotation.*;
+import tech.jhipster.config.JHipsterProperties;
+import tech.jhipster.config.cache.PrefixedKeyGenerator;
+
+@Configuration
+@EnableCaching
+public class CacheConfiguration {
+
+ private GitProperties gitProperties;
+ private BuildProperties buildProperties;
+ private final javax.cache.configuration.Configuration